define(["@jupyter-widgets/base"], (__WEBPACK_EXTERNAL_MODULE__2055__) => { return /******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ 134:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelShellFutureHandler = exports.KernelControlFutureHandler = exports.KernelFutureHandler = void 0;
const coreutils_1 = __webpack_require__(5764);
const disposable_1 = __webpack_require__(7556);
const KernelMessage = __importStar(__webpack_require__(9909));
/**
 * Implementation of a kernel future.
 *
 * If a reply is expected, the Future is considered done when both a `reply`
 * message and an `idle` iopub status message have been received.  Otherwise, it
 * is considered done when the `idle` status is received.
 *
 */
class KernelFutureHandler extends disposable_1.DisposableDelegate {
    /**
     * Construct a new KernelFutureHandler.
     */
    constructor(cb, msg, expectReply, disposeOnDone, kernel) {
        super(cb);
        this._status = 0;
        this._stdin = Private.noOp;
        this._iopub = Private.noOp;
        this._reply = Private.noOp;
        this._done = new coreutils_1.PromiseDelegate();
        this._hooks = new Private.HookList();
        this._disposeOnDone = true;
        this._msg = msg;
        if (!expectReply) {
            this._setFlag(Private.KernelFutureFlag.GotReply);
        }
        this._disposeOnDone = disposeOnDone;
        this._kernel = kernel;
    }
    /**
     * Get the original outgoing message.
     */
    get msg() {
        return this._msg;
    }
    /**
     * A promise that resolves when the future is done.
     */
    get done() {
        return this._done.promise;
    }
    /**
     * Get the reply handler.
     */
    get onReply() {
        return this._reply;
    }
    /**
     * Set the reply handler.
     */
    set onReply(cb) {
        this._reply = cb;
    }
    /**
     * Get the iopub handler.
     */
    get onIOPub() {
        return this._iopub;
    }
    /**
     * Set the iopub handler.
     */
    set onIOPub(cb) {
        this._iopub = cb;
    }
    /**
     * Get the stdin handler.
     */
    get onStdin() {
        return this._stdin;
    }
    /**
     * Set the stdin handler.
     */
    set onStdin(cb) {
        this._stdin = cb;
    }
    /**
     * Register hook for IOPub messages.
     *
     * @param hook - The callback invoked for an IOPub message.
     *
     * #### Notes
     * The IOPub hook system allows you to preempt the handlers for IOPub
     * messages handled by the future.
     *
     * The most recently registered hook is run first. A hook can return a
     * boolean or a promise to a boolean, in which case all kernel message
     * processing pauses until the promise is fulfilled. If a hook return value
     * resolves to false, any later hooks will not run and the function will
     * return a promise resolving to false. If a hook throws an error, the error
     * is logged to the console and the next hook is run. If a hook is
     * registered during the hook processing, it will not run until the next
     * message. If a hook is removed during the hook processing, it will be
     * deactivated immediately.
     */
    registerMessageHook(hook) {
        if (this.isDisposed) {
            throw new Error('Kernel future is disposed');
        }
        this._hooks.add(hook);
    }
    /**
     * Remove a hook for IOPub messages.
     *
     * @param hook - The hook to remove.
     *
     * #### Notes
     * If a hook is removed during the hook processing, it will be deactivated immediately.
     */
    removeMessageHook(hook) {
        if (this.isDisposed) {
            return;
        }
        this._hooks.remove(hook);
    }
    /**
     * Send an `input_reply` message.
     */
    sendInputReply(content, parent_header) {
        this._kernel.sendInputReply(content, parent_header);
    }
    /**
     * Dispose and unregister the future.
     */
    dispose() {
        this._stdin = Private.noOp;
        this._iopub = Private.noOp;
        this._reply = Private.noOp;
        this._hooks = null;
        if (!this._testFlag(Private.KernelFutureFlag.IsDone)) {
            // TODO: Uncomment the following logging code, and check for any tests that trigger it.
            // let status = [];
            // if (!this._testFlag(Private.KernelFutureFlag.GotIdle)) {
            //   status.push('idle');
            // }
            // if (!this._testFlag(Private.KernelFutureFlag.GotReply)) {
            //   status.push('reply');
            // }
            // console.warn(
            //   `*************** DISPOSED BEFORE DONE: K${this._kernel.id.slice(
            //     0,
            //     6
            //   )} M${this._msg.header.msg_id.slice(0, 6)} missing ${status.join(' ')}`
            // );
            // Reject the `done` promise, but catch its error here in case no one else
            // is waiting for the promise to resolve. This prevents the error from
            // being displayed in the console, but does not prevent it from being
            // caught by a client who is waiting for it.
            // Note: any `.then` and `.finally` attached to the `done` promise
            // will cause the error to be thrown as uncaught anyways.
            this._done.promise.catch(() => {
                /* no-op */
            });
            this._done.reject(new Error(`Canceled future for ${this.msg.header.msg_type} message before replies were done`));
        }
        super.dispose();
    }
    /**
     * Handle an incoming kernel message.
     */
    async handleMsg(msg) {
        switch (msg.channel) {
            case 'control':
            case 'shell':
                if (msg.channel === this.msg.channel &&
                    msg.parent_header.msg_id === this.msg.header.msg_id) {
                    await this._handleReply(msg);
                }
                break;
            case 'stdin':
                await this._handleStdin(msg);
                break;
            case 'iopub':
                await this._handleIOPub(msg);
                break;
            default:
                break;
        }
    }
    async _handleReply(msg) {
        const reply = this._reply;
        if (reply) {
            // tslint:disable-next-line:await-promise
            await reply(msg);
        }
        this._replyMsg = msg;
        this._setFlag(Private.KernelFutureFlag.GotReply);
        if (this._testFlag(Private.KernelFutureFlag.GotIdle)) {
            this._handleDone();
        }
    }
    async _handleStdin(msg) {
        this._kernel.hasPendingInput = true;
        const stdin = this._stdin;
        if (stdin) {
            // tslint:disable-next-line:await-promise
            await stdin(msg);
        }
    }
    async _handleIOPub(msg) {
        const process = await this._hooks.process(msg);
        const iopub = this._iopub;
        if (process && iopub) {
            // tslint:disable-next-line:await-promise
            await iopub(msg);
        }
        if (KernelMessage.isStatusMsg(msg) &&
            msg.content.execution_state === 'idle') {
            this._setFlag(Private.KernelFutureFlag.GotIdle);
            if (this._testFlag(Private.KernelFutureFlag.GotReply)) {
                this._handleDone();
            }
        }
    }
    _handleDone() {
        if (this._testFlag(Private.KernelFutureFlag.IsDone)) {
            return;
        }
        this._setFlag(Private.KernelFutureFlag.IsDone);
        this._done.resolve(this._replyMsg);
        if (this._disposeOnDone) {
            this.dispose();
        }
    }
    /**
     * Test whether the given future flag is set.
     */
    _testFlag(flag) {
        // tslint:disable-next-line
        return (this._status & flag) !== 0;
    }
    /**
     * Set the given future flag.
     */
    _setFlag(flag) {
        // tslint:disable-next-line
        this._status |= flag;
    }
}
exports.KernelFutureHandler = KernelFutureHandler;
class KernelControlFutureHandler extends KernelFutureHandler {
}
exports.KernelControlFutureHandler = KernelControlFutureHandler;
class KernelShellFutureHandler extends KernelFutureHandler {
}
exports.KernelShellFutureHandler = KernelShellFutureHandler;
var Private;
(function (Private) {
    /**
     * A no-op function.
     */
    Private.noOp = () => {
        /* no-op */
    };
    /**
     * Defer a computation.
     *
     * #### NOTES
     * We can't just use requestAnimationFrame since it is not available in node.
     * This implementation is from Phosphor:
     * https://github.com/phosphorjs/phosphor/blob/e88e4321289bb1198f3098e7bda40736501f2ed8/tests/test-messaging/src/index.spec.ts#L63
     */
    const defer = (() => {
        const ok = typeof requestAnimationFrame === 'function';
        return ok ? requestAnimationFrame : setImmediate;
    })();
    class HookList {
        constructor() {
            this._hooks = [];
        }
        /**
         * Register a hook.
         *
         * @param hook - The callback to register.
         */
        add(hook) {
            this.remove(hook);
            this._hooks.push(hook);
        }
        /**
         * Remove a hook, if it exists in the hook list.
         *
         * @param hook - The callback to remove.
         */
        remove(hook) {
            const index = this._hooks.indexOf(hook);
            if (index >= 0) {
                this._hooks[index] = null;
                this._scheduleCompact();
            }
        }
        /**
         * Process a message through the hooks.
         *
         * @returns a promise resolving to false if any hook resolved as false,
         * otherwise true
         *
         * #### Notes
         * The most recently registered hook is run first. A hook can return a
         * boolean or a promise to a boolean, in which case processing pauses until
         * the promise is fulfilled. If a hook return value resolves to false, any
         * later hooks will not run and the function will return a promise resolving
         * to false. If a hook throws an error, the error is logged to the console
         * and the next hook is run. If a hook is registered during the hook
         * processing, it will not run until the next message. If a hook is removed
         * during the hook processing, it will be deactivated immediately.
         */
        async process(msg) {
            // Wait until we can start a new process run.
            await this._processing;
            // Start the next process run.
            const processing = new coreutils_1.PromiseDelegate();
            this._processing = processing.promise;
            let continueHandling;
            // Call the end hook (most recently-added) first. Starting at the end also
            // guarantees that hooks added during the processing will not be run in
            // this process run.
            for (let i = this._hooks.length - 1; i >= 0; i--) {
                const hook = this._hooks[i];
                // If the hook has been removed, continue to the next one.
                if (hook === null) {
                    continue;
                }
                // Execute the hook and log any errors.
                try {
                    // tslint:disable-next-line:await-promise
                    continueHandling = await hook(msg);
                }
                catch (err) {
                    continueHandling = true;
                    console.error(err);
                }
                // If the hook resolved to false, stop processing and return.
                if (continueHandling === false) {
                    processing.resolve(undefined);
                    return false;
                }
            }
            // All hooks returned true (or errored out), so return true.
            processing.resolve(undefined);
            return true;
        }
        /**
         * Schedule a cleanup of the list, removing any hooks that have been nulled out.
         */
        _scheduleCompact() {
            if (!this._compactScheduled) {
                this._compactScheduled = true;
                // Schedule a compaction in between processing runs. We do the
                // scheduling in an animation frame to rate-limit our compactions. If we
                // need to compact more frequently, we can change this to directly
                // schedule the compaction.
                defer(() => {
                    this._processing = this._processing.then(() => {
                        this._compactScheduled = false;
                        this._compact();
                    });
                });
            }
        }
        /**
         * Compact the list, removing any nulls.
         */
        _compact() {
            let numNulls = 0;
            for (let i = 0, len = this._hooks.length; i < len; i++) {
                const hook = this._hooks[i];
                if (this._hooks[i] === null) {
                    numNulls++;
                }
                else {
                    this._hooks[i - numNulls] = hook;
                }
            }
            this._hooks.length -= numNulls;
        }
    }
    Private.HookList = HookList;
    /**
     * Bit flags for the kernel future state.
     */
    let KernelFutureFlag;
    (function (KernelFutureFlag) {
        KernelFutureFlag[KernelFutureFlag["GotReply"] = 1] = "GotReply";
        KernelFutureFlag[KernelFutureFlag["GotIdle"] = 2] = "GotIdle";
        KernelFutureFlag[KernelFutureFlag["IsDone"] = 4] = "IsDone";
        KernelFutureFlag[KernelFutureFlag["DisposeOnDone"] = 8] = "DisposeOnDone";
    })(KernelFutureFlag = Private.KernelFutureFlag || (Private.KernelFutureFlag = {}));
})(Private || (Private = {}));
//# sourceMappingURL=future.js.map

/***/ }),

/***/ 733:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelSpecManager = void 0;
const coreutils_1 = __webpack_require__(5764);
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const basemanager_1 = __webpack_require__(3867);
const restapi_1 = __webpack_require__(6492);
/**
 * An implementation of a kernel spec manager.
 */
class KernelSpecManager extends basemanager_1.BaseManager {
    /**
     * Construct a new kernel spec manager.
     *
     * @param options - The default options for kernel.
     */
    constructor(options = {}) {
        var _a, _b;
        super(options);
        this._isReady = false;
        this._connectionFailure = new signaling_1.Signal(this);
        this._specs = null;
        this._specsChanged = new signaling_1.Signal(this);
        this._kernelSpecAPIClient =
            (_a = options.kernelSpecAPIClient) !== null && _a !== void 0 ? _a : new restapi_1.KernelSpecAPIClient({ serverSettings: this.serverSettings });
        // Initialize internal data.
        this._ready = Promise.all([this.requestSpecs()])
            .then(_ => undefined)
            .catch(_ => undefined)
            .then(() => {
            if (this.isDisposed) {
                return;
            }
            this._isReady = true;
        });
        this._pollSpecs = new polling_1.Poll({
            auto: false,
            factory: () => this.requestSpecs(),
            frequency: {
                interval: 61 * 1000,
                backoff: true,
                max: 300 * 1000
            },
            name: `@jupyterlab/services:KernelSpecManager#specs`,
            standby: (_b = options.standby) !== null && _b !== void 0 ? _b : 'when-hidden'
        });
        void this.ready.then(() => {
            void this._pollSpecs.start();
        });
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._ready;
    }
    /**
     * Get the most recently fetched kernel specs.
     */
    get specs() {
        return this._specs;
    }
    /**
     * A signal emitted when the specs change.
     */
    get specsChanged() {
        return this._specsChanged;
    }
    /**
     * A signal emitted when there is a connection failure.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        this._pollSpecs.dispose();
        super.dispose();
    }
    /**
     * Force a refresh of the specs from the server.
     *
     * @returns A promise that resolves when the specs are fetched.
     *
     * #### Notes
     * This is intended to be called only in response to a user action,
     * since the manager maintains its internal state.
     */
    async refreshSpecs() {
        await this._pollSpecs.refresh();
        await this._pollSpecs.tick;
    }
    /**
     * Execute a request to the server to poll specs and update state.
     */
    async requestSpecs() {
        const specs = await this._kernelSpecAPIClient.get();
        if (this.isDisposed) {
            return;
        }
        if (!coreutils_1.JSONExt.deepEqual(specs, this._specs)) {
            this._specs = specs;
            this._specsChanged.emit(specs);
        }
    }
}
exports.KernelSpecManager = KernelSpecManager;
//# sourceMappingURL=manager.js.map

/***/ }),

/***/ 973:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CommsOverSubshells = exports.KernelConnection = exports.KernelAPI = exports.KernelMessage = exports.Kernel = void 0;
// Namespace some of our modules for convenience and backwards compatibility.
const comm_1 = __webpack_require__(7489);
Object.defineProperty(exports, "CommsOverSubshells", ({ enumerable: true, get: function () { return comm_1.CommsOverSubshells; } }));
const Kernel = __importStar(__webpack_require__(2956));
exports.Kernel = Kernel;
const KernelMessage = __importStar(__webpack_require__(9909));
exports.KernelMessage = KernelMessage;
const KernelAPI = __importStar(__webpack_require__(8235));
exports.KernelAPI = KernelAPI;
const default_1 = __webpack_require__(2456);
Object.defineProperty(exports, "KernelConnection", ({ enumerable: true, get: function () { return default_1.KernelConnection; } }));
__exportStar(__webpack_require__(5198), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 1232:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.LruCache = void 0;
const DEFAULT_MAX_SIZE = 128;
/** A least-recently-used cache. */
class LruCache {
    constructor(options = {}) {
        this._map = new Map();
        this._maxSize = (options === null || options === void 0 ? void 0 : options.maxSize) || DEFAULT_MAX_SIZE;
    }
    /**
     * Return the current size of the cache.
     */
    get size() {
        return this._map.size;
    }
    /**
     * Clear the values in the cache.
     */
    clear() {
        this._map.clear();
    }
    /**
     * Get a value (or null) from the cache, pushing the item to the front of the cache.
     */
    get(key) {
        const item = this._map.get(key) || null;
        if (item != null) {
            this._map.delete(key);
            this._map.set(key, item);
        }
        return item;
    }
    /**
     * Set a value in the cache, potentially evicting an old item.
     */
    set(key, value) {
        if (this._map.size >= this._maxSize) {
            this._map.delete(this._map.keys().next().value);
        }
        this._map.set(key, value);
    }
}
exports.LruCache = LruCache;
//# sourceMappingURL=lru.js.map

/***/ }),

/***/ 1359:
/***/ ((__unused_webpack_module, exports) => {

"use strict";


var has = Object.prototype.hasOwnProperty
  , undef;

/**
 * Decode a URI encoded string.
 *
 * @param {String} input The URI encoded string.
 * @returns {String|Null} The decoded string.
 * @api private
 */
function decode(input) {
  try {
    return decodeURIComponent(input.replace(/\+/g, ' '));
  } catch (e) {
    return null;
  }
}

/**
 * Attempts to encode a given input.
 *
 * @param {String} input The string that needs to be encoded.
 * @returns {String|Null} The encoded string.
 * @api private
 */
function encode(input) {
  try {
    return encodeURIComponent(input);
  } catch (e) {
    return null;
  }
}

/**
 * Simple query string parser.
 *
 * @param {String} query The query string that needs to be parsed.
 * @returns {Object}
 * @api public
 */
function querystring(query) {
  var parser = /([^=?#&]+)=?([^&]*)/g
    , result = {}
    , part;

  while (part = parser.exec(query)) {
    var key = decode(part[1])
      , value = decode(part[2]);

    //
    // Prevent overriding of existing properties. This ensures that build-in
    // methods like `toString` or __proto__ are not overriden by malicious
    // querystrings.
    //
    // In the case if failed decoding, we want to omit the key/value pairs
    // from the result.
    //
    if (key === null || value === null || key in result) continue;
    result[key] = value;
  }

  return result;
}

/**
 * Transform a query string to an object.
 *
 * @param {Object} obj Object that should be transformed.
 * @param {String} prefix Optional prefix.
 * @returns {String}
 * @api public
 */
function querystringify(obj, prefix) {
  prefix = prefix || '';

  var pairs = []
    , value
    , key;

  //
  // Optionally prefix with a '?' if needed
  //
  if ('string' !== typeof prefix) prefix = '?';

  for (key in obj) {
    if (has.call(obj, key)) {
      value = obj[key];

      //
      // Edge cases where we actually want to encode the value to an empty
      // string instead of the stringified value.
      //
      if (!value && (value === null || value === undef || isNaN(value))) {
        value = '';
      }

      key = encode(key);
      value = encode(value);

      //
      // If we failed to encode the strings, we should bail out as we don't
      // want to add invalid strings to the query.
      //
      if (key === null || value === null) continue;
      pairs.push(key +'='+ value);
    }
  }

  return pairs.length ? prefix + pairs.join('&') : '';
}

//
// Expose the module.
//
exports.stringify = querystringify;
exports.parse = querystring;


/***/ }),

/***/ 1670:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/* -----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
 * @packageDocumentation
 * @module statedb
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
__exportStar(__webpack_require__(4949), exports);
__exportStar(__webpack_require__(9708), exports);
__exportStar(__webpack_require__(4025), exports);
__exportStar(__webpack_require__(2133), exports);
__exportStar(__webpack_require__(8022), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 1692:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.URLExt = void 0;
const path_1 = __webpack_require__(9942);
const url_parse_1 = __importDefault(__webpack_require__(2225));
/**
 * The namespace for URL-related functions.
 */
var URLExt;
(function (URLExt) {
    /**
     * Parse a url into a URL object.
     *
     * @param url - The URL string to parse.
     *
     * @returns A URL object.
     */
    function parse(url) {
        if (typeof document !== 'undefined' && document) {
            const a = document.createElement('a');
            a.href = url;
            return a;
        }
        return (0, url_parse_1.default)(url);
    }
    URLExt.parse = parse;
    /**
     * Parse URL and retrieve hostname
     *
     * @param url - The URL string to parse
     *
     * @returns a hostname string value
     */
    function getHostName(url) {
        return (0, url_parse_1.default)(url).hostname;
    }
    URLExt.getHostName = getHostName;
    function normalize(url) {
        return url && parse(url).toString();
    }
    URLExt.normalize = normalize;
    /**
     * Join a sequence of url components and normalizes as in node `path.join`.
     *
     * @param parts - The url components.
     *
     * @returns the joined url.
     */
    function join(...parts) {
        let u = (0, url_parse_1.default)(parts[0], {});
        // Schema-less URL can be only parsed as relative to a base URL
        // see https://github.com/unshiftio/url-parse/issues/219#issuecomment-1002219326
        const isSchemaLess = u.protocol === '' && u.slashes;
        if (isSchemaLess) {
            u = (0, url_parse_1.default)(parts[0], 'https:' + parts[0]);
        }
        const prefix = `${isSchemaLess ? '' : u.protocol}${u.slashes ? '//' : ''}${u.auth}${u.auth ? '@' : ''}${u.host}`;
        // If there was a prefix, then the first path must start at the root.
        const path = path_1.posix.join(`${!!prefix && u.pathname[0] !== '/' ? '/' : ''}${u.pathname}`, ...parts.slice(1));
        return `${prefix}${path === '.' ? '' : path}`;
    }
    URLExt.join = join;
    /**
     * Encode the components of a multi-segment url.
     *
     * @param url - The url to encode.
     *
     * @returns the encoded url.
     *
     * #### Notes
     * Preserves the `'/'` separators.
     * Should not include the base url, since all parts are escaped.
     */
    function encodeParts(url) {
        return join(...url.split('/').map(encodeURIComponent));
    }
    URLExt.encodeParts = encodeParts;
    /**
     * Return a serialized object string suitable for a query.
     *
     * @param value The source object.
     *
     * @returns an encoded url query.
     *
     * #### Notes
     * Modified version of [stackoverflow](http://stackoverflow.com/a/30707423).
     */
    function objectToQueryString(value) {
        const keys = Object.keys(value).filter(key => key.length > 0);
        if (!keys.length) {
            return '';
        }
        return ('?' +
            keys
                .map(key => {
                const content = encodeURIComponent(String(value[key]));
                return key + (content ? '=' + content : '');
            })
                .join('&'));
    }
    URLExt.objectToQueryString = objectToQueryString;
    /**
     * Return a parsed object that represents the values in a query string.
     */
    function queryStringToObject(value) {
        return value
            .replace(/^\?/, '')
            .split('&')
            .reduce((acc, val) => {
            const [key, value] = val.split('=');
            if (key.length > 0) {
                acc[key] = decodeURIComponent(value || '');
            }
            return acc;
        }, {});
    }
    URLExt.queryStringToObject = queryStringToObject;
    /**
     * Test whether the url is a local url.
     *
     * @param allowRoot - Whether the paths starting at Unix-style filesystem root (`/`) are permitted.
     *
     * #### Notes
     * This function returns `false` for any fully qualified url, including
     * `data:`, `file:`, and `//` protocol URLs.
     */
    function isLocal(url, allowRoot = false) {
        const { protocol } = parse(url);
        return ((!protocol || url.toLowerCase().indexOf(protocol) !== 0) &&
            (allowRoot ? url.indexOf('//') !== 0 : url.indexOf('/') !== 0));
    }
    URLExt.isLocal = isLocal;
})(URLExt || (exports.URLExt = URLExt = {}));
//# sourceMappingURL=url.js.map

/***/ }),

/***/ 1796:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Time = void 0;
/**
 * A list of time units with their associated value in milliseconds.
 */
const UNITS = [
    { name: 'years', milliseconds: 365 * 24 * 60 * 60 * 1000 },
    { name: 'months', milliseconds: 30 * 24 * 60 * 60 * 1000 },
    { name: 'days', milliseconds: 24 * 60 * 60 * 1000 },
    { name: 'hours', milliseconds: 60 * 60 * 1000 },
    { name: 'minutes', milliseconds: 60 * 1000 },
    { name: 'seconds', milliseconds: 1000 }
];
/**
 * The namespace for date functions.
 */
var Time;
(function (Time) {
    /**
     * Convert a timestring to a human readable string (e.g. 'two minutes ago').
     *
     * @param value - The date timestring or date object.
     *
     * @returns A formatted date.
     */
    function formatHuman(value, format = 'long') {
        const lang = document.documentElement.lang || 'en';
        const formatter = new Intl.RelativeTimeFormat(lang, {
            numeric: 'auto',
            style: format
        });
        const delta = new Date(value).getTime() - Date.now();
        for (let unit of UNITS) {
            const amount = Math.ceil(delta / unit.milliseconds);
            if (amount === 0) {
                continue;
            }
            return formatter.format(amount, unit.name);
        }
        return formatter.format(0, 'seconds');
    }
    Time.formatHuman = formatHuman;
    /**
     * Convenient helper to convert a timestring to a date format.
     *
     * @param value - The date timestring or date object.
     *
     * @returns A formatted date.
     */
    function format(value) {
        const lang = document.documentElement.lang || 'en';
        const formatter = new Intl.DateTimeFormat(lang, {
            dateStyle: 'short',
            timeStyle: 'short'
        });
        return formatter.format(new Date(value));
    }
    Time.format = format;
})(Time || (exports.Time = Time = {}));
//# sourceMappingURL=time.js.map

/***/ }),

/***/ 2055:
/***/ ((module) => {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__2055__;

/***/ }),

/***/ 2133:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.StateDB = void 0;
const signaling_1 = __webpack_require__(3992);
/**
 * The default concrete implementation of a state database.
 */
class StateDB {
    /**
     * Create a new state database.
     *
     * @param options - The instantiation options for a state database.
     */
    constructor(options = {}) {
        this._changed = new signaling_1.Signal(this);
        const { connector, transform } = options;
        this._connector = connector || new StateDB.Connector();
        if (!transform) {
            this._ready = Promise.resolve(undefined);
        }
        else {
            this._ready = transform.then(transformation => {
                const { contents, type } = transformation;
                switch (type) {
                    case 'cancel':
                        return;
                    case 'clear':
                        return this._clear();
                    case 'merge':
                        return this._merge(contents || {});
                    case 'overwrite':
                        return this._overwrite(contents || {});
                    default:
                        return;
                }
            });
        }
    }
    /**
     * A signal that emits the change type any time a value changes.
     */
    get changed() {
        return this._changed;
    }
    /**
     * Clear the entire database.
     */
    async clear() {
        await this._ready;
        await this._clear();
    }
    /**
     * Retrieve a saved bundle from the database.
     *
     * @param id - The identifier used to retrieve a data bundle.
     *
     * @returns A promise that bears a data payload if available.
     *
     * #### Notes
     * The `id` values of stored items in the state database are formatted:
     * `'namespace:identifier'`, which is the same convention that command
     * identifiers in JupyterLab use as well. While this is not a technical
     * requirement for `fetch()`, `remove()`, and `save()`, it *is* necessary for
     * using the `list(namespace: string)` method.
     *
     * The promise returned by this method may be rejected if an error occurs in
     * retrieving the data. Non-existence of an `id` will succeed with the `value`
     * `undefined`.
     */
    async fetch(id) {
        await this._ready;
        return this._fetch(id);
    }
    /**
     * Retrieve all the saved bundles for a namespace.
     *
     * @param namespace The namespace prefix to retrieve.
     *
     * @returns A promise that bears a collection of payloads for a namespace.
     *
     * #### Notes
     * Namespaces are entirely conventional entities. The `id` values of stored
     * items in the state database are formatted: `'namespace:identifier'`, which
     * is the same convention that command identifiers in JupyterLab use as well.
     *
     * If there are any errors in retrieving the data, they will be logged to the
     * console in order to optimistically return any extant data without failing.
     * This promise will always succeed.
     */
    async list(namespace) {
        await this._ready;
        return this._list(namespace);
    }
    /**
     * Remove a value from the database.
     *
     * @param id - The identifier for the data being removed.
     *
     * @returns A promise that is rejected if remove fails and succeeds otherwise.
     */
    async remove(id) {
        await this._ready;
        await this._remove(id);
        this._changed.emit({ id, type: 'remove' });
    }
    /**
     * Save a value in the database.
     *
     * @param id - The identifier for the data being saved.
     *
     * @param value - The data being saved.
     *
     * @returns A promise that is rejected if saving fails and succeeds otherwise.
     *
     * #### Notes
     * The `id` values of stored items in the state database are formatted:
     * `'namespace:identifier'`, which is the same convention that command
     * identifiers in JupyterLab use as well. While this is not a technical
     * requirement for `fetch()`, `remove()`, and `save()`, it *is* necessary for
     * using the `list(namespace: string)` method.
     */
    async save(id, value) {
        await this._ready;
        await this._save(id, value);
        this._changed.emit({ id, type: 'save' });
    }
    /**
     * Return a serialized copy of the state database's entire contents.
     *
     * @returns A promise that resolves with the database contents as JSON.
     */
    async toJSON() {
        await this._ready;
        const { ids, values } = await this._list();
        return values.reduce((acc, val, idx) => {
            acc[ids[idx]] = val;
            return acc;
        }, {});
    }
    /**
     * Clear the entire database.
     */
    async _clear() {
        await Promise.all((await this._list()).ids.map(id => this._remove(id)));
    }
    /**
     * Fetch a value from the database.
     */
    async _fetch(id) {
        const value = await this._connector.fetch(id);
        if (value) {
            return JSON.parse(value).v;
        }
    }
    /**
     * Fetch a list from the database.
     */
    async _list(namespace = '') {
        const { ids, values } = await this._connector.list(namespace);
        return {
            ids,
            values: values.map(val => JSON.parse(val).v)
        };
    }
    /**
     * Merge data into the state database.
     */
    async _merge(contents) {
        await Promise.all(Object.keys(contents).map(key => contents[key] && this._save(key, contents[key])));
    }
    /**
     * Overwrite the entire database with new contents.
     */
    async _overwrite(contents) {
        await this._clear();
        await this._merge(contents);
    }
    /**
     * Remove a key in the database.
     */
    async _remove(id) {
        return this._connector.remove(id);
    }
    /**
     * Save a key and its value in the database.
     */
    async _save(id, value) {
        return this._connector.save(id, JSON.stringify({ v: value }));
    }
}
exports.StateDB = StateDB;
/**
 * A namespace for StateDB statics.
 */
(function (StateDB) {
    /**
     * An in-memory string key/value data connector.
     */
    class Connector {
        constructor() {
            this._storage = {};
        }
        /**
         * Retrieve an item from the data connector.
         */
        async fetch(id) {
            return this._storage[id];
        }
        /**
         * Retrieve the list of items available from the data connector.
         *
         * @param namespace - If not empty, only keys whose first token before `:`
         * exactly match `namespace` will be returned, e.g. `foo` in `foo:bar`.
         */
        async list(namespace = '') {
            return Object.keys(this._storage).reduce((acc, val) => {
                if (namespace === '' ? true : namespace === val.split(':')[0]) {
                    acc.ids.push(val);
                    acc.values.push(this._storage[val]);
                }
                return acc;
            }, { ids: [], values: [] });
        }
        /**
         * Remove a value using the data connector.
         */
        async remove(id) {
            delete this._storage[id];
        }
        /**
         * Save a value using the data connector.
         */
        async save(id, value) {
            this._storage[id] = value;
        }
    }
    StateDB.Connector = Connector;
})(StateDB || (exports.StateDB = StateDB = {}));
//# sourceMappingURL=statedb.js.map

/***/ }),

/***/ 2162:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'pause';
var width = 448;
var height = 512;
var ligatures = [];
var unicode = 'f04c';
var svgPathData = 'M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.G1 = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 2170:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ConfigWithDefaults = exports.ConfigSection = exports.ConfigSectionManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const __1 = __webpack_require__(7883);
/**
 * The url for the config service.
 */
const SERVICE_CONFIG_URL = 'api/config';
/**
 * A manager for config sections.
 */
class ConfigSectionManager {
    /**
     * Create a config section manager.
     */
    constructor(options) {
        var _a;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : __1.ServerConnection.makeSettings();
    }
    /**
     * Create a config section.
     */
    async create(options) {
        const section = new DefaultConfigSection({
            ...options,
            serverSettings: this.serverSettings
        });
        await section.load();
        return section;
    }
}
exports.ConfigSectionManager = ConfigSectionManager;
/**
 * The namespace for ConfigSection statics.
 */
var ConfigSection;
(function (ConfigSection) {
    /**
     * Create a config section.
     *
     * @returns A Promise that is fulfilled with the config section is loaded.
     *
     * @deprecated Creating a config section via the `ConfigSection.create()` global has been deprecated and may be removed in a future version.
     * Instead, require the config section manager via the `IConfigSectionManager` token in a plugin.
     */
    async function create(options) {
        if (!_configSectionManager) {
            const section = new DefaultConfigSection(options);
            await section.load();
            return section;
        }
        const section = await _configSectionManager.create(options);
        return section;
    }
    ConfigSection.create = create;
    let _configSectionManager;
    /**
     * Internal function to set the config section manager.
     *
     * @deprecated This function is an internal helper kept for backward compatiblity.
     * It is not part of the public API and may be removed in a future version.
     */
    function _setConfigSectionManager(manager) {
        if (_configSectionManager) {
            throw new Error('ConfigSectionManager already set. If you would like to create a config section, use the `IConfigSectionManager` token in a plugin.');
        }
        _configSectionManager = manager;
    }
    ConfigSection._setConfigSectionManager = _setConfigSectionManager;
})(ConfigSection || (exports.ConfigSection = ConfigSection = {}));
/**
 * Implementation of the Configurable data section.
 */
class DefaultConfigSection {
    /**
     * Construct a new config section.
     */
    constructor(options) {
        var _a;
        this._url = 'unknown';
        const settings = (this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : __1.ServerConnection.makeSettings());
        this._url = coreutils_1.URLExt.join(settings.baseUrl, SERVICE_CONFIG_URL, encodeURIComponent(options.name));
    }
    /**
     * Get the data for this section.
     */
    get data() {
        return this._data;
    }
    /**
     * Load the initial data for this section.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/config).
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async load() {
        const response = await __1.ServerConnection.makeRequest(this._url, {}, this.serverSettings);
        if (response.status !== 200) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        this._data = await response.json();
    }
    /**
     * Modify the stored config values.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/config).
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     *
     * Updates the local data immediately, sends the change to the server,
     * and updates the local data with the response, and fulfils the promise
     * with that data.
     */
    async update(newdata) {
        this._data = { ...this._data, ...newdata };
        const init = {
            method: 'PATCH',
            body: JSON.stringify(newdata)
        };
        const response = await __1.ServerConnection.makeRequest(this._url, init, this.serverSettings);
        if (response.status !== 200) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        this._data = await response.json();
        return this._data;
    }
}
/**
 * Configurable object with defaults.
 */
class ConfigWithDefaults {
    /**
     * Create a new config with defaults.
     */
    constructor(options) {
        var _a, _b;
        this._className = '';
        this._section = options.section;
        this._defaults = (_a = options.defaults) !== null && _a !== void 0 ? _a : {};
        this._className = (_b = options.className) !== null && _b !== void 0 ? _b : '';
    }
    /**
     * Get data from the config section or fall back to defaults.
     */
    get(key) {
        const data = this._classData();
        return key in data ? data[key] : this._defaults[key];
    }
    /**
     * Set a config value.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/config).
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     *
     * Sends the update to the server, and changes our local copy of the data
     * immediately.
     */
    set(key, value) {
        const d = {};
        d[key] = value;
        if (this._className) {
            const d2 = {};
            d2[this._className] = d;
            return this._section.update(d2);
        }
        else {
            return this._section.update(d);
        }
    }
    /**
     * Get data from the Section with our classname, if available.
     *
     * #### Notes
     * If we have no classname, get all of the data in the Section
     */
    _classData() {
        const data = this._section.data;
        if (this._className && this._className in data) {
            return data[this._className];
        }
        return data;
    }
}
exports.ConfigWithDefaults = ConfigWithDefaults;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 2174:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'edit';
var width = 576;
var height = 512;
var ligatures = [];
var unicode = 'f044';
var svgPathData = 'M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.MT = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 2225:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var required = __webpack_require__(3062)
  , qs = __webpack_require__(1359)
  , controlOrWhitespace = /^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/
  , CRHTLF = /[\n\r\t]/g
  , slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//
  , port = /:\d+$/
  , protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i
  , windowsDriveLetter = /^[a-zA-Z]:/;

/**
 * Remove control characters and whitespace from the beginning of a string.
 *
 * @param {Object|String} str String to trim.
 * @returns {String} A new string representing `str` stripped of control
 *     characters and whitespace from its beginning.
 * @public
 */
function trimLeft(str) {
  return (str ? str : '').toString().replace(controlOrWhitespace, '');
}

/**
 * These are the parse rules for the URL parser, it informs the parser
 * about:
 *
 * 0. The char it Needs to parse, if it's a string it should be done using
 *    indexOf, RegExp using exec and NaN means set as current value.
 * 1. The property we should set when parsing this value.
 * 2. Indication if it's backwards or forward parsing, when set as number it's
 *    the value of extra chars that should be split off.
 * 3. Inherit from location if non existing in the parser.
 * 4. `toLowerCase` the resulting value.
 */
var rules = [
  ['#', 'hash'],                        // Extract from the back.
  ['?', 'query'],                       // Extract from the back.
  function sanitize(address, url) {     // Sanitize what is left of the address
    return isSpecial(url.protocol) ? address.replace(/\\/g, '/') : address;
  },
  ['/', 'pathname'],                    // Extract from the back.
  ['@', 'auth', 1],                     // Extract from the front.
  [NaN, 'host', undefined, 1, 1],       // Set left over value.
  [/:(\d*)$/, 'port', undefined, 1],    // RegExp the back.
  [NaN, 'hostname', undefined, 1, 1]    // Set left over.
];

/**
 * These properties should not be copied or inherited from. This is only needed
 * for all non blob URL's as a blob URL does not include a hash, only the
 * origin.
 *
 * @type {Object}
 * @private
 */
var ignore = { hash: 1, query: 1 };

/**
 * The location object differs when your code is loaded through a normal page,
 * Worker or through a worker using a blob. And with the blobble begins the
 * trouble as the location object will contain the URL of the blob, not the
 * location of the page where our code is loaded in. The actual origin is
 * encoded in the `pathname` so we can thankfully generate a good "default"
 * location from it so we can generate proper relative URL's again.
 *
 * @param {Object|String} loc Optional default location object.
 * @returns {Object} lolcation object.
 * @public
 */
function lolcation(loc) {
  var globalVar;

  if (typeof window !== 'undefined') globalVar = window;
  else if (typeof __webpack_require__.g !== 'undefined') globalVar = __webpack_require__.g;
  else if (typeof self !== 'undefined') globalVar = self;
  else globalVar = {};

  var location = globalVar.location || {};
  loc = loc || location;

  var finaldestination = {}
    , type = typeof loc
    , key;

  if ('blob:' === loc.protocol) {
    finaldestination = new Url(unescape(loc.pathname), {});
  } else if ('string' === type) {
    finaldestination = new Url(loc, {});
    for (key in ignore) delete finaldestination[key];
  } else if ('object' === type) {
    for (key in loc) {
      if (key in ignore) continue;
      finaldestination[key] = loc[key];
    }

    if (finaldestination.slashes === undefined) {
      finaldestination.slashes = slashes.test(loc.href);
    }
  }

  return finaldestination;
}

/**
 * Check whether a protocol scheme is special.
 *
 * @param {String} The protocol scheme of the URL
 * @return {Boolean} `true` if the protocol scheme is special, else `false`
 * @private
 */
function isSpecial(scheme) {
  return (
    scheme === 'file:' ||
    scheme === 'ftp:' ||
    scheme === 'http:' ||
    scheme === 'https:' ||
    scheme === 'ws:' ||
    scheme === 'wss:'
  );
}

/**
 * @typedef ProtocolExtract
 * @type Object
 * @property {String} protocol Protocol matched in the URL, in lowercase.
 * @property {Boolean} slashes `true` if protocol is followed by "//", else `false`.
 * @property {String} rest Rest of the URL that is not part of the protocol.
 */

/**
 * Extract protocol information from a URL with/without double slash ("//").
 *
 * @param {String} address URL we want to extract from.
 * @param {Object} location
 * @return {ProtocolExtract} Extracted information.
 * @private
 */
function extractProtocol(address, location) {
  address = trimLeft(address);
  address = address.replace(CRHTLF, '');
  location = location || {};

  var match = protocolre.exec(address);
  var protocol = match[1] ? match[1].toLowerCase() : '';
  var forwardSlashes = !!match[2];
  var otherSlashes = !!match[3];
  var slashesCount = 0;
  var rest;

  if (forwardSlashes) {
    if (otherSlashes) {
      rest = match[2] + match[3] + match[4];
      slashesCount = match[2].length + match[3].length;
    } else {
      rest = match[2] + match[4];
      slashesCount = match[2].length;
    }
  } else {
    if (otherSlashes) {
      rest = match[3] + match[4];
      slashesCount = match[3].length;
    } else {
      rest = match[4]
    }
  }

  if (protocol === 'file:') {
    if (slashesCount >= 2) {
      rest = rest.slice(2);
    }
  } else if (isSpecial(protocol)) {
    rest = match[4];
  } else if (protocol) {
    if (forwardSlashes) {
      rest = rest.slice(2);
    }
  } else if (slashesCount >= 2 && isSpecial(location.protocol)) {
    rest = match[4];
  }

  return {
    protocol: protocol,
    slashes: forwardSlashes || isSpecial(protocol),
    slashesCount: slashesCount,
    rest: rest
  };
}

/**
 * Resolve a relative URL pathname against a base URL pathname.
 *
 * @param {String} relative Pathname of the relative URL.
 * @param {String} base Pathname of the base URL.
 * @return {String} Resolved pathname.
 * @private
 */
function resolve(relative, base) {
  if (relative === '') return base;

  var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/'))
    , i = path.length
    , last = path[i - 1]
    , unshift = false
    , up = 0;

  while (i--) {
    if (path[i] === '.') {
      path.splice(i, 1);
    } else if (path[i] === '..') {
      path.splice(i, 1);
      up++;
    } else if (up) {
      if (i === 0) unshift = true;
      path.splice(i, 1);
      up--;
    }
  }

  if (unshift) path.unshift('');
  if (last === '.' || last === '..') path.push('');

  return path.join('/');
}

/**
 * The actual URL instance. Instead of returning an object we've opted-in to
 * create an actual constructor as it's much more memory efficient and
 * faster and it pleases my OCD.
 *
 * It is worth noting that we should not use `URL` as class name to prevent
 * clashes with the global URL instance that got introduced in browsers.
 *
 * @constructor
 * @param {String} address URL we want to parse.
 * @param {Object|String} [location] Location defaults for relative paths.
 * @param {Boolean|Function} [parser] Parser for the query string.
 * @private
 */
function Url(address, location, parser) {
  address = trimLeft(address);
  address = address.replace(CRHTLF, '');

  if (!(this instanceof Url)) {
    return new Url(address, location, parser);
  }

  var relative, extracted, parse, instruction, index, key
    , instructions = rules.slice()
    , type = typeof location
    , url = this
    , i = 0;

  //
  // The following if statements allows this module two have compatibility with
  // 2 different API:
  //
  // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
  //    where the boolean indicates that the query string should also be parsed.
  //
  // 2. The `URL` interface of the browser which accepts a URL, object as
  //    arguments. The supplied object will be used as default values / fall-back
  //    for relative paths.
  //
  if ('object' !== type && 'string' !== type) {
    parser = location;
    location = null;
  }

  if (parser && 'function' !== typeof parser) parser = qs.parse;

  location = lolcation(location);

  //
  // Extract protocol information before running the instructions.
  //
  extracted = extractProtocol(address || '', location);
  relative = !extracted.protocol && !extracted.slashes;
  url.slashes = extracted.slashes || relative && location.slashes;
  url.protocol = extracted.protocol || location.protocol || '';
  address = extracted.rest;

  //
  // When the authority component is absent the URL starts with a path
  // component.
  //
  if (
    extracted.protocol === 'file:' && (
      extracted.slashesCount !== 2 || windowsDriveLetter.test(address)) ||
    (!extracted.slashes &&
      (extracted.protocol ||
        extracted.slashesCount < 2 ||
        !isSpecial(url.protocol)))
  ) {
    instructions[3] = [/(.*)/, 'pathname'];
  }

  for (; i < instructions.length; i++) {
    instruction = instructions[i];

    if (typeof instruction === 'function') {
      address = instruction(address, url);
      continue;
    }

    parse = instruction[0];
    key = instruction[1];

    if (parse !== parse) {
      url[key] = address;
    } else if ('string' === typeof parse) {
      index = parse === '@'
        ? address.lastIndexOf(parse)
        : address.indexOf(parse);

      if (~index) {
        if ('number' === typeof instruction[2]) {
          url[key] = address.slice(0, index);
          address = address.slice(index + instruction[2]);
        } else {
          url[key] = address.slice(index);
          address = address.slice(0, index);
        }
      }
    } else if ((index = parse.exec(address))) {
      url[key] = index[1];
      address = address.slice(0, index.index);
    }

    url[key] = url[key] || (
      relative && instruction[3] ? location[key] || '' : ''
    );

    //
    // Hostname, host and protocol should be lowercased so they can be used to
    // create a proper `origin`.
    //
    if (instruction[4]) url[key] = url[key].toLowerCase();
  }

  //
  // Also parse the supplied query string in to an object. If we're supplied
  // with a custom parser as function use that instead of the default build-in
  // parser.
  //
  if (parser) url.query = parser(url.query);

  //
  // If the URL is relative, resolve the pathname against the base URL.
  //
  if (
      relative
    && location.slashes
    && url.pathname.charAt(0) !== '/'
    && (url.pathname !== '' || location.pathname !== '')
  ) {
    url.pathname = resolve(url.pathname, location.pathname);
  }

  //
  // Default to a / for pathname if none exists. This normalizes the URL
  // to always have a /
  //
  if (url.pathname.charAt(0) !== '/' && isSpecial(url.protocol)) {
    url.pathname = '/' + url.pathname;
  }

  //
  // We should not add port numbers if they are already the default port number
  // for a given protocol. As the host also contains the port number we're going
  // override it with the hostname which contains no port number.
  //
  if (!required(url.port, url.protocol)) {
    url.host = url.hostname;
    url.port = '';
  }

  //
  // Parse down the `auth` for the username and password.
  //
  url.username = url.password = '';

  if (url.auth) {
    index = url.auth.indexOf(':');

    if (~index) {
      url.username = url.auth.slice(0, index);
      url.username = encodeURIComponent(decodeURIComponent(url.username));

      url.password = url.auth.slice(index + 1);
      url.password = encodeURIComponent(decodeURIComponent(url.password))
    } else {
      url.username = encodeURIComponent(decodeURIComponent(url.auth));
    }

    url.auth = url.password ? url.username +':'+ url.password : url.username;
  }

  url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host
    ? url.protocol +'//'+ url.host
    : 'null';

  //
  // The href is just the compiled result.
  //
  url.href = url.toString();
}

/**
 * This is convenience method for changing properties in the URL instance to
 * insure that they all propagate correctly.
 *
 * @param {String} part          Property we need to adjust.
 * @param {Mixed} value          The newly assigned value.
 * @param {Boolean|Function} fn  When setting the query, it will be the function
 *                               used to parse the query.
 *                               When setting the protocol, double slash will be
 *                               removed from the final url if it is true.
 * @returns {URL} URL instance for chaining.
 * @public
 */
function set(part, value, fn) {
  var url = this;

  switch (part) {
    case 'query':
      if ('string' === typeof value && value.length) {
        value = (fn || qs.parse)(value);
      }

      url[part] = value;
      break;

    case 'port':
      url[part] = value;

      if (!required(value, url.protocol)) {
        url.host = url.hostname;
        url[part] = '';
      } else if (value) {
        url.host = url.hostname +':'+ value;
      }

      break;

    case 'hostname':
      url[part] = value;

      if (url.port) value += ':'+ url.port;
      url.host = value;
      break;

    case 'host':
      url[part] = value;

      if (port.test(value)) {
        value = value.split(':');
        url.port = value.pop();
        url.hostname = value.join(':');
      } else {
        url.hostname = value;
        url.port = '';
      }

      break;

    case 'protocol':
      url.protocol = value.toLowerCase();
      url.slashes = !fn;
      break;

    case 'pathname':
    case 'hash':
      if (value) {
        var char = part === 'pathname' ? '/' : '#';
        url[part] = value.charAt(0) !== char ? char + value : value;
      } else {
        url[part] = value;
      }
      break;

    case 'username':
    case 'password':
      url[part] = encodeURIComponent(value);
      break;

    case 'auth':
      var index = value.indexOf(':');

      if (~index) {
        url.username = value.slice(0, index);
        url.username = encodeURIComponent(decodeURIComponent(url.username));

        url.password = value.slice(index + 1);
        url.password = encodeURIComponent(decodeURIComponent(url.password));
      } else {
        url.username = encodeURIComponent(decodeURIComponent(value));
      }
  }

  for (var i = 0; i < rules.length; i++) {
    var ins = rules[i];

    if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();
  }

  url.auth = url.password ? url.username +':'+ url.password : url.username;

  url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host
    ? url.protocol +'//'+ url.host
    : 'null';

  url.href = url.toString();

  return url;
}

/**
 * Transform the properties back in to a valid and full URL string.
 *
 * @param {Function} stringify Optional query stringify function.
 * @returns {String} Compiled version of the URL.
 * @public
 */
function toString(stringify) {
  if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;

  var query
    , url = this
    , host = url.host
    , protocol = url.protocol;

  if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';

  var result =
    protocol +
    ((url.protocol && url.slashes) || isSpecial(url.protocol) ? '//' : '');

  if (url.username) {
    result += url.username;
    if (url.password) result += ':'+ url.password;
    result += '@';
  } else if (url.password) {
    result += ':'+ url.password;
    result += '@';
  } else if (
    url.protocol !== 'file:' &&
    isSpecial(url.protocol) &&
    !host &&
    url.pathname !== '/'
  ) {
    //
    // Add back the empty userinfo, otherwise the original invalid URL
    // might be transformed into a valid one with `url.pathname` as host.
    //
    result += '@';
  }

  //
  // Trailing colon is removed from `url.host` when it is parsed. If it still
  // ends with a colon, then add back the trailing colon that was removed. This
  // prevents an invalid URL from being transformed into a valid one.
  //
  if (host[host.length - 1] === ':' || (port.test(url.hostname) && !url.port)) {
    host += ':';
  }

  result += host + url.pathname;

  query = 'object' === typeof url.query ? stringify(url.query) : url.query;
  if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;

  if (url.hash) result += url.hash;

  return result;
}

Url.prototype = { set: set, toString: toString };

//
// Expose the URL parser and some additional properties that might be useful for
// others or testing.
//
Url.extractProtocol = extractProtocol;
Url.location = lolcation;
Url.trimLeft = trimLeft;
Url.qs = qs;

module.exports = Url;


/***/ }),

/***/ 2456:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelConnection = void 0;
const coreutils_1 = __webpack_require__(8925);
const coreutils_2 = __webpack_require__(5764);
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const comm_1 = __webpack_require__(7489);
const KernelMessage = __importStar(__webpack_require__(9909));
const future_1 = __webpack_require__(134);
const validate = __importStar(__webpack_require__(5855));
const restapi_1 = __webpack_require__(8235);
const restapi_2 = __webpack_require__(6492);
const KERNEL_INFO_TIMEOUT = 3000;
const RESTARTING_KERNEL_SESSION = '_RESTARTING_';
const STARTING_KERNEL_SESSION = '';
/**
 * Implementation of the Kernel object.
 *
 * #### Notes
 * Messages from the server are handled in the order they were received and
 * asynchronously. Any message handler can return a promise, and message
 * handling will pause until the promise is fulfilled.
 */
class KernelConnection {
    /**
     * Construct a kernel object.
     */
    constructor(options) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        /**
         * Create the kernel websocket connection and add socket status handlers.
         */
        this._createSocket = (useProtocols = true) => {
            this._errorIfDisposed();
            // Make sure the socket is clear
            this._clearSocket();
            // Update the connection status to reflect opening a new connection.
            this._updateConnectionStatus('connecting');
            const settings = this.serverSettings;
            const partialUrl = coreutils_1.URLExt.join(settings.wsUrl, restapi_1.KERNEL_SERVICE_URL, encodeURIComponent(this._id));
            // Strip any authentication from the display string.
            const display = partialUrl.replace(/^((?:\w+:)?\/\/)(?:[^@\/]+@)/, '$1');
            console.debug(`Starting WebSocket: ${display}`);
            let url = coreutils_1.URLExt.join(partialUrl, 'channels?session_id=' + encodeURIComponent(this._clientId));
            // If token authentication is in use.
            const token = settings.token;
            if (settings.appendToken && token !== '') {
                url = url + `&token=${encodeURIComponent(token)}`;
            }
            // Try opening the websocket with our list of subprotocols.
            // If the server doesn't handle subprotocols,
            // the accepted protocol will be ''.
            // But we cannot send '' as a subprotocol, so if connection fails,
            // reconnect without subprotocols.
            const supportedProtocols = useProtocols ? this._supportedProtocols : [];
            this._ws = new settings.WebSocket(url, supportedProtocols);
            // Ensure incoming binary messages are not Blobs
            this._ws.binaryType = 'arraybuffer';
            let alreadyCalledOnclose = false;
            const getKernelModel = async (evt) => {
                var _a, _b;
                if (this._isDisposed) {
                    return;
                }
                this._reason = '';
                this._model = undefined;
                try {
                    const model = await this._kernelAPIClient.getModel(this._id);
                    this._model = model;
                    if ((model === null || model === void 0 ? void 0 : model.execution_state) === 'dead') {
                        this._updateStatus('dead');
                    }
                    else {
                        this._onWSClose(evt);
                    }
                }
                catch (err) {
                    // Try again, if there is a network failure
                    // Handle network errors, as well as cases where we are on a
                    // JupyterHub and the server is not running. JupyterHub returns a
                    // 503 (<2.0) or 424 (>2.0) in that case.
                    if (err instanceof __1.ServerConnection.NetworkError ||
                        ((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 503 ||
                        ((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 424) {
                        const timeout = Private.getRandomIntInclusive(10, 30) * 1e3;
                        setTimeout(getKernelModel, timeout, evt);
                    }
                    else {
                        this._reason = 'Kernel died unexpectedly';
                        this._updateStatus('dead');
                    }
                }
                return;
            };
            const earlyClose = async (evt) => {
                // If the websocket was closed early, that could mean
                // that the kernel is actually dead. Try getting
                // information about the kernel from the API call,
                // if that fails, then assume the kernel is dead,
                // otherwise just follow the typical websocket closed
                // protocol.
                if (alreadyCalledOnclose) {
                    return;
                }
                alreadyCalledOnclose = true;
                await getKernelModel(evt);
                return;
            };
            this._ws.onmessage = this._onWSMessage;
            this._ws.onopen = this._onWSOpen;
            this._ws.onclose = earlyClose;
            this._ws.onerror = earlyClose;
        };
        // Make websocket callbacks arrow functions so they bind `this`.
        /**
         * Handle a websocket open event.
         */
        this._onWSOpen = (evt) => {
            if (this._ws.protocol !== '' &&
                !this._supportedProtocols.includes(this._ws.protocol)) {
                console.log('Server selected unknown kernel wire protocol:', this._ws.protocol);
                this._updateStatus('dead');
                throw new Error(`Unknown kernel wire protocol:  ${this._ws.protocol}`);
            }
            // Remember the kernel wire protocol selected by the server.
            this._selectedProtocol = this._ws.protocol;
            this._ws.onclose = this._onWSClose;
            this._ws.onerror = this._onWSClose;
            this._updateConnectionStatus('connected');
        };
        /**
         * Handle a websocket message, validating and routing appropriately.
         */
        this._onWSMessage = (evt) => {
            // Notify immediately if there is an error with the message.
            let msg;
            try {
                msg = this.serverSettings.serializer.deserialize(evt.data, this._ws.protocol);
                validate.validateMessage(msg);
            }
            catch (error) {
                error.message = `Kernel message validation error: ${error.message}`;
                // We throw the error so that it bubbles up to the top, and displays the right stack.
                throw error;
            }
            // Update the current kernel session id
            this._kernelSession = msg.header.session;
            // Handle the message asynchronously, in the order received.
            this._msgChain = this._msgChain
                .then(() => {
                // Return so that any promises from handling a message are fulfilled
                // before proceeding to the next message.
                return this._handleMessage(msg);
            })
                .catch(error => {
                // Log any errors in handling the message, thus resetting the _msgChain
                // promise so we can process more messages.
                // Ignore the "Canceled" errors that are thrown during kernel dispose.
                if (error.message.startsWith('Canceled future for ')) {
                    console.error(error);
                }
            });
            // Emit the message receive signal
            this._anyMessage.emit({ msg, direction: 'recv' });
        };
        /**
         * Handle a websocket close event.
         */
        this._onWSClose = (evt) => {
            if (!this.isDisposed) {
                this._reconnect();
            }
        };
        this._id = '';
        this._name = '';
        this._status = 'unknown';
        this._connectionStatus = 'connecting';
        this._kernelSession = '';
        this._isDisposed = false;
        /**
         * Websocket to communicate with kernel.
         */
        this._ws = null;
        this._username = '';
        this._reconnectLimit = 7;
        this._reconnectAttempt = 0;
        this._reconnectTimeout = null;
        this._supportedProtocols = Object.values(KernelMessage.supportedKernelWebSocketProtocols);
        this._selectedProtocol = '';
        this._commsOverSubshells = __1.CommsOverSubshells.PerCommTarget;
        this._futures = new Map();
        this._comms = new Map();
        this._targetRegistry = Object.create(null);
        this._info = new coreutils_2.PromiseDelegate();
        this._pendingMessages = [];
        this._statusChanged = new signaling_1.Signal(this);
        this._connectionStatusChanged = new signaling_1.Signal(this);
        this._disposed = new signaling_1.Signal(this);
        this._iopubMessage = new signaling_1.Signal(this);
        this._anyMessage = new signaling_1.Signal(this);
        this._pendingInput = new signaling_1.Signal(this);
        this._unhandledMessage = new signaling_1.Signal(this);
        this._displayIdToParentIds = new Map();
        this._msgIdToDisplayIds = new Map();
        this._msgChain = Promise.resolve();
        this._hasPendingInput = false;
        this._reason = '';
        this._noOp = () => {
            /* no-op */
        };
        this._supportsSubshells = false;
        this._name = options.model.name;
        this._id = options.model.id;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : __1.ServerConnection.makeSettings();
        this._kernelAPIClient =
            (_b = options.kernelAPIClient) !== null && _b !== void 0 ? _b : new restapi_1.KernelAPIClient({ serverSettings: this.serverSettings });
        this._kernelSpecAPIClient =
            (_c = options.kernelSpecAPIClient) !== null && _c !== void 0 ? _c : new restapi_2.KernelSpecAPIClient({ serverSettings: this.serverSettings });
        this._clientId = (_d = options.clientId) !== null && _d !== void 0 ? _d : coreutils_2.UUID.uuid4();
        this._username = (_e = options.username) !== null && _e !== void 0 ? _e : '';
        this.handleComms = (_f = options.handleComms) !== null && _f !== void 0 ? _f : true;
        this._commsOverSubshells =
            (_g = options.commsOverSubshells) !== null && _g !== void 0 ? _g : __1.CommsOverSubshells.PerCommTarget;
        this._subshellId = (_h = options.subshellId) !== null && _h !== void 0 ? _h : null;
        this._createSocket();
    }
    get disposed() {
        return this._disposed;
    }
    /**
     * Whether comm messages should be sent to kernel subshells, if the
     * kernel supports it.
     *
     * #### Notes
     * Sending comm messages over subshells allows processing comms whilst
     * processing execute-request on the "main shell". This prevents blocking
     * comm processing.
     * Options are:
     * - disabled: not using subshells
     * - one subshell per comm-target (default)
     * - one subshell per comm (can lead to issues if creating many comms)
     */
    get commsOverSubshells() {
        return this._commsOverSubshells;
    }
    set commsOverSubshells(value) {
        this._commsOverSubshells = value;
        for (const [_, comm] of this._comms) {
            comm.commsOverSubshells = value;
        }
    }
    /**
     * A signal emitted when the kernel status changes.
     */
    get statusChanged() {
        return this._statusChanged;
    }
    /**
     * A signal emitted when the kernel status changes.
     */
    get connectionStatusChanged() {
        return this._connectionStatusChanged;
    }
    /**
     * A signal emitted for iopub kernel messages.
     *
     * #### Notes
     * This signal is emitted after the iopub message is handled asynchronously.
     */
    get iopubMessage() {
        return this._iopubMessage;
    }
    /**
     * A signal emitted for unhandled kernel message.
     *
     * #### Notes
     * This signal is emitted for a message that was not handled. It is emitted
     * during the asynchronous message handling code.
     */
    get unhandledMessage() {
        return this._unhandledMessage;
    }
    /**
     * The kernel model
     */
    get model() {
        return (this._model || {
            id: this.id,
            name: this.name,
            reason: this._reason
        });
    }
    /**
     * A signal emitted for any kernel message.
     *
     * #### Notes
     * This signal is emitted when a message is received, before it is handled
     * asynchronously.
     *
     * This message is emitted when a message is queued for sending (either in
     * the websocket buffer, or our own pending message buffer). The message may
     * actually be sent across the wire at a later time.
     *
     * The message emitted in this signal should not be modified in any way.
     */
    get anyMessage() {
        return this._anyMessage;
    }
    /**
     * A signal emitted when a kernel has pending inputs from the user.
     */
    get pendingInput() {
        return this._pendingInput;
    }
    /**
     * The id of the server-side kernel.
     */
    get id() {
        return this._id;
    }
    /**
     * The name of the server-side kernel.
     */
    get name() {
        return this._name;
    }
    /**
     * The client username.
     */
    get username() {
        return this._username;
    }
    /**
     * The client unique id.
     */
    get clientId() {
        return this._clientId;
    }
    /**
     * The subshell ID.
     */
    get subshellId() {
        return this._subshellId;
    }
    /**
     * Set the subshell ID.
     */
    set subshellId(value) {
        this._subshellId = value;
    }
    /**
     * The current status of the kernel.
     */
    get status() {
        return this._status;
    }
    /**
     * The current connection status of the kernel connection.
     */
    get connectionStatus() {
        return this._connectionStatus;
    }
    /**
     * Test whether the kernel has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * The cached kernel info.
     *
     * @returns A promise that resolves to the kernel info.
     */
    get info() {
        return this._info.promise;
    }
    /**
     * The kernel spec.
     *
     * @returns A promise that resolves to the kernel spec.
     */
    get spec() {
        if (this._specPromise) {
            return this._specPromise;
        }
        this._specPromise = this._kernelSpecAPIClient.get().then(specs => {
            return specs.kernelspecs[this._name];
        });
        return this._specPromise;
    }
    /**
     * Check if this kernel supports JEP 91 kernel subshells.
     */
    get supportsSubshells() {
        return this._supportsSubshells;
    }
    /**
     * Clone the current kernel with a new clientId.
     */
    clone(options = {}) {
        return new KernelConnection({
            model: this.model,
            username: this.username,
            serverSettings: this.serverSettings,
            // handleComms defaults to false since that is safer
            handleComms: false,
            kernelAPIClient: this._kernelAPIClient,
            commsOverSubshells: __1.CommsOverSubshells.Disabled,
            ...options
        });
    }
    /**
     * Dispose of the resources held by the kernel.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        const cleanup = () => {
            this._isDisposed = true;
            this._disposed.emit();
            this._updateConnectionStatus('disconnected');
            this._clearKernelState();
            this._pendingMessages = [];
            this._clearSocket();
            // Clear Lumino signals
            signaling_1.Signal.clearData(this);
        };
        if (this._subshellId !== null) {
            const future = this.requestDeleteSubshell({ subshell_id: this._subshellId }, true);
            future.onReply = (msg) => {
                // Ignore the response and clean up.
                cleanup();
            };
        }
        else {
            cleanup();
        }
    }
    /**
     * Send a shell message to the kernel.
     *
     * #### Notes
     * Send a message to the kernel's shell channel, yielding a future object
     * for accepting replies.
     *
     * If `expectReply` is given and `true`, the future is disposed when both a
     * shell reply and an idle status message are received. If `expectReply`
     * is not given or is `false`, the future is resolved when an idle status
     * message is received.
     * If `disposeOnDone` is not given or is `true`, the Future is disposed at this point.
     * If `disposeOnDone` is given and `false`, it is up to the caller to dispose of the Future.
     *
     * All replies are validated as valid kernel messages.
     *
     * If the kernel status is `dead`, this will throw an error.
     */
    sendShellMessage(msg, expectReply = false, disposeOnDone = true) {
        return this._sendKernelShellControl(future_1.KernelShellFutureHandler, msg, expectReply, disposeOnDone);
    }
    /**
     * Send a control message to the kernel.
     *
     * #### Notes
     * Send a message to the kernel's control channel, yielding a future object
     * for accepting replies.
     *
     * If `expectReply` is given and `true`, the future is disposed when both a
     * control reply and an idle status message are received. If `expectReply`
     * is not given or is `false`, the future is resolved when an idle status
     * message is received.
     * If `disposeOnDone` is not given or is `true`, the Future is disposed at this point.
     * If `disposeOnDone` is given and `false`, it is up to the caller to dispose of the Future.
     *
     * All replies are validated as valid kernel messages.
     *
     * If the kernel status is `dead`, this will throw an error.
     */
    sendControlMessage(msg, expectReply = false, disposeOnDone = true) {
        return this._sendKernelShellControl(future_1.KernelControlFutureHandler, msg, expectReply, disposeOnDone);
    }
    _sendKernelShellControl(ctor, msg, expectReply = false, disposeOnDone = true) {
        this._sendMessage(msg);
        this._anyMessage.emit({ msg, direction: 'send' });
        const future = new ctor(() => {
            const msgId = msg.header.msg_id;
            this._futures.delete(msgId);
            // Remove stored display id information.
            const displayIds = this._msgIdToDisplayIds.get(msgId);
            if (!displayIds) {
                return;
            }
            displayIds.forEach(displayId => {
                const msgIds = this._displayIdToParentIds.get(displayId);
                if (msgIds) {
                    const idx = msgIds.indexOf(msgId);
                    if (idx === -1) {
                        return;
                    }
                    if (msgIds.length === 1) {
                        this._displayIdToParentIds.delete(displayId);
                    }
                    else {
                        msgIds.splice(idx, 1);
                        this._displayIdToParentIds.set(displayId, msgIds);
                    }
                }
            });
            this._msgIdToDisplayIds.delete(msgId);
        }, msg, expectReply, disposeOnDone, this);
        this._futures.set(msg.header.msg_id, future);
        return future;
    }
    /**
     * Send a message on the websocket.
     *
     * If queue is true, queue the message for later sending if we cannot send
     * now. Otherwise throw an error.
     *
     * #### Notes
     * As an exception to the queueing, if we are sending a kernel_info_request
     * message while we think the kernel is restarting, we send the message
     * immediately without queueing. This is so that we can trigger a message
     * back, which will then clear the kernel restarting state.
     */
    _sendMessage(msg, queue = true) {
        if (this.status === 'dead') {
            throw new Error('Kernel is dead');
        }
        // If we have a kernel_info_request and we are starting or restarting, send the
        // kernel_info_request immediately if we can, and if not throw an error so
        // we can retry later. On restarting we do this because we must get at least one message
        // from the kernel to reset the kernel session (thus clearing the restart
        // status sentinel).
        if ((this._kernelSession === STARTING_KERNEL_SESSION ||
            this._kernelSession === RESTARTING_KERNEL_SESSION) &&
            KernelMessage.isInfoRequestMsg(msg)) {
            if (this.connectionStatus === 'connected') {
                this._ws.send(this.serverSettings.serializer.serialize(msg, this._ws.protocol));
                return;
            }
            else {
                throw new Error('Could not send message: status is not connected');
            }
        }
        // If there are pending messages, add to the queue so we keep messages in order
        if (queue && this._pendingMessages.length > 0) {
            this._pendingMessages.push(msg);
            return;
        }
        // Send if the ws allows it, otherwise queue the message.
        if (this.connectionStatus === 'connected' &&
            this._kernelSession !== RESTARTING_KERNEL_SESSION) {
            this._ws.send(this.serverSettings.serializer.serialize(msg, this._ws.protocol));
        }
        else if (queue) {
            this._pendingMessages.push(msg);
        }
        else {
            throw new Error('Could not send message');
        }
    }
    /**
     * Interrupt a kernel.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels).
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     *
     * It is assumed that the API call does not mutate the kernel id or name.
     *
     * The promise will be rejected if the kernel status is `Dead` or if the
     * request fails or the response is invalid.
     */
    async interrupt() {
        this.hasPendingInput = false;
        if (this.status === 'dead') {
            throw new Error('Kernel is dead');
        }
        return this._kernelAPIClient.interrupt(this.id);
    }
    /**
     * Request a kernel restart.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels)
     * and validates the response model.
     *
     * Any existing Future or Comm objects are cleared once the kernel has
     * actually be restarted.
     *
     * The promise is fulfilled on a valid server response (after the kernel restarts)
     * and rejected otherwise.
     *
     * It is assumed that the API call does not mutate the kernel id or name.
     *
     * The promise will be rejected if the request fails or the response is
     * invalid.
     */
    async restart() {
        if (this.status === 'dead') {
            throw new Error('Kernel is dead');
        }
        this._updateStatus('restarting');
        this._clearKernelState();
        this._kernelSession = RESTARTING_KERNEL_SESSION;
        await this._kernelAPIClient.restart(this.id);
        // Reconnect to the kernel to address cases where kernel ports
        // have changed during the restart.
        await this.reconnect();
        this.hasPendingInput = false;
    }
    /**
     * Reconnect to a kernel.
     *
     * #### Notes
     * This may try multiple times to reconnect to a kernel, and will sever any
     * existing connection.
     */
    reconnect() {
        this._errorIfDisposed();
        const result = new coreutils_2.PromiseDelegate();
        // Set up a listener for the connection status changing, which accepts or
        // rejects after the retries are done.
        const fulfill = (sender, status) => {
            if (status === 'connected') {
                result.resolve();
                this.connectionStatusChanged.disconnect(fulfill, this);
            }
            else if (status === 'disconnected') {
                result.reject(new Error('Kernel connection disconnected'));
                this.connectionStatusChanged.disconnect(fulfill, this);
            }
        };
        this.connectionStatusChanged.connect(fulfill, this);
        // Reset the reconnect limit so we start the connection attempts fresh
        this._reconnectAttempt = 0;
        // Start the reconnection process, which will also clear any existing
        // connection.
        this._reconnect();
        // Return the promise that should resolve on connection or reject if the
        // retries don't work.
        return result.promise;
    }
    /**
     * Shutdown a kernel.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels).
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     *
     * On a valid response, disposes this kernel connection.
     *
     * If the kernel is already `dead`, disposes this kernel connection without
     * a server request.
     */
    async shutdown() {
        if (this.status !== 'dead') {
            await this._kernelAPIClient.shutdown(this.id);
        }
        this.handleShutdown();
    }
    /**
     * Handles a kernel shutdown.
     *
     * #### Notes
     * This method should be called if we know from outside information that a
     * kernel is dead (for example, we cannot find the kernel model on the
     * server).
     */
    handleShutdown() {
        this._updateStatus('dead');
        this.dispose();
    }
    /**
     * Send a `kernel_info_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#kernel-info).
     *
     * Fulfills with the `kernel_info_response` content when the shell reply is
     * received and validated.
     */
    async requestKernelInfo() {
        const msg = KernelMessage.createMessage({
            msgType: 'kernel_info_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content: {}
        });
        let reply;
        try {
            reply = (await Private.handleShellMessage(this, msg));
        }
        catch (e) {
            // If we rejected because the future was disposed, ignore and return.
            if (this.isDisposed) {
                return;
            }
            else {
                throw e;
            }
        }
        this._errorIfDisposed();
        if (!reply) {
            return;
        }
        // Kernels sometimes do not include a status field on kernel_info_reply
        // messages, so set a default for now.
        // See https://github.com/jupyterlab/jupyterlab/issues/6760
        if (reply.content.status === undefined) {
            reply.content.status = 'ok';
        }
        if (reply.content.status !== 'ok') {
            this._info.reject('Kernel info reply errored');
            return reply;
        }
        this._info.resolve(reply.content);
        this._kernelSession = reply.header.session;
        const supportedFeatures = reply.content.supported_features;
        this._supportsSubshells =
            supportedFeatures !== undefined &&
                supportedFeatures.includes('kernel subshells');
        return reply;
    }
    /**
     * Send a `complete_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#completion).
     *
     * Fulfills with the `complete_reply` content when the shell reply is
     * received and validated.
     */
    requestComplete(content) {
        const msg = KernelMessage.createMessage({
            msgType: 'complete_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content
        });
        return Private.handleShellMessage(this, msg);
    }
    /**
     * Send an `inspect_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#introspection).
     *
     * Fulfills with the `inspect_reply` content when the shell reply is
     * received and validated.
     */
    requestInspect(content) {
        const msg = KernelMessage.createMessage({
            msgType: 'inspect_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content: content
        });
        return Private.handleShellMessage(this, msg);
    }
    /**
     * Send a `history_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#history).
     *
     * Fulfills with the `history_reply` content when the shell reply is
     * received and validated.
     */
    requestHistory(content) {
        const msg = KernelMessage.createMessage({
            msgType: 'history_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content
        });
        return Private.handleShellMessage(this, msg);
    }
    /**
     * Send an `execute_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#execute).
     *
     * Future `onReply` is called with the `execute_reply` content when the
     * shell reply is received and validated. The future will resolve when
     * this message is received and the `idle` iopub status is received.
     * The future will also be disposed at this point unless `disposeOnDone`
     * is specified and `false`, in which case it is up to the caller to dispose
     * of the future.
     *
     * **See also:** [[IExecuteReply]]
     */
    requestExecute(content, disposeOnDone = true, metadata) {
        const defaults = {
            silent: false,
            store_history: true,
            user_expressions: {},
            allow_stdin: true,
            stop_on_error: false
        };
        const msg = KernelMessage.createMessage({
            msgType: 'execute_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content: { ...defaults, ...content },
            metadata
        });
        return this.sendShellMessage(msg, true, disposeOnDone);
    }
    /**
     * Send an experimental `debug_request` message.
     *
     * @hidden
     *
     * #### Notes
     * Debug messages are experimental messages that are not in the official
     * kernel message specification. As such, this function is *NOT* considered
     * part of the public API, and may change without notice.
     */
    requestDebug(content, disposeOnDone = true) {
        const msg = KernelMessage.createMessage({
            msgType: 'debug_request',
            channel: 'control',
            username: this._username,
            session: this._clientId,
            content
        });
        return this.sendControlMessage(msg, true, disposeOnDone);
    }
    /**
     * Send a `create_subshell_request` message.
     *
     * https://github.com/jupyter/enhancement-proposals/pull/91
     */
    requestCreateSubshell(content, disposeOnDone = true) {
        if (!this.supportsSubshells) {
            throw new Error('Kernel subshells are not supported');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'create_subshell_request',
            channel: 'control',
            username: this._username,
            session: this._clientId,
            content
        });
        return this.sendControlMessage(msg, true, disposeOnDone);
    }
    /**
     * Send a `delete_subshell_request` message.
     *
     * https://github.com/jupyter/enhancement-proposals/pull/91
     */
    requestDeleteSubshell(content, disposeOnDone = true) {
        if (!this.supportsSubshells) {
            throw new Error('Kernel subshells are not supported');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'delete_subshell_request',
            channel: 'control',
            username: this._username,
            session: this._clientId,
            content
        });
        return this.sendControlMessage(msg, true, disposeOnDone);
    }
    /**
     * Send a `list_subshell_request` message.
     *
     * https://github.com/jupyter/enhancement-proposals/pull/91
     */
    requestListSubshell(content, disposeOnDone = true) {
        if (!this.supportsSubshells) {
            throw new Error('Kernel subshells are not supported');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'list_subshell_request',
            channel: 'control',
            username: this._username,
            session: this._clientId,
            content
        });
        return this.sendControlMessage(msg, true, disposeOnDone);
    }
    /**
     * Send an `is_complete_request` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#code-completeness).
     *
     * Fulfills with the `is_complete_response` content when the shell reply is
     * received and validated.
     */
    requestIsComplete(content) {
        const msg = KernelMessage.createMessage({
            msgType: 'is_complete_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content
        });
        return Private.handleShellMessage(this, msg);
    }
    /**
     * Send a `comm_info_request` message.
     *
     * #### Notes
     * Fulfills with the `comm_info_reply` content when the shell reply is
     * received and validated.
     */
    requestCommInfo(content) {
        const msg = KernelMessage.createMessage({
            msgType: 'comm_info_request',
            channel: 'shell',
            username: this._username,
            session: this._clientId,
            subshellId: this._subshellId,
            content
        });
        return Private.handleShellMessage(this, msg);
    }
    /**
     * Send an `input_reply` message.
     *
     * #### Notes
     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#messages-on-the-stdin-router-dealer-sockets).
     */
    sendInputReply(content, parent_header) {
        const msg = KernelMessage.createMessage({
            msgType: 'input_reply',
            channel: 'stdin',
            username: this._username,
            session: this._clientId,
            content
        });
        msg.parent_header = parent_header;
        this._sendMessage(msg);
        this._anyMessage.emit({ msg, direction: 'send' });
        this.hasPendingInput = false;
    }
    /**
     * Create a new comm.
     *
     * #### Notes
     * If a client-side comm already exists with the given commId, an error is thrown.
     * If the kernel does not handle comms, an error is thrown.
     */
    createComm(targetName, commId = coreutils_2.UUID.uuid4()) {
        if (!this.handleComms) {
            throw new Error('Comms are disabled on this kernel connection');
        }
        if (this._comms.has(commId)) {
            throw new Error('Comm is already created');
        }
        const comm = new comm_1.CommHandler(targetName, commId, this, () => {
            this._unregisterComm(commId);
        }, this._commsOverSubshells);
        this._comms.set(commId, comm);
        return comm;
    }
    /**
     * Check if a comm exists.
     */
    hasComm(commId) {
        return this._comms.has(commId);
    }
    /**
     * Register a comm target handler.
     *
     * @param targetName - The name of the comm target.
     *
     * @param callback - The callback invoked for a comm open message.
     *
     * @returns A disposable used to unregister the comm target.
     *
     * #### Notes
     * Only one comm target can be registered to a target name at a time, an
     * existing callback for the same target name will be overridden.  A registered
     * comm target handler will take precedence over a comm which specifies a
     * `target_module`.
     *
     * If the callback returns a promise, kernel message processing will pause
     * until the returned promise is fulfilled.
     */
    registerCommTarget(targetName, callback) {
        if (!this.handleComms) {
            return;
        }
        this._targetRegistry[targetName] = callback;
    }
    /**
     * Remove a comm target handler.
     *
     * @param targetName - The name of the comm target to remove.
     *
     * @param callback - The callback to remove.
     *
     * #### Notes
     * The comm target is only removed if the callback argument matches.
     */
    removeCommTarget(targetName, callback) {
        if (!this.handleComms) {
            return;
        }
        if (!this.isDisposed && this._targetRegistry[targetName] === callback) {
            delete this._targetRegistry[targetName];
        }
    }
    /**
     * Register an IOPub message hook.
     *
     * @param msg_id - The parent_header message id the hook will intercept.
     *
     * @param hook - The callback invoked for the message.
     *
     * #### Notes
     * The IOPub hook system allows you to preempt the handlers for IOPub
     * messages that are responses to a given message id.
     *
     * The most recently registered hook is run first. A hook can return a
     * boolean or a promise to a boolean, in which case all kernel message
     * processing pauses until the promise is fulfilled. If a hook return value
     * resolves to false, any later hooks will not run and the function will
     * return a promise resolving to false. If a hook throws an error, the error
     * is logged to the console and the next hook is run. If a hook is
     * registered during the hook processing, it will not run until the next
     * message. If a hook is removed during the hook processing, it will be
     * deactivated immediately.
     *
     * See also [[IFuture.registerMessageHook]].
     */
    registerMessageHook(msgId, hook) {
        var _a;
        const future = (_a = this._futures) === null || _a === void 0 ? void 0 : _a.get(msgId);
        if (future) {
            future.registerMessageHook(hook);
        }
    }
    /**
     * Remove an IOPub message hook.
     *
     * @param msg_id - The parent_header message id the hook intercepted.
     *
     * @param hook - The callback invoked for the message.
     *
     */
    removeMessageHook(msgId, hook) {
        var _a;
        const future = (_a = this._futures) === null || _a === void 0 ? void 0 : _a.get(msgId);
        if (future) {
            future.removeMessageHook(hook);
        }
    }
    /**
     * Remove the input guard, if any.
     */
    removeInputGuard() {
        this.hasPendingInput = false;
    }
    /**
     * Handle a message with a display id.
     *
     * @returns Whether the message was handled.
     */
    async _handleDisplayId(displayId, msg) {
        var _a, _b;
        const msgId = msg.parent_header.msg_id;
        let parentIds = this._displayIdToParentIds.get(displayId);
        if (parentIds) {
            // We've seen it before, update existing outputs with same display_id
            // by handling display_data as update_display_data.
            const updateMsg = {
                header: coreutils_2.JSONExt.deepCopy(msg.header),
                parent_header: coreutils_2.JSONExt.deepCopy(msg.parent_header),
                metadata: coreutils_2.JSONExt.deepCopy(msg.metadata),
                content: coreutils_2.JSONExt.deepCopy(msg.content),
                channel: msg.channel,
                buffers: msg.buffers ? msg.buffers.slice() : []
            };
            updateMsg.header.msg_type = 'update_display_data';
            await Promise.all(parentIds.map(async (parentId) => {
                const future = this._futures && this._futures.get(parentId);
                if (future) {
                    await future.handleMsg(updateMsg);
                }
            }));
        }
        // We're done here if it's update_display.
        if (msg.header.msg_type === 'update_display_data') {
            // It's an update, don't proceed to the normal display.
            return true;
        }
        // Regular display_data with id, record it for future updating
        // in _displayIdToParentIds for future lookup.
        parentIds = (_a = this._displayIdToParentIds.get(displayId)) !== null && _a !== void 0 ? _a : [];
        if (parentIds.indexOf(msgId) === -1) {
            parentIds.push(msgId);
        }
        this._displayIdToParentIds.set(displayId, parentIds);
        // Add to our map of display ids for this message.
        const displayIds = (_b = this._msgIdToDisplayIds.get(msgId)) !== null && _b !== void 0 ? _b : [];
        if (displayIds.indexOf(msgId) === -1) {
            displayIds.push(msgId);
        }
        this._msgIdToDisplayIds.set(msgId, displayIds);
        // Let the message propagate to the intended recipient.
        return false;
    }
    /**
     * Forcefully clear the socket state.
     *
     * #### Notes
     * This will clear all socket state without calling any handlers and will
     * not update the connection status. If you call this method, you are
     * responsible for updating the connection status as needed and recreating
     * the socket if you plan to reconnect.
     */
    _clearSocket() {
        if (this._ws !== null) {
            // Clear the websocket event handlers and the socket itself.
            this._ws.onopen = this._noOp;
            this._ws.onclose = this._noOp;
            this._ws.onerror = this._noOp;
            this._ws.onmessage = this._noOp;
            this._ws.close();
            this._ws = null;
        }
    }
    /**
     * Handle status iopub messages from the kernel.
     */
    _updateStatus(status) {
        if (this._status === status || this._status === 'dead') {
            return;
        }
        this._status = status;
        Private.logKernelStatus(this);
        this._statusChanged.emit(status);
        if (status === 'dead') {
            this.dispose();
        }
    }
    /**
     * Send pending messages to the kernel.
     */
    _sendPending() {
        // We check to make sure we are still connected each time. For
        // example, if a websocket buffer overflows, it may close, so we should
        // stop sending messages.
        while (this.connectionStatus === 'connected' &&
            this._kernelSession !== RESTARTING_KERNEL_SESSION &&
            this._pendingMessages.length > 0) {
            this._sendMessage(this._pendingMessages[0], false);
            // We shift the message off the queue after the message is sent so that
            // if there is an exception, the message is still pending.
            this._pendingMessages.shift();
        }
    }
    /**
     * Clear the internal state.
     */
    _clearKernelState() {
        this._kernelSession = '';
        this._pendingMessages = [];
        this._futures.forEach(future => {
            future.dispose();
        });
        this._comms.forEach(comm => {
            comm.dispose();
        });
        this._msgChain = Promise.resolve();
        this._futures = new Map();
        this._comms = new Map();
        this._displayIdToParentIds.clear();
        this._msgIdToDisplayIds.clear();
    }
    /**
     * Check to make sure it is okay to proceed to handle a message.
     *
     * #### Notes
     * Because we handle messages asynchronously, before a message is handled the
     * kernel might be disposed or restarted (and have a different session id).
     * This function throws an error in each of these cases. This is meant to be
     * called at the start of an asynchronous message handler to cancel message
     * processing if the message no longer is valid.
     */
    _assertCurrentMessage(msg) {
        this._errorIfDisposed();
        if (msg.header.session !== this._kernelSession) {
            throw new Error(`Canceling handling of old message: ${msg.header.msg_type}`);
        }
    }
    /**
     * Handle a `comm_open` kernel message.
     */
    async _handleCommOpen(msg) {
        this._assertCurrentMessage(msg);
        const content = msg.content;
        const comm = new comm_1.CommHandler(content.target_name, content.comm_id, this, () => {
            this._unregisterComm(content.comm_id);
        }, this.commsOverSubshells);
        this._comms.set(content.comm_id, comm);
        try {
            const target = await Private.loadObject(content.target_name, content.target_module, this._targetRegistry);
            await target(comm, msg);
        }
        catch (e) {
            // Close the comm asynchronously. We cannot block message processing on
            // kernel messages to wait for another kernel message.
            comm.close();
            console.error('Exception opening new comm');
            throw e;
        }
    }
    /**
     * Handle 'comm_close' kernel message.
     */
    async _handleCommClose(msg) {
        this._assertCurrentMessage(msg);
        const content = msg.content;
        const comm = this._comms.get(content.comm_id);
        if (!comm) {
            console.error('Comm not found for comm id ' + content.comm_id);
            return;
        }
        this._unregisterComm(comm.commId);
        const onClose = comm.onClose;
        if (onClose) {
            // tslint:disable-next-line:await-promise
            await onClose(msg);
        }
        comm.dispose();
    }
    /**
     * Handle a 'comm_msg' kernel message.
     */
    async _handleCommMsg(msg) {
        this._assertCurrentMessage(msg);
        const content = msg.content;
        const comm = this._comms.get(content.comm_id);
        if (!comm) {
            return;
        }
        const onMsg = comm.onMsg;
        if (onMsg) {
            // tslint:disable-next-line:await-promise
            await onMsg(msg);
        }
    }
    /**
     * Unregister a comm instance.
     */
    _unregisterComm(commId) {
        this._comms.delete(commId);
    }
    /**
     * Handle connection status changes.
     */
    _updateConnectionStatus(connectionStatus) {
        if (this._connectionStatus === connectionStatus) {
            return;
        }
        this._connectionStatus = connectionStatus;
        // If we are not 'connecting', reset any reconnection attempts.
        if (connectionStatus !== 'connecting') {
            this._reconnectAttempt = 0;
            clearTimeout(this._reconnectTimeout);
        }
        if (this.status !== 'dead') {
            if (connectionStatus === 'connected') {
                let restarting = this._kernelSession === RESTARTING_KERNEL_SESSION;
                // Send a kernel info request to make sure we send at least one
                // message to get kernel status back. Always request kernel info
                // first, to get kernel status back and ensure iopub is fully
                // established. If we are restarting, this message will skip the queue
                // and be sent immediately.
                let p = this.requestKernelInfo();
                // Send any pending messages after the kernelInfo resolves, or after a
                // timeout as a failsafe.
                let sendPendingCalled = false;
                let sendPendingOnce = () => {
                    if (sendPendingCalled) {
                        return;
                    }
                    sendPendingCalled = true;
                    if (restarting && this._kernelSession === RESTARTING_KERNEL_SESSION) {
                        // We were restarting and a message didn't arrive to set the
                        // session, but we just assume the restart succeeded and send any
                        // pending messages.
                        // FIXME: it would be better to retry the kernel_info_request here
                        this._kernelSession = '';
                    }
                    clearTimeout(timeoutHandle);
                    if (this._pendingMessages.length > 0) {
                        this._sendPending();
                    }
                };
                void p.then(sendPendingOnce);
                // FIXME: if sent while zmq subscriptions are not established,
                // kernelInfo may not resolve, so use a timeout to ensure we don't hang forever.
                // It may be preferable to retry kernelInfo rather than give up after one timeout.
                let timeoutHandle = setTimeout(sendPendingOnce, KERNEL_INFO_TIMEOUT);
            }
            else {
                // If the connection is down, then we do not know what is happening
                // with the kernel, so set the status to unknown.
                this._updateStatus('unknown');
            }
        }
        // Notify others that the connection status changed.
        this._connectionStatusChanged.emit(connectionStatus);
    }
    async _handleMessage(msg) {
        var _a, _b;
        let handled = false;
        // Check to see if we have a display_id we need to reroute.
        if (msg.parent_header &&
            msg.channel === 'iopub' &&
            (KernelMessage.isDisplayDataMsg(msg) ||
                KernelMessage.isUpdateDisplayDataMsg(msg) ||
                KernelMessage.isExecuteResultMsg(msg))) {
            // display_data messages may re-route based on their display_id.
            const transient = ((_a = msg.content.transient) !== null && _a !== void 0 ? _a : {});
            const displayId = transient['display_id'];
            if (displayId) {
                handled = await this._handleDisplayId(displayId, msg);
                // The await above may make this message out of date, so check again.
                this._assertCurrentMessage(msg);
            }
        }
        if (!handled && msg.parent_header) {
            const parentHeader = msg.parent_header;
            const future = (_b = this._futures) === null || _b === void 0 ? void 0 : _b.get(parentHeader.msg_id);
            if (future) {
                await future.handleMsg(msg);
                this._assertCurrentMessage(msg);
            }
            else {
                // If the message was sent by us and was not iopub, it is orphaned.
                const owned = parentHeader.session === this.clientId;
                if (msg.channel !== 'iopub' && owned) {
                    this._unhandledMessage.emit(msg);
                }
            }
        }
        if (msg.channel === 'iopub') {
            switch (msg.header.msg_type) {
                case 'status': {
                    // Updating the status is synchronous, and we call no async user code
                    const executionState = msg.content
                        .execution_state;
                    if (executionState === 'restarting') {
                        // The kernel has been auto-restarted by the server. After
                        // processing for this message is completely done, we want to
                        // handle this restart, so we don't await, but instead schedule
                        // the work as a microtask (i.e., in a promise resolution). We
                        // schedule this here so that it comes before any microtasks that
                        // might be scheduled in the status signal emission below.
                        void Promise.resolve().then(async () => {
                            this._updateStatus('autorestarting');
                            this._clearKernelState();
                            // We must reconnect since the kernel connection information may have
                            // changed, and the server only refreshes its zmq connection when a new
                            // websocket is opened.
                            await this.reconnect();
                        });
                    }
                    this._updateStatus(executionState);
                    break;
                }
                case 'comm_open':
                    if (this.handleComms) {
                        await this._handleCommOpen(msg);
                    }
                    break;
                case 'comm_msg':
                    if (this.handleComms) {
                        await this._handleCommMsg(msg);
                    }
                    break;
                case 'comm_close':
                    if (this.handleComms) {
                        await this._handleCommClose(msg);
                    }
                    break;
                default:
                    break;
            }
            // If the message was a status dead message, we might have disposed ourselves.
            if (!this.isDisposed) {
                this._assertCurrentMessage(msg);
                // the message wouldn't be emitted if we were disposed anyway.
                this._iopubMessage.emit(msg);
            }
        }
    }
    /**
     * Attempt a connection if we have not exhausted connection attempts.
     */
    _reconnect() {
        this._errorIfDisposed();
        // Clear any existing reconnection attempt
        clearTimeout(this._reconnectTimeout);
        // Update the connection status and schedule a possible reconnection.
        if (this._reconnectAttempt < this._reconnectLimit) {
            this._updateConnectionStatus('connecting');
            // The first reconnect attempt should happen immediately, and subsequent
            // attempts should pick a random number in a growing range so that we
            // don't overload the server with synchronized reconnection attempts
            // across multiple kernels.
            const timeout = Private.getRandomIntInclusive(0, 1e3 * (Math.pow(2, this._reconnectAttempt) - 1));
            console.warn(`Connection lost, reconnecting in ${Math.floor(timeout / 1000)} seconds.`);
            // Try reconnection with subprotocols if the server had supported them.
            // Otherwise, try reconnection without subprotocols.
            const useProtocols = this._selectedProtocol !== '' ? true : false;
            this._reconnectTimeout = setTimeout(this._createSocket, timeout, useProtocols);
            this._reconnectAttempt += 1;
        }
        else {
            this._updateConnectionStatus('disconnected');
        }
        // Clear the websocket event handlers and the socket itself.
        this._clearSocket();
    }
    /**
     * Utility function to throw an error if this instance is disposed.
     */
    _errorIfDisposed() {
        if (this.isDisposed) {
            throw new Error('Kernel connection is disposed');
        }
    }
    get hasPendingInput() {
        return this._hasPendingInput;
    }
    set hasPendingInput(value) {
        this._hasPendingInput = value;
        this._pendingInput.emit(value);
    }
}
exports.KernelConnection = KernelConnection;
/**
 * A private namespace for the Kernel.
 */
var Private;
(function (Private) {
    /**
     * Log the current kernel status.
     */
    function logKernelStatus(kernel) {
        switch (kernel.status) {
            case 'idle':
            case 'busy':
            case 'unknown':
                return;
            default:
                console.debug(`Kernel: ${kernel.status} (${kernel.id})`);
                break;
        }
    }
    Private.logKernelStatus = logKernelStatus;
    /**
     * Send a kernel message to the kernel and resolve the reply message.
     */
    async function handleShellMessage(kernel, msg) {
        const future = kernel.sendShellMessage(msg, true);
        return future.done;
    }
    Private.handleShellMessage = handleShellMessage;
    /**
     * Try to load an object from a module or a registry.
     *
     * Try to load an object from a module asynchronously if a module
     * is specified, otherwise tries to load an object from the global
     * registry, if the global registry is provided.
     *
     * #### Notes
     * Loading a module uses requirejs.
     */
    function loadObject(name, moduleName, registry) {
        return new Promise((resolve, reject) => {
            // Try loading the module using require.js
            if (moduleName) {
                if (typeof requirejs === 'undefined') {
                    throw new Error('requirejs not found');
                }
                requirejs([moduleName], (mod) => {
                    if (mod[name] === void 0) {
                        const msg = `Object '${name}' not found in module '${moduleName}'`;
                        reject(new Error(msg));
                    }
                    else {
                        resolve(mod[name]);
                    }
                }, reject);
            }
            else {
                if (registry === null || registry === void 0 ? void 0 : registry[name]) {
                    resolve(registry[name]);
                }
                else {
                    reject(new Error(`Object '${name}' not found in registry`));
                }
            }
        });
    }
    Private.loadObject = loadObject;
    /**
     * Get a random integer between min and max, inclusive of both.
     *
     * #### Notes
     * From
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
     *
     * From the MDN page: It might be tempting to use Math.round() to accomplish
     * that, but doing so would cause your random numbers to follow a non-uniform
     * distribution, which may not be acceptable for your needs.
     */
    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    Private.getRandomIntInclusive = getRandomIntInclusive;
})(Private || (Private = {}));
//# sourceMappingURL=default.js.map

/***/ }),

/***/ 2598:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.validateSpecModel = validateSpecModel;
exports.validateSpecModels = validateSpecModels;
const validate_1 = __webpack_require__(7441);
/**
 * Validate a server kernelspec model to a client side model.
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function validateSpecModel(data) {
    const spec = data.spec;
    if (!spec) {
        throw new Error('Invalid kernel spec');
    }
    (0, validate_1.validateProperty)(data, 'name', 'string');
    (0, validate_1.validateProperty)(data, 'resources', 'object');
    (0, validate_1.validateProperty)(spec, 'language', 'string');
    (0, validate_1.validateProperty)(spec, 'display_name', 'string');
    (0, validate_1.validateProperty)(spec, 'argv', 'array');
    let metadata = null;
    if (spec.hasOwnProperty('metadata')) {
        (0, validate_1.validateProperty)(spec, 'metadata', 'object');
        metadata = spec.metadata;
    }
    let env = null;
    if (spec.hasOwnProperty('env')) {
        (0, validate_1.validateProperty)(spec, 'env', 'object');
        env = spec.env;
    }
    return {
        name: data.name,
        resources: data.resources,
        language: spec.language,
        display_name: spec.display_name,
        argv: spec.argv,
        metadata,
        env
    };
}
/**
 * Validate a `Kernel.ISpecModels` object.
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function validateSpecModels(data) {
    if (!data.hasOwnProperty('kernelspecs')) {
        throw new Error('No kernelspecs found');
    }
    let keys = Object.keys(data.kernelspecs);
    const kernelspecs = Object.create(null);
    let defaultSpec = data.default;
    for (let i = 0; i < keys.length; i++) {
        const ks = data.kernelspecs[keys[i]];
        try {
            kernelspecs[keys[i]] = validateSpecModel(ks);
        }
        catch (err) {
            // Remove the errant kernel spec.
            console.warn(`Removing errant kernel spec: ${keys[i]}`);
        }
    }
    keys = Object.keys(kernelspecs);
    if (!keys.length) {
        throw new Error('No valid kernelspecs found');
    }
    if (!defaultSpec ||
        typeof defaultSpec !== 'string' ||
        !(defaultSpec in kernelspecs)) {
        defaultSpec = keys[0];
        console.warn(`Default kernel not found, using '${keys[0]}'`);
    }
    return {
        default: defaultSpec,
        kernelspecs
    };
}
//# sourceMappingURL=validate.js.map

/***/ }),

/***/ 2706:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.validateContentsModel = validateContentsModel;
exports.validateCheckpointModel = validateCheckpointModel;
const validate_1 = __webpack_require__(7441);
/**
 * Validate an `Contents.IModel` object.
 */
function validateContentsModel(model) {
    (0, validate_1.validateProperty)(model, 'name', 'string');
    (0, validate_1.validateProperty)(model, 'path', 'string');
    (0, validate_1.validateProperty)(model, 'type', 'string');
    (0, validate_1.validateProperty)(model, 'created', 'string');
    (0, validate_1.validateProperty)(model, 'last_modified', 'string');
    (0, validate_1.validateProperty)(model, 'mimetype', 'object');
    (0, validate_1.validateProperty)(model, 'content', 'object');
    (0, validate_1.validateProperty)(model, 'format', 'object');
}
/**
 * Validate an `Contents.ICheckpointModel` object.
 */
function validateCheckpointModel(model) {
    (0, validate_1.validateProperty)(model, 'id', 'string');
    (0, validate_1.validateProperty)(model, 'last_modified', 'string');
}
//# sourceMappingURL=validate.js.map

/***/ }),

/***/ 2888:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'check';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f00c';
var svgPathData = 'M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.e6 = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 2920:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ServerConnection = void 0;
const coreutils_1 = __webpack_require__(8925);
const serialize_1 = __webpack_require__(7179);
let WEBSOCKET;
if (typeof window === 'undefined') {
    // Mangle the require statements so it does not get picked up in the
    // browser assets.
    WEBSOCKET = __webpack_require__(7251);
}
else {
    WEBSOCKET = WebSocket;
}
/**
 * The namespace for ServerConnection functions.
 *
 * #### Notes
 * This is only intended to manage communication with the Jupyter server.
 *
 * The default values can be used in a JupyterLab or Jupyter Notebook context.
 *
 * We use `token` authentication if available, falling back on an XSRF
 * cookie if one has been provided on the `document`.
 *
 * A content type of `'application/json'` is added when using authentication
 * and there is no body data to allow the server to prevent malicious forms.
 */
var ServerConnection;
(function (ServerConnection) {
    /**
     * Create a settings object given a subset of options.
     *
     * @param options - An optional partial set of options.
     *
     * @returns The full settings object.
     */
    function makeSettings(options) {
        return Private.makeSettings(options);
    }
    ServerConnection.makeSettings = makeSettings;
    /**
     * Make an request to the notebook server.
     *
     * @param url - The url for the request.
     *
     * @param init - The initialization options for the request.
     *
     * @param settings - The server settings to apply to the request.
     *
     * @returns a Promise that resolves with the response.
     *
     * @throws If the url of the request is not a notebook server url.
     *
     * #### Notes
     * The `url` must start with `settings.baseUrl`.  The `init` settings are
     * merged with `settings.init`, with `init` taking precedence.
     * The headers in the two objects are not merged.
     * If there is no body data, we set the content type to `application/json`
     * because it is required by the Notebook server.
     */
    function makeRequest(url, init, settings) {
        return Private.handleRequest(url, init, settings);
    }
    ServerConnection.makeRequest = makeRequest;
    /**
     * A wrapped error for a fetch response.
     */
    class ResponseError extends Error {
        /**
         * Create a ResponseError from a response, handling the traceback and message
         * as appropriate.
         *
         * @param response The response object.
         *
         * @returns A promise that resolves with a `ResponseError` object.
         */
        static async create(response) {
            try {
                const data = await response.json();
                const { message, traceback } = data;
                if (traceback) {
                    console.error(traceback);
                }
                return new ResponseError(response, message !== null && message !== void 0 ? message : ResponseError._defaultMessage(response), traceback !== null && traceback !== void 0 ? traceback : '');
            }
            catch (e) {
                console.debug(e);
                return new ResponseError(response);
            }
        }
        /**
         * Create a new response error.
         */
        constructor(response, message = ResponseError._defaultMessage(response), traceback = '') {
            super(message);
            this.response = response;
            this.traceback = traceback;
        }
        static _defaultMessage(response) {
            return `Invalid response: ${response.status} ${response.statusText}`;
        }
    }
    ServerConnection.ResponseError = ResponseError;
    /**
     * A wrapped error for a network error.
     */
    class NetworkError extends TypeError {
        /**
         * Create a new network error.
         */
        constructor(original) {
            super(original.message);
            this.stack = original.stack;
        }
    }
    ServerConnection.NetworkError = NetworkError;
})(ServerConnection || (exports.ServerConnection = ServerConnection = {}));
/**
 * The namespace for module private data.
 */
var Private;
(function (Private) {
    /**
     * Handle the server connection settings, returning a new value.
     */
    function makeSettings(options = {}) {
        var _a;
        const pageBaseUrl = coreutils_1.PageConfig.getBaseUrl();
        const pageWsUrl = coreutils_1.PageConfig.getWsUrl();
        const baseUrl = coreutils_1.URLExt.normalize(options.baseUrl) || pageBaseUrl;
        let wsUrl = options.wsUrl;
        // Prefer the default wsUrl if we are using the default baseUrl.
        if (!wsUrl && baseUrl === pageBaseUrl) {
            wsUrl = pageWsUrl;
        }
        // Otherwise convert the baseUrl to a wsUrl if possible.
        if (!wsUrl && baseUrl.indexOf('http') === 0) {
            wsUrl = 'ws' + baseUrl.slice(4);
        }
        // Otherwise fall back on the default wsUrl.
        wsUrl = wsUrl !== null && wsUrl !== void 0 ? wsUrl : pageWsUrl;
        const appendTokenConfig = coreutils_1.PageConfig.getOption('appendToken').toLowerCase();
        let appendToken;
        if (appendTokenConfig === '') {
            appendToken =
                typeof window === 'undefined' ||
                    (typeof process !== 'undefined' &&
                        ((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.JEST_WORKER_ID) !== undefined) ||
                    coreutils_1.URLExt.getHostName(pageBaseUrl) !== coreutils_1.URLExt.getHostName(wsUrl);
        }
        else {
            appendToken = appendTokenConfig === 'true';
        }
        return {
            init: { cache: 'no-store', credentials: 'same-origin' },
            fetch,
            Headers,
            Request,
            WebSocket: WEBSOCKET,
            token: coreutils_1.PageConfig.getToken(),
            appUrl: coreutils_1.PageConfig.getOption('appUrl'),
            appendToken,
            serializer: { serialize: serialize_1.serialize, deserialize: serialize_1.deserialize },
            ...options,
            baseUrl,
            wsUrl
        };
    }
    Private.makeSettings = makeSettings;
    /**
     * Handle a request.
     *
     * @param url - The url for the request.
     *
     * @param init - The overrides for the request init.
     *
     * @param settings - The settings object for the request.
     *
     * #### Notes
     * The `url` must start with `settings.baseUrl`.  The `init` settings
     * take precedence over `settings.init`.
     */
    function handleRequest(url, init, settings) {
        var _a;
        // Handle notebook server requests.
        if (url.indexOf(settings.baseUrl) !== 0) {
            throw new Error('Can only be used for notebook server requests');
        }
        // Use explicit cache buster when `no-store` is set since
        // not all browsers use it properly.
        const cache = (_a = init.cache) !== null && _a !== void 0 ? _a : settings.init.cache;
        if (cache === 'no-store') {
            // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache
            url += (/\?/.test(url) ? '&' : '?') + new Date().getTime();
        }
        const request = new settings.Request(url, { ...settings.init, ...init });
        // Handle authentication. Authentication can be overdetermined by
        // settings token and XSRF token.
        let authenticated = false;
        if (settings.token) {
            authenticated = true;
            request.headers.append('Authorization', `token ${settings.token}`);
        }
        if (typeof document !== 'undefined') {
            const xsrfToken = getCookie('_xsrf');
            if (xsrfToken !== undefined) {
                authenticated = true;
                request.headers.append('X-XSRFToken', xsrfToken);
            }
        }
        // Set the content type if there is no given data and we are
        // using an authenticated connection.
        if (!request.headers.has('Content-Type') && authenticated) {
            request.headers.set('Content-Type', 'application/json');
        }
        // Use `call` to avoid a `TypeError` in the browser.
        return settings.fetch.call(null, request).catch((e) => {
            // Convert the TypeError into a more specific error.
            throw new ServerConnection.NetworkError(e);
        });
        // TODO: *this* is probably where we need a system-wide connectionFailure
        // signal we can hook into.
    }
    Private.handleRequest = handleRequest;
    /**
     * Get a cookie from the document.
     */
    function getCookie(name) {
        // From http://www.tornadoweb.org/en/stable/guide/security.html
        let cookie = '';
        try {
            cookie = document.cookie;
        }
        catch (e) {
            // e.g. SecurityError in case of CSP Sandbox
            return;
        }
        const matches = cookie.match('\\b' + name + '=([^;]*)\\b');
        return matches === null || matches === void 0 ? void 0 : matches[1];
    }
})(Private || (Private = {}));
//# sourceMappingURL=serverconnection.js.map

/***/ }),

/***/ 2946:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelSpecAPI = exports.KernelSpec = void 0;
const KernelSpec = __importStar(__webpack_require__(4806));
exports.KernelSpec = KernelSpec;
const KernelSpecAPI = __importStar(__webpack_require__(6492));
exports.KernelSpecAPI = KernelSpecAPI;
__exportStar(__webpack_require__(733), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 2956:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
//# sourceMappingURL=kernel.js.map

/***/ }),

/***/ 3062:
/***/ ((module) => {

"use strict";


/**
 * Check if we're required to add a port number.
 *
 * @see https://url.spec.whatwg.org/#default-port
 * @param {Number|String} port Port number we need to check
 * @param {String} protocol Protocol we need to check against.
 * @returns {Boolean} Is it a default port for the given protocol
 * @api private
 */
module.exports = function required(port, protocol) {
  protocol = protocol.split(':')[0];
  port = +port;

  if (!port) return false;

  switch (protocol) {
    case 'http':
    case 'ws':
    return port !== 80;

    case 'https':
    case 'wss':
    return port !== 443;

    case 'ftp':
    return port !== 21;

    case 'gopher':
    return port !== 70;

    case 'file':
    return false;
  }

  return port !== 0;
};


/***/ }),

/***/ 3430:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'question-circle';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f059';
var svgPathData = 'M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.wR = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 3801:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'list-ol';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f0cb';
var svgPathData = 'M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.Ts = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 3852:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'play';
var width = 448;
var height = 512;
var ligatures = [];
var unicode = 'f04b';
var svgPathData = 'M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.ij = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 3867:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.BaseManager = void 0;
const signaling_1 = __webpack_require__(3992);
const serverconnection_1 = __webpack_require__(2920);
class BaseManager {
    constructor(options) {
        var _a;
        this._isDisposed = false;
        this._disposed = new signaling_1.Signal(this);
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * A signal emitted when the delegate is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * Test whether the delegate has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Whether the manager is active.
     */
    get isActive() {
        return true;
    }
    /**
     * Dispose of the delegate and invoke the callback function.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._isDisposed = true;
        this._disposed.emit(undefined);
        signaling_1.Signal.clearData(this);
    }
}
exports.BaseManager = BaseManager;
//# sourceMappingURL=basemanager.js.map

/***/ }),

/***/ 3992:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Signal: () => (/* binding */ Signal),
/* harmony export */   Stream: () => (/* binding */ Stream)
/* harmony export */ });
/* harmony import */ var _lumino_algorithm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8135);
/* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5764);
/* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__);



// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * @packageDocumentation
 * @module signaling
 */
/**
 * A concrete implementation of `ISignal`.
 *
 * #### Example
 * ```typescript
 * import { ISignal, Signal } from '@lumino/signaling';
 *
 * class SomeClass {
 *
 *   constructor(name: string) {
 *     this.name = name;
 *   }
 *
 *   readonly name: string;
 *
 *   get valueChanged: ISignal<this, number> {
 *     return this._valueChanged;
 *   }
 *
 *   get value(): number {
 *     return this._value;
 *   }
 *
 *   set value(value: number) {
 *     if (value === this._value) {
 *       return;
 *     }
 *     this._value = value;
 *     this._valueChanged.emit(value);
 *   }
 *
 *   private _value = 0;
 *   private _valueChanged = new Signal<this, number>(this);
 * }
 *
 * function logger(sender: SomeClass, value: number): void {
 *   console.log(sender.name, value);
 * }
 *
 * let m1 = new SomeClass('foo');
 * let m2 = new SomeClass('bar');
 *
 * m1.valueChanged.connect(logger);
 * m2.valueChanged.connect(logger);
 *
 * m1.value = 42;  // logs: foo 42
 * m2.value = 17;  // logs: bar 17
 * ```
 */
class Signal {
    /**
     * Construct a new signal.
     *
     * @param sender - The sender which owns the signal.
     */
    constructor(sender) {
        this.sender = sender;
    }
    /**
     * Connect a slot to the signal.
     *
     * @param slot - The slot to invoke when the signal is emitted.
     *
     * @param thisArg - The `this` context for the slot. If provided,
     *   this must be a non-primitive object.
     *
     * @returns `true` if the connection succeeds, `false` otherwise.
     */
    connect(slot, thisArg) {
        return Private.connect(this, slot, thisArg);
    }
    /**
     * Disconnect a slot from the signal.
     *
     * @param slot - The slot to disconnect from the signal.
     *
     * @param thisArg - The `this` context for the slot. If provided,
     *   this must be a non-primitive object.
     *
     * @returns `true` if the connection is removed, `false` otherwise.
     */
    disconnect(slot, thisArg) {
        return Private.disconnect(this, slot, thisArg);
    }
    /**
     * Emit the signal and invoke the connected slots.
     *
     * @param args - The args to pass to the connected slots.
     *
     * #### Notes
     * Slots are invoked synchronously in connection order.
     *
     * Exceptions thrown by connected slots will be caught and logged.
     */
    emit(args) {
        Private.emit(this, args);
    }
}
/**
 * The namespace for the `Signal` class statics.
 */
(function (Signal) {
    /**
     * Remove all connections between a sender and receiver.
     *
     * @param sender - The sender object of interest.
     *
     * @param receiver - The receiver object of interest.
     *
     * #### Notes
     * If a `thisArg` is provided when connecting a signal, that object
     * is considered the receiver. Otherwise, the `slot` is considered
     * the receiver.
     */
    function disconnectBetween(sender, receiver) {
        Private.disconnectBetween(sender, receiver);
    }
    Signal.disconnectBetween = disconnectBetween;
    /**
     * Remove all connections where the given object is the sender.
     *
     * @param sender - The sender object of interest.
     */
    function disconnectSender(sender) {
        Private.disconnectSender(sender);
    }
    Signal.disconnectSender = disconnectSender;
    /**
     * Remove all connections where the given object is the receiver.
     *
     * @param receiver - The receiver object of interest.
     *
     * #### Notes
     * If a `thisArg` is provided when connecting a signal, that object
     * is considered the receiver. Otherwise, the `slot` is considered
     * the receiver.
     */
    function disconnectReceiver(receiver) {
        Private.disconnectReceiver(receiver);
    }
    Signal.disconnectReceiver = disconnectReceiver;
    /**
     * Remove all connections where an object is the sender or receiver.
     *
     * @param object - The object of interest.
     *
     * #### Notes
     * If a `thisArg` is provided when connecting a signal, that object
     * is considered the receiver. Otherwise, the `slot` is considered
     * the receiver.
     */
    function disconnectAll(object) {
        Private.disconnectAll(object);
    }
    Signal.disconnectAll = disconnectAll;
    /**
     * Clear all signal data associated with the given object.
     *
     * @param object - The object for which the data should be cleared.
     *
     * #### Notes
     * This removes all signal connections and any other signal data
     * associated with the object.
     */
    function clearData(object) {
        Private.disconnectAll(object);
    }
    Signal.clearData = clearData;
    /**
     * Get the signal exception handler.
     *
     * @returns The current exception handler.
     *
     * #### Notes
     * The default exception handler is `console.error`.
     */
    function getExceptionHandler() {
        return Private.exceptionHandler;
    }
    Signal.getExceptionHandler = getExceptionHandler;
    /**
     * Set the signal exception handler.
     *
     * @param handler - The function to use as the exception handler.
     *
     * @returns The old exception handler.
     *
     * #### Notes
     * The exception handler is invoked when a slot throws an exception.
     */
    function setExceptionHandler(handler) {
        let old = Private.exceptionHandler;
        Private.exceptionHandler = handler;
        return old;
    }
    Signal.setExceptionHandler = setExceptionHandler;
})(Signal || (Signal = {}));
/**
 * A concrete implementation of `IStream`.
 *
 * #### Example
 * ```typescript
 * import { IStream, Stream } from '@lumino/signaling';
 *
 * class SomeClass {
 *
 *   constructor(name: string) {
 *     this.name = name;
 *   }
 *
 *   readonly name: string;
 *
 *   get pings(): IStream<this, string> {
 *     return this._pings;
 *   }
 *
 *   ping(value: string) {
 *     this._pings.emit(value);
 *   }
 *
 *   private _pings = new Stream<this, string>(this);
 * }
 *
 * let m1 = new SomeClass('foo');
 *
 * m1.pings.connect((_, value: string) => {
 *   console.log('connect', value);
 * });
 *
 * void (async () => {
 *   for await (const ping of m1.pings) {
 *     console.log('iterator', ping);
 *   }
 * })();
 *
 * m1.ping('alpha');  // logs: connect alpha
 *                    // logs: iterator alpha
 * m1.ping('beta');   // logs: connect beta
 *                    // logs: iterator beta
 * ```
 */
class Stream extends Signal {
    constructor() {
        super(...arguments);
        this._pending = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__.PromiseDelegate();
    }
    /**
     * Return an async iterator that yields every emission.
     */
    async *[Symbol.asyncIterator]() {
        let pending = this._pending;
        while (true) {
            try {
                const { args, next } = await pending.promise;
                pending = next;
                yield args;
            }
            catch (_) {
                return; // Any promise rejection stops the iterator.
            }
        }
    }
    /**
     * Emit the signal, invoke the connected slots, and yield the emission.
     *
     * @param args - The args to pass to the connected slots.
     */
    emit(args) {
        const pending = this._pending;
        const next = (this._pending = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__.PromiseDelegate());
        pending.resolve({ args, next });
        super.emit(args);
    }
    /**
     * Stop the stream's async iteration.
     */
    stop() {
        this._pending.promise.catch(() => undefined);
        this._pending.reject('stop');
        this._pending = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__.PromiseDelegate();
    }
}
/**
 * The namespace for the module implementation details.
 */
var Private;
(function (Private) {
    /**
     * The signal exception handler function.
     */
    Private.exceptionHandler = (err) => {
        console.error(err);
    };
    /**
     * Connect a slot to a signal.
     *
     * @param signal - The signal of interest.
     *
     * @param slot - The slot to invoke when the signal is emitted.
     *
     * @param thisArg - The `this` context for the slot. If provided,
     *   this must be a non-primitive object.
     *
     * @returns `true` if the connection succeeds, `false` otherwise.
     */
    function connect(signal, slot, thisArg) {
        // Coerce a `null` `thisArg` to `undefined`.
        thisArg = thisArg || undefined;
        // Ensure the sender's array of receivers is created.
        let receivers = receiversForSender.get(signal.sender);
        if (!receivers) {
            receivers = [];
            receiversForSender.set(signal.sender, receivers);
        }
        // Bail if a matching connection already exists.
        if (findConnection(receivers, signal, slot, thisArg)) {
            return false;
        }
        // Choose the best object for the receiver.
        let receiver = thisArg || slot;
        // Ensure the receiver's array of senders is created.
        let senders = sendersForReceiver.get(receiver);
        if (!senders) {
            senders = [];
            sendersForReceiver.set(receiver, senders);
        }
        // Create a new connection and add it to the end of each array.
        let connection = { signal, slot, thisArg };
        receivers.push(connection);
        senders.push(connection);
        // Indicate a successful connection.
        return true;
    }
    Private.connect = connect;
    /**
     * Disconnect a slot from a signal.
     *
     * @param signal - The signal of interest.
     *
     * @param slot - The slot to disconnect from the signal.
     *
     * @param thisArg - The `this` context for the slot. If provided,
     *   this must be a non-primitive object.
     *
     * @returns `true` if the connection is removed, `false` otherwise.
     */
    function disconnect(signal, slot, thisArg) {
        // Coerce a `null` `thisArg` to `undefined`.
        thisArg = thisArg || undefined;
        // Lookup the list of receivers, and bail if none exist.
        let receivers = receiversForSender.get(signal.sender);
        if (!receivers || receivers.length === 0) {
            return false;
        }
        // Bail if no matching connection exits.
        let connection = findConnection(receivers, signal, slot, thisArg);
        if (!connection) {
            return false;
        }
        // Choose the best object for the receiver.
        let receiver = thisArg || slot;
        // Lookup the array of senders, which is now known to exist.
        let senders = sendersForReceiver.get(receiver);
        // Clear the connection and schedule cleanup of the arrays.
        connection.signal = null;
        scheduleCleanup(receivers);
        scheduleCleanup(senders);
        // Indicate a successful disconnection.
        return true;
    }
    Private.disconnect = disconnect;
    /**
     * Remove all connections between a sender and receiver.
     *
     * @param sender - The sender object of interest.
     *
     * @param receiver - The receiver object of interest.
     */
    function disconnectBetween(sender, receiver) {
        // If there are no receivers, there is nothing to do.
        let receivers = receiversForSender.get(sender);
        if (!receivers || receivers.length === 0) {
            return;
        }
        // If there are no senders, there is nothing to do.
        let senders = sendersForReceiver.get(receiver);
        if (!senders || senders.length === 0) {
            return;
        }
        // Clear each connection between the sender and receiver.
        for (const connection of senders) {
            // Skip connections which have already been cleared.
            if (!connection.signal) {
                continue;
            }
            // Clear the connection if it matches the sender.
            if (connection.signal.sender === sender) {
                connection.signal = null;
            }
        }
        // Schedule a cleanup of the senders and receivers.
        scheduleCleanup(receivers);
        scheduleCleanup(senders);
    }
    Private.disconnectBetween = disconnectBetween;
    /**
     * Remove all connections where the given object is the sender.
     *
     * @param sender - The sender object of interest.
     */
    function disconnectSender(sender) {
        // If there are no receivers, there is nothing to do.
        let receivers = receiversForSender.get(sender);
        if (!receivers || receivers.length === 0) {
            return;
        }
        // Clear each receiver connection.
        for (const connection of receivers) {
            // Skip connections which have already been cleared.
            if (!connection.signal) {
                continue;
            }
            // Choose the best object for the receiver.
            let receiver = connection.thisArg || connection.slot;
            // Clear the connection.
            connection.signal = null;
            // Cleanup the array of senders, which is now known to exist.
            scheduleCleanup(sendersForReceiver.get(receiver));
        }
        // Schedule a cleanup of the receivers.
        scheduleCleanup(receivers);
    }
    Private.disconnectSender = disconnectSender;
    /**
     * Remove all connections where the given object is the receiver.
     *
     * @param receiver - The receiver object of interest.
     */
    function disconnectReceiver(receiver) {
        // If there are no senders, there is nothing to do.
        let senders = sendersForReceiver.get(receiver);
        if (!senders || senders.length === 0) {
            return;
        }
        // Clear each sender connection.
        for (const connection of senders) {
            // Skip connections which have already been cleared.
            if (!connection.signal) {
                continue;
            }
            // Lookup the sender for the connection.
            let sender = connection.signal.sender;
            // Clear the connection.
            connection.signal = null;
            // Cleanup the array of receivers, which is now known to exist.
            scheduleCleanup(receiversForSender.get(sender));
        }
        // Schedule a cleanup of the list of senders.
        scheduleCleanup(senders);
    }
    Private.disconnectReceiver = disconnectReceiver;
    /**
     * Remove all connections where an object is the sender or receiver.
     *
     * @param object - The object of interest.
     */
    function disconnectAll(object) {
        // Remove all connections where the given object is the sender.
        disconnectSender(object);
        // Remove all connections where the given object is the receiver.
        disconnectReceiver(object);
    }
    Private.disconnectAll = disconnectAll;
    /**
     * Emit a signal and invoke its connected slots.
     *
     * @param signal - The signal of interest.
     *
     * @param args - The args to pass to the connected slots.
     *
     * #### Notes
     * Slots are invoked synchronously in connection order.
     *
     * Exceptions thrown by connected slots will be caught and logged.
     */
    function emit(signal, args) {
        // If there are no receivers, there is nothing to do.
        let receivers = receiversForSender.get(signal.sender);
        if (!receivers || receivers.length === 0) {
            return;
        }
        // Invoke the slots for connections with a matching signal.
        // Any connections added during emission are not invoked.
        for (let i = 0, n = receivers.length; i < n; ++i) {
            let connection = receivers[i];
            if (connection.signal === signal) {
                invokeSlot(connection, args);
            }
        }
    }
    Private.emit = emit;
    /**
     * A weak mapping of sender to array of receiver connections.
     */
    const receiversForSender = new WeakMap();
    /**
     * A weak mapping of receiver to array of sender connections.
     */
    const sendersForReceiver = new WeakMap();
    /**
     * A set of connection arrays which are pending cleanup.
     */
    const dirtySet = new Set();
    /**
     * A function to schedule an event loop callback.
     */
    const schedule = (() => {
        let ok = typeof requestAnimationFrame === 'function';
        return ok ? requestAnimationFrame : setImmediate;
    })();
    /**
     * Find a connection which matches the given parameters.
     */
    function findConnection(connections, signal, slot, thisArg) {
        return (0,_lumino_algorithm__WEBPACK_IMPORTED_MODULE_0__.find)(connections, connection => connection.signal === signal &&
            connection.slot === slot &&
            connection.thisArg === thisArg);
    }
    /**
     * Invoke a slot with the given parameters.
     *
     * The connection is assumed to be valid.
     *
     * Exceptions in the slot will be caught and logged.
     */
    function invokeSlot(connection, args) {
        let { signal, slot, thisArg } = connection;
        try {
            slot.call(thisArg, signal.sender, args);
        }
        catch (err) {
            Private.exceptionHandler(err);
        }
    }
    /**
     * Schedule a cleanup of a connection array.
     *
     * This will add the array to the dirty set and schedule a deferred
     * cleanup of the array contents. On cleanup, any connection with a
     * `null` signal will be removed from the array.
     */
    function scheduleCleanup(array) {
        if (dirtySet.size === 0) {
            schedule(cleanupDirtySet);
        }
        dirtySet.add(array);
    }
    /**
     * Cleanup the connection lists in the dirty set.
     *
     * This function should only be invoked asynchronously, when the
     * stack frame is guaranteed to not be on the path of user code.
     */
    function cleanupDirtySet() {
        dirtySet.forEach(cleanupConnections);
        dirtySet.clear();
    }
    /**
     * Cleanup the dirty connections in a connections array.
     *
     * This will remove any connection with a `null` signal.
     *
     * This function should only be invoked asynchronously, when the
     * stack frame is guaranteed to not be on the path of user code.
     */
    function cleanupConnections(connections) {
        _lumino_algorithm__WEBPACK_IMPORTED_MODULE_0__.ArrayExt.removeAllWhere(connections, isDeadConnection);
    }
    /**
     * Test whether a connection is dead.
     *
     * A dead connection has a `null` signal.
     */
    function isDeadConnection(connection) {
        return connection.signal === null;
    }
})(Private || (Private = {}));


//# sourceMappingURL=index.es6.js.map


/***/ }),

/***/ 4025:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.RestorablePool = void 0;
const coreutils_1 = __webpack_require__(5764);
const properties_1 = __webpack_require__(6573);
const signaling_1 = __webpack_require__(3992);
/**
 * An object pool that supports restoration.
 *
 * @typeparam T - The type of object being tracked.
 */
class RestorablePool {
    /**
     * Create a new restorable pool.
     *
     * @param options - The instantiation options for a restorable pool.
     */
    constructor(options) {
        this._added = new signaling_1.Signal(this);
        this._current = null;
        this._currentChanged = new signaling_1.Signal(this);
        this._hasRestored = false;
        this._isDisposed = false;
        this._objects = new Set();
        this._restore = null;
        this._restored = new coreutils_1.PromiseDelegate();
        this._updated = new signaling_1.Signal(this);
        this.namespace = options.namespace;
    }
    /**
     * A signal emitted when an object object is added.
     *
     * #### Notes
     * This signal will only fire when an object is added to the pool.
     * It will not fire if an object injected into the pool.
     */
    get added() {
        return this._added;
    }
    /**
     * The current object.
     *
     * #### Notes
     * The restorable pool does not set `current`. It is intended for client use.
     *
     * If `current` is set to an object that does not exist in the pool, it is a
     * no-op.
     */
    get current() {
        return this._current;
    }
    set current(obj) {
        if (this._current === obj) {
            return;
        }
        if (obj !== null && this._objects.has(obj)) {
            this._current = obj;
            this._currentChanged.emit(this._current);
        }
    }
    /**
     * A signal emitted when the current widget changes.
     */
    get currentChanged() {
        return this._currentChanged;
    }
    /**
     * Test whether the pool is disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * A promise resolved when the restorable pool has been restored.
     */
    get restored() {
        return this._restored.promise;
    }
    /**
     * The number of objects held by the pool.
     */
    get size() {
        return this._objects.size;
    }
    /**
     * A signal emitted when an object is updated.
     */
    get updated() {
        return this._updated;
    }
    /**
     * Add a new object to the pool.
     *
     * @param obj - The object object being added.
     *
     * #### Notes
     * The object passed into the pool is added synchronously; its existence in
     * the pool can be checked with the `has()` method. The promise this method
     * returns resolves after the object has been added and saved to an underlying
     * restoration connector, if one is available.
     */
    async add(obj) {
        var _a, _b;
        if (obj.isDisposed) {
            const warning = 'A disposed object cannot be added.';
            console.warn(warning, obj);
            throw new Error(warning);
        }
        if (this._objects.has(obj)) {
            const warning = 'This object already exists in the pool.';
            console.warn(warning, obj);
            throw new Error(warning);
        }
        this._objects.add(obj);
        obj.disposed.connect(this._onInstanceDisposed, this);
        if (Private.injectedProperty.get(obj)) {
            return;
        }
        if (this._restore) {
            const { connector } = this._restore;
            const objName = this._restore.name(obj);
            if (objName) {
                const name = `${this.namespace}:${objName}`;
                const data = (_b = (_a = this._restore).args) === null || _b === void 0 ? void 0 : _b.call(_a, obj);
                Private.nameProperty.set(obj, name);
                await connector.save(name, { data });
            }
        }
        // Emit the added signal.
        this._added.emit(obj);
    }
    /**
     * Dispose of the resources held by the pool.
     *
     * #### Notes
     * Disposing a pool does not affect the underlying data in the data connector,
     * it simply disposes the client-side pool without making any connector calls.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._current = null;
        this._isDisposed = true;
        this._objects.clear();
        signaling_1.Signal.clearData(this);
    }
    /**
     * Find the first object in the pool that satisfies a filter function.
     *
     * @param fn The filter function to call on each object.
     */
    find(fn) {
        const values = this._objects.values();
        for (const value of values) {
            if (fn(value)) {
                return value;
            }
        }
        return undefined;
    }
    /**
     * Iterate through each object in the pool.
     *
     * @param fn - The function to call on each object.
     */
    forEach(fn) {
        this._objects.forEach(fn);
    }
    /**
     * Filter the objects in the pool based on a predicate.
     *
     * @param fn - The function by which to filter.
     */
    filter(fn) {
        const filtered = [];
        this.forEach(obj => {
            if (fn(obj)) {
                filtered.push(obj);
            }
        });
        return filtered;
    }
    /**
     * Inject an object into the restorable pool without the pool handling its
     * restoration lifecycle.
     *
     * @param obj - The object to inject into the pool.
     */
    inject(obj) {
        Private.injectedProperty.set(obj, true);
        return this.add(obj);
    }
    /**
     * Check if this pool has the specified object.
     *
     * @param obj - The object whose existence is being checked.
     */
    has(obj) {
        return this._objects.has(obj);
    }
    /**
     * Restore the objects in this pool's namespace.
     *
     * @param options - The configuration options that describe restoration.
     *
     * @returns A promise that resolves when restoration has completed.
     *
     * #### Notes
     * This function should almost never be invoked by client code. Its primary
     * use case is to be invoked by a layout restorer plugin that handles
     * multiple restorable pools and, when ready, asks them each to restore their
     * respective objects.
     */
    async restore(options) {
        if (this._hasRestored) {
            throw new Error('This pool has already been restored.');
        }
        this._hasRestored = true;
        const { command, connector, registry, when } = options;
        const namespace = this.namespace;
        const promises = when
            ? [connector.list(namespace)].concat(when)
            : [connector.list(namespace)];
        this._restore = options;
        const [saved] = await Promise.all(promises);
        const values = await Promise.all(saved.ids.map(async (id, index) => {
            const value = saved.values[index];
            const args = value && value.data;
            if (args === undefined) {
                return connector.remove(id);
            }
            // Execute the command and if it fails, delete the state restore data.
            return registry
                .execute(command, args)
                .catch(() => connector.remove(id));
        }));
        this._restored.resolve();
        return values;
    }
    /**
     * Save the restore data for a given object.
     *
     * @param obj - The object being saved.
     */
    async save(obj) {
        var _a, _b;
        const injected = Private.injectedProperty.get(obj);
        if (!this._restore || !this.has(obj) || injected) {
            return;
        }
        const { connector } = this._restore;
        const objName = this._restore.name(obj);
        const oldName = Private.nameProperty.get(obj);
        const newName = objName ? `${this.namespace}:${objName}` : '';
        if (oldName && oldName !== newName) {
            await connector.remove(oldName);
        }
        // Set the name property irrespective of whether the new name is null.
        Private.nameProperty.set(obj, newName);
        if (newName) {
            const data = (_b = (_a = this._restore).args) === null || _b === void 0 ? void 0 : _b.call(_a, obj);
            await connector.save(newName, { data });
        }
        if (oldName !== newName) {
            this._updated.emit(obj);
        }
    }
    /**
     * Clean up after disposed objects.
     */
    _onInstanceDisposed(obj) {
        this._objects.delete(obj);
        if (obj === this._current) {
            this._current = null;
            this._currentChanged.emit(this._current);
        }
        if (Private.injectedProperty.get(obj)) {
            return;
        }
        if (!this._restore) {
            return;
        }
        const { connector } = this._restore;
        const name = Private.nameProperty.get(obj);
        if (name) {
            void connector.remove(name);
        }
    }
}
exports.RestorablePool = RestorablePool;
/*
 * A namespace for private data.
 */
var Private;
(function (Private) {
    /**
     * An attached property to indicate whether an object has been injected.
     */
    Private.injectedProperty = new properties_1.AttachedProperty({
        name: 'injected',
        create: () => false
    });
    /**
     * An attached property for an object's ID.
     */
    Private.nameProperty = new properties_1.AttachedProperty({
        name: 'name',
        create: () => ''
    });
})(Private || (Private = {}));
//# sourceMappingURL=restorablepool.js.map

/***/ }),

/***/ 4219:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.BuildManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const serverconnection_1 = __webpack_require__(2920);
/**
 * The url for the lab build service.
 */
const BUILD_SETTINGS_URL = 'api/build';
/**
 * The build API service manager.
 */
class BuildManager {
    /**
     * Create a new setting manager.
     */
    constructor(options = {}) {
        var _a;
        this._url = '';
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
        const { baseUrl, appUrl } = this.serverSettings;
        this._url = coreutils_1.URLExt.join(baseUrl, appUrl, BUILD_SETTINGS_URL);
    }
    /**
     * Test whether the build service is available.
     */
    get isAvailable() {
        return coreutils_1.PageConfig.getOption('buildAvailable').toLowerCase() === 'true';
    }
    /**
     * Test whether to check build status automatically.
     */
    get shouldCheck() {
        return coreutils_1.PageConfig.getOption('buildCheck').toLowerCase() === 'true';
    }
    /**
     * Get whether the application should be built.
     */
    getStatus() {
        const { _url, serverSettings } = this;
        const promise = serverconnection_1.ServerConnection.makeRequest(_url, {}, serverSettings);
        return promise
            .then(response => {
            if (response.status !== 200) {
                throw new serverconnection_1.ServerConnection.ResponseError(response);
            }
            return response.json();
        })
            .then(data => {
            if (typeof data.status !== 'string') {
                throw new Error('Invalid data');
            }
            if (typeof data.message !== 'string') {
                throw new Error('Invalid data');
            }
            return data;
        });
    }
    /**
     * Build the application.
     */
    build() {
        const { _url, serverSettings } = this;
        const init = { method: 'POST' };
        const promise = serverconnection_1.ServerConnection.makeRequest(_url, init, serverSettings);
        return promise.then(response => {
            if (response.status === 400) {
                throw new serverconnection_1.ServerConnection.ResponseError(response, 'Build aborted');
            }
            if (response.status !== 200) {
                const message = `Build failed with ${response.status}.

        If you are experiencing the build failure after installing an extension (or trying to include previously installed extension after updating JupyterLab) please check the extension repository for new installation instructions as many extensions migrated to the prebuilt extensions system which no longer requires rebuilding JupyterLab (but uses a different installation procedure, typically involving a package manager such as 'pip' or 'conda').

        If you specifically intended to install a source extension, please run 'jupyter lab build' on the server for full output.`;
                throw new serverconnection_1.ServerConnection.ResponseError(response, message);
            }
        });
    }
    /**
     * Cancel an active build.
     */
    cancel() {
        const { _url, serverSettings } = this;
        const init = { method: 'DELETE' };
        const promise = serverconnection_1.ServerConnection.makeRequest(_url, init, serverSettings);
        return promise.then(response => {
            if (response.status !== 204) {
                throw new serverconnection_1.ServerConnection.ResponseError(response);
            }
        });
    }
}
exports.BuildManager = BuildManager;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 4383:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'chart-bar';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f080';
var svgPathData = 'M332.8 320h38.4c6.4 0 12.8-6.4 12.8-12.8V172.8c0-6.4-6.4-12.8-12.8-12.8h-38.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h38.4c6.4 0 12.8-6.4 12.8-12.8V76.8c0-6.4-6.4-12.8-12.8-12.8h-38.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-288 0h38.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-38.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h38.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-38.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zM496 384H64V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-32c0-8.84-7.16-16-16-16z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.$F = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 4584:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'sort';
var width = 320;
var height = 512;
var ligatures = [];
var unicode = 'f0dc';
var svgPathData = 'M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41zm255-105L177 64c-9.4-9.4-24.6-9.4-33.9 0L24 183c-15.1 15.1-4.4 41 17 41h238c21.4 0 32.1-25.9 17-41z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.OM = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 4733:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'align-justify';
var width = 448;
var height = 512;
var ligatures = [];
var unicode = 'f039';
var svgPathData = 'M432 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-128H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.Ti = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 4806:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
//# sourceMappingURL=kernelspec.js.map

/***/ }),

/***/ 4949:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DataConnector = void 0;
/**
 * An abstract class that adheres to the data connector interface.
 *
 * @typeparam T - The basic entity response type a service's connector.
 *
 * @typeparam U - The basic entity request type, which is conventionally the
 * same as the response type but may be different if a service's implementation
 * requires input data to be different from output responses. Defaults to `T`.
 *
 * @typeparam V - The basic token applied to a request, conventionally a string
 * ID or filter, but may be set to a different type when an implementation
 * requires it. Defaults to `string`.
 *
 * @typeparam W - The type of the optional `query` parameter of the `list`
 * method. Defaults to `string`.
 *
 * #### Notes
 * The only abstract method in this class is the `fetch` method, which must be
 * reimplemented by all subclasses. The `remove` and `save` methods have a
 * default implementation that returns a promise that will always reject. This
 * class is a convenience superclass for connectors that only need to `fetch`.
 */
class DataConnector {
    /**
     * Retrieve the list of items available from the data connector.
     *
     * @param query - The optional query filter to apply to the connector request.
     *
     * @returns A promise that always rejects with an error.
     *
     * #### Notes
     * Subclasses should reimplement if they support a back-end that can list.
     */
    async list(query) {
        throw new Error('DataConnector#list method has not been implemented.');
    }
    /**
     * Remove a value using the data connector.
     *
     * @param id - The identifier for the data being removed.
     *
     * @returns A promise that always rejects with an error.
     *
     * #### Notes
     * Subclasses should reimplement if they support a back-end that can remove.
     */
    async remove(id) {
        throw new Error('DataConnector#remove method has not been implemented.');
    }
    /**
     * Save a value using the data connector.
     *
     * @param id - The identifier for the data being saved.
     *
     * @param value - The data being saved.
     *
     * @returns A promise that always rejects with an error.
     *
     * #### Notes
     * Subclasses should reimplement if they support a back-end that can save.
     */
    async save(id, value) {
        throw new Error('DataConnector#save method has not been implemented.');
    }
}
exports.DataConnector = DataConnector;
//# sourceMappingURL=dataconnector.js.map

/***/ }),

/***/ 5198:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelManager = void 0;
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const basemanager_1 = __webpack_require__(3867);
const restapi_1 = __webpack_require__(8235);
const default_1 = __webpack_require__(2456);
const restapi_2 = __webpack_require__(6492);
/**
 * An implementation of a kernel manager.
 */
class KernelManager extends basemanager_1.BaseManager {
    /**
     * Construct a new kernel manager.
     *
     * @param options - The default options for kernel.
     */
    constructor(options = {}) {
        var _a, _b, _c;
        super(options);
        this._commsOverSubshells = __1.CommsOverSubshells.PerCommTarget;
        this._isReady = false;
        this._kernelConnections = new Set();
        this._models = new Map();
        this._runningChanged = new signaling_1.Signal(this);
        this._connectionFailure = new signaling_1.Signal(this);
        this._kernelAPIClient =
            (_a = options.kernelAPIClient) !== null && _a !== void 0 ? _a : new restapi_1.KernelAPIClient({ serverSettings: this.serverSettings });
        this._kernelSpecAPIClient =
            (_b = options.kernelSpecAPIClient) !== null && _b !== void 0 ? _b : new restapi_2.KernelSpecAPIClient({
                serverSettings: this.serverSettings
            });
        // Start model and specs polling with exponential backoff.
        this._pollModels = new polling_1.Poll({
            auto: false,
            factory: () => this.requestRunning(),
            frequency: {
                interval: 10 * 1000,
                backoff: true,
                max: 300 * 1000
            },
            name: `@jupyterlab/services:KernelManager#models`,
            standby: (_c = options.standby) !== null && _c !== void 0 ? _c : 'when-hidden'
        });
        // Initialize internal data.
        this._ready = (async () => {
            await this._pollModels.start();
            await this._pollModels.tick;
            this._isReady = true;
        })();
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._ready;
    }
    /**
     * A signal emitted when the running kernels change.
     */
    get runningChanged() {
        return this._runningChanged;
    }
    /**
     * A signal emitted when there is a connection failure.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._models.clear();
        this._kernelConnections.forEach(x => x.dispose());
        this._pollModels.dispose();
        super.dispose();
    }
    /**
     * Connect to an existing kernel.
     *
     * @returns The new kernel connection.
     *
     * #### Notes
     * This will use the manager's server settings and ignore any server
     * settings passed in the options.
     */
    connectTo(options) {
        var _a;
        const { id } = options.model;
        let handleComms = (_a = options.handleComms) !== null && _a !== void 0 ? _a : true;
        // By default, handle comms only if no other kernel connection is.
        if (options.handleComms === undefined) {
            for (const kc of this._kernelConnections) {
                if (kc.id === id && kc.handleComms) {
                    handleComms = false;
                    break;
                }
            }
        }
        options.commsOverSubshells = this._commsOverSubshells;
        const kernelConnection = new default_1.KernelConnection({
            handleComms,
            ...options,
            serverSettings: this.serverSettings,
            kernelAPIClient: this._kernelAPIClient,
            kernelSpecAPIClient: this._kernelSpecAPIClient
        });
        this._onStarted(kernelConnection);
        if (!this._models.has(id)) {
            // We trust the user to connect to an existing kernel, but we verify
            // asynchronously.
            void this.refreshRunning().catch(() => {
                /* no-op */
            });
        }
        return kernelConnection;
    }
    /**
     * Create an iterator over the most recent running kernels.
     *
     * @returns A new iterator over the running kernels.
     */
    running() {
        return this._models.values();
    }
    /**
     * The number of running kernels.
     */
    get runningCount() {
        return this._models.size;
    }
    /**
     * Whether comms are running on subshell or not.
     */
    get commsOverSubshells() {
        return this._commsOverSubshells;
    }
    set commsOverSubshells(value) {
        this._commsOverSubshells = value;
        for (const connection of this._kernelConnections) {
            connection.commsOverSubshells = value;
        }
    }
    /**
     * Force a refresh of the running kernels.
     *
     * @returns A promise that resolves when the running list has been refreshed.
     *
     * #### Notes
     * This is not typically meant to be called by the user, since the
     * manager maintains its own internal state.
     */
    async refreshRunning() {
        await this._pollModels.refresh();
        await this._pollModels.tick;
    }
    /**
     * Start a new kernel.
     *
     * @param createOptions - The kernel creation options
     *
     * @param connectOptions - The kernel connection options
     *
     * @returns A promise that resolves with the kernel connection.
     *
     * #### Notes
     * The manager `serverSettings` will be always be used.
     */
    async startNew(createOptions = {}, connectOptions = {}) {
        const model = await this._kernelAPIClient.startNew(createOptions);
        return this.connectTo({
            ...connectOptions,
            model
        });
    }
    /**
     * Shut down a kernel by id.
     *
     * @param id - The id of the target kernel.
     *
     * @returns A promise that resolves when the operation is complete.
     */
    async shutdown(id) {
        await this._kernelAPIClient.shutdown(id);
        await this.refreshRunning();
    }
    /**
     * Shut down all kernels.
     *
     * @returns A promise that resolves when all of the kernels are shut down.
     */
    async shutdownAll() {
        // Update the list of models to make sure our list is current.
        await this.refreshRunning();
        // Shut down all models.
        await Promise.all([...this._models.keys()].map(id => this._kernelAPIClient.shutdown(id)));
        // Update the list of models to clear out our state.
        await this.refreshRunning();
    }
    /**
     * Find a kernel by id.
     *
     * @param id - The id of the target kernel.
     *
     * @returns A promise that resolves with the kernel's model.
     */
    async findById(id) {
        if (this._models.has(id)) {
            return this._models.get(id);
        }
        await this.refreshRunning();
        return this._models.get(id);
    }
    /**
     * Execute a request to the server to poll running kernels and update state.
     */
    async requestRunning() {
        var _a, _b;
        let models;
        try {
            models = await this._kernelAPIClient.listRunning();
        }
        catch (err) {
            // Handle network errors, as well as cases where we are on a
            // JupyterHub and the server is not running. JupyterHub returns a
            // 503 (<2.0) or 424 (>2.0) in that case.
            if (err instanceof __1.ServerConnection.NetworkError ||
                ((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 503 ||
                ((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 424) {
                this._connectionFailure.emit(err);
            }
            throw err;
        }
        if (this.isDisposed) {
            return;
        }
        if (this._models.size === models.length &&
            models.every(model => {
                const existing = this._models.get(model.id);
                if (!existing) {
                    return false;
                }
                return (existing.connections === model.connections &&
                    existing.execution_state === model.execution_state &&
                    existing.last_activity === model.last_activity &&
                    existing.name === model.name &&
                    existing.reason === model.reason &&
                    existing.traceback === model.traceback);
            })) {
            // Identical models list (presuming models does not contain duplicate
            // ids), so just return
            return;
        }
        this._models = new Map(models.map(x => [x.id, x]));
        // For any kernel connection to a kernel that doesn't exist, notify it of
        // the shutdown.
        this._kernelConnections.forEach(kc => {
            if (!this._models.has(kc.id)) {
                kc.handleShutdown();
            }
        });
        this._runningChanged.emit(models);
    }
    /**
     * Handle a kernel starting.
     */
    _onStarted(kernelConnection) {
        this._kernelConnections.add(kernelConnection);
        kernelConnection.statusChanged.connect(this._onStatusChanged, this);
        kernelConnection.disposed.connect(this._onDisposed, this);
    }
    _onDisposed(kernelConnection) {
        this._kernelConnections.delete(kernelConnection);
        // A dispose emission could mean the server session is deleted, or that
        // the kernel JS object is disposed and the kernel still exists on the
        // server, so we refresh from the server to make sure we reflect the
        // server state.
        void this.refreshRunning().catch(() => {
            /* no-op */
        });
    }
    _onStatusChanged(kernelConnection, status) {
        if (status === 'dead') {
            // We asynchronously update our list of kernels, which asynchronously
            // will dispose them. We do not want to immediately dispose them because
            // there may be other signal handlers that want to be called.
            void this.refreshRunning().catch(() => {
                /* no-op */
            });
        }
    }
}
exports.KernelManager = KernelManager;
/**
 * The namespace for `KernelManager` class statics.
 */
(function (KernelManager) {
    /**
     * A no-op kernel manager to be used when starting kernels.
     */
    class NoopManager extends KernelManager {
        constructor() {
            super(...arguments);
            this._readyPromise = new Promise(() => {
                /* no-op */
            });
        }
        /**
         * Whether the manager is active.
         */
        get isActive() {
            return false;
        }
        /**
         * Used for testing.
         */
        get parentReady() {
            return super.ready;
        }
        /**
         * Start a new kernel - throws an error since it is not supported.
         */
        async startNew(createOptions = {}, connectOptions = {}) {
            return Promise.reject(new Error('Not implemented in no-op Kernel Manager'));
        }
        /**
         * Connect to an existing kernel - throws an error since it is not supported.
         */
        connectTo(options) {
            throw new Error('Not implemented in no-op Kernel Manager');
        }
        /**
         * Shut down a kernel by id - throws an error since it is not supported.
         */
        async shutdown(id) {
            return Promise.reject(new Error('Not implemented in no-op Kernel Manager'));
        }
        /**
         * A promise that fulfills when the manager is ready (never).
         */
        get ready() {
            return this.parentReady.then(() => this._readyPromise);
        }
        /**
         * Execute a request to the server to poll running kernels and update state.
         */
        async requestRunning() {
            return Promise.resolve();
        }
    }
    KernelManager.NoopManager = NoopManager;
})(KernelManager || (exports.KernelManager = KernelManager = {}));
//# sourceMappingURL=manager.js.map

/***/ }),

/***/ 5341:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SessionConnection = void 0;
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const coreutils_1 = __webpack_require__(5764);
const restapi_1 = __webpack_require__(7570);
/**
 * Session object for accessing the session REST api. The session
 * should be used to start kernels and then shut them down -- for
 * all other kernel operations, the kernel object should be used.
 */
class SessionConnection {
    /**
     * Construct a new session.
     */
    constructor(options) {
        var _a, _b, _c, _d, _e;
        this._id = '';
        this._path = '';
        this._name = '';
        this._type = '';
        this._kernel = null;
        this._isDisposed = false;
        this._disposed = new signaling_1.Signal(this);
        this._kernelChanged = new signaling_1.Signal(this);
        this._statusChanged = new signaling_1.Signal(this);
        this._connectionStatusChanged = new signaling_1.Signal(this);
        this._pendingInput = new signaling_1.Signal(this);
        this._iopubMessage = new signaling_1.Signal(this);
        this._unhandledMessage = new signaling_1.Signal(this);
        this._anyMessage = new signaling_1.Signal(this);
        this._propertyChanged = new signaling_1.Signal(this);
        this._id = options.model.id;
        this._name = options.model.name;
        this._path = options.model.path;
        this._type = options.model.type;
        this._username = (_a = options.username) !== null && _a !== void 0 ? _a : '';
        this._clientId = (_b = options.clientId) !== null && _b !== void 0 ? _b : coreutils_1.UUID.uuid4();
        this._connectToKernel = options.connectToKernel;
        this._kernelConnectionOptions = (_c = options.kernelConnectionOptions) !== null && _c !== void 0 ? _c : {};
        this.serverSettings =
            (_d = options.serverSettings) !== null && _d !== void 0 ? _d : __1.ServerConnection.makeSettings();
        this._sessionAPIClient =
            (_e = options.sessionAPIClient) !== null && _e !== void 0 ? _e : new restapi_1.SessionAPIClient({ serverSettings: this.serverSettings });
        this.setupKernel(options.model.kernel);
    }
    /**
     * A signal emitted when the session is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * A signal emitted when the kernel changes.
     */
    get kernelChanged() {
        return this._kernelChanged;
    }
    /**
     * A signal proxied from the connection about the kernel status.
     */
    get statusChanged() {
        return this._statusChanged;
    }
    /**
     * A signal proxied from the kernel about the connection status.
     */
    get connectionStatusChanged() {
        return this._connectionStatusChanged;
    }
    /**
     * A signal proxied from the kernel pending input.
     */
    get pendingInput() {
        return this._pendingInput;
    }
    /**
     * A signal proxied from the kernel about iopub kernel messages.
     */
    get iopubMessage() {
        return this._iopubMessage;
    }
    /**
     * A signal proxied from the kernel for an unhandled kernel message.
     */
    get unhandledMessage() {
        return this._unhandledMessage;
    }
    /**
     * A signal proxied from the kernel emitted for any kernel message.
     *
     * #### Notes
     * The behavior is undefined if the message is modified during message
     * handling. As such, it should be treated as read-only.
     */
    get anyMessage() {
        return this._anyMessage;
    }
    /**
     * A signal emitted when a session property changes.
     */
    get propertyChanged() {
        return this._propertyChanged;
    }
    /**
     * Get the session id.
     */
    get id() {
        return this._id;
    }
    /**
     * Get the session kernel connection object.
     *
     * #### Notes
     * This is a read-only property, and can be altered by [changeKernel].
     */
    get kernel() {
        return this._kernel;
    }
    /**
     * Get the session path.
     */
    get path() {
        return this._path;
    }
    /**
     * Get the session type.
     */
    get type() {
        return this._type;
    }
    /**
     * Get the session name.
     */
    get name() {
        return this._name;
    }
    /**
     * Get the model associated with the session.
     */
    get model() {
        return {
            id: this.id,
            kernel: this.kernel && { id: this.kernel.id, name: this.kernel.name },
            path: this._path,
            type: this._type,
            name: this._name
        };
    }
    /**
     * Test whether the session has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Update the session based on a session model from the server.
     *
     * #### Notes
     * This only updates this session connection instance. Use `setPath`,
     * `setName`, `setType`, and `changeKernel` to change the session values on
     * the server.
     */
    update(model) {
        const oldModel = this.model;
        this._path = model.path;
        this._name = model.name;
        this._type = model.type;
        if ((this._kernel === null && model.kernel !== null) ||
            (this._kernel !== null && model.kernel === null) ||
            (this._kernel !== null &&
                model.kernel !== null &&
                this._kernel.id !== model.kernel.id)) {
            if (this._kernel !== null) {
                this._kernel.dispose();
            }
            const oldValue = this._kernel || null;
            this.setupKernel(model.kernel);
            const newValue = this._kernel || null;
            this._kernelChanged.emit({ name: 'kernel', oldValue, newValue });
        }
        this._handleModelChange(oldModel);
    }
    /**
     * Dispose of the resources held by the session.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._isDisposed = true;
        this._disposed.emit();
        if (this._kernel) {
            this._kernel.dispose();
            const oldValue = this._kernel;
            this._kernel = null;
            const newValue = this._kernel;
            this._kernelChanged.emit({ name: 'kernel', oldValue, newValue });
        }
        signaling_1.Signal.clearData(this);
    }
    /**
     * Change the session path.
     *
     * @param path - The new session path.
     *
     * @returns A promise that resolves when the session has renamed.
     *
     * #### Notes
     * This uses the Jupyter REST API, and the response is validated.
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async setPath(path) {
        if (this.isDisposed) {
            throw new Error('Session is disposed');
        }
        await this._patch({ path });
    }
    /**
     * Change the session name.
     */
    async setName(name) {
        if (this.isDisposed) {
            throw new Error('Session is disposed');
        }
        await this._patch({ name });
    }
    /**
     * Change the session type.
     */
    async setType(type) {
        if (this.isDisposed) {
            throw new Error('Session is disposed');
        }
        await this._patch({ type });
    }
    /**
     * Change the kernel.
     *
     * @param options - The name or id of the new kernel.
     *
     * #### Notes
     * This shuts down the existing kernel and creates a new kernel,
     * keeping the existing session ID and session path.
     */
    async changeKernel(options) {
        if (this.isDisposed) {
            throw new Error('Session is disposed');
        }
        await this._patch({ kernel: options });
        return this.kernel;
    }
    /**
     * Kill the kernel and shutdown the session.
     *
     * @returns - The promise fulfilled on a valid response from the server.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions), and validates the response.
     * Disposes of the session and emits a [sessionDied] signal on success.
     */
    async shutdown() {
        if (this.isDisposed) {
            throw new Error('Session is disposed');
        }
        await this._sessionAPIClient.shutdown(this.id);
        this.dispose();
    }
    /**
     * Create a new kernel connection and connect to its signals.
     *
     * #### Notes
     * This method is not meant to be subclassed.
     */
    setupKernel(model) {
        if (model === null) {
            this._kernel = null;
            return;
        }
        const kc = this._connectToKernel({
            ...this._kernelConnectionOptions,
            model,
            username: this._username,
            clientId: this._clientId,
            serverSettings: this.serverSettings
        });
        this._kernel = kc;
        kc.statusChanged.connect(this.onKernelStatus, this);
        kc.connectionStatusChanged.connect(this.onKernelConnectionStatus, this);
        kc.pendingInput.connect(this.onPendingInput, this);
        kc.unhandledMessage.connect(this.onUnhandledMessage, this);
        kc.iopubMessage.connect(this.onIOPubMessage, this);
        kc.anyMessage.connect(this.onAnyMessage, this);
    }
    /**
     * Handle to changes in the Kernel status.
     */
    onKernelStatus(sender, state) {
        this._statusChanged.emit(state);
    }
    /**
     * Handle to changes in the Kernel status.
     */
    onKernelConnectionStatus(sender, state) {
        this._connectionStatusChanged.emit(state);
    }
    /**
     * Handle a change in the pendingInput.
     */
    onPendingInput(sender, state) {
        this._pendingInput.emit(state);
    }
    /**
     * Handle iopub kernel messages.
     */
    onIOPubMessage(sender, msg) {
        this._iopubMessage.emit(msg);
    }
    /**
     * Handle unhandled kernel messages.
     */
    onUnhandledMessage(sender, msg) {
        this._unhandledMessage.emit(msg);
    }
    /**
     * Handle any kernel messages.
     */
    onAnyMessage(sender, args) {
        this._anyMessage.emit(args);
    }
    /**
     * Send a PATCH to the server, updating the session path or the kernel.
     */
    async _patch(body) {
        const model = await this._sessionAPIClient.update({
            ...body,
            id: this._id
        });
        this.update(model);
        return model;
    }
    /**
     * Handle a change to the model.
     */
    _handleModelChange(oldModel) {
        if (oldModel.name !== this._name) {
            this._propertyChanged.emit('name');
        }
        if (oldModel.type !== this._type) {
            this._propertyChanged.emit('type');
        }
        if (oldModel.path !== this._path) {
            this._propertyChanged.emit('path');
        }
    }
}
exports.SessionConnection = SessionConnection;
//# sourceMappingURL=default.js.map

/***/ }),

/***/ 5573:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ConnectionStatus = void 0;
/**
 * Application connection status
 */
class ConnectionStatus {
    constructor() {
        /**
         * Whether the application is connected to the server or not.
         *
         * #### Notes
         *
         * Every periodic network polling should be paused while this is set
         * to `false`. Extensions should use this value to decide whether to proceed
         * with the polling.
         * The extensions may also set this value to `false` if there is no need to
         * fetch anything from the server backend basing on some conditions
         * (e.g. when an error message dialog is displayed).
         * At the same time, the extensions are responsible for setting this value
         * back to `true`.
         */
        this.isConnected = true;
    }
}
exports.ConnectionStatus = ConnectionStatus;
//# sourceMappingURL=connectionstatus.js.map

/***/ }),

/***/ 5684:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.validateModel = validateModel;
exports.updateLegacySessionModel = updateLegacySessionModel;
exports.validateModels = validateModels;
const validate_1 = __webpack_require__(5855);
const validate_2 = __webpack_require__(7441);
/**
 * Validate an `Session.IModel` object.
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function validateModel(data) {
    (0, validate_2.validateProperty)(data, 'id', 'string');
    (0, validate_2.validateProperty)(data, 'type', 'string');
    (0, validate_2.validateProperty)(data, 'name', 'string');
    (0, validate_2.validateProperty)(data, 'path', 'string');
    (0, validate_2.validateProperty)(data, 'kernel', 'object');
    (0, validate_1.validateModel)(data.kernel);
}
/**
 * Update model from legacy session data.
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function updateLegacySessionModel(data) {
    if (data.path === undefined && data.notebook !== undefined) {
        data.path = data.notebook.path;
        data.type = 'notebook';
        data.name = '';
    }
}
/**
 * Validate an array of `Session.IModel` objects.
 */
function validateModels(models) {
    if (!Array.isArray(models)) {
        throw new Error('Invalid session list');
    }
    models.forEach(d => validateModel(d));
}
//# sourceMappingURL=validate.js.map

/***/ }),

/***/ 5764:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

(function (global, factory) {
     true ? factory(exports, __webpack_require__(8135)) :
    0;
})(this, (function (exports, algorithm) { 'use strict';

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for JSON-specific functions.
     */
    exports.JSONExt = void 0;
    (function (JSONExt) {
        /**
         * A shared frozen empty JSONObject
         */
        JSONExt.emptyObject = Object.freeze({});
        /**
         * A shared frozen empty JSONArray
         */
        JSONExt.emptyArray = Object.freeze([]);
        /**
         * Test whether a JSON value is a primitive.
         *
         * @param value - The JSON value of interest.
         *
         * @returns `true` if the value is a primitive,`false` otherwise.
         */
        function isPrimitive(value) {
            return (value === null ||
                typeof value === 'boolean' ||
                typeof value === 'number' ||
                typeof value === 'string');
        }
        JSONExt.isPrimitive = isPrimitive;
        function isArray(value) {
            return Array.isArray(value);
        }
        JSONExt.isArray = isArray;
        function isObject(value) {
            return !isPrimitive(value) && !isArray(value);
        }
        JSONExt.isObject = isObject;
        /**
         * Compare two JSON values for deep equality.
         *
         * @param first - The first JSON value of interest.
         *
         * @param second - The second JSON value of interest.
         *
         * @returns `true` if the values are equivalent, `false` otherwise.
         */
        function deepEqual(first, second) {
            // Check referential and primitive equality first.
            if (first === second) {
                return true;
            }
            // If one is a primitive, the `===` check ruled out the other.
            if (isPrimitive(first) || isPrimitive(second)) {
                return false;
            }
            // Test whether they are arrays.
            let a1 = isArray(first);
            let a2 = isArray(second);
            // Bail if the types are different.
            if (a1 !== a2) {
                return false;
            }
            // If they are both arrays, compare them.
            if (a1 && a2) {
                return deepArrayEqual(first, second);
            }
            // At this point, they must both be objects.
            return deepObjectEqual(first, second);
        }
        JSONExt.deepEqual = deepEqual;
        /**
         * Create a deep copy of a JSON value.
         *
         * @param value - The JSON value to copy.
         *
         * @returns A deep copy of the given JSON value.
         */
        function deepCopy(value) {
            // Do nothing for primitive values.
            if (isPrimitive(value)) {
                return value;
            }
            // Deep copy an array.
            if (isArray(value)) {
                return deepArrayCopy(value);
            }
            // Deep copy an object.
            return deepObjectCopy(value);
        }
        JSONExt.deepCopy = deepCopy;
        /**
         * Compare two JSON arrays for deep equality.
         */
        function deepArrayEqual(first, second) {
            // Check referential equality first.
            if (first === second) {
                return true;
            }
            // Test the arrays for equal length.
            if (first.length !== second.length) {
                return false;
            }
            // Compare the values for equality.
            for (let i = 0, n = first.length; i < n; ++i) {
                if (!deepEqual(first[i], second[i])) {
                    return false;
                }
            }
            // At this point, the arrays are equal.
            return true;
        }
        /**
         * Compare two JSON objects for deep equality.
         */
        function deepObjectEqual(first, second) {
            // Check referential equality first.
            if (first === second) {
                return true;
            }
            // Check for the first object's keys in the second object.
            for (let key in first) {
                if (first[key] !== undefined && !(key in second)) {
                    return false;
                }
            }
            // Check for the second object's keys in the first object.
            for (let key in second) {
                if (second[key] !== undefined && !(key in first)) {
                    return false;
                }
            }
            // Compare the values for equality.
            for (let key in first) {
                // Get the values.
                let firstValue = first[key];
                let secondValue = second[key];
                // If both are undefined, ignore the key.
                if (firstValue === undefined && secondValue === undefined) {
                    continue;
                }
                // If only one value is undefined, the objects are not equal.
                if (firstValue === undefined || secondValue === undefined) {
                    return false;
                }
                // Compare the values.
                if (!deepEqual(firstValue, secondValue)) {
                    return false;
                }
            }
            // At this point, the objects are equal.
            return true;
        }
        /**
         * Create a deep copy of a JSON array.
         */
        function deepArrayCopy(value) {
            let result = new Array(value.length);
            for (let i = 0, n = value.length; i < n; ++i) {
                result[i] = deepCopy(value[i]);
            }
            return result;
        }
        /**
         * Create a deep copy of a JSON object.
         */
        function deepObjectCopy(value) {
            let result = {};
            for (let key in value) {
                // Ignore undefined values.
                let subvalue = value[key];
                if (subvalue === undefined) {
                    continue;
                }
                result[key] = deepCopy(subvalue);
            }
            return result;
        }
    })(exports.JSONExt || (exports.JSONExt = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * An object which stores MIME data for general application use.
     *
     * #### Notes
     * This class does not attempt to enforce "correctness" of MIME types
     * and their associated data. Since this class is designed to transfer
     * arbitrary data and objects within the same application, it assumes
     * that the user provides correct and accurate data.
     */
    class MimeData {
        constructor() {
            this._types = [];
            this._values = [];
        }
        /**
         * Get an array of the MIME types contained within the dataset.
         *
         * @returns A new array of the MIME types, in order of insertion.
         */
        types() {
            return this._types.slice();
        }
        /**
         * Test whether the dataset has an entry for the given type.
         *
         * @param mime - The MIME type of interest.
         *
         * @returns `true` if the dataset contains a value for the given
         *   MIME type, `false` otherwise.
         */
        hasData(mime) {
            return this._types.indexOf(mime) !== -1;
        }
        /**
         * Get the data value for the given MIME type.
         *
         * @param mime - The MIME type of interest.
         *
         * @returns The value for the given MIME type, or `undefined` if
         *   the dataset does not contain a value for the type.
         */
        getData(mime) {
            let i = this._types.indexOf(mime);
            return i !== -1 ? this._values[i] : undefined;
        }
        /**
         * Set the data value for the given MIME type.
         *
         * @param mime - The MIME type of interest.
         *
         * @param data - The data value for the given MIME type.
         *
         * #### Notes
         * This will overwrite any previous entry for the MIME type.
         */
        setData(mime, data) {
            this.clearData(mime);
            this._types.push(mime);
            this._values.push(data);
        }
        /**
         * Remove the data entry for the given MIME type.
         *
         * @param mime - The MIME type of interest.
         *
         * #### Notes
         * This is a no-op if there is no entry for the given MIME type.
         */
        clearData(mime) {
            let i = this._types.indexOf(mime);
            if (i !== -1) {
                this._types.splice(i, 1);
                this._values.splice(i, 1);
            }
        }
        /**
         * Remove all data entries from the dataset.
         */
        clear() {
            this._types.length = 0;
            this._values.length = 0;
        }
    }

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /**
     * Plugin registry.
     */
    class PluginRegistry {
        constructor(options = {}) {
            this._application = null;
            this._validatePlugin = () => true;
            this._plugins = new Map();
            this._services = new Map();
            if (options.validatePlugin) {
                console.info('Plugins may be rejected by the custom validation plugin method.');
                this._validatePlugin = options.validatePlugin;
            }
        }
        /**
         * The application object.
         *
         * It will be provided as first argument to the
         * plugins activation and deactivation functions.
         *
         * It can only be set once.
         *
         * By default, it is `null`.
         */
        get application() {
            return this._application;
        }
        set application(v) {
            if (this._application !== null) {
                throw Error('PluginRegistry.application is already set. It cannot be overridden.');
            }
            this._application = v;
        }
        /**
         * The list of all the deferred plugins.
         */
        get deferredPlugins() {
            return Array.from(this._plugins)
                .filter(([id, plugin]) => plugin.autoStart === 'defer')
                .map(([id, plugin]) => id);
        }
        /**
         * Get a plugin description.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @returns The plugin description.
         */
        getPluginDescription(id) {
            var _a, _b;
            return (_b = (_a = this._plugins.get(id)) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : '';
        }
        /**
         * Test whether a plugin is registered with the application.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @returns `true` if the plugin is registered, `false` otherwise.
         */
        hasPlugin(id) {
            return this._plugins.has(id);
        }
        /**
         * Test whether a plugin is activated with the application.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @returns `true` if the plugin is activated, `false` otherwise.
         */
        isPluginActivated(id) {
            var _a, _b;
            return (_b = (_a = this._plugins.get(id)) === null || _a === void 0 ? void 0 : _a.activated) !== null && _b !== void 0 ? _b : false;
        }
        /**
         * List the IDs of the plugins registered with the application.
         *
         * @returns A new array of the registered plugin IDs.
         */
        listPlugins() {
            return Array.from(this._plugins.keys());
        }
        /**
         * Register a plugin with the application.
         *
         * @param plugin - The plugin to register.
         *
         * #### Notes
         * An error will be thrown if a plugin with the same ID is already
         * registered, or if the plugin has a circular dependency.
         *
         * If the plugin provides a service which has already been provided
         * by another plugin, the new service will override the old service.
         */
        registerPlugin(plugin) {
            // Throw an error if the plugin ID is already registered.
            if (this._plugins.has(plugin.id)) {
                throw new TypeError(`Plugin '${plugin.id}' is already registered.`);
            }
            if (!this._validatePlugin(plugin)) {
                throw new Error(`Plugin '${plugin.id}' is not valid.`);
            }
            // Create the normalized plugin data.
            const data = Private.createPluginData(plugin);
            // Ensure the plugin does not cause a cyclic dependency.
            Private.ensureNoCycle(data, this._plugins, this._services);
            // Add the service token to the service map.
            if (data.provides) {
                this._services.set(data.provides, data.id);
            }
            // Add the plugin to the plugin map.
            this._plugins.set(data.id, data);
        }
        /**
         * Register multiple plugins with the application.
         *
         * @param plugins - The plugins to register.
         *
         * #### Notes
         * This calls `registerPlugin()` for each of the given plugins.
         */
        registerPlugins(plugins) {
            for (const plugin of plugins) {
                this.registerPlugin(plugin);
            }
        }
        /**
         * Deregister a plugin with the application.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @param force - Whether to deregister the plugin even if it is active.
         */
        deregisterPlugin(id, force) {
            const plugin = this._plugins.get(id);
            if (!plugin) {
                return;
            }
            if (plugin.activated && !force) {
                throw new Error(`Plugin '${id}' is still active.`);
            }
            this._plugins.delete(id);
        }
        /**
         * Activate the plugin with the given ID.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @returns A promise which resolves when the plugin is activated
         *   or rejects with an error if it cannot be activated.
         */
        async activatePlugin(id) {
            // Reject the promise if the plugin is not registered.
            const plugin = this._plugins.get(id);
            if (!plugin) {
                throw new ReferenceError(`Plugin '${id}' is not registered.`);
            }
            // Resolve immediately if the plugin is already activated.
            if (plugin.activated) {
                return;
            }
            // Return the pending resolver promise if it exists.
            if (plugin.promise) {
                return plugin.promise;
            }
            // Resolve the required services for the plugin.
            const required = plugin.requires.map(t => this.resolveRequiredService(t));
            // Resolve the optional services for the plugin.
            const optional = plugin.optional.map(t => this.resolveOptionalService(t));
            // Setup the resolver promise for the plugin.
            plugin.promise = Promise.all([...required, ...optional])
                .then(services => plugin.activate.apply(undefined, [this.application, ...services]))
                .then(service => {
                plugin.service = service;
                plugin.activated = true;
                plugin.promise = null;
            })
                .catch(error => {
                plugin.promise = null;
                throw error;
            });
            // Return the pending resolver promise.
            return plugin.promise;
        }
        /**
         * Activate all the deferred plugins.
         *
         * @returns A promise which will resolve when each plugin is activated
         * or rejects with an error if one cannot be activated.
         */
        async activatePlugins(kind, options = {}) {
            switch (kind) {
                case 'defer': {
                    const promises = this.deferredPlugins
                        .filter(pluginId => this._plugins.get(pluginId).autoStart)
                        .map(pluginId => {
                        return this.activatePlugin(pluginId);
                    });
                    await Promise.all(promises);
                    break;
                }
                case 'startUp': {
                    // Collect the ids of the startup plugins.
                    const startups = Private.collectStartupPlugins(this._plugins, options);
                    // Generate the activation promises.
                    const promises = startups.map(async (id) => {
                        try {
                            return await this.activatePlugin(id);
                        }
                        catch (error) {
                            console.error(`Plugin '${id}' failed to activate.`, error);
                        }
                    });
                    await Promise.all(promises);
                    break;
                }
            }
        }
        /**
         * Deactivate the plugin and its downstream dependents if and only if the
         * plugin and its dependents all support `deactivate`.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @returns A list of IDs of downstream plugins deactivated with this one.
         */
        async deactivatePlugin(id) {
            // Reject the promise if the plugin is not registered.
            const plugin = this._plugins.get(id);
            if (!plugin) {
                throw new ReferenceError(`Plugin '${id}' is not registered.`);
            }
            // Bail early if the plugin is not activated.
            if (!plugin.activated) {
                return [];
            }
            // Check that this plugin can deactivate.
            if (!plugin.deactivate) {
                throw new TypeError(`Plugin '${id}'#deactivate() method missing`);
            }
            // Find the optimal deactivation order for plugins downstream of this one.
            const manifest = Private.findDependents(id, this._plugins, this._services);
            const downstream = manifest.map(id => this._plugins.get(id));
            // Check that all downstream plugins can deactivate.
            for (const plugin of downstream) {
                if (!plugin.deactivate) {
                    throw new TypeError(`Plugin ${plugin.id}#deactivate() method missing (depends on ${id})`);
                }
            }
            // Deactivate all downstream plugins.
            for (const plugin of downstream) {
                const services = [...plugin.requires, ...plugin.optional].map(service => {
                    const id = this._services.get(service);
                    return id ? this._plugins.get(id).service : null;
                });
                // Await deactivation so the next plugins only receive active services.
                await plugin.deactivate(this.application, ...services);
                plugin.service = null;
                plugin.activated = false;
            }
            // Remove plugin ID and return manifest of deactivated plugins.
            manifest.pop();
            return manifest;
        }
        /**
         * Resolve a required service of a given type.
         *
         * @param token - The token for the service type of interest.
         *
         * @returns A promise which resolves to an instance of the requested
         *   service, or rejects with an error if it cannot be resolved.
         *
         * #### Notes
         * Services are singletons. The same instance will be returned each
         * time a given service token is resolved.
         *
         * If the plugin which provides the service has not been activated,
         * resolving the service will automatically activate the plugin.
         *
         * User code will not typically call this method directly. Instead,
         * the required services for the user's plugins will be resolved
         * automatically when the plugin is activated.
         */
        async resolveRequiredService(token) {
            // Reject the promise if there is no provider for the type.
            const id = this._services.get(token);
            if (!id) {
                throw new TypeError(`No provider for: ${token.name}.`);
            }
            // Activate the plugin if necessary.
            const plugin = this._plugins.get(id);
            if (!plugin.activated) {
                await this.activatePlugin(id);
            }
            return plugin.service;
        }
        /**
         * Resolve an optional service of a given type.
         *
         * @param token - The token for the service type of interest.
         *
         * @returns A promise which resolves to an instance of the requested
         *   service, or `null` if it cannot be resolved.
         *
         * #### Notes
         * Services are singletons. The same instance will be returned each
         * time a given service token is resolved.
         *
         * If the plugin which provides the service has not been activated,
         * resolving the service will automatically activate the plugin.
         *
         * User code will not typically call this method directly. Instead,
         * the optional services for the user's plugins will be resolved
         * automatically when the plugin is activated.
         */
        async resolveOptionalService(token) {
            // Resolve with `null` if there is no provider for the type.
            const id = this._services.get(token);
            if (!id) {
                return null;
            }
            // Activate the plugin if necessary.
            const plugin = this._plugins.get(id);
            if (!plugin.activated) {
                try {
                    await this.activatePlugin(id);
                }
                catch (reason) {
                    console.error(reason);
                    return null;
                }
            }
            return plugin.service;
        }
    }
    /**
     * The namespace for the module implementation details.
     */
    var Private;
    (function (Private) {
        class PluginData {
            constructor(plugin) {
                var _a, _b, _c, _d;
                this._activated = false;
                this._promise = null;
                this._service = null;
                this.id = plugin.id;
                this.description = (_a = plugin.description) !== null && _a !== void 0 ? _a : '';
                this.activate = plugin.activate;
                this.deactivate = (_b = plugin.deactivate) !== null && _b !== void 0 ? _b : null;
                this.provides = (_c = plugin.provides) !== null && _c !== void 0 ? _c : null;
                this.autoStart = (_d = plugin.autoStart) !== null && _d !== void 0 ? _d : false;
                this.requires = plugin.requires ? plugin.requires.slice() : [];
                this.optional = plugin.optional ? plugin.optional.slice() : [];
            }
            /**
             * Whether the plugin has been activated.
             */
            get activated() {
                return this._activated;
            }
            set activated(a) {
                this._activated = a;
            }
            /**
             * The resolved service for the plugin, or `null`.
             */
            get service() {
                return this._service;
            }
            set service(s) {
                this._service = s;
            }
            /**
             * The pending resolver promise, or `null`.
             */
            get promise() {
                return this._promise;
            }
            set promise(p) {
                this._promise = p;
            }
        }
        /**
         * Create a normalized plugin data object for the given plugin.
         */
        function createPluginData(plugin) {
            return new PluginData(plugin);
        }
        Private.createPluginData = createPluginData;
        /**
         * Ensure no cycle is present in the plugin resolution graph.
         *
         * If a cycle is detected, an error will be thrown.
         */
        function ensureNoCycle(plugin, plugins, services) {
            const dependencies = [...plugin.requires, ...plugin.optional];
            const visit = (token) => {
                if (token === plugin.provides) {
                    return true;
                }
                const id = services.get(token);
                if (!id) {
                    return false;
                }
                const visited = plugins.get(id);
                const dependencies = [...visited.requires, ...visited.optional];
                if (dependencies.length === 0) {
                    return false;
                }
                trace.push(id);
                if (dependencies.some(visit)) {
                    return true;
                }
                trace.pop();
                return false;
            };
            // Bail early if there cannot be a cycle.
            if (!plugin.provides || dependencies.length === 0) {
                return;
            }
            // Setup a stack to trace service resolution.
            const trace = [plugin.id];
            // Throw an exception if a cycle is present.
            if (dependencies.some(visit)) {
                throw new ReferenceError(`Cycle detected: ${trace.join(' -> ')}.`);
            }
        }
        Private.ensureNoCycle = ensureNoCycle;
        /**
         * Find dependents in deactivation order.
         *
         * @param id - The ID of the plugin of interest.
         *
         * @param plugins - The map containing all plugins.
         *
         * @param services - The map containing all services.
         *
         * @returns A list of dependent plugin IDs in order of deactivation
         *
         * #### Notes
         * The final item of the returned list is always the plugin of interest.
         */
        function findDependents(id, plugins, services) {
            const edges = new Array();
            const add = (id) => {
                const plugin = plugins.get(id);
                // FIXME In the case of missing optional dependencies, we may consider
                // deactivating and reactivating the plugin without the missing service.
                const dependencies = [...plugin.requires, ...plugin.optional];
                edges.push(...dependencies.reduce((acc, dep) => {
                    const service = services.get(dep);
                    if (service) {
                        // An edge is oriented from dependent to provider.
                        acc.push([id, service]);
                    }
                    return acc;
                }, []));
            };
            for (const id of plugins.keys()) {
                add(id);
            }
            // Filter edges
            // - Get all packages that dependent on the package to be deactivated
            const newEdges = edges.filter(edge => edge[1] === id);
            let oldSize = 0;
            while (newEdges.length > oldSize) {
                const previousSize = newEdges.length;
                // Get all packages that dependent on packages that will be deactivated
                const packagesOfInterest = new Set(newEdges.map(edge => edge[0]));
                for (const poi of packagesOfInterest) {
                    edges
                        .filter(edge => edge[1] === poi)
                        .forEach(edge => {
                        // We check it is not already included to deal with circular dependencies
                        if (!newEdges.includes(edge)) {
                            newEdges.push(edge);
                        }
                    });
                }
                oldSize = previousSize;
            }
            const sorted = algorithm.topologicSort(newEdges);
            const index = sorted.findIndex(candidate => candidate === id);
            if (index === -1) {
                return [id];
            }
            return sorted.slice(0, index + 1);
        }
        Private.findDependents = findDependents;
        /**
         * Collect the IDs of the plugins to activate on startup.
         */
        function collectStartupPlugins(plugins, options) {
            // Create a set to hold the plugin IDs.
            const collection = new Set();
            // Collect the auto-start (non deferred) plugins.
            for (const id of plugins.keys()) {
                if (plugins.get(id).autoStart === true) {
                    collection.add(id);
                }
            }
            // Add the startup plugins.
            if (options.startPlugins) {
                for (const id of options.startPlugins) {
                    collection.add(id);
                }
            }
            // Remove the ignored plugins.
            if (options.ignorePlugins) {
                for (const id of options.ignorePlugins) {
                    collection.delete(id);
                }
            }
            // Return the collected startup plugins.
            return Array.from(collection);
        }
        Private.collectStartupPlugins = collectStartupPlugins;
    })(Private || (Private = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * A class which wraps a promise into a delegate object.
     *
     * #### Notes
     * This class is useful when the logic to resolve or reject a promise
     * cannot be defined at the point where the promise is created.
     */
    class PromiseDelegate {
        /**
         * Construct a new promise delegate.
         */
        constructor() {
            this.promise = new Promise((resolve, reject) => {
                this._resolve = resolve;
                this._reject = reject;
            });
        }
        /**
         * Resolve the wrapped promise with the given value.
         *
         * @param value - The value to use for resolving the promise.
         */
        resolve(value) {
            let resolve = this._resolve;
            resolve(value);
        }
        /**
         * Reject the wrapped promise with the given value.
         *
         * @reason - The reason for rejecting the promise.
         */
        reject(reason) {
            let reject = this._reject;
            reject(reason);
        }
    }

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * A runtime object which captures compile-time type information.
     *
     * #### Notes
     * A token captures the compile-time type of an interface or class in
     * an object which can be used at runtime in a type-safe fashion.
     */
    class Token {
        /**
         * Construct a new token.
         *
         * @param name - A human readable name for the token.
         * @param description - Token purpose description for documentation.
         */
        constructor(name, description) {
            this.name = name;
            this.description = description !== null && description !== void 0 ? description : '';
            this._tokenStructuralPropertyT = null;
        }
    }

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    // Fallback
    function fallbackRandomValues(buffer) {
        let value = 0;
        for (let i = 0, n = buffer.length; i < n; ++i) {
            if (i % 4 === 0) {
                value = (Math.random() * 0xffffffff) >>> 0;
            }
            buffer[i] = value & 0xff;
            value >>>= 8;
        }
    }

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for random number related functionality.
     */
    exports.Random = void 0;
    (function (Random) {
        /**
         * A function which generates random bytes.
         *
         * @param buffer - The `Uint8Array` to fill with random bytes.
         *
         * #### Notes
         * A cryptographically strong random number generator will be used if
         * available. Otherwise, `Math.random` will be used as a fallback for
         * randomness.
         *
         * The following RNGs are supported, listed in order of precedence:
         *   - `window.crypto.getRandomValues`
         *   - `window.msCrypto.getRandomValues`
         *   - `require('crypto').randomFillSync
         *   - `require('crypto').randomBytes
         *   - `Math.random`
         */
        Random.getRandomValues = (() => {
            // Look up the crypto module if available.
            const crypto = (typeof window !== 'undefined' && (window.crypto || window.msCrypto)) ||
                null;
            // Modern browsers and IE 11
            if (crypto && typeof crypto.getRandomValues === 'function') {
                return function getRandomValues(buffer) {
                    return crypto.getRandomValues(buffer);
                };
            }
            // Fallback
            return fallbackRandomValues;
        })();
    })(exports.Random || (exports.Random = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * A function which creates a function that generates UUID v4 identifiers.
     *
     * @returns A new function that creates a UUID v4 string.
     *
     * #### Notes
     * This implementation complies with RFC 4122.
     *
     * This uses `Random.getRandomValues()` for random bytes, which in
     * turn will use the underlying `crypto` module of the platform if
     * it is available. The fallback for randomness is `Math.random`.
     */
    function uuid4Factory(getRandomValues) {
        // Create a 16 byte array to hold the random values.
        const bytes = new Uint8Array(16);
        // Create a look up table from bytes to hex strings.
        const lut = new Array(256);
        // Pad the single character hex digits with a leading zero.
        for (let i = 0; i < 16; ++i) {
            lut[i] = '0' + i.toString(16);
        }
        // Populate the rest of the hex digits.
        for (let i = 16; i < 256; ++i) {
            lut[i] = i.toString(16);
        }
        // Return a function which generates the UUID.
        return function uuid4() {
            // Get a new batch of random values.
            getRandomValues(bytes);
            // Set the UUID version number to 4.
            bytes[6] = 0x40 | (bytes[6] & 0x0f);
            // Set the clock sequence bit to the RFC spec.
            bytes[8] = 0x80 | (bytes[8] & 0x3f);
            // Assemble the UUID string.
            return (lut[bytes[0]] +
                lut[bytes[1]] +
                lut[bytes[2]] +
                lut[bytes[3]] +
                '-' +
                lut[bytes[4]] +
                lut[bytes[5]] +
                '-' +
                lut[bytes[6]] +
                lut[bytes[7]] +
                '-' +
                lut[bytes[8]] +
                lut[bytes[9]] +
                '-' +
                lut[bytes[10]] +
                lut[bytes[11]] +
                lut[bytes[12]] +
                lut[bytes[13]] +
                lut[bytes[14]] +
                lut[bytes[15]]);
        };
    }

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for UUID related functionality.
     */
    exports.UUID = void 0;
    (function (UUID) {
        /**
         * A function which generates UUID v4 identifiers.
         *
         * @returns A new UUID v4 string.
         *
         * #### Notes
         * This implementation complies with RFC 4122.
         *
         * This uses `Random.getRandomValues()` for random bytes, which in
         * turn will use the underlying `crypto` module of the platform if
         * it is available. The fallback for randomness is `Math.random`.
         */
        UUID.uuid4 = uuid4Factory(exports.Random.getRandomValues);
    })(exports.UUID || (exports.UUID = {}));

    exports.MimeData = MimeData;
    exports.PluginRegistry = PluginRegistry;
    exports.PromiseDelegate = PromiseDelegate;
    exports.Token = Token;

}));
//# sourceMappingURL=index.js.map


/***/ }),

/***/ 5855:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.validateMessage = validateMessage;
exports.validateModel = validateModel;
exports.validateModels = validateModels;
const validate_1 = __webpack_require__(7441);
/**
 * Required fields for `IKernelHeader`.
 */
const HEADER_FIELDS = ['username', 'version', 'session', 'msg_id', 'msg_type'];
/**
 * Required fields and types for contents of various types of `kernel.IMessage`
 * messages on the iopub channel.
 */
const IOPUB_CONTENT_FIELDS = {
    stream: { name: 'string', text: 'string' },
    display_data: { data: 'object', metadata: 'object' },
    execute_input: { code: 'string', execution_count: 'number' },
    execute_result: {
        execution_count: 'number',
        data: 'object',
        metadata: 'object'
    },
    error: { ename: 'string', evalue: 'string', traceback: 'object' },
    status: {
        execution_state: [
            'string',
            ['starting', 'idle', 'busy', 'restarting', 'dead']
        ]
    },
    clear_output: { wait: 'boolean' },
    comm_open: { comm_id: 'string', target_name: 'string', data: 'object' },
    comm_msg: { comm_id: 'string', data: 'object' },
    comm_close: { comm_id: 'string' },
    shutdown_reply: { restart: 'boolean' } // Emitted by the IPython kernel.
};
/**
 * Validate the header of a kernel message.
 */
function validateHeader(header) {
    for (let i = 0; i < HEADER_FIELDS.length; i++) {
        (0, validate_1.validateProperty)(header, HEADER_FIELDS[i], 'string');
    }
}
/**
 * Validate a kernel message object.
 */
function validateMessage(msg) {
    (0, validate_1.validateProperty)(msg, 'metadata', 'object');
    (0, validate_1.validateProperty)(msg, 'content', 'object');
    (0, validate_1.validateProperty)(msg, 'channel', 'string');
    validateHeader(msg.header);
    if (msg.channel === 'iopub') {
        validateIOPubContent(msg);
    }
}
/**
 * Validate content an kernel message on the iopub channel.
 */
function validateIOPubContent(msg) {
    if (msg.channel === 'iopub') {
        const fields = IOPUB_CONTENT_FIELDS[msg.header.msg_type];
        // Check for unknown message type.
        if (fields === undefined) {
            return;
        }
        const names = Object.keys(fields);
        const content = msg.content;
        for (let i = 0; i < names.length; i++) {
            let args = fields[names[i]];
            if (!Array.isArray(args)) {
                args = [args];
            }
            (0, validate_1.validateProperty)(content, names[i], ...args);
        }
    }
}
/**
 * Validate a `Kernel.IModel` object.
 */
function validateModel(model) {
    (0, validate_1.validateProperty)(model, 'name', 'string');
    (0, validate_1.validateProperty)(model, 'id', 'string');
}
/**
 * Validate an array of `IModel` objects.
 */
function validateModels(models) {
    if (!Array.isArray(models)) {
        throw new Error('Invalid kernel list');
    }
    models.forEach(d => validateModel(d));
}
//# sourceMappingURL=validate.js.map

/***/ }),

/***/ 5964:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PageConfig = void 0;
const coreutils_1 = __webpack_require__(5764);
const minimist_1 = __importDefault(__webpack_require__(9600));
const url_1 = __webpack_require__(1692);
/**
 * The namespace for `PageConfig` functions.
 */
var PageConfig;
(function (PageConfig) {
    /**
     * Get global configuration data for the Jupyter application.
     *
     * @param name - The name of the configuration option.
     *
     * @returns The config value or an empty string if not found.
     *
     * #### Notes
     * All values are treated as strings.
     * For browser based applications, it is assumed that the page HTML
     * includes a script tag with the id `jupyter-config-data` containing the
     * configuration as valid JSON.  In order to support the classic Notebook,
     * we fall back on checking for `body` data of the given `name`.
     *
     * For node applications, it is assumed that the process was launched
     * with a `--jupyter-config-data` option pointing to a JSON settings
     * file.
     */
    function getOption(name) {
        if (configData) {
            return configData[name] || getBodyData(name);
        }
        configData = Object.create(null);
        let found = false;
        // Use script tag if available.
        if (typeof document !== 'undefined' && document) {
            const el = document.getElementById('jupyter-config-data');
            if (el) {
                configData = JSON.parse(el.textContent || '');
                found = true;
            }
        }
        // Otherwise use CLI if given.
        if (!found && typeof process !== 'undefined' && process.argv) {
            try {
                const cli = (0, minimist_1.default)(process.argv.slice(2));
                const path = __webpack_require__(9942);
                let fullPath = '';
                if ('jupyter-config-data' in cli) {
                    fullPath = path.resolve(cli['jupyter-config-data']);
                }
                else if ('JUPYTER_CONFIG_DATA' in process.env) {
                    fullPath = path.resolve(process.env['JUPYTER_CONFIG_DATA']);
                }
                if (fullPath) {
                    // Force Webpack to ignore this require.
                    // eslint-disable-next-line
                    configData = eval('require')(fullPath);
                }
            }
            catch (e) {
                console.error(e);
            }
        }
        if (!coreutils_1.JSONExt.isObject(configData)) {
            configData = Object.create(null);
        }
        else {
            for (const key in configData) {
                // PageConfig expects strings
                if (typeof configData[key] !== 'string') {
                    configData[key] = JSON.stringify(configData[key]);
                }
            }
        }
        return configData[name] || getBodyData(name);
    }
    PageConfig.getOption = getOption;
    /**
     * Set global configuration data for the Jupyter application.
     *
     * @param name - The name of the configuration option.
     * @param value - The value to set the option to.
     *
     * @returns The last config value or an empty string if it doesn't exist.
     */
    function setOption(name, value) {
        const last = getOption(name);
        configData[name] = value;
        return last;
    }
    PageConfig.setOption = setOption;
    /**
     * Get the base url for a Jupyter application, or the base url of the page.
     */
    function getBaseUrl() {
        return url_1.URLExt.normalize(getOption('baseUrl') || '/');
    }
    PageConfig.getBaseUrl = getBaseUrl;
    /**
     * Get the tree url for a JupyterLab application.
     */
    function getTreeUrl() {
        return url_1.URLExt.join(getBaseUrl(), getOption('treeUrl'));
    }
    PageConfig.getTreeUrl = getTreeUrl;
    /**
     * Get the base url for sharing links (usually baseUrl)
     */
    function getShareUrl() {
        return url_1.URLExt.normalize(getOption('shareUrl') || getBaseUrl());
    }
    PageConfig.getShareUrl = getShareUrl;
    /**
     * Get the tree url for shareable links.
     * Usually the same as treeUrl,
     * but overridable e.g. when sharing with JupyterHub.
     */
    function getTreeShareUrl() {
        return url_1.URLExt.normalize(url_1.URLExt.join(getShareUrl(), getOption('treeUrl')));
    }
    PageConfig.getTreeShareUrl = getTreeShareUrl;
    /**
     * Create a new URL given an optional mode and tree path.
     *
     * This is used to create URLS when the mode or tree path change as the user
     * changes mode or the current document in the main area. If fields in
     * options are omitted, the value in PageConfig will be used.
     *
     * @param options - IGetUrlOptions for the new path.
     */
    function getUrl(options) {
        var _a, _b, _c, _d;
        let path = options.toShare ? getShareUrl() : getBaseUrl();
        const mode = (_a = options.mode) !== null && _a !== void 0 ? _a : getOption('mode');
        const workspace = (_b = options.workspace) !== null && _b !== void 0 ? _b : getOption('workspace');
        const labOrDoc = mode === 'single-document' ? 'doc' : 'lab';
        path = url_1.URLExt.join(path, labOrDoc);
        if (workspace !== PageConfig.defaultWorkspace) {
            path = url_1.URLExt.join(path, 'workspaces', encodeURIComponent((_c = getOption('workspace')) !== null && _c !== void 0 ? _c : PageConfig.defaultWorkspace));
        }
        const treePath = (_d = options.treePath) !== null && _d !== void 0 ? _d : getOption('treePath');
        if (treePath) {
            path = url_1.URLExt.join(path, 'tree', url_1.URLExt.encodeParts(treePath));
        }
        return path;
    }
    PageConfig.getUrl = getUrl;
    PageConfig.defaultWorkspace = 'default';
    /**
     * Get the base websocket url for a Jupyter application, or an empty string.
     */
    function getWsUrl(baseUrl) {
        let wsUrl = getOption('wsUrl');
        if (!wsUrl) {
            baseUrl = baseUrl ? url_1.URLExt.normalize(baseUrl) : getBaseUrl();
            if (baseUrl.indexOf('http') !== 0) {
                return '';
            }
            wsUrl = 'ws' + baseUrl.slice(4);
        }
        return url_1.URLExt.normalize(wsUrl);
    }
    PageConfig.getWsUrl = getWsUrl;
    /**
     * Returns the URL converting this notebook to a certain
     * format with nbconvert.
     */
    function getNBConvertURL({ path, format, download }) {
        const notebookPath = url_1.URLExt.encodeParts(path);
        const url = url_1.URLExt.join(getBaseUrl(), 'nbconvert', format, notebookPath);
        if (download) {
            return url + '?download=true';
        }
        return url;
    }
    PageConfig.getNBConvertURL = getNBConvertURL;
    /**
     * Get the authorization token for a Jupyter application.
     */
    function getToken() {
        return getOption('token') || getBodyData('jupyterApiToken');
    }
    PageConfig.getToken = getToken;
    /**
     * Get the Notebook version info [major, minor, patch].
     */
    function getNotebookVersion() {
        const notebookVersion = getOption('notebookVersion');
        if (notebookVersion === '') {
            return [0, 0, 0];
        }
        return JSON.parse(notebookVersion);
    }
    PageConfig.getNotebookVersion = getNotebookVersion;
    /**
     * Private page config data for the Jupyter application.
     */
    let configData = null;
    /**
     * Get a url-encoded item from `body.data` and decode it
     * We should never have any encoded URLs anywhere else in code
     * until we are building an actual request.
     */
    function getBodyData(key) {
        if (typeof document === 'undefined' || !document.body) {
            return '';
        }
        const val = document.body.dataset[key];
        if (typeof val === 'undefined') {
            return '';
        }
        return decodeURIComponent(val);
    }
    /**
     * The namespace for page config `Extension` functions.
     */
    let Extension;
    (function (Extension) {
        /**
         * Populate an array from page config.
         *
         * @param key - The page config key (e.g., `deferredExtensions`).
         *
         * #### Notes
         * This is intended for `deferredExtensions` and `disabledExtensions`.
         */
        function populate(key) {
            try {
                const raw = getOption(key);
                if (raw) {
                    return JSON.parse(raw);
                }
            }
            catch (error) {
                console.warn(`Unable to parse ${key}.`, error);
            }
            return [];
        }
        /**
         * The collection of deferred extensions in page config.
         */
        Extension.deferred = populate('deferredExtensions');
        /**
         * The collection of disabled extensions in page config.
         */
        Extension.disabled = populate('disabledExtensions');
        /**
         * Returns whether a plugin is deferred.
         *
         * @param id - The plugin ID.
         */
        function isDeferred(id) {
            // Check for either a full plugin id match or an extension
            // name match.
            const separatorIndex = id.indexOf(':');
            let extName = '';
            if (separatorIndex !== -1) {
                extName = id.slice(0, separatorIndex);
            }
            return Extension.deferred.some(val => val === id || (extName && val === extName));
        }
        Extension.isDeferred = isDeferred;
        /**
         * Returns whether a plugin is disabled.
         *
         * @param id - The plugin ID.
         */
        function isDisabled(id) {
            // Check for either a full plugin id match or an extension
            // name match.
            const separatorIndex = id.indexOf(':');
            let extName = '';
            if (separatorIndex !== -1) {
                extName = id.slice(0, separatorIndex);
            }
            return Extension.disabled.some(val => val === id || (extName && val === extName));
        }
        Extension.isDisabled = isDisabled;
    })(Extension = PageConfig.Extension || (PageConfig.Extension = {}));
})(PageConfig || (exports.PageConfig = PageConfig = {}));
//# sourceMappingURL=pageconfig.js.map

/***/ }),

/***/ 6049:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Debouncer: () => (/* binding */ Debouncer),
/* harmony export */   Poll: () => (/* binding */ Poll),
/* harmony export */   RateLimiter: () => (/* binding */ RateLimiter),
/* harmony export */   Throttler: () => (/* binding */ Throttler)
/* harmony export */ });
/* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5764);
/* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lumino_signaling__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3992);



// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/**
 * A class that wraps an asynchronous function to poll at a regular interval
 * with exponential increases to the interval length if the poll fails.
 *
 * @typeparam T - The resolved type of the factory's promises.
 * Defaults to `any`.
 *
 * @typeparam U - The rejected type of the factory's promises.
 * Defaults to `any`.
 *
 * @typeparam V - An optional type to extend the phases supported by a poll.
 * Defaults to `standby`, which already exists in the `Phase` type.
 */
class Poll {
    /**
     * Instantiate a new poll with exponential backoff in case of failure.
     *
     * @param options - The poll instantiation options.
     */
    constructor(options) {
        var _a;
        this._disposed = new _lumino_signaling__WEBPACK_IMPORTED_MODULE_1__.Signal(this);
        this._lingered = 0;
        this._tick = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.PromiseDelegate();
        this._ticked = new _lumino_signaling__WEBPACK_IMPORTED_MODULE_1__.Signal(this);
        this._factory = options.factory;
        this._linger = (_a = options.linger) !== null && _a !== void 0 ? _a : Private.DEFAULT_LINGER;
        this._standby = options.standby || Private.DEFAULT_STANDBY;
        this._state = { ...Private.DEFAULT_STATE, timestamp: new Date().getTime() };
        // Normalize poll frequency `max` to be the greater of
        // default `max`, `options.frequency.max`, or `options.frequency.interval`.
        const frequency = options.frequency || {};
        const max = Math.max(frequency.interval || 0, frequency.max || 0, Private.DEFAULT_FREQUENCY.max);
        this.frequency = { ...Private.DEFAULT_FREQUENCY, ...frequency, ...{ max } };
        this.name = options.name || Private.DEFAULT_NAME;
        if ('auto' in options ? options.auto : true) {
            setTimeout(() => this.start());
        }
    }
    /**
     * A signal emitted when the poll is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * The polling frequency parameters.
     */
    get frequency() {
        return this._frequency;
    }
    set frequency(frequency) {
        if (this.isDisposed || _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.JSONExt.deepEqual(frequency, this.frequency || {})) {
            return;
        }
        let { backoff, interval, max } = frequency;
        interval = Math.round(interval);
        max = Math.round(max);
        if (typeof backoff === 'number' && backoff < 1) {
            throw new Error('Poll backoff growth factor must be at least 1');
        }
        if ((interval < 0 || interval > max) && interval !== Poll.NEVER) {
            throw new Error('Poll interval must be between 0 and max');
        }
        if (max > Poll.MAX_INTERVAL && max !== Poll.NEVER) {
            throw new Error(`Max interval must be less than ${Poll.MAX_INTERVAL}`);
        }
        this._frequency = { backoff, interval, max };
    }
    /**
     * Whether the poll is disposed.
     */
    get isDisposed() {
        return this.state.phase === 'disposed';
    }
    /**
     * Indicates when the poll switches to standby.
     */
    get standby() {
        return this._standby;
    }
    set standby(standby) {
        if (this.isDisposed || this.standby === standby) {
            return;
        }
        this._standby = standby;
    }
    /**
     * The poll state, which is the content of the current poll tick.
     */
    get state() {
        return this._state;
    }
    /**
     * A promise that resolves when the poll next ticks.
     */
    get tick() {
        return this._tick.promise;
    }
    /**
     * A signal emitted when the poll ticks and fires off a new request.
     */
    get ticked() {
        return this._ticked;
    }
    /**
     * Return an async iterator that yields every tick.
     */
    async *[Symbol.asyncIterator]() {
        while (!this.isDisposed) {
            yield this.state;
            await this.tick.catch(() => undefined);
        }
    }
    /**
     * Dispose the poll.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._state = {
            ...Private.DISPOSED_STATE,
            timestamp: new Date().getTime()
        };
        this._tick.promise.catch(_ => undefined);
        this._tick.reject(new Error(`Poll (${this.name}) is disposed.`));
        this._disposed.emit(undefined);
        _lumino_signaling__WEBPACK_IMPORTED_MODULE_1__.Signal.clearData(this);
    }
    /**
     * Refreshes the poll. Schedules `refreshed` tick if necessary.
     *
     * @returns A promise that resolves after tick is scheduled and never rejects.
     *
     * #### Notes
     * The returned promise resolves after the tick is scheduled, but before
     * the polling action is run. To wait until after the poll action executes,
     * await the `poll.tick` promise: `await poll.refresh(); await poll.tick;`
     */
    refresh() {
        return this.schedule({
            cancel: ({ phase }) => phase === 'refreshed',
            interval: Poll.IMMEDIATE,
            phase: 'refreshed'
        });
    }
    /**
     * Schedule the next poll tick.
     *
     * @param next - The next poll state data to schedule. Defaults to standby.
     *
     * @param next.cancel - Cancels state transition if function returns `true`.
     *
     * @returns A promise that resolves when the next poll state is active.
     *
     * #### Notes
     * This method is not meant to be invoked by user code typically. It is public
     * to allow poll instances to be composed into classes that schedule ticks.
     */
    async schedule(next = {}) {
        if (this.isDisposed) {
            return;
        }
        // Check if the phase transition should be canceled.
        if (next.cancel && next.cancel(this.state)) {
            return;
        }
        // Update poll state.
        const pending = this._tick;
        const scheduled = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.PromiseDelegate();
        const state = {
            interval: this.frequency.interval,
            payload: null,
            phase: 'standby',
            timestamp: new Date().getTime(),
            ...next
        };
        this._state = state;
        this._tick = scheduled;
        // Clear the schedule if possible.
        clearTimeout(this._timeout);
        // Emit ticked signal, resolve pending promise, and await its settlement.
        this._ticked.emit(this.state);
        pending.resolve(this);
        await pending.promise;
        if (state.interval === Poll.NEVER) {
            this._timeout = undefined;
            return;
        }
        // Schedule next execution and cache its timeout handle.
        const execute = () => {
            if (this.isDisposed || this.tick !== scheduled.promise) {
                return;
            }
            this._execute();
        };
        // Cache the handle in case it needs to be unscheduled.
        this._timeout = setTimeout(execute, state.interval);
    }
    /**
     * Starts the poll. Schedules `started` tick if necessary.
     *
     * @returns A promise that resolves after tick is scheduled and never rejects.
     */
    start() {
        return this.schedule({
            cancel: ({ phase }) => phase !== 'constructed' && phase !== 'standby' && phase !== 'stopped',
            interval: Poll.IMMEDIATE,
            phase: 'started'
        });
    }
    /**
     * Stops the poll. Schedules `stopped` tick if necessary.
     *
     * @returns A promise that resolves after tick is scheduled and never rejects.
     */
    stop() {
        return this.schedule({
            cancel: ({ phase }) => phase === 'stopped',
            interval: Poll.NEVER,
            phase: 'stopped'
        });
    }
    /**
     * Whether the poll is hidden.
     *
     * #### Notes
     * This property is only relevant in a browser context.
     */
    get hidden() {
        return Private.hidden;
    }
    /**
     * Execute a new poll factory promise or stand by if necessary.
     */
    _execute() {
        let standby = typeof this.standby === 'function' ? this.standby() : this.standby;
        // Check if execution should proceed, linger, or stand by.
        if (standby === 'never') {
            standby = false;
        }
        else if (standby === 'when-hidden') {
            if (this.hidden) {
                standby = ++this._lingered > this._linger;
            }
            else {
                this._lingered = 0;
                standby = false;
            }
        }
        // If in standby mode schedule next tick without calling the factory.
        if (standby) {
            void this.schedule();
            return;
        }
        const pending = this.tick;
        this._factory(this.state)
            .then((resolved) => {
            if (this.isDisposed || this.tick !== pending) {
                return;
            }
            void this.schedule({
                payload: resolved,
                phase: this.state.phase === 'rejected' ? 'reconnected' : 'resolved'
            });
        })
            .catch((rejected) => {
            if (this.isDisposed || this.tick !== pending) {
                return;
            }
            void this.schedule({
                interval: Private.sleep(this.frequency, this.state),
                payload: rejected,
                phase: 'rejected'
            });
        });
    }
}
/**
 * A namespace for `Poll` types, interfaces, and statics.
 */
(function (Poll) {
    /**
     * An interval value in ms that indicates the poll should tick immediately.
     */
    Poll.IMMEDIATE = 0;
    /**
     * Delays are 32-bit integers in many browsers so intervals need to be capped.
     *
     * #### Notes
     * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Maximum_delay_value
     */
    Poll.MAX_INTERVAL = 2147483647;
    /**
     * An interval value that indicates the poll should never tick.
     */
    Poll.NEVER = Infinity;
})(Poll || (Poll = {}));
/**
 * A namespace for private module data.
 */
var Private;
(function (Private) {
    /**
     * The default backoff growth rate if `backoff` is `true`.
     */
    Private.DEFAULT_BACKOFF = 3;
    /**
     * The default polling frequency.
     */
    Private.DEFAULT_FREQUENCY = {
        backoff: true,
        interval: 1000,
        max: 30 * 1000
    };
    /**
     * The default number of times to `linger` when a poll is hidden.
     */
    Private.DEFAULT_LINGER = 1;
    /**
     * The default poll name.
     */
    Private.DEFAULT_NAME = 'unknown';
    /**
     * The default poll standby behavior.
     */
    Private.DEFAULT_STANDBY = 'when-hidden';
    /**
     * The first poll tick state's default values superseded in constructor.
     */
    Private.DEFAULT_STATE = {
        interval: Poll.NEVER,
        payload: null,
        phase: 'constructed',
        timestamp: new Date(0).getTime()
    };
    /**
     * The disposed tick state values.
     */
    Private.DISPOSED_STATE = {
        interval: Poll.NEVER,
        payload: null,
        phase: 'disposed',
        timestamp: new Date(0).getTime()
    };
    /**
     * Returns the number of milliseconds to sleep before the next tick.
     *
     * @param frequency - The poll's base frequency.
     * @param last - The poll's last tick.
     */
    function sleep(frequency, last) {
        const { backoff, interval, max } = frequency;
        if (interval === Poll.NEVER) {
            return interval;
        }
        const growth = backoff === true ? Private.DEFAULT_BACKOFF : backoff === false ? 1 : backoff;
        const random = getRandomIntInclusive(interval, last.interval * growth);
        return Math.min(max, random);
    }
    Private.sleep = sleep;
    /**
     * Keep track of whether the document is hidden. This flag is only relevant in
     * a browser context.
     *
     * Listen to `visibilitychange` event to set the `hidden` flag.
     *
     * Listening to `pagehide` is also necessary because Safari support for
     * `visibilitychange` events is partial, cf.
     * https://developer.mozilla.org/docs/Web/API/Document/visibilitychange_event
     */
    Private.hidden = (() => {
        if (typeof document === 'undefined') {
            return false;
        }
        document.addEventListener('visibilitychange', () => {
            Private.hidden = document.visibilityState === 'hidden';
        });
        document.addEventListener('pagehide', () => {
            Private.hidden = document.visibilityState === 'hidden';
        });
        return document.visibilityState === 'hidden';
    })();
    /**
     * Get a random integer between min and max, inclusive of both.
     *
     * #### Notes
     * From
     * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
     *
     * From the MDN page: It might be tempting to use Math.round() to accomplish
     * that, but doing so would cause your random numbers to follow a non-uniform
     * distribution, which may not be acceptable for your needs.
     */
    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
})(Private || (Private = {}));

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/**
 * A base class to implement rate limiters with different invocation strategies.
 *
 * @typeparam T - The resolved type of the underlying function.
 *
 * @typeparam U - The rejected type of the underlying function.
 *
 * @typeparam V - Arguments for the underlying function.
 */
class RateLimiter {
    /**
     * Instantiate a rate limiter.
     *
     * @param fn - The function to rate limit.
     *
     * @param limit - The rate limit; defaults to 500ms.
     */
    constructor(fn, limit = 500) {
        /**
         * Arguments for the underlying function.
         */
        this.args = undefined;
        /**
         * A promise that resolves on each successful invocation.
         */
        this.payload = null;
        this.limit = limit;
        this.poll = new Poll({
            auto: false,
            factory: async () => {
                const { args } = this;
                this.args = undefined;
                return fn(...args);
            },
            frequency: { backoff: false, interval: Poll.NEVER, max: Poll.NEVER },
            standby: 'never'
        });
        this.payload = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.PromiseDelegate();
        this.poll.ticked.connect((_, state) => {
            const { payload } = this;
            if (state.phase === 'resolved') {
                this.payload = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.PromiseDelegate();
                payload.resolve(state.payload);
                return;
            }
            if (state.phase === 'rejected' || state.phase === 'stopped') {
                this.payload = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.PromiseDelegate();
                payload.promise.catch(_ => undefined);
                payload.reject(state.payload);
                return;
            }
        }, this);
    }
    /**
     * Whether the rate limiter is disposed.
     */
    get isDisposed() {
        return this.payload === null;
    }
    /**
     * Disposes the rate limiter.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this.args = undefined;
        this.payload = null;
        this.poll.dispose();
    }
    /**
     * Stop the function if it is mid-flight.
     */
    async stop() {
        return this.poll.stop();
    }
}
/**
 * Wraps and debounces a function that can be called multiple times and only
 * executes the underlying function one `interval` after the last invocation.
 *
 * @typeparam T - The resolved type of the underlying function. Defaults to any.
 *
 * @typeparam U - The rejected type of the underlying function. Defaults to any.
 *
 * @typeparam V - Arguments for the underlying function. Defaults to any[].
 */
class Debouncer extends RateLimiter {
    /**
     * Invokes the function and only executes after rate limit has elapsed.
     * Each invocation resets the timer.
     */
    invoke(...args) {
        this.args = args;
        void this.poll.schedule({ interval: this.limit, phase: 'invoked' });
        return this.payload.promise;
    }
}
/**
 * Wraps and throttles a function that can be called multiple times and only
 * executes the underlying function once per `interval`.
 *
 * @typeparam T - The resolved type of the underlying function. Defaults to any.
 *
 * @typeparam U - The rejected type of the underlying function. Defaults to any.
 *
 * @typeparam V - Arguments for the underlying function. Defaults to any[].
 */
class Throttler extends RateLimiter {
    /**
     * Instantiate a throttler.
     *
     * @param fn - The function being throttled.
     *
     * @param options - Throttling configuration or throttling limit in ms.
     *
     * #### Notes
     * The `edge` defaults to `leading`; the `limit` defaults to `500`.
     */
    constructor(fn, options) {
        super(fn, typeof options === 'number' ? options : options && options.limit);
        this._trailing = false;
        if (typeof options !== 'number' && options && options.edge === 'trailing') {
            this._trailing = true;
        }
        this._interval = this._trailing ? this.limit : Poll.IMMEDIATE;
    }
    /**
     * Throttles function invocations if one is currently in flight.
     */
    invoke(...args) {
        const idle = this.poll.state.phase !== 'invoked';
        if (idle || this._trailing) {
            this.args = args;
        }
        if (idle) {
            void this.poll.schedule({ interval: this._interval, phase: 'invoked' });
        }
        return this.payload.promise;
    }
}


//# sourceMappingURL=index.es6.js.map


/***/ }),

/***/ 6134:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TerminalAPIClient = exports.TERMINAL_SERVICE_URL = void 0;
exports.isAvailable = isAvailable;
exports.startNew = startNew;
exports.listRunning = listRunning;
exports.shutdownTerminal = shutdownTerminal;
const coreutils_1 = __webpack_require__(8925);
const serverconnection_1 = __webpack_require__(2920);
/**
 * The url for the terminal service.
 */
exports.TERMINAL_SERVICE_URL = 'api/terminals';
/**
 * Whether the terminal service is available.
 */
function isAvailable() {
    const available = String(coreutils_1.PageConfig.getOption('terminalsAvailable'));
    return available.toLowerCase() === 'true';
}
/**
 * Start a new terminal session.
 *
 * @param settings - The server settings to use.
 *
 * @param name - The name of the target terminal.
 *
 * @param cwd - The path in which the terminal will start.
 *
 * @returns A promise that resolves with the session model.
 */
async function startNew(settings = serverconnection_1.ServerConnection.makeSettings(), name, cwd) {
    Private.errorIfNotAvailable();
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.TERMINAL_SERVICE_URL);
    const init = {
        method: 'POST',
        body: JSON.stringify({ name, cwd })
    };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    // TODO: Validate model
    return data;
}
/**
 * List the running terminal sessions.
 *
 * @param settings - The server settings to use.
 *
 * @returns A promise that resolves with the list of running session models.
 */
async function listRunning(settings = serverconnection_1.ServerConnection.makeSettings()) {
    Private.errorIfNotAvailable();
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.TERMINAL_SERVICE_URL);
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    if (!Array.isArray(data)) {
        throw new Error('Invalid terminal list');
    }
    // TODO: validate each model
    return data;
}
/**
 * Shut down a terminal session by name.
 *
 * @param name - The name of the target session.
 *
 * @param settings - The server settings to use.
 *
 * @returns A promise that resolves when the session is shut down.
 */
async function shutdownTerminal(name, settings = serverconnection_1.ServerConnection.makeSettings()) {
    var _a;
    Private.errorIfNotAvailable();
    const workspacesBase = coreutils_1.URLExt.join(settings.baseUrl, exports.TERMINAL_SERVICE_URL);
    const url = coreutils_1.URLExt.join(workspacesBase, name);
    if (!url.startsWith(workspacesBase)) {
        throw new Error('Can only be used for terminal requests');
    }
    const init = { method: 'DELETE' };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status === 404) {
        const data = await response.json();
        const msg = (_a = data.message) !== null && _a !== void 0 ? _a : `The terminal session "${name}"" does not exist on the server`;
        console.warn(msg);
    }
    else if (response.status !== 204) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
}
/**
 * The Terminal API client.
 *
 * #### Notes
 * Use this class to interact with the Jupyter Server Terminal API.
 * This class adheres to the Jupyter Server API endpoints.
 */
class TerminalAPIClient {
    /**
     * Create a new Terminal API client.
     */
    constructor(options = {}) {
        var _a;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * Whether terminals are available.
     */
    get isAvailable() {
        return isAvailable();
    }
    /**
     * Start a new terminal session.
     *
     * @param options - The options used to create the terminal.
     *
     * @returns A promise that resolves with the terminal session model.
     */
    async startNew(options = {}) {
        const { name, cwd } = options;
        return startNew(this.serverSettings, name, cwd);
    }
    /**
     * List the running terminal sessions.
     *
     * @returns A promise that resolves with the list of running session models.
     */
    async listRunning() {
        return listRunning(this.serverSettings);
    }
    /**
     * Shut down a terminal session by name.
     *
     * @param name - The name of the target session.
     *
     * @returns A promise that resolves when the session is shut down.
     */
    async shutdown(name) {
        return shutdownTerminal(name, this.serverSettings);
    }
}
exports.TerminalAPIClient = TerminalAPIClient;
/**
 * Namespace for private statics.
 */
var Private;
(function (Private) {
    /**
     * Throw an error if terminals are not available.
     */
    function errorIfNotAvailable() {
        if (!isAvailable()) {
            throw new Error('Terminals Unavailable');
        }
    }
    Private.errorIfNotAvailable = errorIfNotAvailable;
})(Private || (Private = {}));
//# sourceMappingURL=restapi.js.map

/***/ }),

/***/ 6492:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelSpecAPIClient = void 0;
exports.getSpecs = getSpecs;
const serverconnection_1 = __webpack_require__(2920);
const validate_1 = __webpack_require__(2598);
const coreutils_1 = __webpack_require__(8925);
/**
 * The url for the kernelspec service.
 */
const KERNELSPEC_SERVICE_URL = 'api/kernelspecs';
/**
 * Fetch all of the kernel specs.
 *
 * @param settings - The optional server settings.
 * @param useCache - Whether to use the cache. If false, always request.
 *
 * @returns A promise that resolves with the kernel specs.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernelspecs).
 */
async function getSpecs(settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, KERNELSPEC_SERVICE_URL);
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    return (0, validate_1.validateSpecModels)(data);
}
/**
 * The Kernel Spec API client.
 *
 * #### Notes
 * Use this class to interact with the Jupyter Server Kernel Spec API.
 * This class adheres to the Jupyter Server API endpoints.
 */
class KernelSpecAPIClient {
    /**
     * Create a new Kernel Spec API client.
     *
     * @param options - The options used to create the client.
     */
    constructor(options = {}) {
        var _a;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * Fetch all of the kernel specs.
     *
     * @returns A promise that resolves with the kernel specs.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernelspecs).
     */
    async get() {
        return getSpecs(this.serverSettings);
    }
}
exports.KernelSpecAPIClient = KernelSpecAPIClient;
//# sourceMappingURL=restapi.js.map

/***/ }),

/***/ 6573:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   AttachedProperty: () => (/* binding */ AttachedProperty)
/* harmony export */ });
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * @packageDocumentation
 * @module properties
 */
/**
 * A class which attaches a value to an external object.
 *
 * #### Notes
 * Attached properties are used to extend the state of an object with
 * semantic data from an unrelated class. They also encapsulate value
 * creation, coercion, and notification.
 *
 * Because attached property values are stored in a hash table, which
 * in turn is stored in a WeakMap keyed on the owner object, there is
 * non-trivial storage overhead involved in their use. The pattern is
 * therefore best used for the storage of rare data.
 */
class AttachedProperty {
    /**
     * Construct a new attached property.
     *
     * @param options - The options for initializing the property.
     */
    constructor(options) {
        this._pid = Private.nextPID();
        this.name = options.name;
        this._create = options.create;
        this._coerce = options.coerce || null;
        this._compare = options.compare || null;
        this._changed = options.changed || null;
    }
    /**
     * Get the current value of the property for a given owner.
     *
     * @param owner - The property owner of interest.
     *
     * @returns The current value of the property.
     *
     * #### Notes
     * If the value has not yet been set, the default value will be
     * computed and assigned as the current value of the property.
     */
    get(owner) {
        let value;
        let map = Private.ensureMap(owner);
        if (this._pid in map) {
            value = map[this._pid];
        }
        else {
            value = map[this._pid] = this._createValue(owner);
        }
        return value;
    }
    /**
     * Set the current value of the property for a given owner.
     *
     * @param owner - The property owner of interest.
     *
     * @param value - The value for the property.
     *
     * #### Notes
     * If the value has not yet been set, the default value will be
     * computed and used as the previous value for the comparison.
     */
    set(owner, value) {
        let oldValue;
        let map = Private.ensureMap(owner);
        if (this._pid in map) {
            oldValue = map[this._pid];
        }
        else {
            oldValue = map[this._pid] = this._createValue(owner);
        }
        let newValue = this._coerceValue(owner, value);
        this._maybeNotify(owner, oldValue, (map[this._pid] = newValue));
    }
    /**
     * Explicitly coerce the current property value for a given owner.
     *
     * @param owner - The property owner of interest.
     *
     * #### Notes
     * If the value has not yet been set, the default value will be
     * computed and used as the previous value for the comparison.
     */
    coerce(owner) {
        let oldValue;
        let map = Private.ensureMap(owner);
        if (this._pid in map) {
            oldValue = map[this._pid];
        }
        else {
            oldValue = map[this._pid] = this._createValue(owner);
        }
        let newValue = this._coerceValue(owner, oldValue);
        this._maybeNotify(owner, oldValue, (map[this._pid] = newValue));
    }
    /**
     * Get or create the default value for the given owner.
     */
    _createValue(owner) {
        let create = this._create;
        return create(owner);
    }
    /**
     * Coerce the value for the given owner.
     */
    _coerceValue(owner, value) {
        let coerce = this._coerce;
        return coerce ? coerce(owner, value) : value;
    }
    /**
     * Compare the old value and new value for equality.
     */
    _compareValue(oldValue, newValue) {
        let compare = this._compare;
        return compare ? compare(oldValue, newValue) : oldValue === newValue;
    }
    /**
     * Run the change notification if the given values are different.
     */
    _maybeNotify(owner, oldValue, newValue) {
        let changed = this._changed;
        if (changed && !this._compareValue(oldValue, newValue)) {
            changed(owner, oldValue, newValue);
        }
    }
}
/**
 * The namespace for the `AttachedProperty` class statics.
 */
(function (AttachedProperty) {
    /**
     * Clear the stored property data for the given owner.
     *
     * @param owner - The property owner of interest.
     *
     * #### Notes
     * This will clear all property values for the owner, but it will
     * **not** run the change notification for any of the properties.
     */
    function clearData(owner) {
        Private.ownerData.delete(owner);
    }
    AttachedProperty.clearData = clearData;
})(AttachedProperty || (AttachedProperty = {}));
/**
 * The namespace for the module implementation details.
 */
var Private;
(function (Private) {
    /**
     * A weak mapping of property owner to property map.
     */
    Private.ownerData = new WeakMap();
    /**
     * A function which computes successive unique property ids.
     */
    Private.nextPID = (() => {
        let id = 0;
        return () => {
            let rand = Math.random();
            let stem = `${rand}`.slice(2);
            return `pid-${stem}-${id++}`;
        };
    })();
    /**
     * Lookup the data map for the property owner.
     *
     * This will create the map if one does not already exist.
     */
    function ensureMap(owner) {
        let map = Private.ownerData.get(owner);
        if (map) {
            return map;
        }
        map = Object.create(null);
        Private.ownerData.set(owner, map);
        return map;
    }
    Private.ensureMap = ensureMap;
})(Private || (Private = {}));


//# sourceMappingURL=index.es6.js.map


/***/ }),

/***/ 6705:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'image';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f03e';
var svgPathData = 'M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.jb = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 6919:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SessionManager = void 0;
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const serverconnection_1 = __webpack_require__(2920);
const basemanager_1 = __webpack_require__(3867);
const default_1 = __webpack_require__(5341);
const restapi_1 = __webpack_require__(7570);
/**
 * An implementation of a session manager.
 */
class SessionManager extends basemanager_1.BaseManager {
    /**
     * Construct a new session manager.
     *
     * @param options - The default options for each session.
     */
    constructor(options) {
        var _a, _b;
        super(options);
        this._isReady = false;
        this._sessionConnections = new Set();
        this._models = new Map();
        this._runningChanged = new signaling_1.Signal(this);
        this._connectionFailure = new signaling_1.Signal(this);
        // We define these here so they bind `this` correctly
        this._connectToKernel = (options) => {
            return this._kernelManager.connectTo(options);
        };
        this._kernelManager = options.kernelManager;
        this._sessionAPIClient =
            (_a = options.sessionAPIClient) !== null && _a !== void 0 ? _a : new restapi_1.SessionAPIClient({ serverSettings: options.serverSettings });
        // Start model polling with exponential backoff.
        this._pollModels = new polling_1.Poll({
            auto: false,
            factory: () => this.requestRunning(),
            frequency: {
                interval: 10 * 1000,
                backoff: true,
                max: 300 * 1000
            },
            name: `@jupyterlab/services:SessionManager#models`,
            standby: (_b = options.standby) !== null && _b !== void 0 ? _b : 'when-hidden'
        });
        // Initialize internal data.
        this._ready = (async () => {
            await this._pollModels.start();
            await this._pollModels.tick;
            if (this._kernelManager.isActive) {
                await this._kernelManager.ready;
            }
            this._isReady = true;
        })();
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._ready;
    }
    /**
     * A signal emitted when the running sessions change.
     */
    get runningChanged() {
        return this._runningChanged;
    }
    /**
     * A signal emitted when there is a connection failure.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._models.clear();
        this._sessionConnections.forEach(x => x.dispose());
        this._pollModels.dispose();
        super.dispose();
    }
    /*
     * Connect to a running session.  See also [[connectToSession]].
     */
    connectTo(options) {
        const sessionConnection = new default_1.SessionConnection({
            ...options,
            connectToKernel: this._connectToKernel,
            serverSettings: this.serverSettings,
            sessionAPIClient: this._sessionAPIClient
        });
        this._onStarted(sessionConnection);
        if (!this._models.has(options.model.id)) {
            // We trust the user to connect to an existing session, but we verify
            // asynchronously.
            void this.refreshRunning().catch(() => {
                /* no-op */
            });
        }
        return sessionConnection;
    }
    /**
     * Create an iterator over the most recent running sessions.
     *
     * @returns A new iterator over the running sessions.
     */
    running() {
        return this._models.values();
    }
    /**
     * Force a refresh of the running sessions.
     *
     * @returns A promise that with the list of running sessions.
     *
     * #### Notes
     * This is not typically meant to be called by the user, since the
     * manager maintains its own internal state.
     */
    async refreshRunning() {
        await this._pollModels.refresh();
        await this._pollModels.tick;
    }
    /**
     * Start a new session.  See also [[startNewSession]].
     *
     * @param createOptions - Options for creating the session
     *
     * @param connectOptions - Options for connecting to the session
     */
    async startNew(createOptions, connectOptions = {}) {
        const model = await this._sessionAPIClient.startNew(createOptions);
        await this.refreshRunning();
        return this.connectTo({ ...connectOptions, model });
    }
    /**
     * Shut down a session by id.
     */
    async shutdown(id) {
        await this._sessionAPIClient.shutdown(id);
        await this.refreshRunning();
    }
    /**
     * Shut down all sessions.
     *
     * @returns A promise that resolves when all of the kernels are shut down.
     */
    async shutdownAll() {
        // Update the list of models to make sure our list is current.
        await this.refreshRunning();
        // Shut down all models.
        await Promise.all([...this._models.keys()].map(id => this._sessionAPIClient.shutdown(id)));
        // Update the list of models to clear out our state.
        await this.refreshRunning();
    }
    /**
     * Find a session associated with a path and stop it if it is the only session
     * using that kernel.
     *
     * @param path - The path in question.
     *
     * @returns A promise that resolves when the relevant sessions are stopped.
     */
    async stopIfNeeded(path) {
        try {
            const sessions = await this._sessionAPIClient.listRunning();
            const matches = sessions.filter(value => value.path === path);
            if (matches.length === 1) {
                const id = matches[0].id;
                await this.shutdown(id);
            }
        }
        catch (error) {
            /* Always succeed. */
        }
    }
    /**
     * Find a session by id.
     */
    async findById(id) {
        if (this._models.has(id)) {
            return this._models.get(id);
        }
        await this.refreshRunning();
        return this._models.get(id);
    }
    /**
     * Find a session by path.
     */
    async findByPath(path) {
        for (const m of this._models.values()) {
            if (m.path === path) {
                return m;
            }
        }
        await this.refreshRunning();
        for (const m of this._models.values()) {
            if (m.path === path) {
                return m;
            }
        }
        return undefined;
    }
    /**
     * Execute a request to the server to poll running kernels and update state.
     */
    async requestRunning() {
        var _a, _b;
        let models;
        try {
            models = await this._sessionAPIClient.listRunning();
        }
        catch (err) {
            // Handle network errors, as well as cases where we are on a
            // JupyterHub and the server is not running. JupyterHub returns a
            // 503 (<2.0) or 424 (>2.0) in that case.
            if (err instanceof serverconnection_1.ServerConnection.NetworkError ||
                ((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 503 ||
                ((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 424) {
                this._connectionFailure.emit(err);
            }
            throw err;
        }
        if (this.isDisposed) {
            return;
        }
        if (this._models.size === models.length &&
            models.every(model => {
                var _a, _b, _c, _d;
                const existing = this._models.get(model.id);
                if (!existing) {
                    return false;
                }
                return (((_a = existing.kernel) === null || _a === void 0 ? void 0 : _a.id) === ((_b = model.kernel) === null || _b === void 0 ? void 0 : _b.id) &&
                    ((_c = existing.kernel) === null || _c === void 0 ? void 0 : _c.name) === ((_d = model.kernel) === null || _d === void 0 ? void 0 : _d.name) &&
                    existing.name === model.name &&
                    existing.path === model.path &&
                    existing.type === model.type);
            })) {
            // Identical models list (presuming models does not contain duplicate
            // ids), so just return
            return;
        }
        this._models = new Map(models.map(x => [x.id, x]));
        this._sessionConnections.forEach(sc => {
            if (this._models.has(sc.id)) {
                sc.update(this._models.get(sc.id));
            }
            else {
                sc.dispose();
            }
        });
        this._runningChanged.emit(models);
    }
    /**
     * Handle a session starting.
     */
    _onStarted(sessionConnection) {
        this._sessionConnections.add(sessionConnection);
        sessionConnection.disposed.connect(this._onDisposed, this);
        sessionConnection.propertyChanged.connect(this._onChanged, this);
        sessionConnection.kernelChanged.connect(this._onChanged, this);
    }
    _onDisposed(sessionConnection) {
        this._sessionConnections.delete(sessionConnection);
        // A session termination emission could mean the server session is deleted,
        // or that the session JS object is disposed and the session still exists on
        // the server, so we refresh from the server to make sure we reflect the
        // server state.
        void this.refreshRunning().catch(() => {
            /* no-op */
        });
    }
    _onChanged() {
        void this.refreshRunning().catch(() => {
            /* no-op */
        });
    }
}
exports.SessionManager = SessionManager;
/**
 * The namespace for `SessionManager` class statics.
 */
(function (SessionManager) {
    /**
     * A no-op session manager to be used when starting sessions is not supported.
     */
    class NoopManager extends SessionManager {
        constructor() {
            super(...arguments);
            this._readyPromise = new Promise(() => {
                /* no-op */
            });
        }
        /**
         * Whether the manager is active.
         */
        get isActive() {
            return false;
        }
        /**
         * Used for testing.
         */
        get parentReady() {
            return super.ready;
        }
        /**
         * Start a new session - throw an error since it is not supported.
         */
        async startNew(createOptions, connectOptions = {}) {
            return Promise.reject(new Error('Not implemented in no-op Session Manager'));
        }
        /*
         * Connect to a running session - throw an error since it is not supported.
         */
        connectTo(options) {
            throw Error('Not implemented in no-op Session Manager');
        }
        /**
         * A promise that fulfills when the manager is ready (never).
         */
        get ready() {
            return this.parentReady.then(() => this._readyPromise);
        }
        /**
         * Shut down a session by id - throw an error since it is not supported.
         */
        async shutdown(id) {
            return Promise.reject(new Error('Not implemented in no-op Session Manager'));
        }
        /**
         * Execute a request to the server to poll running sessions and update state.
         */
        async requestRunning() {
            return Promise.resolve();
        }
    }
    SessionManager.NoopManager = NoopManager;
})(SessionManager || (exports.SessionManager = SessionManager = {}));
//# sourceMappingURL=manager.js.map

/***/ }),

/***/ 6994:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isAvailable = void 0;
const restapi_1 = __webpack_require__(6134);
Object.defineProperty(exports, "isAvailable", ({ enumerable: true, get: function () { return restapi_1.isAvailable; } }));
//# sourceMappingURL=terminal.js.map

/***/ }),

/***/ 7179:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.serialize = serialize;
exports.deserialize = deserialize;
const KernelMessage = __importStar(__webpack_require__(9909));
/**
 * Serialize a kernel message for transport.
 */
function serialize(msg, protocol = '') {
    switch (protocol) {
        case KernelMessage.supportedKernelWebSocketProtocols
            .v1KernelWebsocketJupyterOrg:
            return Private.serializeV1KernelWebsocketJupyterOrg(msg);
        default:
            return Private.serializeDefault(msg);
    }
}
/**
 * Deserialize and return the unpacked message.
 */
function deserialize(data, protocol = '') {
    switch (protocol) {
        case KernelMessage.supportedKernelWebSocketProtocols
            .v1KernelWebsocketJupyterOrg:
            return Private.deserializeV1KernelWebsocketJupyterOrg(data);
        default:
            return Private.deserializeDefault(data);
    }
}
var Private;
(function (Private) {
    /**
     * Deserialize and return the unpacked message.
     * Protocol `v1.kernel.websocket.jupyter.org`
     */
    function deserializeV1KernelWebsocketJupyterOrg(binMsg) {
        let msg;
        const data = new DataView(binMsg);
        const offsetNumber = Number(data.getBigUint64(0, true /* littleEndian */));
        let offsets = [];
        for (let i = 0; i < offsetNumber; i++) {
            // WARNING: we cast our 64-bit unsigned int to a number!
            // so offsets cannot index up to 2**64 bytes
            offsets.push(Number(data.getBigUint64(8 * (i + 1), true /* littleEndian */)));
        }
        const decoder = new TextDecoder('utf8');
        const channel = decoder.decode(binMsg.slice(offsets[0], offsets[1]));
        const header = JSON.parse(decoder.decode(binMsg.slice(offsets[1], offsets[2])));
        const parent_header = JSON.parse(decoder.decode(binMsg.slice(offsets[2], offsets[3])));
        const metadata = JSON.parse(decoder.decode(binMsg.slice(offsets[3], offsets[4])));
        const content = JSON.parse(decoder.decode(binMsg.slice(offsets[4], offsets[5])));
        let buffers = [];
        for (let i = 5; i < offsets.length - 1; i++) {
            buffers.push(new DataView(binMsg.slice(offsets[i], offsets[i + 1])));
        }
        msg = {
            channel,
            header,
            parent_header,
            metadata,
            content,
            buffers
        };
        return msg;
    }
    Private.deserializeV1KernelWebsocketJupyterOrg = deserializeV1KernelWebsocketJupyterOrg;
    /**
     * Serialize a kernel message for transport.
     * Protocol `v1.kernel.websocket.jupyter.org`
     */
    function serializeV1KernelWebsocketJupyterOrg(msg) {
        const header = JSON.stringify(msg.header);
        const parentHeader = msg.parent_header == null ? '{}' : JSON.stringify(msg.parent_header);
        const metadata = JSON.stringify(msg.metadata);
        const content = JSON.stringify(msg.content);
        const buffers = msg.buffers !== undefined ? msg.buffers : [];
        const offsetNumber = 1 + 4 + buffers.length + 1;
        let offsets = [];
        offsets.push(8 * (1 + offsetNumber));
        offsets.push(msg.channel.length + offsets[offsets.length - 1]);
        const encoder = new TextEncoder();
        const channelEncoded = encoder.encode(msg.channel);
        const headerEncoded = encoder.encode(header);
        const parentHeaderEncoded = encoder.encode(parentHeader);
        const metadataEncoded = encoder.encode(metadata);
        const contentEncoded = encoder.encode(content);
        const binMsgNoBuff = new Uint8Array(channelEncoded.length +
            headerEncoded.length +
            parentHeaderEncoded.length +
            metadataEncoded.length +
            contentEncoded.length);
        binMsgNoBuff.set(channelEncoded);
        binMsgNoBuff.set(headerEncoded, channelEncoded.length);
        binMsgNoBuff.set(parentHeaderEncoded, channelEncoded.length + headerEncoded.length);
        binMsgNoBuff.set(metadataEncoded, channelEncoded.length + headerEncoded.length + parentHeaderEncoded.length);
        binMsgNoBuff.set(contentEncoded, channelEncoded.length +
            headerEncoded.length +
            parentHeaderEncoded.length +
            metadataEncoded.length);
        for (let length of [
            headerEncoded.length,
            parentHeaderEncoded.length,
            metadataEncoded.length,
            contentEncoded.length
        ]) {
            offsets.push(length + offsets[offsets.length - 1]);
        }
        let buffersByteLength = 0;
        for (let buffer of buffers) {
            let length = buffer.byteLength;
            offsets.push(length + offsets[offsets.length - 1]);
            buffersByteLength += length;
        }
        const binMsg = new Uint8Array(8 * (1 + offsetNumber) + binMsgNoBuff.byteLength + buffersByteLength);
        const word = new ArrayBuffer(8);
        const data = new DataView(word);
        data.setBigUint64(0, BigInt(offsetNumber), true /* littleEndian */);
        binMsg.set(new Uint8Array(word), 0);
        for (let i = 0; i < offsets.length; i++) {
            data.setBigUint64(0, BigInt(offsets[i]), true /* littleEndian */);
            binMsg.set(new Uint8Array(word), 8 * (i + 1));
        }
        binMsg.set(binMsgNoBuff, offsets[0]);
        for (let i = 0; i < buffers.length; i++) {
            const buffer = buffers[i];
            binMsg.set(new Uint8Array(ArrayBuffer.isView(buffer) ? buffer.buffer : buffer), offsets[5 + i]);
        }
        return binMsg.buffer;
    }
    Private.serializeV1KernelWebsocketJupyterOrg = serializeV1KernelWebsocketJupyterOrg;
    /**
     * Deserialize and return the unpacked message.
     * Default protocol
     *
     * #### Notes
     * Handles JSON blob strings and binary messages.
     */
    function deserializeDefault(data) {
        let value;
        if (typeof data === 'string') {
            value = JSON.parse(data);
        }
        else {
            value = deserializeBinary(data);
        }
        return value;
    }
    Private.deserializeDefault = deserializeDefault;
    /**
     * Serialize a kernel message for transport.
     * Default protocol
     *
     * #### Notes
     * If there is binary content, an `ArrayBuffer` is returned,
     * otherwise the message is converted to a JSON string.
     */
    function serializeDefault(msg) {
        var _a;
        let value;
        if ((_a = msg.buffers) === null || _a === void 0 ? void 0 : _a.length) {
            value = serializeBinary(msg);
        }
        else {
            value = JSON.stringify(msg);
        }
        return value;
    }
    Private.serializeDefault = serializeDefault;
    /**
     * Deserialize a binary message to a Kernel Message.
     */
    function deserializeBinary(buf) {
        const data = new DataView(buf);
        // read the header: 1 + nbufs 32b integers
        const nbufs = data.getUint32(0);
        const offsets = [];
        if (nbufs < 2) {
            throw new Error('Invalid incoming Kernel Message');
        }
        for (let i = 1; i <= nbufs; i++) {
            offsets.push(data.getUint32(i * 4));
        }
        const jsonBytes = new Uint8Array(buf.slice(offsets[0], offsets[1]));
        const msg = JSON.parse(new TextDecoder('utf8').decode(jsonBytes));
        // the remaining chunks are stored as DataViews in msg.buffers
        msg.buffers = [];
        for (let i = 1; i < nbufs; i++) {
            const start = offsets[i];
            const stop = offsets[i + 1] || buf.byteLength;
            msg.buffers.push(new DataView(buf.slice(start, stop)));
        }
        return msg;
    }
    /**
     * Implement the binary serialization protocol.
     *
     * Serialize Kernel message to ArrayBuffer.
     */
    function serializeBinary(msg) {
        const offsets = [];
        const buffers = [];
        const encoder = new TextEncoder();
        let origBuffers = [];
        if (msg.buffers !== undefined) {
            origBuffers = msg.buffers;
            delete msg['buffers'];
        }
        const jsonUtf8 = encoder.encode(JSON.stringify(msg));
        buffers.push(jsonUtf8.buffer);
        for (let i = 0; i < origBuffers.length; i++) {
            // msg.buffers elements could be either views or ArrayBuffers
            // buffers elements are ArrayBuffers
            const b = origBuffers[i];
            buffers.push(ArrayBuffer.isView(b) ? b.buffer : b);
        }
        const nbufs = buffers.length;
        offsets.push(4 * (nbufs + 1));
        for (let i = 0; i + 1 < buffers.length; i++) {
            offsets.push(offsets[offsets.length - 1] + buffers[i].byteLength);
        }
        const msgBuf = new Uint8Array(offsets[offsets.length - 1] + buffers[buffers.length - 1].byteLength);
        // use DataView.setUint32 for network byte-order
        const view = new DataView(msgBuf.buffer);
        // write nbufs to first 4 bytes
        view.setUint32(0, nbufs);
        // write offsets to next 4 * nbufs bytes
        for (let i = 0; i < offsets.length; i++) {
            view.setUint32(4 * (i + 1), offsets[i]);
        }
        // write all the buffers at their respective offsets
        for (let i = 0; i < buffers.length; i++) {
            msgBuf.set(new Uint8Array(buffers[i]), offsets[i]);
        }
        return msgBuf.buffer;
    }
})(Private || (Private = {}));
//# sourceMappingURL=serialize.js.map

/***/ }),

/***/ 7184:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'table';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f0ce';
var svgPathData = 'M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64v-96h160v96zm0-160H64v-96h160v96zm224 160H288v-96h160v96zm0-160H288v-96h160v96z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.w9 = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 7240:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
//# sourceMappingURL=session.js.map

/***/ }),

/***/ 7251:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

/*
 * Copyright (c) Jupyter Development Team.
 * Distributed under the terms of the Modified BSD License.
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports["default"] = WebSocket;
//# sourceMappingURL=ws.js.map

/***/ }),

/***/ 7290:
/***/ ((module) => {

/*!
 * wavesurfer.js 5.2.0 (2021-08-16)
 * https://wavesurfer-js.org
 * @license BSD-3-Clause
 */
(function webpackUniversalModuleDefinition(root, factory) {
	if(true)
		module.exports = factory();
	else {}
})(self, function() {
return /******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/drawer.canvasentry.js":
/*!***********************************!*\
  !*** ./src/drawer.canvasentry.js ***!
  \***********************************/
/***/ ((module, exports, __nested_webpack_require_747__) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var _style = _interopRequireDefault(__nested_webpack_require_747__(/*! ./util/style */ "./src/util/style.js"));

var _getId = _interopRequireDefault(__nested_webpack_require_747__(/*! ./util/get-id */ "./src/util/get-id.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/**
 * The `CanvasEntry` class represents an element consisting of a wave `canvas`
 * and an (optional) progress wave `canvas`.
 *
 * The `MultiCanvas` renderer uses one or more `CanvasEntry` instances to
 * render a waveform, depending on the zoom level.
 */
var CanvasEntry = /*#__PURE__*/function () {
  function CanvasEntry() {
    _classCallCheck(this, CanvasEntry);

    /**
     * The wave node
     *
     * @type {HTMLCanvasElement}
     */
    this.wave = null;
    /**
     * The wave canvas rendering context
     *
     * @type {CanvasRenderingContext2D}
     */

    this.waveCtx = null;
    /**
     * The (optional) progress wave node
     *
     * @type {HTMLCanvasElement}
     */

    this.progress = null;
    /**
     * The (optional) progress wave canvas rendering context
     *
     * @type {CanvasRenderingContext2D}
     */

    this.progressCtx = null;
    /**
     * Start of the area the canvas should render, between 0 and 1
     *
     * @type {number}
     */

    this.start = 0;
    /**
     * End of the area the canvas should render, between 0 and 1
     *
     * @type {number}
     */

    this.end = 1;
    /**
     * Unique identifier for this entry
     *
     * @type {string}
     */

    this.id = (0, _getId.default)(typeof this.constructor.name !== 'undefined' ? this.constructor.name.toLowerCase() + '_' : 'canvasentry_');
    /**
     * Canvas 2d context attributes
     *
     * @type {object}
     */

    this.canvasContextAttributes = {};
  }
  /**
   * Store the wave canvas element and create the 2D rendering context
   *
   * @param {HTMLCanvasElement} element The wave `canvas` element.
   */


  _createClass(CanvasEntry, [{
    key: "initWave",
    value: function initWave(element) {
      this.wave = element;
      this.waveCtx = this.wave.getContext('2d', this.canvasContextAttributes);
    }
    /**
     * Store the progress wave canvas element and create the 2D rendering
     * context
     *
     * @param {HTMLCanvasElement} element The progress wave `canvas` element.
     */

  }, {
    key: "initProgress",
    value: function initProgress(element) {
      this.progress = element;
      this.progressCtx = this.progress.getContext('2d', this.canvasContextAttributes);
    }
    /**
     * Update the dimensions
     *
     * @param {number} elementWidth Width of the entry
     * @param {number} totalWidth Total width of the multi canvas renderer
     * @param {number} width The new width of the element
     * @param {number} height The new height of the element
     */

  }, {
    key: "updateDimensions",
    value: function updateDimensions(elementWidth, totalWidth, width, height) {
      // where the canvas starts and ends in the waveform, represented as a
      // decimal between 0 and 1
      this.start = this.wave.offsetLeft / totalWidth || 0;
      this.end = this.start + elementWidth / totalWidth; // set wave canvas dimensions

      this.wave.width = width;
      this.wave.height = height;
      var elementSize = {
        width: elementWidth + 'px'
      };
      (0, _style.default)(this.wave, elementSize);

      if (this.hasProgressCanvas) {
        // set progress canvas dimensions
        this.progress.width = width;
        this.progress.height = height;
        (0, _style.default)(this.progress, elementSize);
      }
    }
    /**
     * Clear the wave and progress rendering contexts
     */

  }, {
    key: "clearWave",
    value: function clearWave() {
      // wave
      this.waveCtx.clearRect(0, 0, this.waveCtx.canvas.width, this.waveCtx.canvas.height); // progress

      if (this.hasProgressCanvas) {
        this.progressCtx.clearRect(0, 0, this.progressCtx.canvas.width, this.progressCtx.canvas.height);
      }
    }
    /**
     * Set the fill styles for wave and progress
     *
     * @param {string} waveColor Fill color for the wave canvas
     * @param {?string} progressColor Fill color for the progress canvas
     */

  }, {
    key: "setFillStyles",
    value: function setFillStyles(waveColor, progressColor) {
      this.waveCtx.fillStyle = waveColor;

      if (this.hasProgressCanvas) {
        this.progressCtx.fillStyle = progressColor;
      }
    }
    /**
     * Set the canvas transforms for wave and progress
     *
     * @param {boolean} vertical Whether to render vertically
     */

  }, {
    key: "applyCanvasTransforms",
    value: function applyCanvasTransforms(vertical) {
      if (vertical) {
        // Reflect the waveform across the line y = -x
        this.waveCtx.setTransform(0, 1, 1, 0, 0, 0);

        if (this.hasProgressCanvas) {
          this.progressCtx.setTransform(0, 1, 1, 0, 0, 0);
        }
      }
    }
    /**
     * Draw a rectangle for wave and progress
     *
     * @param {number} x X start position
     * @param {number} y Y start position
     * @param {number} width Width of the rectangle
     * @param {number} height Height of the rectangle
     * @param {number} radius Radius of the rectangle
     */

  }, {
    key: "fillRects",
    value: function fillRects(x, y, width, height, radius) {
      this.fillRectToContext(this.waveCtx, x, y, width, height, radius);

      if (this.hasProgressCanvas) {
        this.fillRectToContext(this.progressCtx, x, y, width, height, radius);
      }
    }
    /**
     * Draw the actual rectangle on a `canvas` element
     *
     * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
     * @param {number} x X start position
     * @param {number} y Y start position
     * @param {number} width Width of the rectangle
     * @param {number} height Height of the rectangle
     * @param {number} radius Radius of the rectangle
     */

  }, {
    key: "fillRectToContext",
    value: function fillRectToContext(ctx, x, y, width, height, radius) {
      if (!ctx) {
        return;
      }

      if (radius) {
        this.drawRoundedRect(ctx, x, y, width, height, radius);
      } else {
        ctx.fillRect(x, y, width, height);
      }
    }
    /**
     * Draw a rounded rectangle on Canvas
     *
     * @param {CanvasRenderingContext2D} ctx Canvas context
     * @param {number} x X-position of the rectangle
     * @param {number} y Y-position of the rectangle
     * @param {number} width Width of the rectangle
     * @param {number} height Height of the rectangle
     * @param {number} radius Radius of the rectangle
     *
     * @return {void}
     * @example drawRoundedRect(ctx, 50, 50, 5, 10, 3)
     */

  }, {
    key: "drawRoundedRect",
    value: function drawRoundedRect(ctx, x, y, width, height, radius) {
      if (height === 0) {
        return;
      } // peaks are float values from -1 to 1. Use absolute height values in
      // order to correctly calculate rounded rectangle coordinates


      if (height < 0) {
        height *= -1;
        y -= height;
      }

      ctx.beginPath();
      ctx.moveTo(x + radius, y);
      ctx.lineTo(x + width - radius, y);
      ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
      ctx.lineTo(x + width, y + height - radius);
      ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
      ctx.lineTo(x + radius, y + height);
      ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
      ctx.lineTo(x, y + radius);
      ctx.quadraticCurveTo(x, y, x + radius, y);
      ctx.closePath();
      ctx.fill();
    }
    /**
     * Render the actual wave and progress lines
     *
     * @param {number[]} peaks Array with peaks data
     * @param {number} absmax Maximum peak value (absolute)
     * @param {number} halfH Half the height of the waveform
     * @param {number} offsetY Offset to the top
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that
     * should be rendered
     */

  }, {
    key: "drawLines",
    value: function drawLines(peaks, absmax, halfH, offsetY, start, end) {
      this.drawLineToContext(this.waveCtx, peaks, absmax, halfH, offsetY, start, end);

      if (this.hasProgressCanvas) {
        this.drawLineToContext(this.progressCtx, peaks, absmax, halfH, offsetY, start, end);
      }
    }
    /**
     * Render the actual waveform line on a `canvas` element
     *
     * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
     * @param {number[]} peaks Array with peaks data
     * @param {number} absmax Maximum peak value (absolute)
     * @param {number} halfH Half the height of the waveform
     * @param {number} offsetY Offset to the top
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that
     * should be rendered
     */

  }, {
    key: "drawLineToContext",
    value: function drawLineToContext(ctx, peaks, absmax, halfH, offsetY, start, end) {
      if (!ctx) {
        return;
      }

      var length = peaks.length / 2;
      var first = Math.round(length * this.start); // use one more peak value to make sure we join peaks at ends -- unless,
      // of course, this is the last canvas

      var last = Math.round(length * this.end) + 1;
      var canvasStart = first;
      var canvasEnd = last;
      var scale = this.wave.width / (canvasEnd - canvasStart - 1); // optimization

      var halfOffset = halfH + offsetY;
      var absmaxHalf = absmax / halfH;
      ctx.beginPath();
      ctx.moveTo((canvasStart - first) * scale, halfOffset);
      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf));
      var i, peak, h;

      for (i = canvasStart; i < canvasEnd; i++) {
        peak = peaks[2 * i] || 0;
        h = Math.round(peak / absmaxHalf);
        ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);
      } // draw the bottom edge going backwards, to make a single
      // closed hull to fill


      var j = canvasEnd - 1;

      for (j; j >= canvasStart; j--) {
        peak = peaks[2 * j + 1] || 0;
        h = Math.round(peak / absmaxHalf);
        ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - h);
      }

      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf));
      ctx.closePath();
      ctx.fill();
    }
    /**
     * Destroys this entry
     */

  }, {
    key: "destroy",
    value: function destroy() {
      this.waveCtx = null;
      this.wave = null;
      this.progressCtx = null;
      this.progress = null;
    }
    /**
     * Return image data of the wave `canvas` element
     *
     * When using a `type` of `'blob'`, this will return a `Promise` that
     * resolves with a `Blob` instance.
     *
     * @param {string} format='image/png' An optional value of a format type.
     * @param {number} quality=0.92 An optional value between 0 and 1.
     * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
     * @return {string|Promise} When using the default `'dataURL'` `type` this
     * returns a data URL. When using the `'blob'` `type` this returns a
     * `Promise` that resolves with a `Blob` instance.
     */

  }, {
    key: "getImage",
    value: function getImage(format, quality, type) {
      var _this = this;

      if (type === 'blob') {
        return new Promise(function (resolve) {
          _this.wave.toBlob(resolve, format, quality);
        });
      } else if (type === 'dataURL') {
        return this.wave.toDataURL(format, quality);
      }
    }
  }]);

  return CanvasEntry;
}();

exports.default = CanvasEntry;
module.exports = exports.default;

/***/ }),

/***/ "./src/drawer.js":
/*!***********************!*\
  !*** ./src/drawer.js ***!
  \***********************/
/***/ ((module, exports, __nested_webpack_require_13686__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var util = _interopRequireWildcard(__nested_webpack_require_13686__(/*! ./util */ "./src/util/index.js"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

/**
 * Parent class for renderers
 *
 * @extends {Observer}
 */
var Drawer = /*#__PURE__*/function (_util$Observer) {
  _inherits(Drawer, _util$Observer);

  var _super = _createSuper(Drawer);

  /**
   * @param {HTMLElement} container The container node of the wavesurfer instance
   * @param {WavesurferParams} params The wavesurfer initialisation options
   */
  function Drawer(container, params) {
    var _this;

    _classCallCheck(this, Drawer);

    _this = _super.call(this);
    _this.container = util.withOrientation(container, params.vertical);
    /**
     * @type {WavesurferParams}
     */

    _this.params = params;
    /**
     * The width of the renderer
     * @type {number}
     */

    _this.width = 0;
    /**
     * The height of the renderer
     * @type {number}
     */

    _this.height = params.height * _this.params.pixelRatio;
    _this.lastPos = 0;
    /**
     * The `<wave>` element which is added to the container
     * @type {HTMLElement}
     */

    _this.wrapper = null;
    return _this;
  }
  /**
   * Alias of `util.style`
   *
   * @param {HTMLElement} el The element that the styles will be applied to
   * @param {Object} styles The map of propName: attribute, both are used as-is
   * @return {HTMLElement} el
   */


  _createClass(Drawer, [{
    key: "style",
    value: function style(el, styles) {
      return util.style(el, styles);
    }
    /**
     * Create the wrapper `<wave>` element, style it and set up the events for
     * interaction
     */

  }, {
    key: "createWrapper",
    value: function createWrapper() {
      this.wrapper = util.withOrientation(this.container.appendChild(document.createElement('wave')), this.params.vertical);
      this.style(this.wrapper, {
        display: 'block',
        position: 'relative',
        userSelect: 'none',
        webkitUserSelect: 'none',
        height: this.params.height + 'px'
      });

      if (this.params.fillParent || this.params.scrollParent) {
        this.style(this.wrapper, {
          width: '100%',
          overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',
          overflowY: 'hidden'
        });
      }

      this.setupWrapperEvents();
    }
    /**
     * Handle click event
     *
     * @param {Event} e Click event
     * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`
     * @return {number} Playback position from 0 to 1
     */

  }, {
    key: "handleEvent",
    value: function handleEvent(e, noPrevent) {
      !noPrevent && e.preventDefault();
      var clientX = util.withOrientation(e.targetTouches ? e.targetTouches[0] : e, this.params.vertical).clientX;
      var bbox = this.wrapper.getBoundingClientRect();
      var nominalWidth = this.width;
      var parentWidth = this.getWidth();
      var progressPixels = this.getProgressPixels(bbox, clientX);
      var progress;

      if (!this.params.fillParent && nominalWidth < parentWidth) {
        progress = progressPixels * (this.params.pixelRatio / nominalWidth) || 0;
      } else {
        progress = (progressPixels + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0;
      }

      return util.clamp(progress, 0, 1);
    }
  }, {
    key: "getProgressPixels",
    value: function getProgressPixels(wrapperBbox, clientX) {
      if (this.params.rtl) {
        return wrapperBbox.right - clientX;
      } else {
        return clientX - wrapperBbox.left;
      }
    }
  }, {
    key: "setupWrapperEvents",
    value: function setupWrapperEvents() {
      var _this2 = this;

      this.wrapper.addEventListener('click', function (e) {
        var orientedEvent = util.withOrientation(e, _this2.params.vertical);
        var scrollbarHeight = _this2.wrapper.offsetHeight - _this2.wrapper.clientHeight;

        if (scrollbarHeight !== 0) {
          // scrollbar is visible.  Check if click was on it
          var bbox = _this2.wrapper.getBoundingClientRect();

          if (orientedEvent.clientY >= bbox.bottom - scrollbarHeight) {
            // ignore mousedown as it was on the scrollbar
            return;
          }
        }

        if (_this2.params.interact) {
          _this2.fireEvent('click', e, _this2.handleEvent(e));
        }
      });
      this.wrapper.addEventListener('dblclick', function (e) {
        if (_this2.params.interact) {
          _this2.fireEvent('dblclick', e, _this2.handleEvent(e));
        }
      });
      this.wrapper.addEventListener('scroll', function (e) {
        return _this2.fireEvent('scroll', e);
      });
    }
    /**
     * Draw peaks on the canvas
     *
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
     * for split channel rendering
     * @param {number} length The width of the area that should be drawn
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that should be
     * rendered
     */

  }, {
    key: "drawPeaks",
    value: function drawPeaks(peaks, length, start, end) {
      if (!this.setWidth(length)) {
        this.clearWave();
      }

      this.params.barWidth ? this.drawBars(peaks, 0, start, end) : this.drawWave(peaks, 0, start, end);
    }
    /**
     * Scroll to the beginning
     */

  }, {
    key: "resetScroll",
    value: function resetScroll() {
      if (this.wrapper !== null) {
        this.wrapper.scrollLeft = 0;
      }
    }
    /**
     * Recenter the view-port at a certain percent of the waveform
     *
     * @param {number} percent Value from 0 to 1 on the waveform
     */

  }, {
    key: "recenter",
    value: function recenter(percent) {
      var position = this.wrapper.scrollWidth * percent;
      this.recenterOnPosition(position, true);
    }
    /**
     * Recenter the view-port on a position, either scroll there immediately or
     * in steps of 5 pixels
     *
     * @param {number} position X-offset in pixels
     * @param {boolean} immediate Set to true to immediately scroll somewhere
     */

  }, {
    key: "recenterOnPosition",
    value: function recenterOnPosition(position, immediate) {
      var scrollLeft = this.wrapper.scrollLeft;
      var half = ~~(this.wrapper.clientWidth / 2);
      var maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
      var target = position - half;
      var offset = target - scrollLeft;

      if (maxScroll == 0) {
        // no need to continue if scrollbar is not there
        return;
      } // if the cursor is currently visible...


      if (!immediate && -half <= offset && offset < half) {
        // set rate at which waveform is centered
        var rate = this.params.autoCenterRate; // make rate depend on width of view and length of waveform

        rate /= half;
        rate *= maxScroll;
        offset = Math.max(-rate, Math.min(rate, offset));
        target = scrollLeft + offset;
      } // limit target to valid range (0 to maxScroll)


      target = Math.max(0, Math.min(maxScroll, target)); // no use attempting to scroll if we're not moving

      if (target != scrollLeft) {
        this.wrapper.scrollLeft = target;
      }
    }
    /**
     * Get the current scroll position in pixels
     *
     * @return {number} Horizontal scroll position in pixels
     */

  }, {
    key: "getScrollX",
    value: function getScrollX() {
      var x = 0;

      if (this.wrapper) {
        var pixelRatio = this.params.pixelRatio;
        x = Math.round(this.wrapper.scrollLeft * pixelRatio); // In cases of elastic scroll (safari with mouse wheel) you can
        // scroll beyond the limits of the container
        // Calculate and floor the scrollable extent to make sure an out
        // of bounds value is not returned
        // Ticket #1312

        if (this.params.scrollParent) {
          var maxScroll = ~~(this.wrapper.scrollWidth * pixelRatio - this.getWidth());
          x = Math.min(maxScroll, Math.max(0, x));
        }
      }

      return x;
    }
    /**
     * Get the width of the container
     *
     * @return {number} The width of the container
     */

  }, {
    key: "getWidth",
    value: function getWidth() {
      return Math.round(this.container.clientWidth * this.params.pixelRatio);
    }
    /**
     * Set the width of the container
     *
     * @param {number} width The new width of the container
     * @return {boolean} Whether the width of the container was updated or not
     */

  }, {
    key: "setWidth",
    value: function setWidth(width) {
      if (this.width == width) {
        return false;
      }

      this.width = width;

      if (this.params.fillParent || this.params.scrollParent) {
        this.style(this.wrapper, {
          width: ''
        });
      } else {
        var newWidth = ~~(this.width / this.params.pixelRatio) + 'px';
        this.style(this.wrapper, {
          width: newWidth
        });
      }

      this.updateSize();
      return true;
    }
    /**
     * Set the height of the container
     *
     * @param {number} height The new height of the container.
     * @return {boolean} Whether the height of the container was updated or not
     */

  }, {
    key: "setHeight",
    value: function setHeight(height) {
      if (height == this.height) {
        return false;
      }

      this.height = height;
      this.style(this.wrapper, {
        height: ~~(this.height / this.params.pixelRatio) + 'px'
      });
      this.updateSize();
      return true;
    }
    /**
     * Called by wavesurfer when progress should be rendered
     *
     * @param {number} progress From 0 to 1
     */

  }, {
    key: "progress",
    value: function progress(_progress) {
      var minPxDelta = 1 / this.params.pixelRatio;
      var pos = Math.round(_progress * this.width) * minPxDelta;

      if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {
        this.lastPos = pos;

        if (this.params.scrollParent && this.params.autoCenter) {
          var newPos = ~~(this.wrapper.scrollWidth * _progress);
          this.recenterOnPosition(newPos, this.params.autoCenterImmediately);
        }

        this.updateProgress(pos);
      }
    }
    /**
     * This is called when wavesurfer is destroyed
     */

  }, {
    key: "destroy",
    value: function destroy() {
      this.unAll();

      if (this.wrapper) {
        if (this.wrapper.parentNode == this.container.domElement) {
          this.container.removeChild(this.wrapper.domElement);
        }

        this.wrapper = null;
      }
    }
    /* Renderer-specific methods */

    /**
     * Called after cursor related params have changed.
     *
     * @abstract
     */

  }, {
    key: "updateCursor",
    value: function updateCursor() {}
    /**
     * Called when the size of the container changes so the renderer can adjust
     *
     * @abstract
     */

  }, {
    key: "updateSize",
    value: function updateSize() {}
    /**
     * Draw a waveform with bars
     *
     * @abstract
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
     * rendering
     * @param {number} channelIndex The index of the current channel. Normally
     * should be 0
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that should be
     * rendered
     */

  }, {
    key: "drawBars",
    value: function drawBars(peaks, channelIndex, start, end) {}
    /**
     * Draw a waveform
     *
     * @abstract
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
     * rendering
     * @param {number} channelIndex The index of the current channel. Normally
     * should be 0
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that should be
     * rendered
     */

  }, {
    key: "drawWave",
    value: function drawWave(peaks, channelIndex, start, end) {}
    /**
     * Clear the waveform
     *
     * @abstract
     */

  }, {
    key: "clearWave",
    value: function clearWave() {}
    /**
     * Render the new progress
     *
     * @abstract
     * @param {number} position X-Offset of progress position in pixels
     */

  }, {
    key: "updateProgress",
    value: function updateProgress(position) {}
  }]);

  return Drawer;
}(util.Observer);

exports.default = Drawer;
module.exports = exports.default;

/***/ }),

/***/ "./src/drawer.multicanvas.js":
/*!***********************************!*\
  !*** ./src/drawer.multicanvas.js ***!
  \***********************************/
/***/ ((module, exports, __nested_webpack_require_30815__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var _drawer = _interopRequireDefault(__nested_webpack_require_30815__(/*! ./drawer */ "./src/drawer.js"));

var util = _interopRequireWildcard(__nested_webpack_require_30815__(/*! ./util */ "./src/util/index.js"));

var _drawer2 = _interopRequireDefault(__nested_webpack_require_30815__(/*! ./drawer.canvasentry */ "./src/drawer.canvasentry.js"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

/**
 * MultiCanvas renderer for wavesurfer. Is currently the default and sole
 * builtin renderer.
 *
 * A `MultiCanvas` consists of one or more `CanvasEntry` instances, depending
 * on the zoom level.
 */
var MultiCanvas = /*#__PURE__*/function (_Drawer) {
  _inherits(MultiCanvas, _Drawer);

  var _super = _createSuper(MultiCanvas);

  /**
   * @param {HTMLElement} container The container node of the wavesurfer instance
   * @param {WavesurferParams} params The wavesurfer initialisation options
   */
  function MultiCanvas(container, params) {
    var _this;

    _classCallCheck(this, MultiCanvas);

    _this = _super.call(this, container, params);
    /**
     * @type {number}
     */

    _this.maxCanvasWidth = params.maxCanvasWidth;
    /**
     * @type {number}
     */

    _this.maxCanvasElementWidth = Math.round(params.maxCanvasWidth / params.pixelRatio);
    /**
     * Whether or not the progress wave is rendered. If the `waveColor`
     * and `progressColor` are the same color it is not.
     *
     * @type {boolean}
     */

    _this.hasProgressCanvas = params.waveColor != params.progressColor;
    /**
     * @type {number}
     */

    _this.halfPixel = 0.5 / params.pixelRatio;
    /**
     * List of `CanvasEntry` instances.
     *
     * @type {Array}
     */

    _this.canvases = [];
    /**
     * @type {HTMLElement}
     */

    _this.progressWave = null;
    /**
     * Class used to generate entries.
     *
     * @type {function}
     */

    _this.EntryClass = _drawer2.default;
    /**
     * Canvas 2d context attributes.
     *
     * @type {object}
     */

    _this.canvasContextAttributes = params.drawingContextAttributes;
    /**
     * Overlap added between entries to prevent vertical white stripes
     * between `canvas` elements.
     *
     * @type {number}
     */

    _this.overlap = 2 * Math.ceil(params.pixelRatio / 2);
    /**
     * The radius of the wave bars. Makes bars rounded
     *
     * @type {number}
     */

    _this.barRadius = params.barRadius || 0;
    /**
     * Whether to render the waveform vertically. Defaults to false.
     *
     * @type {boolean}
     */

    _this.vertical = params.vertical;
    return _this;
  }
  /**
   * Initialize the drawer
   */


  _createClass(MultiCanvas, [{
    key: "init",
    value: function init() {
      this.createWrapper();
      this.createElements();
    }
    /**
     * Create the canvas elements and style them
     *
     */

  }, {
    key: "createElements",
    value: function createElements() {
      this.progressWave = util.withOrientation(this.wrapper.appendChild(document.createElement('wave')), this.params.vertical);
      this.style(this.progressWave, {
        position: 'absolute',
        zIndex: 3,
        left: 0,
        top: 0,
        bottom: 0,
        overflow: 'hidden',
        width: '0',
        display: 'none',
        boxSizing: 'border-box',
        borderRightStyle: 'solid',
        pointerEvents: 'none'
      });
      this.addCanvas();
      this.updateCursor();
    }
    /**
     * Update cursor style
     */

  }, {
    key: "updateCursor",
    value: function updateCursor() {
      this.style(this.progressWave, {
        borderRightWidth: this.params.cursorWidth + 'px',
        borderRightColor: this.params.cursorColor
      });
    }
    /**
     * Adjust to the updated size by adding or removing canvases
     */

  }, {
    key: "updateSize",
    value: function updateSize() {
      var _this2 = this;

      var totalWidth = Math.round(this.width / this.params.pixelRatio);
      var requiredCanvases = Math.ceil(totalWidth / (this.maxCanvasElementWidth + this.overlap)); // add required canvases

      while (this.canvases.length < requiredCanvases) {
        this.addCanvas();
      } // remove older existing canvases, if any


      while (this.canvases.length > requiredCanvases) {
        this.removeCanvas();
      }

      var canvasWidth = this.maxCanvasWidth + this.overlap;
      var lastCanvas = this.canvases.length - 1;
      this.canvases.forEach(function (entry, i) {
        if (i == lastCanvas) {
          canvasWidth = _this2.width - _this2.maxCanvasWidth * lastCanvas;
        }

        _this2.updateDimensions(entry, canvasWidth, _this2.height);

        entry.clearWave();
      });
    }
    /**
     * Add a canvas to the canvas list
     *
     */

  }, {
    key: "addCanvas",
    value: function addCanvas() {
      var entry = new this.EntryClass();
      entry.canvasContextAttributes = this.canvasContextAttributes;
      entry.hasProgressCanvas = this.hasProgressCanvas;
      entry.halfPixel = this.halfPixel;
      var leftOffset = this.maxCanvasElementWidth * this.canvases.length; // wave

      var wave = util.withOrientation(this.wrapper.appendChild(document.createElement('canvas')), this.params.vertical);
      this.style(wave, {
        position: 'absolute',
        zIndex: 2,
        left: leftOffset + 'px',
        top: 0,
        bottom: 0,
        height: '100%',
        pointerEvents: 'none'
      });
      entry.initWave(wave); // progress

      if (this.hasProgressCanvas) {
        var progress = util.withOrientation(this.progressWave.appendChild(document.createElement('canvas')), this.params.vertical);
        this.style(progress, {
          position: 'absolute',
          left: leftOffset + 'px',
          top: 0,
          bottom: 0,
          height: '100%'
        });
        entry.initProgress(progress);
      }

      this.canvases.push(entry);
    }
    /**
     * Pop single canvas from the list
     *
     */

  }, {
    key: "removeCanvas",
    value: function removeCanvas() {
      var lastEntry = this.canvases[this.canvases.length - 1]; // wave

      lastEntry.wave.parentElement.removeChild(lastEntry.wave.domElement); // progress

      if (this.hasProgressCanvas) {
        lastEntry.progress.parentElement.removeChild(lastEntry.progress.domElement);
      } // cleanup


      if (lastEntry) {
        lastEntry.destroy();
        lastEntry = null;
      }

      this.canvases.pop();
    }
    /**
     * Update the dimensions of a canvas element
     *
     * @param {CanvasEntry} entry Target entry
     * @param {number} width The new width of the element
     * @param {number} height The new height of the element
     */

  }, {
    key: "updateDimensions",
    value: function updateDimensions(entry, width, height) {
      var elementWidth = Math.round(width / this.params.pixelRatio);
      var totalWidth = Math.round(this.width / this.params.pixelRatio); // update canvas dimensions

      entry.updateDimensions(elementWidth, totalWidth, width, height); // style element

      this.style(this.progressWave, {
        display: 'block'
      });
    }
    /**
     * Clear the whole multi-canvas
     */

  }, {
    key: "clearWave",
    value: function clearWave() {
      var _this3 = this;

      util.frame(function () {
        _this3.canvases.forEach(function (entry) {
          return entry.clearWave();
        });
      })();
    }
    /**
     * Draw a waveform with bars
     *
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
     * for split channel rendering
     * @param {number} channelIndex The index of the current channel. Normally
     * should be 0. Must be an integer.
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that should be
     * rendered
     * @returns {void}
     */

  }, {
    key: "drawBars",
    value: function drawBars(peaks, channelIndex, start, end) {
      var _this4 = this;

      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref) {
        var absmax = _ref.absmax,
            hasMinVals = _ref.hasMinVals,
            height = _ref.height,
            offsetY = _ref.offsetY,
            halfH = _ref.halfH,
            peaks = _ref.peaks,
            ch = _ref.channelIndex;

        // if drawBars was called within ws.empty we don't pass a start and
        // don't want anything to happen
        if (start === undefined) {
          return;
        } // Skip every other value if there are negatives.


        var peakIndexScale = hasMinVals ? 2 : 1;
        var length = peaks.length / peakIndexScale;
        var bar = _this4.params.barWidth * _this4.params.pixelRatio;
        var gap = _this4.params.barGap === null ? Math.max(_this4.params.pixelRatio, ~~(bar / 2)) : Math.max(_this4.params.pixelRatio, _this4.params.barGap * _this4.params.pixelRatio);
        var step = bar + gap;
        var scale = length / _this4.width;
        var first = start;
        var last = end;
        var i = first;

        for (i; i < last; i += step) {
          var peak = peaks[Math.floor(i * scale * peakIndexScale)] || 0;
          var h = Math.round(peak / absmax * halfH);
          /* in case of silences, allow the user to specify that we
           * always draw *something* (normally a 1px high bar) */

          if (h == 0 && _this4.params.barMinHeight) {
            h = _this4.params.barMinHeight;
          }

          _this4.fillRect(i + _this4.halfPixel, halfH - h + offsetY, bar + _this4.halfPixel, h * 2, _this4.barRadius, ch);
        }
      });
    }
    /**
     * Draw a waveform
     *
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
     * for split channel rendering
     * @param {number} channelIndex The index of the current channel. Normally
     * should be 0
     * @param {number?} start The x-offset of the beginning of the area that
     * should be rendered (If this isn't set only a flat line is rendered)
     * @param {number?} end The x-offset of the end of the area that should be
     * rendered
     * @returns {void}
     */

  }, {
    key: "drawWave",
    value: function drawWave(peaks, channelIndex, start, end) {
      var _this5 = this;

      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref2) {
        var absmax = _ref2.absmax,
            hasMinVals = _ref2.hasMinVals,
            height = _ref2.height,
            offsetY = _ref2.offsetY,
            halfH = _ref2.halfH,
            peaks = _ref2.peaks,
            channelIndex = _ref2.channelIndex;

        if (!hasMinVals) {
          var reflectedPeaks = [];
          var len = peaks.length;
          var i = 0;

          for (i; i < len; i++) {
            reflectedPeaks[2 * i] = peaks[i];
            reflectedPeaks[2 * i + 1] = -peaks[i];
          }

          peaks = reflectedPeaks;
        } // if drawWave was called within ws.empty we don't pass a start and
        // end and simply want a flat line


        if (start !== undefined) {
          _this5.drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex);
        } // always draw a median line


        _this5.fillRect(0, halfH + offsetY - _this5.halfPixel, _this5.width, _this5.halfPixel, _this5.barRadius, channelIndex);
      });
    }
    /**
     * Tell the canvas entries to render their portion of the waveform
     *
     * @param {number[]} peaks Peaks data
     * @param {number} absmax Maximum peak value (absolute)
     * @param {number} halfH Half the height of the waveform
     * @param {number} offsetY Offset to the top
     * @param {number} start The x-offset of the beginning of the area that
     * should be rendered
     * @param {number} end The x-offset of the end of the area that
     * should be rendered
     * @param {channelIndex} channelIndex The channel index of the line drawn
     */

  }, {
    key: "drawLine",
    value: function drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex) {
      var _this6 = this;

      var _ref3 = this.params.splitChannelsOptions.channelColors[channelIndex] || {},
          waveColor = _ref3.waveColor,
          progressColor = _ref3.progressColor;

      this.canvases.forEach(function (entry, i) {
        _this6.setFillStyles(entry, waveColor, progressColor);

        _this6.applyCanvasTransforms(entry, _this6.params.vertical);

        entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
      });
    }
    /**
     * Draw a rectangle on the multi-canvas
     *
     * @param {number} x X-position of the rectangle
     * @param {number} y Y-position of the rectangle
     * @param {number} width Width of the rectangle
     * @param {number} height Height of the rectangle
     * @param {number} radius Radius of the rectangle
     * @param {channelIndex} channelIndex The channel index of the bar drawn
     */

  }, {
    key: "fillRect",
    value: function fillRect(x, y, width, height, radius, channelIndex) {
      var startCanvas = Math.floor(x / this.maxCanvasWidth);
      var endCanvas = Math.min(Math.ceil((x + width) / this.maxCanvasWidth) + 1, this.canvases.length);
      var i = startCanvas;

      for (i; i < endCanvas; i++) {
        var entry = this.canvases[i];
        var leftOffset = i * this.maxCanvasWidth;
        var intersection = {
          x1: Math.max(x, i * this.maxCanvasWidth),
          y1: y,
          x2: Math.min(x + width, i * this.maxCanvasWidth + entry.wave.width),
          y2: y + height
        };

        if (intersection.x1 < intersection.x2) {
          var _ref4 = this.params.splitChannelsOptions.channelColors[channelIndex] || {},
              waveColor = _ref4.waveColor,
              progressColor = _ref4.progressColor;

          this.setFillStyles(entry, waveColor, progressColor);
          this.applyCanvasTransforms(entry, this.params.vertical);
          entry.fillRects(intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1, radius);
        }
      }
    }
    /**
     * Returns whether to hide the channel from being drawn based on params.
     *
     * @param {number} channelIndex The index of the current channel.
     * @returns {bool} True to hide the channel, false to draw.
     */

  }, {
    key: "hideChannel",
    value: function hideChannel(channelIndex) {
      return this.params.splitChannels && this.params.splitChannelsOptions.filterChannels.includes(channelIndex);
    }
    /**
     * Performs preparation tasks and calculations which are shared by `drawBars`
     * and `drawWave`
     *
     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for
     * split channel rendering
     * @param {number} channelIndex The index of the current channel. Normally
     * should be 0
     * @param {number?} start The x-offset of the beginning of the area that
     * should be rendered. If this isn't set only a flat line is rendered
     * @param {number?} end The x-offset of the end of the area that should be
     * rendered
     * @param {function} fn The render function to call, e.g. `drawWave`
     * @param {number} drawIndex The index of the current channel after filtering.
     * @param {number?} normalizedMax Maximum modulation value across channels for use with relativeNormalization. Ignored when undefined
     * @returns {void}
     */

  }, {
    key: "prepareDraw",
    value: function prepareDraw(peaks, channelIndex, start, end, fn, drawIndex, normalizedMax) {
      var _this7 = this;

      return util.frame(function () {
        // Split channels and call this function with the channelIndex set
        if (peaks[0] instanceof Array) {
          var channels = peaks;

          if (_this7.params.splitChannels) {
            var filteredChannels = channels.filter(function (c, i) {
              return !_this7.hideChannel(i);
            });

            if (!_this7.params.splitChannelsOptions.overlay) {
              _this7.setHeight(Math.max(filteredChannels.length, 1) * _this7.params.height * _this7.params.pixelRatio);
            }

            var overallAbsMax;

            if (_this7.params.splitChannelsOptions && _this7.params.splitChannelsOptions.relativeNormalization) {
              // calculate maximum peak across channels to use for normalization
              overallAbsMax = util.max(channels.map(function (channelPeaks) {
                return util.absMax(channelPeaks);
              }));
            }

            return channels.forEach(function (channelPeaks, i) {
              return _this7.prepareDraw(channelPeaks, i, start, end, fn, filteredChannels.indexOf(channelPeaks), overallAbsMax);
            });
          }

          peaks = channels[0];
        } // Return and do not draw channel peaks if hidden.


        if (_this7.hideChannel(channelIndex)) {
          return;
        } // calculate maximum modulation value, either from the barHeight
        // parameter or if normalize=true from the largest value in the peak
        // set


        var absmax = 1 / _this7.params.barHeight;

        if (_this7.params.normalize) {
          absmax = normalizedMax === undefined ? util.absMax(peaks) : normalizedMax;
        } // Bar wave draws the bottom only as a reflection of the top,
        // so we don't need negative values


        var hasMinVals = [].some.call(peaks, function (val) {
          return val < 0;
        });
        var height = _this7.params.height * _this7.params.pixelRatio;
        var halfH = height / 2;
        var offsetY = height * drawIndex || 0; // Override offsetY if overlay is true

        if (_this7.params.splitChannelsOptions && _this7.params.splitChannelsOptions.overlay) {
          offsetY = 0;
        }

        return fn({
          absmax: absmax,
          hasMinVals: hasMinVals,
          height: height,
          offsetY: offsetY,
          halfH: halfH,
          peaks: peaks,
          channelIndex: channelIndex
        });
      })();
    }
    /**
     * Set the fill styles for a certain entry (wave and progress)
     *
     * @param {CanvasEntry} entry Target entry
     * @param {string} waveColor Wave color to draw this entry
     * @param {string} progressColor Progress color to draw this entry
     */

  }, {
    key: "setFillStyles",
    value: function setFillStyles(entry) {
      var waveColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.params.waveColor;
      var progressColor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.params.progressColor;
      entry.setFillStyles(waveColor, progressColor);
    }
    /**
     * Set the canvas transforms for a certain entry (wave and progress)
     *
     * @param {CanvasEntry} entry Target entry
     * @param {boolean} vertical Whether to render the waveform vertically
     */

  }, {
    key: "applyCanvasTransforms",
    value: function applyCanvasTransforms(entry) {
      var vertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      entry.applyCanvasTransforms(vertical);
    }
    /**
     * Return image data of the multi-canvas
     *
     * When using a `type` of `'blob'`, this will return a `Promise`.
     *
     * @param {string} format='image/png' An optional value of a format type.
     * @param {number} quality=0.92 An optional value between 0 and 1.
     * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
     * @return {string|string[]|Promise} When using the default `'dataURL'`
     * `type` this returns a single data URL or an array of data URLs,
     * one for each canvas. When using the `'blob'` `type` this returns a
     * `Promise` that resolves with an array of `Blob` instances, one for each
     * canvas.
     */

  }, {
    key: "getImage",
    value: function getImage(format, quality, type) {
      if (type === 'blob') {
        return Promise.all(this.canvases.map(function (entry) {
          return entry.getImage(format, quality, type);
        }));
      } else if (type === 'dataURL') {
        var images = this.canvases.map(function (entry) {
          return entry.getImage(format, quality, type);
        });
        return images.length > 1 ? images : images[0];
      }
    }
    /**
     * Render the new progress
     *
     * @param {number} position X-offset of progress position in pixels
     */

  }, {
    key: "updateProgress",
    value: function updateProgress(position) {
      this.style(this.progressWave, {
        width: position + 'px'
      });
    }
  }]);

  return MultiCanvas;
}(_drawer.default);

exports.default = MultiCanvas;
module.exports = exports.default;

/***/ }),

/***/ "./src/mediaelement-webaudio.js":
/*!**************************************!*\
  !*** ./src/mediaelement-webaudio.js ***!
  \**************************************/
/***/ ((module, exports, __nested_webpack_require_56119__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var _mediaelement = _interopRequireDefault(__nested_webpack_require_56119__(/*! ./mediaelement */ "./src/mediaelement.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

/**
 * MediaElementWebAudio backend: load audio via an HTML5 audio tag, but playback with the WebAudio API.
 * The advantage here is that the html5 <audio> tag can perform range requests on the server and not
 * buffer the entire file in one request, and you still get the filtering and scripting functionality
 * of the webaudio API.
 * Note that in order to use range requests and prevent buffering, you must provide peak data.
 *
 * @since 3.2.0
 */
var MediaElementWebAudio = /*#__PURE__*/function (_MediaElement) {
  _inherits(MediaElementWebAudio, _MediaElement);

  var _super = _createSuper(MediaElementWebAudio);

  /**
   * Construct the backend
   *
   * @param {WavesurferParams} params Wavesurfer parameters
   */
  function MediaElementWebAudio(params) {
    var _this;

    _classCallCheck(this, MediaElementWebAudio);

    _this = _super.call(this, params);
    /** @private */

    _this.params = params;
    /** @private */

    _this.sourceMediaElement = null;
    return _this;
  }
  /**
   * Initialise the backend, called in `wavesurfer.createBackend()`
   */


  _createClass(MediaElementWebAudio, [{
    key: "init",
    value: function init() {
      this.setPlaybackRate(this.params.audioRate);
      this.createTimer();
      this.createVolumeNode();
      this.createScriptNode();
      this.createAnalyserNode();
    }
    /**
     * Private method called by both `load` (from url)
     * and `loadElt` (existing media element) methods.
     *
     * @param {HTMLMediaElement} media HTML5 Audio or Video element
     * @param {number[]|Number.<Array[]>} peaks Array of peak data
     * @param {string} preload HTML 5 preload attribute value
     * @private
     */

  }, {
    key: "_load",
    value: function _load(media, peaks, preload) {
      _get(_getPrototypeOf(MediaElementWebAudio.prototype), "_load", this).call(this, media, peaks, preload);

      this.createMediaElementSource(media);
    }
    /**
     * Create MediaElementSource node
     *
     * @since 3.2.0
     * @param {HTMLMediaElement} mediaElement HTML5 Audio to load
     */

  }, {
    key: "createMediaElementSource",
    value: function createMediaElementSource(mediaElement) {
      this.sourceMediaElement = this.ac.createMediaElementSource(mediaElement);
      this.sourceMediaElement.connect(this.analyser);
    }
  }, {
    key: "play",
    value: function play(start, end) {
      this.resumeAudioContext();
      return _get(_getPrototypeOf(MediaElementWebAudio.prototype), "play", this).call(this, start, end);
    }
    /**
     * This is called when wavesurfer is destroyed
     *
     */

  }, {
    key: "destroy",
    value: function destroy() {
      _get(_getPrototypeOf(MediaElementWebAudio.prototype), "destroy", this).call(this);

      this.destroyWebAudio();
    }
  }]);

  return MediaElementWebAudio;
}(_mediaelement.default);

exports.default = MediaElementWebAudio;
module.exports = exports.default;

/***/ }),

/***/ "./src/mediaelement.js":
/*!*****************************!*\
  !*** ./src/mediaelement.js ***!
  \*****************************/
/***/ ((module, exports, __nested_webpack_require_63244__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var _webaudio = _interopRequireDefault(__nested_webpack_require_63244__(/*! ./webaudio */ "./src/webaudio.js"));

var util = _interopRequireWildcard(__nested_webpack_require_63244__(/*! ./util */ "./src/util/index.js"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

/**
 * MediaElement backend
 */
var MediaElement = /*#__PURE__*/function (_WebAudio) {
  _inherits(MediaElement, _WebAudio);

  var _super = _createSuper(MediaElement);

  /**
   * Construct the backend
   *
   * @param {WavesurferParams} params Wavesurfer parameters
   */
  function MediaElement(params) {
    var _this;

    _classCallCheck(this, MediaElement);

    _this = _super.call(this, params);
    /** @private */

    _this.params = params;
    /**
     * Initially a dummy media element to catch errors. Once `_load` is
     * called, this will contain the actual `HTMLMediaElement`.
     * @private
     */

    _this.media = {
      currentTime: 0,
      duration: 0,
      paused: true,
      playbackRate: 1,
      play: function play() {},
      pause: function pause() {},
      volume: 0
    };
    /** @private */

    _this.mediaType = params.mediaType.toLowerCase();
    /** @private */

    _this.elementPosition = params.elementPosition;
    /** @private */

    _this.peaks = null;
    /** @private */

    _this.playbackRate = 1;
    /** @private */

    _this.volume = 1;
    /** @private */

    _this.isMuted = false;
    /** @private */

    _this.buffer = null;
    /** @private */

    _this.onPlayEnd = null;
    /** @private */

    _this.mediaListeners = {};
    return _this;
  }
  /**
   * Initialise the backend, called in `wavesurfer.createBackend()`
   */


  _createClass(MediaElement, [{
    key: "init",
    value: function init() {
      this.setPlaybackRate(this.params.audioRate);
      this.createTimer();
    }
    /**
     * Attach event listeners to media element.
     */

  }, {
    key: "_setupMediaListeners",
    value: function _setupMediaListeners() {
      var _this2 = this;

      this.mediaListeners.error = function () {
        _this2.fireEvent('error', 'Error loading media element');
      };

      this.mediaListeners.canplay = function () {
        _this2.fireEvent('canplay');
      };

      this.mediaListeners.ended = function () {
        _this2.fireEvent('finish');
      }; // listen to and relay play, pause and seeked events to enable
      // playback control from the external media element


      this.mediaListeners.play = function () {
        _this2.fireEvent('play');
      };

      this.mediaListeners.pause = function () {
        _this2.fireEvent('pause');
      };

      this.mediaListeners.seeked = function (event) {
        _this2.fireEvent('seek');
      };

      this.mediaListeners.volumechange = function (event) {
        _this2.isMuted = _this2.media.muted;

        if (_this2.isMuted) {
          _this2.volume = 0;
        } else {
          _this2.volume = _this2.media.volume;
        }

        _this2.fireEvent('volume');
      }; // reset event listeners


      Object.keys(this.mediaListeners).forEach(function (id) {
        _this2.media.removeEventListener(id, _this2.mediaListeners[id]);

        _this2.media.addEventListener(id, _this2.mediaListeners[id]);
      });
    }
    /**
     * Create a timer to provide a more precise `audioprocess` event.
     */

  }, {
    key: "createTimer",
    value: function createTimer() {
      var _this3 = this;

      var onAudioProcess = function onAudioProcess() {
        if (_this3.isPaused()) {
          return;
        }

        _this3.fireEvent('audioprocess', _this3.getCurrentTime()); // Call again in the next frame


        util.frame(onAudioProcess)();
      };

      this.on('play', onAudioProcess); // Update the progress one more time to prevent it from being stuck in
      // case of lower framerates

      this.on('pause', function () {
        _this3.fireEvent('audioprocess', _this3.getCurrentTime());
      });
    }
    /**
     * Create media element with url as its source,
     * and append to container element.
     *
     * @param {string} url Path to media file
     * @param {HTMLElement} container HTML element
     * @param {number[]|Number.<Array[]>} peaks Array of peak data
     * @param {string} preload HTML 5 preload attribute value
     * @throws Will throw an error if the `url` argument is not a valid media
     * element.
     */

  }, {
    key: "load",
    value: function load(url, container, peaks, preload) {
      var media = document.createElement(this.mediaType);
      media.controls = this.params.mediaControls;
      media.autoplay = this.params.autoplay || false;
      media.preload = preload == null ? 'auto' : preload;
      media.src = url;
      media.style.width = '100%';
      var prevMedia = container.querySelector(this.mediaType);

      if (prevMedia) {
        container.removeChild(prevMedia);
      }

      container.appendChild(media);

      this._load(media, peaks, preload);
    }
    /**
     * Load existing media element.
     *
     * @param {HTMLMediaElement} elt HTML5 Audio or Video element
     * @param {number[]|Number.<Array[]>} peaks Array of peak data
     */

  }, {
    key: "loadElt",
    value: function loadElt(elt, peaks) {
      elt.controls = this.params.mediaControls;
      elt.autoplay = this.params.autoplay || false;

      this._load(elt, peaks, elt.preload);
    }
    /**
     * Method called by both `load` (from url)
     * and `loadElt` (existing media element) methods.
     *
     * @param {HTMLMediaElement} media HTML5 Audio or Video element
     * @param {number[]|Number.<Array[]>} peaks Array of peak data
     * @param {string} preload HTML 5 preload attribute value
     * @throws Will throw an error if the `media` argument is not a valid media
     * element.
     * @private
     */

  }, {
    key: "_load",
    value: function _load(media, peaks, preload) {
      // verify media element is valid
      if (!(media instanceof HTMLMediaElement) || typeof media.addEventListener === 'undefined') {
        throw new Error('media parameter is not a valid media element');
      } // load must be called manually on iOS, otherwise peaks won't draw
      // until a user interaction triggers load --> 'ready' event
      //
      // note that we avoid calling media.load here when given peaks and preload == 'none'
      // as this almost always triggers some browser fetch of the media.


      if (typeof media.load == 'function' && !(peaks && preload == 'none')) {
        // Resets the media element and restarts the media resource. Any
        // pending events are discarded. How much media data is fetched is
        // still affected by the preload attribute.
        media.load();
      }

      this.media = media;

      this._setupMediaListeners();

      this.peaks = peaks;
      this.onPlayEnd = null;
      this.buffer = null;
      this.isMuted = media.muted;
      this.setPlaybackRate(this.playbackRate);
      this.setVolume(this.volume);
    }
    /**
     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
     *
     * @return {boolean} Media paused or not
     */

  }, {
    key: "isPaused",
    value: function isPaused() {
      return !this.media || this.media.paused;
    }
    /**
     * Used by `wavesurfer.getDuration()`
     *
     * @return {number} Duration
     */

  }, {
    key: "getDuration",
    value: function getDuration() {
      if (this.explicitDuration) {
        return this.explicitDuration;
      }

      var duration = (this.buffer || this.media).duration;

      if (duration >= Infinity) {
        // streaming audio
        duration = this.media.seekable.end(0);
      }

      return duration;
    }
    /**
     * Returns the current time in seconds relative to the audio-clip's
     * duration.
     *
     * @return {number} Current time
     */

  }, {
    key: "getCurrentTime",
    value: function getCurrentTime() {
      return this.media && this.media.currentTime;
    }
    /**
     * Get the position from 0 to 1
     *
     * @return {number} Current position
     */

  }, {
    key: "getPlayedPercents",
    value: function getPlayedPercents() {
      return this.getCurrentTime() / this.getDuration() || 0;
    }
    /**
     * Get the audio source playback rate.
     *
     * @return {number} Playback rate
     */

  }, {
    key: "getPlaybackRate",
    value: function getPlaybackRate() {
      return this.playbackRate || this.media.playbackRate;
    }
    /**
     * Set the audio source playback rate.
     *
     * @param {number} value Playback rate
     */

  }, {
    key: "setPlaybackRate",
    value: function setPlaybackRate(value) {
      this.playbackRate = value || 1;
      this.media.playbackRate = this.playbackRate;
    }
    /**
     * Used by `wavesurfer.seekTo()`
     *
     * @param {number} start Position to start at in seconds
     */

  }, {
    key: "seekTo",
    value: function seekTo(start) {
      if (start != null) {
        this.media.currentTime = start;
      }

      this.clearPlayEnd();
    }
    /**
     * Plays the loaded audio region.
     *
     * @param {number} start Start offset in seconds, relative to the beginning
     * of a clip.
     * @param {number} end When to stop, relative to the beginning of a clip.
     * @emits MediaElement#play
     * @return {Promise} Result
     */

  }, {
    key: "play",
    value: function play(start, end) {
      this.seekTo(start);
      var promise = this.media.play();
      end && this.setPlayEnd(end);
      return promise;
    }
    /**
     * Pauses the loaded audio.
     *
     * @emits MediaElement#pause
     * @return {Promise} Result
     */

  }, {
    key: "pause",
    value: function pause() {
      var promise;

      if (this.media) {
        promise = this.media.pause();
      }

      this.clearPlayEnd();
      return promise;
    }
    /**
     * Set the play end
     *
     * @param {number} end Where to end
     */

  }, {
    key: "setPlayEnd",
    value: function setPlayEnd(end) {
      var _this4 = this;

      this.clearPlayEnd();

      this._onPlayEnd = function (time) {
        if (time >= end) {
          _this4.pause();

          _this4.seekTo(end);
        }
      };

      this.on('audioprocess', this._onPlayEnd);
    }
    /** @private */

  }, {
    key: "clearPlayEnd",
    value: function clearPlayEnd() {
      if (this._onPlayEnd) {
        this.un('audioprocess', this._onPlayEnd);
        this._onPlayEnd = null;
      }
    }
    /**
     * Compute the max and min value of the waveform when broken into
     * <length> subranges.
     *
     * @param {number} length How many subranges to break the waveform into.
     * @param {number} first First sample in the required range.
     * @param {number} last Last sample in the required range.
     * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of
     * arrays of peaks consisting of (max, min) values for each subrange.
     */

  }, {
    key: "getPeaks",
    value: function getPeaks(length, first, last) {
      if (this.buffer) {
        return _get(_getPrototypeOf(MediaElement.prototype), "getPeaks", this).call(this, length, first, last);
      }

      return this.peaks || [];
    }
    /**
     * Set the sink id for the media player
     *
     * @param {string} deviceId String value representing audio device id.
     * @returns {Promise} A Promise that resolves to `undefined` when there
     * are no errors.
     */

  }, {
    key: "setSinkId",
    value: function setSinkId(deviceId) {
      if (deviceId) {
        if (!this.media.setSinkId) {
          return Promise.reject(new Error('setSinkId is not supported in your browser'));
        }

        return this.media.setSinkId(deviceId);
      }

      return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
    }
    /**
     * Get the current volume
     *
     * @return {number} value A floating point value between 0 and 1.
     */

  }, {
    key: "getVolume",
    value: function getVolume() {
      return this.volume;
    }
    /**
     * Set the audio volume
     *
     * @param {number} value A floating point value between 0 and 1.
     */

  }, {
    key: "setVolume",
    value: function setVolume(value) {
      this.volume = value; // no need to change when it's already at that volume

      if (this.media.volume !== this.volume) {
        this.media.volume = this.volume;
      }
    }
    /**
     * Enable or disable muted audio
     *
     * @since 4.0.0
     * @param {boolean} muted Specify `true` to mute audio.
     */

  }, {
    key: "setMute",
    value: function setMute(muted) {
      // This causes a volume change to be emitted too through the
      // volumechange event listener.
      this.isMuted = this.media.muted = muted;
    }
    /**
     * This is called when wavesurfer is destroyed
     *
     */

  }, {
    key: "destroy",
    value: function destroy() {
      var _this5 = this;

      this.pause();
      this.unAll();
      this.destroyed = true; // cleanup media event listeners

      Object.keys(this.mediaListeners).forEach(function (id) {
        if (_this5.media) {
          _this5.media.removeEventListener(id, _this5.mediaListeners[id]);
        }
      });

      if (this.params.removeMediaElementOnDestroy && this.media && this.media.parentNode) {
        this.media.parentNode.removeChild(this.media);
      }

      this.media = null;
    }
  }]);

  return MediaElement;
}(_webaudio.default);

exports.default = MediaElement;
module.exports = exports.default;

/***/ }),

/***/ "./src/peakcache.js":
/*!**************************!*\
  !*** ./src/peakcache.js ***!
  \**************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/**
 * Caches the decoded peaks data to improve rendering speed for large audio
 *
 * Is used if the option parameter `partialRender` is set to `true`
 */
var PeakCache = /*#__PURE__*/function () {
  /**
   * Instantiate cache
   */
  function PeakCache() {
    _classCallCheck(this, PeakCache);

    this.clearPeakCache();
  }
  /**
   * Empty the cache
   */


  _createClass(PeakCache, [{
    key: "clearPeakCache",
    value: function clearPeakCache() {
      /**
       * Flat array with entries that are always in pairs to mark the
       * beginning and end of each subrange.  This is a convenience so we can
       * iterate over the pairs for easy set difference operations.
       * @private
       */
      this.peakCacheRanges = [];
      /**
       * Length of the entire cachable region, used for resetting the cache
       * when this changes (zoom events, for instance).
       * @private
       */

      this.peakCacheLength = -1;
    }
    /**
     * Add a range of peaks to the cache
     *
     * @param {number} length The length of the range
     * @param {number} start The x offset of the start of the range
     * @param {number} end The x offset of the end of the range
     * @return {Number.<Array[]>} Array with arrays of numbers
     */

  }, {
    key: "addRangeToPeakCache",
    value: function addRangeToPeakCache(length, start, end) {
      if (length != this.peakCacheLength) {
        this.clearPeakCache();
        this.peakCacheLength = length;
      } // Return ranges that weren't in the cache before the call.


      var uncachedRanges = [];
      var i = 0; // Skip ranges before the current start.

      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] < start) {
        i++;
      } // If |i| is even, |start| falls after an existing range.  Otherwise,
      // |start| falls between an existing range, and the uncached region
      // starts when we encounter the next node in |peakCacheRanges| or
      // |end|, whichever comes first.


      if (i % 2 == 0) {
        uncachedRanges.push(start);
      }

      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] <= end) {
        uncachedRanges.push(this.peakCacheRanges[i]);
        i++;
      } // If |i| is even, |end| is after all existing ranges.


      if (i % 2 == 0) {
        uncachedRanges.push(end);
      } // Filter out the 0-length ranges.


      uncachedRanges = uncachedRanges.filter(function (item, pos, arr) {
        if (pos == 0) {
          return item != arr[pos + 1];
        } else if (pos == arr.length - 1) {
          return item != arr[pos - 1];
        }

        return item != arr[pos - 1] && item != arr[pos + 1];
      }); // Merge the two ranges together, uncachedRanges will either contain
      // wholly new points, or duplicates of points in peakCacheRanges.  If
      // duplicates are detected, remove both and extend the range.

      this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
      this.peakCacheRanges = this.peakCacheRanges.sort(function (a, b) {
        return a - b;
      }).filter(function (item, pos, arr) {
        if (pos == 0) {
          return item != arr[pos + 1];
        } else if (pos == arr.length - 1) {
          return item != arr[pos - 1];
        }

        return item != arr[pos - 1] && item != arr[pos + 1];
      }); // Push the uncached ranges into an array of arrays for ease of
      // iteration in the functions that call this.

      var uncachedRangePairs = [];

      for (i = 0; i < uncachedRanges.length; i += 2) {
        uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);
      }

      return uncachedRangePairs;
    }
    /**
     * For testing
     *
     * @return {Number.<Array[]>} Array with arrays of numbers
     */

  }, {
    key: "getCacheRanges",
    value: function getCacheRanges() {
      var peakCacheRangePairs = [];
      var i;

      for (i = 0; i < this.peakCacheRanges.length; i += 2) {
        peakCacheRangePairs.push([this.peakCacheRanges[i], this.peakCacheRanges[i + 1]]);
      }

      return peakCacheRangePairs;
    }
  }]);

  return PeakCache;
}();

exports.default = PeakCache;
module.exports = exports.default;

/***/ }),

/***/ "./src/util/absMax.js":
/*!****************************!*\
  !*** ./src/util/absMax.js ***!
  \****************************/
/***/ ((module, exports, __nested_webpack_require_87138__) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = absMax;

var _max = _interopRequireDefault(__nested_webpack_require_87138__(/*! ./max */ "./src/util/max.js"));

var _min = _interopRequireDefault(__nested_webpack_require_87138__(/*! ./min */ "./src/util/min.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Get the largest absolute value in an array
 *
 * @param   {Array} values Array of numbers
 * @returns {Number} Largest number found
 * @example console.log(max([-3, 2, 1]), max([-3, 2, 4])); // logs 3 4
 * @since 4.3.0
 */
function absMax(values) {
  var max = (0, _max.default)(values);
  var min = (0, _min.default)(values);
  return -min > max ? -min : max;
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/clamp.js":
/*!***************************!*\
  !*** ./src/util/clamp.js ***!
  \***************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = clamp;

/**
 * Returns a number limited to the given range.
 *
 * @param {number} val The number to be limited to a range
 * @param {number} min The lower boundary of the limit range
 * @param {number} max The upper boundary of the limit range
 * @returns {number} A number in the range [min, max]
 */
function clamp(val, min, max) {
  return Math.min(Math.max(min, val), max);
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/fetch.js":
/*!***************************!*\
  !*** ./src/util/fetch.js ***!
  \***************************/
/***/ ((module, exports, __nested_webpack_require_88816__) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = fetchFile;

var _observer = _interopRequireDefault(__nested_webpack_require_88816__(/*! ./observer */ "./src/util/observer.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var ProgressHandler = /*#__PURE__*/function () {
  /**
   * Instantiate ProgressHandler
   *
   * @param {Observer} instance The `fetchFile` observer instance.
   * @param {Number} contentLength Content length.
   * @param {Response} response Response object.
   */
  function ProgressHandler(instance, contentLength, response) {
    _classCallCheck(this, ProgressHandler);

    this.instance = instance;
    this.instance._reader = response.body.getReader();
    this.total = parseInt(contentLength, 10);
    this.loaded = 0;
  }
  /**
   * A method that is called once, immediately after the `ReadableStream``
   * is constructed.
   *
   * @param {ReadableStreamDefaultController} controller Controller instance
   *     used to control the stream.
   */


  _createClass(ProgressHandler, [{
    key: "start",
    value: function start(controller) {
      var _this = this;

      var read = function read() {
        // instance._reader.read() returns a promise that resolves
        // when a value has been received
        _this.instance._reader.read().then(function (_ref) {
          var done = _ref.done,
              value = _ref.value;

          // result objects contain two properties:
          // done  - true if the stream has already given you all its data.
          // value - some data. Always undefined when done is true.
          if (done) {
            // ensure onProgress called when content-length=0
            if (_this.total === 0) {
              _this.instance.onProgress.call(_this.instance, {
                loaded: _this.loaded,
                total: _this.total,
                lengthComputable: false
              });
            } // no more data needs to be consumed, close the stream


            controller.close();
            return;
          }

          _this.loaded += value.byteLength;

          _this.instance.onProgress.call(_this.instance, {
            loaded: _this.loaded,
            total: _this.total,
            lengthComputable: !(_this.total === 0)
          }); // enqueue the next data chunk into our target stream


          controller.enqueue(value);
          read();
        }).catch(function (error) {
          controller.error(error);
        });
      };

      read();
    }
  }]);

  return ProgressHandler;
}();
/**
 * Load a file using `fetch`.
 *
 * @param {object} options Request options to use. See example below.
 * @returns {Observer} Observer instance
 * @example
 * // default options
 * let options = {
 *     url: undefined,
 *     method: 'GET',
 *     mode: 'cors',
 *     credentials: 'same-origin',
 *     cache: 'default',
 *     responseType: 'json',
 *     requestHeaders: [],
 *     redirect: 'follow',
 *     referrer: 'client'
 * };
 *
 * // override some options
 * options.url = '../media/demo.wav';

 * // available types: 'arraybuffer', 'blob', 'json' or 'text'
 * options.responseType = 'arraybuffer';
 *
 * // make fetch call
 * let request = util.fetchFile(options);
 *
 * // listen for events
 * request.on('progress', e => {
 *     console.log('progress', e);
 * });
 *
 * request.on('success', data => {
 *     console.log('success!', data);
 * });
 *
 * request.on('error', e => {
 *     console.warn('fetchFile error: ', e);
 * });
 */


function fetchFile(options) {
  if (!options) {
    throw new Error('fetch options missing');
  } else if (!options.url) {
    throw new Error('fetch url missing');
  }

  var instance = new _observer.default();
  var fetchHeaders = new Headers();
  var fetchRequest = new Request(options.url); // add ability to abort

  instance.controller = new AbortController(); // check if headers have to be added

  if (options && options.requestHeaders) {
    // add custom request headers
    options.requestHeaders.forEach(function (header) {
      fetchHeaders.append(header.key, header.value);
    });
  } // parse fetch options


  var responseType = options.responseType || 'json';
  var fetchOptions = {
    method: options.method || 'GET',
    headers: fetchHeaders,
    mode: options.mode || 'cors',
    credentials: options.credentials || 'same-origin',
    cache: options.cache || 'default',
    redirect: options.redirect || 'follow',
    referrer: options.referrer || 'client',
    signal: instance.controller.signal
  };
  fetch(fetchRequest, fetchOptions).then(function (response) {
    // store response reference
    instance.response = response;
    var progressAvailable = true;

    if (!response.body) {
      // ReadableStream is not yet supported in this browser
      // see https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream
      progressAvailable = false;
    } // Server must send CORS header "Access-Control-Expose-Headers: content-length"


    var contentLength = response.headers.get('content-length');

    if (contentLength === null) {
      // Content-Length server response header missing.
      // Don't evaluate download progress if we can't compare against a total size
      // see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Access-Control-Expose-Headers
      progressAvailable = false;
    }

    if (!progressAvailable) {
      // not able to check download progress so skip it
      return response;
    } // fire progress event when during load


    instance.onProgress = function (e) {
      instance.fireEvent('progress', e);
    };

    return new Response(new ReadableStream(new ProgressHandler(instance, contentLength, response)), fetchOptions);
  }).then(function (response) {
    var errMsg;

    if (response.ok) {
      switch (responseType) {
        case 'arraybuffer':
          return response.arrayBuffer();

        case 'json':
          return response.json();

        case 'blob':
          return response.blob();

        case 'text':
          return response.text();

        default:
          errMsg = 'Unknown responseType: ' + responseType;
          break;
      }
    }

    if (!errMsg) {
      errMsg = 'HTTP error status: ' + response.status;
    }

    throw new Error(errMsg);
  }).then(function (response) {
    instance.fireEvent('success', response);
  }).catch(function (error) {
    instance.fireEvent('error', error);
  }); // return the fetch request

  instance.fetchRequest = fetchRequest;
  return instance;
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/frame.js":
/*!***************************!*\
  !*** ./src/util/frame.js ***!
  \***************************/
/***/ ((module, exports, __nested_webpack_require_96321__) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = frame;

var _requestAnimationFrame = _interopRequireDefault(__nested_webpack_require_96321__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Create a function which will be called at the next requestAnimationFrame
 * cycle
 *
 * @param {function} func The function to call
 *
 * @return {func} The function wrapped within a requestAnimationFrame
 */
function frame(func) {
  return function () {
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return (0, _requestAnimationFrame.default)(function () {
      return func.apply(void 0, args);
    });
  };
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/get-id.js":
/*!****************************!*\
  !*** ./src/util/get-id.js ***!
  \****************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = getId;

/**
 * Get a random prefixed ID
 *
 * @param {String} prefix Prefix to use. Default is `'wavesurfer_'`.
 * @returns {String} Random prefixed ID
 * @example
 * console.log(getId()); // logs 'wavesurfer_b5pors4ru6g'
 *
 * let prefix = 'foo-';
 * console.log(getId(prefix)); // logs 'foo-b5pors4ru6g'
 */
function getId(prefix) {
  if (prefix === undefined) {
    prefix = 'wavesurfer_';
  }

  return prefix + Math.random().toString(32).substring(2);
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/index.js":
/*!***************************!*\
  !*** ./src/util/index.js ***!
  \***************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_98203__) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
Object.defineProperty(exports, "getId", ({
  enumerable: true,
  get: function get() {
    return _getId.default;
  }
}));
Object.defineProperty(exports, "max", ({
  enumerable: true,
  get: function get() {
    return _max.default;
  }
}));
Object.defineProperty(exports, "min", ({
  enumerable: true,
  get: function get() {
    return _min.default;
  }
}));
Object.defineProperty(exports, "absMax", ({
  enumerable: true,
  get: function get() {
    return _absMax.default;
  }
}));
Object.defineProperty(exports, "Observer", ({
  enumerable: true,
  get: function get() {
    return _observer.default;
  }
}));
Object.defineProperty(exports, "style", ({
  enumerable: true,
  get: function get() {
    return _style.default;
  }
}));
Object.defineProperty(exports, "requestAnimationFrame", ({
  enumerable: true,
  get: function get() {
    return _requestAnimationFrame.default;
  }
}));
Object.defineProperty(exports, "frame", ({
  enumerable: true,
  get: function get() {
    return _frame.default;
  }
}));
Object.defineProperty(exports, "debounce", ({
  enumerable: true,
  get: function get() {
    return _debounce.default;
  }
}));
Object.defineProperty(exports, "preventClick", ({
  enumerable: true,
  get: function get() {
    return _preventClick.default;
  }
}));
Object.defineProperty(exports, "fetchFile", ({
  enumerable: true,
  get: function get() {
    return _fetch.default;
  }
}));
Object.defineProperty(exports, "clamp", ({
  enumerable: true,
  get: function get() {
    return _clamp.default;
  }
}));
Object.defineProperty(exports, "withOrientation", ({
  enumerable: true,
  get: function get() {
    return _orientation.default;
  }
}));
Object.defineProperty(exports, "ignoreSilenceMode", ({
  enumerable: true,
  get: function get() {
    return _silenceMode.default;
  }
}));

var _getId = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./get-id */ "./src/util/get-id.js"));

var _max = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./max */ "./src/util/max.js"));

var _min = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./min */ "./src/util/min.js"));

var _absMax = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./absMax */ "./src/util/absMax.js"));

var _observer = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./observer */ "./src/util/observer.js"));

var _style = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./style */ "./src/util/style.js"));

var _requestAnimationFrame = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));

var _frame = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./frame */ "./src/util/frame.js"));

var _debounce = _interopRequireDefault(__nested_webpack_require_98203__(/*! debounce */ "./node_modules/debounce/index.js"));

var _preventClick = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./prevent-click */ "./src/util/prevent-click.js"));

var _fetch = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./fetch */ "./src/util/fetch.js"));

var _clamp = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./clamp */ "./src/util/clamp.js"));

var _orientation = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./orientation */ "./src/util/orientation.js"));

var _silenceMode = _interopRequireDefault(__nested_webpack_require_98203__(/*! ./silence-mode */ "./src/util/silence-mode.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/***/ }),

/***/ "./src/util/max.js":
/*!*************************!*\
  !*** ./src/util/max.js ***!
  \*************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = max;

/**
 * Get the largest value
 *
 * @param   {Array} values Array of numbers
 * @returns {Number} Largest number found
 * @example console.log(max([1, 2, 3])); // logs 3
 */
function max(values) {
  var largest = -Infinity;
  Object.keys(values).forEach(function (i) {
    if (values[i] > largest) {
      largest = values[i];
    }
  });
  return largest;
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/min.js":
/*!*************************!*\
  !*** ./src/util/min.js ***!
  \*************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = min;

/**
 * Get the smallest value
 *
 * @param   {Array} values Array of numbers
 * @returns {Number} Smallest number found
 * @example console.log(min([1, 2, 3])); // logs 1
 */
function min(values) {
  var smallest = Number(Infinity);
  Object.keys(values).forEach(function (i) {
    if (values[i] < smallest) {
      smallest = values[i];
    }
  });
  return smallest;
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/observer.js":
/*!******************************!*\
  !*** ./src/util/observer.js ***!
  \******************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/**
 * @typedef {Object} ListenerDescriptor
 * @property {string} name The name of the event
 * @property {function} callback The callback
 * @property {function} un The function to call to remove the listener
 */

/**
 * Observer class
 */
var Observer = /*#__PURE__*/function () {
  /**
   * Instantiate Observer
   */
  function Observer() {
    _classCallCheck(this, Observer);

    /**
     * @private
     * @todo Initialise the handlers here already and remove the conditional
     * assignment in `on()`
     */
    this._disabledEventEmissions = [];
    this.handlers = null;
  }
  /**
   * Attach a handler function for an event.
   *
   * @param {string} event Name of the event to listen to
   * @param {function} fn The callback to trigger when the event is fired
   * @return {ListenerDescriptor} The event descriptor
   */


  _createClass(Observer, [{
    key: "on",
    value: function on(event, fn) {
      var _this = this;

      if (!this.handlers) {
        this.handlers = {};
      }

      var handlers = this.handlers[event];

      if (!handlers) {
        handlers = this.handlers[event] = [];
      }

      handlers.push(fn); // Return an event descriptor

      return {
        name: event,
        callback: fn,
        un: function un(e, fn) {
          return _this.un(e, fn);
        }
      };
    }
    /**
     * Remove an event handler.
     *
     * @param {string} event Name of the event the listener that should be
     * removed listens to
     * @param {function} fn The callback that should be removed
     */

  }, {
    key: "un",
    value: function un(event, fn) {
      if (!this.handlers) {
        return;
      }

      var handlers = this.handlers[event];
      var i;

      if (handlers) {
        if (fn) {
          for (i = handlers.length - 1; i >= 0; i--) {
            if (handlers[i] == fn) {
              handlers.splice(i, 1);
            }
          }
        } else {
          handlers.length = 0;
        }
      }
    }
    /**
     * Remove all event handlers.
     */

  }, {
    key: "unAll",
    value: function unAll() {
      this.handlers = null;
    }
    /**
     * Attach a handler to an event. The handler is executed at most once per
     * event type.
     *
     * @param {string} event The event to listen to
     * @param {function} handler The callback that is only to be called once
     * @return {ListenerDescriptor} The event descriptor
     */

  }, {
    key: "once",
    value: function once(event, handler) {
      var _this2 = this;

      var fn = function fn() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

        /*  eslint-disable no-invalid-this */
        handler.apply(_this2, args);
        /*  eslint-enable no-invalid-this */

        setTimeout(function () {
          _this2.un(event, fn);
        }, 0);
      };

      return this.on(event, fn);
    }
    /**
     * Disable firing a list of events by name. When specified, event handlers for any event type
     * passed in here will not be called.
     *
     * @since 4.0.0
     * @param {string[]} eventNames an array of event names to disable emissions for
     * @example
     * // disable seek and interaction events
     * wavesurfer.setDisabledEventEmissions(['seek', 'interaction']);
     */

  }, {
    key: "setDisabledEventEmissions",
    value: function setDisabledEventEmissions(eventNames) {
      this._disabledEventEmissions = eventNames;
    }
    /**
     * plugins borrow part of this class without calling the constructor,
     * so we have to be careful about _disabledEventEmissions
     */

  }, {
    key: "_isDisabledEventEmission",
    value: function _isDisabledEventEmission(event) {
      return this._disabledEventEmissions && this._disabledEventEmissions.includes(event);
    }
    /**
     * Manually fire an event
     *
     * @param {string} event The event to fire manually
     * @param {...any} args The arguments with which to call the listeners
     */

  }, {
    key: "fireEvent",
    value: function fireEvent(event) {
      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
        args[_key2 - 1] = arguments[_key2];
      }

      if (!this.handlers || this._isDisabledEventEmission(event)) {
        return;
      }

      var handlers = this.handlers[event];
      handlers && handlers.forEach(function (fn) {
        fn.apply(void 0, args);
      });
    }
  }]);

  return Observer;
}();

exports.default = Observer;
module.exports = exports.default;

/***/ }),

/***/ "./src/util/orientation.js":
/*!*********************************!*\
  !*** ./src/util/orientation.js ***!
  \*********************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = withOrientation;
var verticalPropMap = {
  width: 'height',
  height: 'width',
  overflowX: 'overflowY',
  overflowY: 'overflowX',
  clientWidth: 'clientHeight',
  clientHeight: 'clientWidth',
  clientX: 'clientY',
  clientY: 'clientX',
  scrollWidth: 'scrollHeight',
  scrollLeft: 'scrollTop',
  offsetLeft: 'offsetTop',
  offsetTop: 'offsetLeft',
  offsetHeight: 'offsetWidth',
  offsetWidth: 'offsetHeight',
  left: 'top',
  right: 'bottom',
  top: 'left',
  bottom: 'right',
  borderRightStyle: 'borderBottomStyle',
  borderRightWidth: 'borderBottomWidth',
  borderRightColor: 'borderBottomColor'
};
/**
 * Convert a horizontally-oriented property name to a vertical one.
 *
 * @param {string} prop A property name
 * @param {bool} vertical Whether the element is oriented vertically
 * @returns {string} prop, converted appropriately
 */

function mapProp(prop, vertical) {
  if (Object.prototype.hasOwnProperty.call(verticalPropMap, prop)) {
    return vertical ? verticalPropMap[prop] : prop;
  } else {
    return prop;
  }
}

var isProxy = Symbol("isProxy");
/**
 * Returns an appropriately oriented object based on vertical.
 * If vertical is true, attribute getting and setting will be mapped through
 * verticalPropMap, so that e.g. getting the object's .width will give its
 * .height instead.
 * Certain methods of an oriented object will return oriented objects as well.
 * Oriented objects can't be added to the DOM directly since they are Proxy objects
 * and thus fail typechecks. Use domElement to get the actual element for this.
 *
 * @param {object} target The object to be wrapped and oriented
 * @param {bool} vertical Whether the element is oriented vertically
 * @returns {Proxy} An oriented object with attr translation via verticalAttrMap
 * @since 5.0.0
 */

function withOrientation(target, vertical) {
  if (target[isProxy]) {
    return target;
  } else {
    return new Proxy(target, {
      get: function get(obj, prop, receiver) {
        if (prop === isProxy) {
          return true;
        } else if (prop === 'domElement') {
          return obj;
        } else if (prop === 'style') {
          return withOrientation(obj.style, vertical);
        } else if (prop === 'canvas') {
          return withOrientation(obj.canvas, vertical);
        } else if (prop === 'getBoundingClientRect') {
          return function () {
            return withOrientation(obj.getBoundingClientRect.apply(obj, arguments), vertical);
          };
        } else if (prop === 'getContext') {
          return function () {
            return withOrientation(obj.getContext.apply(obj, arguments), vertical);
          };
        } else {
          var value = obj[mapProp(prop, vertical)];
          return typeof value == 'function' ? value.bind(obj) : value;
        }
      },
      set: function set(obj, prop, value) {
        obj[mapProp(prop, vertical)] = value;
        return true;
      }
    });
  }
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/prevent-click.js":
/*!***********************************!*\
  !*** ./src/util/prevent-click.js ***!
  \***********************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = preventClick;

/**
 * Stops propagation of click event and removes event listener
 *
 * @private
 * @param {object} event The click event
 */
function preventClickHandler(event) {
  event.stopPropagation();
  document.body.removeEventListener('click', preventClickHandler, true);
}
/**
 * Starts listening for click event and prevent propagation
 *
 * @param {object} values Values
 */


function preventClick(values) {
  document.body.addEventListener('click', preventClickHandler, true);
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/request-animation-frame.js":
/*!*********************************************!*\
  !*** ./src/util/request-animation-frame.js ***!
  \*********************************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

/* eslint-disable valid-jsdoc */

/**
 * Returns the `requestAnimationFrame` function for the browser, or a shim with
 * `setTimeout` if the function is not found
 *
 * @return {function} Available `requestAnimationFrame` function for the browser
 */
var _default = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
  return setTimeout(callback, 1000 / 60);
}).bind(window);

exports.default = _default;
module.exports = exports.default;

/***/ }),

/***/ "./src/util/silence-mode.js":
/*!**********************************!*\
  !*** ./src/util/silence-mode.js ***!
  \**********************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = ignoreSilenceMode;

/**
 * Ignores device silence mode when using the `WebAudio` backend.
 *
 * Many mobile devices contain a hardware button to mute the ringtone for incoming
 * calls and messages. Unfortunately, on some platforms like iOS, this also mutes
 * wavesurfer's audio when using the `WebAudio` backend. This function creates a
 * temporary `<audio>` element that makes sure the WebAudio backend keeps playing
 * when muting the device ringer.
 *
 * @since 5.2.0
 */
function ignoreSilenceMode() {
  // Set the src to a short bit of url encoded as a silent mp3
  // NOTE The silence MP3 must be high quality, when web audio sounds are played
  // in parallel the web audio sound is mixed to match the bitrate of the html sound
  // 0.01 seconds of silence VBR220-260 Joint Stereo 859B
  var audioData = "data:audio/mpeg;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA//////////////////////////////////////////////////////////////////8AAABhTEFNRTMuMTAwA8MAAAAAAAAAABQgJAUHQQAB9AAAAnGMHkkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxAADgnABGiAAQBCqgCRMAAgEAH///////////////7+n/9FTuQsQH//////2NG0jWUGlio5gLQTOtIoeR2WX////X4s9Atb/JRVCbBUpeRUq//////////////////9RUi0f2jn/+xDECgPCjAEQAABN4AAANIAAAAQVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ=="; // disable iOS Airplay (setting the attribute in js doesn't work)

  var tmp = document.createElement("div");
  tmp.innerHTML = '<audio x-webkit-airplay="deny"></audio>';
  var audioSilentMode = tmp.children.item(0);
  audioSilentMode.src = audioData;
  audioSilentMode.preload = "auto";
  audioSilentMode.type = "audio/mpeg";
  audioSilentMode.disableRemotePlayback = true; // play

  audioSilentMode.play(); // cleanup

  audioSilentMode.remove();
  tmp.remove();
}

module.exports = exports.default;

/***/ }),

/***/ "./src/util/style.js":
/*!***************************!*\
  !*** ./src/util/style.js ***!
  \***************************/
/***/ ((module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = style;

/**
 * Apply a map of styles to an element
 *
 * @param {HTMLElement} el The element that the styles will be applied to
 * @param {Object} styles The map of propName: attribute, both are used as-is
 *
 * @return {HTMLElement} el
 */
function style(el, styles) {
  Object.keys(styles).forEach(function (prop) {
    if (el.style[prop] !== styles[prop]) {
      el.style[prop] = styles[prop];
    }
  });
  return el;
}

module.exports = exports.default;

/***/ }),

/***/ "./src/wavesurfer.js":
/*!***************************!*\
  !*** ./src/wavesurfer.js ***!
  \***************************/
/***/ ((module, exports, __nested_webpack_require_117085__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var util = _interopRequireWildcard(__nested_webpack_require_117085__(/*! ./util */ "./src/util/index.js"));

var _drawer = _interopRequireDefault(__nested_webpack_require_117085__(/*! ./drawer.multicanvas */ "./src/drawer.multicanvas.js"));

var _webaudio = _interopRequireDefault(__nested_webpack_require_117085__(/*! ./webaudio */ "./src/webaudio.js"));

var _mediaelement = _interopRequireDefault(__nested_webpack_require_117085__(/*! ./mediaelement */ "./src/mediaelement.js"));

var _peakcache = _interopRequireDefault(__nested_webpack_require_117085__(/*! ./peakcache */ "./src/peakcache.js"));

var _mediaelementWebaudio = _interopRequireDefault(__nested_webpack_require_117085__(/*! ./mediaelement-webaudio */ "./src/mediaelement-webaudio.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

/*
 * This work is licensed under a BSD-3-Clause License.
 */

/** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */

/** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */

/** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */

/** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */

/** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */

/** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */

/** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */

/**
 * @typedef {Object} WavesurferParams
 * @property {AudioContext} audioContext=null Use your own previously
 * initialized AudioContext or leave blank.
 * @property {number} audioRate=1 Speed at which to play audio. Lower number is
 * slower.
 * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously
 * initialized ScriptProcessorNode or leave blank.
 * @property {boolean} autoCenter=true If a scrollbar is present, center the
 * waveform on current progress
 * @property {number} autoCenterRate=5 If autoCenter is active, rate at which the
 * waveform is centered
 * @property {boolean} autoCenterImmediately=false If autoCenter is active, immediately
 * center waveform on current progress
 * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'|'MediaElementWebAudio'` In most cases
 * you don't have to set this manually. MediaElement is a fallback for unsupported browsers.
 * MediaElementWebAudio allows to use WebAudio API also with big audio files, loading audio like with
 * MediaElement backend (HTML5 audio tag). You have to use the same methods of MediaElement backend for loading and
 * playback, giving also peaks, so the audio data are not decoded. In this way you can use WebAudio features, like filters,
 * also with audio with big duration. For example:
 * ` wavesurfer.load(url | HTMLMediaElement, peaks, preload, duration);
 *   wavesurfer.play();
 *   wavesurfer.setFilter(customFilter);
 * `
 * @property {string} backgroundColor=null Change background color of the
 * waveform container.
 * @property {number} barHeight=1 The height of the wave bars.
 * @property {number} barRadius=0 The radius of the wave bars. Makes bars rounded
 * @property {number} barGap=null The optional spacing between bars of the wave,
 * if not provided will be calculated in legacy format.
 * @property {number} barWidth=null Draw the waveform using bars.
 * @property {number} barMinHeight=null If specified, draw at least a bar of this height,
 * eliminating waveform gaps
 * @property {boolean} closeAudioContext=false Close and nullify all audio
 * contexts when the destroy method is called.
 * @property {!string|HTMLElement} container CSS selector or HTML element where
 * the waveform should be drawn. This is the only required parameter.
 * @property {string} cursorColor='#333' The fill color of the cursor indicating
 * the playhead position.
 * @property {number} cursorWidth=1 Measured in pixels.
 * @property {object} drawingContextAttributes={desynchronized: false} Drawing context
 * attributes.
 * @property {number} duration=null Optional audio length so pre-rendered peaks
 * can be display immediately for example.
 * @property {boolean} fillParent=true Whether to fill the entire container or
 * draw only according to `minPxPerSec`.
 * @property {boolean} forceDecode=false Force decoding of audio using web audio
 * when zooming to get a more detailed waveform.
 * @property {number} height=128 The height of the waveform. Measured in
 * pixels.
 * @property {boolean} hideScrollbar=false Whether to hide the horizontal
 * scrollbar when one would normally be shown.
 * @property {boolean} ignoreSilenceMode=false If true, ignores device silence mode
 * when using the `WebAudio` backend.
 * @property {boolean} interact=true Whether the mouse interaction will be
 * enabled at initialization. You can switch this parameter at any time later
 * on.
 * @property {boolean} loopSelection=true (Use with regions plugin) Enable
 * looping of selected regions
 * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in
 * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next
 * even integer). If the waveform is longer than this value, additional canvases
 * will be used to render the waveform, which is useful for very large waveforms
 * that may be too wide for browsers to draw on a single canvas.
 * @property {boolean} mediaControls=false (Use with backend `MediaElement` or `MediaElementWebAudio`)
 * this enables the native controls for the media element
 * @property {string} mediaType='audio' (Use with backend `MediaElement` or `MediaElementWebAudio`)
 * `'audio'|'video'` ('video' only for `MediaElement`)
 * @property {number} minPxPerSec=20 Minimum number of pixels per second of
 * audio.
 * @property {boolean} normalize=false If true, normalize by the maximum peak
 * instead of 1.0.
 * @property {boolean} partialRender=false Use the PeakCache to improve
 * rendering speed of large waveforms
 * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to
 * calculate display
 * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to
 * register during instantiation, they will be directly initialised unless they
 * are added with the `deferInit` property set to true.
 * @property {string} progressColor='#555' The fill color of the part of the
 * waveform behind the cursor. When `progressColor` and `waveColor` are the same
 * the progress wave is not rendered at all.
 * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the
 * media element in the DOM when the player is destroyed. This is useful when
 * reusing an existing media element via the `loadMediaElement` method.
 * @property {Object} renderer=MultiCanvas Can be used to inject a custom
 * renderer.
 * @property {boolean|number} responsive=false If set to `true` resize the
 * waveform, when the window is resized. This is debounced with a `100ms`
 * timeout by default. If this parameter is a number it represents that timeout.
 * @property {boolean} rtl=false If set to `true`, renders waveform from
 * right-to-left.
 * @property {boolean} scrollParent=false Whether to scroll the container with a
 * lengthy waveform. Otherwise the waveform is shrunk to the container width
 * (see fillParent).
 * @property {number} skipLength=2 Number of seconds to skip with the
 * skipForward() and skipBackward() methods.
 * @property {boolean} splitChannels=false Render with separate waveforms for
 * the channels of the audio
 * @property {SplitChannelOptions} splitChannelsOptions={} Options for splitChannel rendering
 * @property {boolean} vertical=false Render the waveform vertically instead of horizontally.
 * @property {string} waveColor='#999' The fill color of the waveform after the
 * cursor.
 * @property {object} xhr={} XHR options. For example:
 * `let xhr = {
 *     cache: 'default',
 *     mode: 'cors',
 *     method: 'GET',
 *     credentials: 'same-origin',
 *     redirect: 'follow',
 *     referrer: 'client',
 *     requestHeaders: [
 *         {
 *             key: 'Authorization',
 *             value: 'my-token'
 *         }
 *     ]
 * };`
 */

/**
 * @typedef {Object} PluginDefinition
 * @desc The Object used to describe a plugin
 * @example wavesurfer.addPlugin(pluginDefinition);
 * @property {string} name The name of the plugin, the plugin instance will be
 * added as a property to the wavesurfer instance under this name
 * @property {?Object} staticProps The properties that should be added to the
 * wavesurfer instance as static properties
 * @property {?boolean} deferInit Don't initialise plugin
 * automatically
 * @property {Object} params={} The plugin parameters, they are the first parameter
 * passed to the plugin class constructor function
 * @property {PluginClass} instance The plugin instance factory, is called with
 * the dependency specified in extends. Returns the plugin class.
 */

/**
 * @typedef {Object} SplitChannelOptions
 * @desc parameters applied when splitChannels option is true
 * @property {boolean} overlay=false determines whether channels are rendered on top of each other or on separate tracks
 * @property {object} channelColors={} object describing color for each channel. Example:
 * {
 *     0: {
 *         progressColor: 'green',
 *         waveColor: 'pink'
 *     },
 *     1: {
 *         progressColor: 'orange',
 *         waveColor: 'purple'
 *     }
 * }
 * @property {number[]} filterChannels=[] indexes of channels to be hidden from rendering
 * @property {boolean} relativeNormalization=false determines whether
 * normalization is done per channel or maintains proportionality between
 * channels. Only applied when normalize and splitChannels are both true.
 * @since 4.3.0
 */

/**
 * @interface PluginClass
 *
 * @desc This is the interface which is implemented by all plugin classes. Note
 * that this only turns into an observer after being passed through
 * `wavesurfer.addPlugin`.
 *
 * @extends {Observer}
 */
var PluginClass = /*#__PURE__*/function () {
  /**
   * Construct the plugin
   *
   * @param {Object} params={} The plugin params (specific to the plugin)
   * @param {Object} ws The wavesurfer instance
   */
  function PluginClass(params, ws) {
    _classCallCheck(this, PluginClass);
  }
  /**
   * Initialise the plugin
   *
   * Start doing something. This is called by
   * `wavesurfer.initPlugin(pluginName)`
   */


  _createClass(PluginClass, [{
    key: "create",
    value:
    /**
     * Plugin definition factory
     *
     * This function must be used to create a plugin definition which can be
     * used by wavesurfer to correctly instantiate the plugin.
     *
     * It returns a `PluginDefinition` object representing the plugin.
     *
     * @param {Object} params={} The plugin params (specific to the plugin)
     */
    function create(params) {}
  }, {
    key: "init",
    value: function init() {}
    /**
     * Destroy the plugin instance
     *
     * Stop doing something. This is called by
     * `wavesurfer.destroyPlugin(pluginName)`
     */

  }, {
    key: "destroy",
    value: function destroy() {}
  }]);

  return PluginClass;
}();
/**
 * WaveSurfer core library class
 *
 * @extends {Observer}
 * @example
 * const params = {
 *   container: '#waveform',
 *   waveColor: 'violet',
 *   progressColor: 'purple'
 * };
 *
 * // initialise like this
 * const wavesurfer = WaveSurfer.create(params);
 *
 * // or like this ...
 * const wavesurfer = new WaveSurfer(params);
 * wavesurfer.init();
 *
 * // load audio file
 * wavesurfer.load('example/media/demo.wav');
 */


var WaveSurfer = /*#__PURE__*/function (_util$Observer) {
  _inherits(WaveSurfer, _util$Observer);

  var _super = _createSuper(WaveSurfer);

  /**
   * Initialise wavesurfer instance
   *
   * @param {WavesurferParams} params Instantiation options for wavesurfer
   * @example
   * const wavesurfer = new WaveSurfer(params);
   * @returns {this} Wavesurfer instance
   */
  function WaveSurfer(params) {
    var _this;

    _classCallCheck(this, WaveSurfer);

    _this = _super.call(this);
    /**
     * Extract relevant parameters (or defaults)
     * @private
     */

    _this.defaultParams = {
      audioContext: null,
      audioScriptProcessor: null,
      audioRate: 1,
      autoCenter: true,
      autoCenterRate: 5,
      autoCenterImmediately: false,
      backend: 'WebAudio',
      backgroundColor: null,
      barHeight: 1,
      barRadius: 0,
      barGap: null,
      barMinHeight: null,
      container: null,
      cursorColor: '#333',
      cursorWidth: 1,
      dragSelection: true,
      drawingContextAttributes: {
        // Boolean that hints the user agent to reduce the latency
        // by desynchronizing the canvas paint cycle from the event
        // loop
        desynchronized: false
      },
      duration: null,
      fillParent: true,
      forceDecode: false,
      height: 128,
      hideScrollbar: false,
      ignoreSilenceMode: false,
      interact: true,
      loopSelection: true,
      maxCanvasWidth: 4000,
      mediaContainer: null,
      mediaControls: false,
      mediaType: 'audio',
      minPxPerSec: 20,
      normalize: false,
      partialRender: false,
      pixelRatio: window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,
      plugins: [],
      progressColor: '#555',
      removeMediaElementOnDestroy: true,
      renderer: _drawer.default,
      responsive: false,
      rtl: false,
      scrollParent: false,
      skipLength: 2,
      splitChannels: false,
      splitChannelsOptions: {
        overlay: false,
        channelColors: {},
        filterChannels: [],
        relativeNormalization: false
      },
      vertical: false,
      waveColor: '#999',
      xhr: {}
    };
    _this.backends = {
      MediaElement: _mediaelement.default,
      WebAudio: _webaudio.default,
      MediaElementWebAudio: _mediaelementWebaudio.default
    };
    _this.util = util;
    _this.params = Object.assign({}, _this.defaultParams, params);
    _this.params.splitChannelsOptions = Object.assign({}, _this.defaultParams.splitChannelsOptions, params.splitChannelsOptions);
    /** @private */

    _this.container = 'string' == typeof params.container ? document.querySelector(_this.params.container) : _this.params.container;

    if (!_this.container) {
      throw new Error('Container element not found');
    }

    if (_this.params.mediaContainer == null) {
      /** @private */
      _this.mediaContainer = _this.container;
    } else if (typeof _this.params.mediaContainer == 'string') {
      /** @private */
      _this.mediaContainer = document.querySelector(_this.params.mediaContainer);
    } else {
      /** @private */
      _this.mediaContainer = _this.params.mediaContainer;
    }

    if (!_this.mediaContainer) {
      throw new Error('Media Container element not found');
    }

    if (_this.params.maxCanvasWidth <= 1) {
      throw new Error('maxCanvasWidth must be greater than 1');
    } else if (_this.params.maxCanvasWidth % 2 == 1) {
      throw new Error('maxCanvasWidth must be an even number');
    }

    if (_this.params.rtl === true) {
      if (_this.params.vertical === true) {
        util.style(_this.container, {
          transform: 'rotateX(180deg)'
        });
      } else {
        util.style(_this.container, {
          transform: 'rotateY(180deg)'
        });
      }
    }

    if (_this.params.backgroundColor) {
      _this.setBackgroundColor(_this.params.backgroundColor);
    }
    /**
     * @private Used to save the current volume when muting so we can
     * restore once unmuted
     * @type {number}
     */


    _this.savedVolume = 0;
    /**
     * @private The current muted state
     * @type {boolean}
     */

    _this.isMuted = false;
    /**
     * @private Will hold a list of event descriptors that need to be
     * canceled on subsequent loads of audio
     * @type {Object[]}
     */

    _this.tmpEvents = [];
    /**
     * @private Holds any running audio downloads
     * @type {Observer}
     */

    _this.currentRequest = null;
    /** @private */

    _this.arraybuffer = null;
    /** @private */

    _this.drawer = null;
    /** @private */

    _this.backend = null;
    /** @private */

    _this.peakCache = null; // cache constructor objects

    if (typeof _this.params.renderer !== 'function') {
      throw new Error('Renderer parameter is invalid');
    }
    /**
     * @private The uninitialised Drawer class
     */


    _this.Drawer = _this.params.renderer;
    /**
     * @private The uninitialised Backend class
     */
    // Back compat

    if (_this.params.backend == 'AudioElement') {
      _this.params.backend = 'MediaElement';
    }

    if ((_this.params.backend == 'WebAudio' || _this.params.backend === 'MediaElementWebAudio') && !_webaudio.default.prototype.supportsWebAudio.call(null)) {
      _this.params.backend = 'MediaElement';
    }

    _this.Backend = _this.backends[_this.params.backend];
    /**
     * @private map of plugin names that are currently initialised
     */

    _this.initialisedPluginList = {};
    /** @private */

    _this.isDestroyed = false;
    /**
     * Get the current ready status.
     *
     * @example const isReady = wavesurfer.isReady;
     * @return {boolean}
     */

    _this.isReady = false; // responsive debounced event listener. If this.params.responsive is not
    // set, this is never called. Use 100ms or this.params.responsive as
    // timeout for the debounce function.

    var prevWidth = 0;
    _this._onResize = util.debounce(function () {
      if (prevWidth != _this.drawer.wrapper.clientWidth && !_this.params.scrollParent) {
        prevWidth = _this.drawer.wrapper.clientWidth;

        _this.drawer.fireEvent('redraw');
      }
    }, typeof _this.params.responsive === 'number' ? _this.params.responsive : 100);
    return _possibleConstructorReturn(_this, _assertThisInitialized(_this));
  }
  /**
   * Initialise the wave
   *
   * @example
   * var wavesurfer = new WaveSurfer(params);
   * wavesurfer.init();
   * @return {this} The wavesurfer instance
   */


  _createClass(WaveSurfer, [{
    key: "init",
    value: function init() {
      this.registerPlugins(this.params.plugins);
      this.createDrawer();
      this.createBackend();
      this.createPeakCache();
      return this;
    }
    /**
     * Add and initialise array of plugins (if `plugin.deferInit` is falsey),
     * this function is called in the init function of wavesurfer
     *
     * @param {PluginDefinition[]} plugins An array of plugin definitions
     * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions
     * @return {this} The wavesurfer instance
     */

  }, {
    key: "registerPlugins",
    value: function registerPlugins(plugins) {
      var _this2 = this;

      // first instantiate all the plugins
      plugins.forEach(function (plugin) {
        return _this2.addPlugin(plugin);
      }); // now run the init functions

      plugins.forEach(function (plugin) {
        // call init function of the plugin if deferInit is falsey
        // in that case you would manually use initPlugins()
        if (!plugin.deferInit) {
          _this2.initPlugin(plugin.name);
        }
      });
      this.fireEvent('plugins-registered', plugins);
      return this;
    }
    /**
     * Get a map of plugin names that are currently initialised
     *
     * @example wavesurfer.getPlugins();
     * @return {Object} Object with plugin names
     */

  }, {
    key: "getActivePlugins",
    value: function getActivePlugins() {
      return this.initialisedPluginList;
    }
    /**
     * Add a plugin object to wavesurfer
     *
     * @param {PluginDefinition} plugin A plugin definition
     * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added
     * @example wavesurfer.addPlugin(WaveSurfer.minimap());
     * @return {this} The wavesurfer instance
     */

  }, {
    key: "addPlugin",
    value: function addPlugin(plugin) {
      var _this3 = this;

      if (!plugin.name) {
        throw new Error('Plugin does not have a name!');
      }

      if (!plugin.instance) {
        throw new Error("Plugin ".concat(plugin.name, " does not have an instance property!"));
      } // staticProps properties are applied to wavesurfer instance


      if (plugin.staticProps) {
        Object.keys(plugin.staticProps).forEach(function (pluginStaticProp) {
          /**
           * Properties defined in a plugin definition's `staticProps` property are added as
           * staticProps properties of the WaveSurfer instance
           */
          _this3[pluginStaticProp] = plugin.staticProps[pluginStaticProp];
        });
      }

      var Instance = plugin.instance; // turn the plugin instance into an observer

      var observerPrototypeKeys = Object.getOwnPropertyNames(util.Observer.prototype);
      observerPrototypeKeys.forEach(function (key) {
        Instance.prototype[key] = util.Observer.prototype[key];
      });
      /**
       * Instantiated plugin classes are added as a property of the wavesurfer
       * instance
       * @type {Object}
       */

      this[plugin.name] = new Instance(plugin.params || {}, this);
      this.fireEvent('plugin-added', plugin.name);
      return this;
    }
    /**
     * Initialise a plugin
     *
     * @param {string} name A plugin name
     * @emits WaveSurfer#plugin-initialised
     * @example wavesurfer.initPlugin('minimap');
     * @return {this} The wavesurfer instance
     */

  }, {
    key: "initPlugin",
    value: function initPlugin(name) {
      if (!this[name]) {
        throw new Error("Plugin ".concat(name, " has not been added yet!"));
      }

      if (this.initialisedPluginList[name]) {
        // destroy any already initialised plugins
        this.destroyPlugin(name);
      }

      this[name].init();
      this.initialisedPluginList[name] = true;
      this.fireEvent('plugin-initialised', name);
      return this;
    }
    /**
     * Destroy a plugin
     *
     * @param {string} name A plugin name
     * @emits WaveSurfer#plugin-destroyed
     * @example wavesurfer.destroyPlugin('minimap');
     * @returns {this} The wavesurfer instance
     */

  }, {
    key: "destroyPlugin",
    value: function destroyPlugin(name) {
      if (!this[name]) {
        throw new Error("Plugin ".concat(name, " has not been added yet and cannot be destroyed!"));
      }

      if (!this.initialisedPluginList[name]) {
        throw new Error("Plugin ".concat(name, " is not active and cannot be destroyed!"));
      }

      if (typeof this[name].destroy !== 'function') {
        throw new Error("Plugin ".concat(name, " does not have a destroy function!"));
      }

      this[name].destroy();
      delete this.initialisedPluginList[name];
      this.fireEvent('plugin-destroyed', name);
      return this;
    }
    /**
     * Destroy all initialised plugins. Convenience function to use when
     * wavesurfer is removed
     *
     * @private
     */

  }, {
    key: "destroyAllPlugins",
    value: function destroyAllPlugins() {
      var _this4 = this;

      Object.keys(this.initialisedPluginList).forEach(function (name) {
        return _this4.destroyPlugin(name);
      });
    }
    /**
     * Create the drawer and draw the waveform
     *
     * @private
     * @emits WaveSurfer#drawer-created
     */

  }, {
    key: "createDrawer",
    value: function createDrawer() {
      var _this5 = this;

      this.drawer = new this.Drawer(this.container, this.params);
      this.drawer.init();
      this.fireEvent('drawer-created', this.drawer);

      if (this.params.responsive !== false) {
        window.addEventListener('resize', this._onResize, true);
        window.addEventListener('orientationchange', this._onResize, true);
      }

      this.drawer.on('redraw', function () {
        _this5.drawBuffer();

        _this5.drawer.progress(_this5.backend.getPlayedPercents());
      }); // Click-to-seek

      this.drawer.on('click', function (e, progress) {
        setTimeout(function () {
          return _this5.seekTo(progress);
        }, 0);
      }); // Relay the scroll event from the drawer

      this.drawer.on('scroll', function (e) {
        if (_this5.params.partialRender) {
          _this5.drawBuffer();
        }

        _this5.fireEvent('scroll', e);
      });
    }
    /**
     * Create the backend
     *
     * @private
     * @emits WaveSurfer#backend-created
     */

  }, {
    key: "createBackend",
    value: function createBackend() {
      var _this6 = this;

      if (this.backend) {
        this.backend.destroy();
      }

      this.backend = new this.Backend(this.params);
      this.backend.init();
      this.fireEvent('backend-created', this.backend);
      this.backend.on('finish', function () {
        _this6.drawer.progress(_this6.backend.getPlayedPercents());

        _this6.fireEvent('finish');
      });
      this.backend.on('play', function () {
        return _this6.fireEvent('play');
      });
      this.backend.on('pause', function () {
        return _this6.fireEvent('pause');
      });
      this.backend.on('audioprocess', function (time) {
        _this6.drawer.progress(_this6.backend.getPlayedPercents());

        _this6.fireEvent('audioprocess', time);
      }); // only needed for MediaElement and MediaElementWebAudio backend

      if (this.params.backend === 'MediaElement' || this.params.backend === 'MediaElementWebAudio') {
        this.backend.on('seek', function () {
          _this6.drawer.progress(_this6.backend.getPlayedPercents());
        });
        this.backend.on('volume', function () {
          var newVolume = _this6.getVolume();

          _this6.fireEvent('volume', newVolume);

          if (_this6.backend.isMuted !== _this6.isMuted) {
            _this6.isMuted = _this6.backend.isMuted;

            _this6.fireEvent('mute', _this6.isMuted);
          }
        });
      }
    }
    /**
     * Create the peak cache
     *
     * @private
     */

  }, {
    key: "createPeakCache",
    value: function createPeakCache() {
      if (this.params.partialRender) {
        this.peakCache = new _peakcache.default();
      }
    }
    /**
     * Get the duration of the audio clip
     *
     * @example const duration = wavesurfer.getDuration();
     * @return {number} Duration in seconds
     */

  }, {
    key: "getDuration",
    value: function getDuration() {
      return this.backend.getDuration();
    }
    /**
     * Get the current playback position
     *
     * @example const currentTime = wavesurfer.getCurrentTime();
     * @return {number} Playback position in seconds
     */

  }, {
    key: "getCurrentTime",
    value: function getCurrentTime() {
      return this.backend.getCurrentTime();
    }
    /**
     * Set the current play time in seconds.
     *
     * @param {number} seconds A positive number in seconds. E.g. 10 means 10
     * seconds, 60 means 1 minute
     */

  }, {
    key: "setCurrentTime",
    value: function setCurrentTime(seconds) {
      if (seconds >= this.getDuration()) {
        this.seekTo(1);
      } else {
        this.seekTo(seconds / this.getDuration());
      }
    }
    /**
     * Starts playback from the current position. Optional start and end
     * measured in seconds can be used to set the range of audio to play.
     *
     * @param {?number} start Position to start at
     * @param {?number} end Position to end at
     * @emits WaveSurfer#interaction
     * @return {Promise} Result of the backend play method
     * @example
     * // play from second 1 to 5
     * wavesurfer.play(1, 5);
     */

  }, {
    key: "play",
    value: function play(start, end) {
      var _this7 = this;

      if (this.params.ignoreSilenceMode) {
        // ignores device hardware silence mode
        util.ignoreSilenceMode();
      }

      this.fireEvent('interaction', function () {
        return _this7.play(start, end);
      });
      return this.backend.play(start, end);
    }
    /**
     * Set a point in seconds for playback to stop at.
     *
     * @param {number} position Position (in seconds) to stop at
     * @version 3.3.0
     */

  }, {
    key: "setPlayEnd",
    value: function setPlayEnd(position) {
      this.backend.setPlayEnd(position);
    }
    /**
     * Stops and pauses playback
     *
     * @example wavesurfer.pause();
     * @return {Promise} Result of the backend pause method
     */

  }, {
    key: "pause",
    value: function pause() {
      if (!this.backend.isPaused()) {
        return this.backend.pause();
      }
    }
    /**
     * Toggle playback
     *
     * @example wavesurfer.playPause();
     * @return {Promise} Result of the backend play or pause method
     */

  }, {
    key: "playPause",
    value: function playPause() {
      return this.backend.isPaused() ? this.play() : this.pause();
    }
    /**
     * Get the current playback state
     *
     * @example const isPlaying = wavesurfer.isPlaying();
     * @return {boolean} False if paused, true if playing
     */

  }, {
    key: "isPlaying",
    value: function isPlaying() {
      return !this.backend.isPaused();
    }
    /**
     * Skip backward
     *
     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
     * is used
     * @example wavesurfer.skipBackward();
     */

  }, {
    key: "skipBackward",
    value: function skipBackward(seconds) {
      this.skip(-seconds || -this.params.skipLength);
    }
    /**
     * Skip forward
     *
     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
     * is used
     * @example wavesurfer.skipForward();
     */

  }, {
    key: "skipForward",
    value: function skipForward(seconds) {
      this.skip(seconds || this.params.skipLength);
    }
    /**
     * Skip a number of seconds from the current position (use a negative value
     * to go backwards).
     *
     * @param {number} offset Amount to skip back or forwards
     * @example
     * // go back 2 seconds
     * wavesurfer.skip(-2);
     */

  }, {
    key: "skip",
    value: function skip(offset) {
      var duration = this.getDuration() || 1;
      var position = this.getCurrentTime() || 0;
      position = Math.max(0, Math.min(duration, position + (offset || 0)));
      this.seekAndCenter(position / duration);
    }
    /**
     * Seeks to a position and centers the view
     *
     * @param {number} progress Between 0 (=beginning) and 1 (=end)
     * @example
     * // seek and go to the middle of the audio
     * wavesurfer.seekTo(0.5);
     */

  }, {
    key: "seekAndCenter",
    value: function seekAndCenter(progress) {
      this.seekTo(progress);
      this.drawer.recenter(progress);
    }
    /**
     * Seeks to a position
     *
     * @param {number} progress Between 0 (=beginning) and 1 (=end)
     * @emits WaveSurfer#interaction
     * @emits WaveSurfer#seek
     * @example
     * // seek to the middle of the audio
     * wavesurfer.seekTo(0.5);
     */

  }, {
    key: "seekTo",
    value: function seekTo(progress) {
      var _this8 = this;

      // return an error if progress is not a number between 0 and 1
      if (typeof progress !== 'number' || !isFinite(progress) || progress < 0 || progress > 1) {
        throw new Error('Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!');
      }

      this.fireEvent('interaction', function () {
        return _this8.seekTo(progress);
      });
      var isWebAudioBackend = this.params.backend === 'WebAudio';
      var paused = this.backend.isPaused();

      if (isWebAudioBackend && !paused) {
        this.backend.pause();
      } // avoid small scrolls while paused seeking


      var oldScrollParent = this.params.scrollParent;
      this.params.scrollParent = false;
      this.backend.seekTo(progress * this.getDuration());
      this.drawer.progress(progress);

      if (isWebAudioBackend && !paused) {
        this.backend.play();
      }

      this.params.scrollParent = oldScrollParent;
      this.fireEvent('seek', progress);
    }
    /**
     * Stops and goes to the beginning.
     *
     * @example wavesurfer.stop();
     */

  }, {
    key: "stop",
    value: function stop() {
      this.pause();
      this.seekTo(0);
      this.drawer.progress(0);
    }
    /**
     * Sets the ID of the audio device to use for output and returns a Promise.
     *
     * @param {string} deviceId String value representing underlying output
     * device
     * @returns {Promise} `Promise` that resolves to `undefined` when there are
     * no errors detected.
     */

  }, {
    key: "setSinkId",
    value: function setSinkId(deviceId) {
      return this.backend.setSinkId(deviceId);
    }
    /**
     * Set the playback volume.
     *
     * @param {number} newVolume A value between 0 and 1, 0 being no
     * volume and 1 being full volume.
     * @emits WaveSurfer#volume
     */

  }, {
    key: "setVolume",
    value: function setVolume(newVolume) {
      this.backend.setVolume(newVolume);
      this.fireEvent('volume', newVolume);
    }
    /**
     * Get the playback volume.
     *
     * @return {number} A value between 0 and 1, 0 being no
     * volume and 1 being full volume.
     */

  }, {
    key: "getVolume",
    value: function getVolume() {
      return this.backend.getVolume();
    }
    /**
     * Set the playback rate.
     *
     * @param {number} rate A positive number. E.g. 0.5 means half the normal
     * speed, 2 means double speed and so on.
     * @example wavesurfer.setPlaybackRate(2);
     */

  }, {
    key: "setPlaybackRate",
    value: function setPlaybackRate(rate) {
      this.backend.setPlaybackRate(rate);
    }
    /**
     * Get the playback rate.
     *
     * @return {number} The current playback rate.
     */

  }, {
    key: "getPlaybackRate",
    value: function getPlaybackRate() {
      return this.backend.getPlaybackRate();
    }
    /**
     * Toggle the volume on and off. If not currently muted it will save the
     * current volume value and turn the volume off. If currently muted then it
     * will restore the volume to the saved value, and then rest the saved
     * value.
     *
     * @example wavesurfer.toggleMute();
     */

  }, {
    key: "toggleMute",
    value: function toggleMute() {
      this.setMute(!this.isMuted);
    }
    /**
     * Enable or disable muted audio
     *
     * @param {boolean} mute Specify `true` to mute audio.
     * @emits WaveSurfer#volume
     * @emits WaveSurfer#mute
     * @example
     * // unmute
     * wavesurfer.setMute(false);
     * console.log(wavesurfer.getMute()) // logs false
     */

  }, {
    key: "setMute",
    value: function setMute(mute) {
      // ignore all muting requests if the audio is already in that state
      if (mute === this.isMuted) {
        this.fireEvent('mute', this.isMuted);
        return;
      }

      if (this.backend.setMute) {
        // Backends such as the MediaElement backend have their own handling
        // of mute, let them handle it.
        this.backend.setMute(mute);
        this.isMuted = mute;
      } else {
        if (mute) {
          // If currently not muted then save current volume,
          // turn off the volume and update the mute properties
          this.savedVolume = this.backend.getVolume();
          this.backend.setVolume(0);
          this.isMuted = true;
          this.fireEvent('volume', 0);
        } else {
          // If currently muted then restore to the saved volume
          // and update the mute properties
          this.backend.setVolume(this.savedVolume);
          this.isMuted = false;
          this.fireEvent('volume', this.savedVolume);
        }
      }

      this.fireEvent('mute', this.isMuted);
    }
    /**
     * Get the current mute status.
     *
     * @example const isMuted = wavesurfer.getMute();
     * @return {boolean} Current mute status
     */

  }, {
    key: "getMute",
    value: function getMute() {
      return this.isMuted;
    }
    /**
     * Get the list of current set filters as an array.
     *
     * Filters must be set with setFilters method first
     *
     * @return {array} List of enabled filters
     */

  }, {
    key: "getFilters",
    value: function getFilters() {
      return this.backend.filters || [];
    }
    /**
     * Toggles `scrollParent` and redraws
     *
     * @example wavesurfer.toggleScroll();
     */

  }, {
    key: "toggleScroll",
    value: function toggleScroll() {
      this.params.scrollParent = !this.params.scrollParent;
      this.drawBuffer();
    }
    /**
     * Toggle mouse interaction
     *
     * @example wavesurfer.toggleInteraction();
     */

  }, {
    key: "toggleInteraction",
    value: function toggleInteraction() {
      this.params.interact = !this.params.interact;
    }
    /**
     * Get the fill color of the waveform after the cursor.
     *
     * @return {string} A CSS color string.
     */

  }, {
    key: "getWaveColor",
    value: function getWaveColor() {
      return this.params.waveColor;
    }
    /**
     * Set the fill color of the waveform after the cursor.
     *
     * @param {string} color A CSS color string.
     * @example wavesurfer.setWaveColor('#ddd');
     */

  }, {
    key: "setWaveColor",
    value: function setWaveColor(color) {
      this.params.waveColor = color;
      this.drawBuffer();
    }
    /**
     * Get the fill color of the waveform behind the cursor.
     *
     * @return {string} A CSS color string.
     */

  }, {
    key: "getProgressColor",
    value: function getProgressColor() {
      return this.params.progressColor;
    }
    /**
     * Set the fill color of the waveform behind the cursor.
     *
     * @param {string} color A CSS color string.
     * @example wavesurfer.setProgressColor('#400');
     */

  }, {
    key: "setProgressColor",
    value: function setProgressColor(color) {
      this.params.progressColor = color;
      this.drawBuffer();
    }
    /**
     * Get the background color of the waveform container.
     *
     * @return {string} A CSS color string.
     */

  }, {
    key: "getBackgroundColor",
    value: function getBackgroundColor() {
      return this.params.backgroundColor;
    }
    /**
     * Set the background color of the waveform container.
     *
     * @param {string} color A CSS color string.
     * @example wavesurfer.setBackgroundColor('#FF00FF');
     */

  }, {
    key: "setBackgroundColor",
    value: function setBackgroundColor(color) {
      this.params.backgroundColor = color;
      util.style(this.container, {
        background: this.params.backgroundColor
      });
    }
    /**
     * Get the fill color of the cursor indicating the playhead
     * position.
     *
     * @return {string} A CSS color string.
     */

  }, {
    key: "getCursorColor",
    value: function getCursorColor() {
      return this.params.cursorColor;
    }
    /**
     * Set the fill color of the cursor indicating the playhead
     * position.
     *
     * @param {string} color A CSS color string.
     * @example wavesurfer.setCursorColor('#222');
     */

  }, {
    key: "setCursorColor",
    value: function setCursorColor(color) {
      this.params.cursorColor = color;
      this.drawer.updateCursor();
    }
    /**
     * Get the height of the waveform.
     *
     * @return {number} Height measured in pixels.
     */

  }, {
    key: "getHeight",
    value: function getHeight() {
      return this.params.height;
    }
    /**
     * Set the height of the waveform.
     *
     * @param {number} height Height measured in pixels.
     * @example wavesurfer.setHeight(200);
     */

  }, {
    key: "setHeight",
    value: function setHeight(height) {
      this.params.height = height;
      this.drawer.setHeight(height * this.params.pixelRatio);
      this.drawBuffer();
    }
    /**
     * Hide channels from being drawn on the waveform if splitting channels.
     *
     * For example, if we want to draw only the peaks for the right stereo channel:
     *
     * const wavesurfer = new WaveSurfer.create({...splitChannels: true});
     * wavesurfer.load('stereo_audio.mp3');
     *
     * wavesurfer.setFilteredChannel([0]); <-- hide left channel peaks.
     *
     * @param {array} channelIndices Channels to be filtered out from drawing.
     * @version 4.0.0
     */

  }, {
    key: "setFilteredChannels",
    value: function setFilteredChannels(channelIndices) {
      this.params.splitChannelsOptions.filterChannels = channelIndices;
      this.drawBuffer();
    }
    /**
     * Get the correct peaks for current wave view-port and render wave
     *
     * @private
     * @emits WaveSurfer#redraw
     */

  }, {
    key: "drawBuffer",
    value: function drawBuffer() {
      var nominalWidth = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio);
      var parentWidth = this.drawer.getWidth();
      var width = nominalWidth; // always start at 0 after zooming for scrolling : issue redraw left part

      var start = 0;
      var end = Math.max(start + parentWidth, width); // Fill container

      if (this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth)) {
        width = parentWidth;
        start = 0;
        end = width;
      }

      var peaks;

      if (this.params.partialRender) {
        var newRanges = this.peakCache.addRangeToPeakCache(width, start, end);
        var i;

        for (i = 0; i < newRanges.length; i++) {
          peaks = this.backend.getPeaks(width, newRanges[i][0], newRanges[i][1]);
          this.drawer.drawPeaks(peaks, width, newRanges[i][0], newRanges[i][1]);
        }
      } else {
        peaks = this.backend.getPeaks(width, start, end);
        this.drawer.drawPeaks(peaks, width, start, end);
      }

      this.fireEvent('redraw', peaks, width);
    }
    /**
     * Horizontally zooms the waveform in and out. It also changes the parameter
     * `minPxPerSec` and enables the `scrollParent` option. Calling the function
     * with a falsey parameter will reset the zoom state.
     *
     * @param {?number} pxPerSec Number of horizontal pixels per second of
     * audio, if none is set the waveform returns to unzoomed state
     * @emits WaveSurfer#zoom
     * @example wavesurfer.zoom(20);
     */

  }, {
    key: "zoom",
    value: function zoom(pxPerSec) {
      if (!pxPerSec) {
        this.params.minPxPerSec = this.defaultParams.minPxPerSec;
        this.params.scrollParent = false;
      } else {
        this.params.minPxPerSec = pxPerSec;
        this.params.scrollParent = true;
      }

      this.drawBuffer();
      this.drawer.progress(this.backend.getPlayedPercents());
      this.drawer.recenter(this.getCurrentTime() / this.getDuration());
      this.fireEvent('zoom', pxPerSec);
    }
    /**
     * Decode buffer and load
     *
     * @private
     * @param {ArrayBuffer} arraybuffer Buffer to process
     */

  }, {
    key: "loadArrayBuffer",
    value: function loadArrayBuffer(arraybuffer) {
      var _this9 = this;

      this.decodeArrayBuffer(arraybuffer, function (data) {
        if (!_this9.isDestroyed) {
          _this9.loadDecodedBuffer(data);
        }
      });
    }
    /**
     * Directly load an externally decoded AudioBuffer
     *
     * @private
     * @param {AudioBuffer} buffer Buffer to process
     * @emits WaveSurfer#ready
     */

  }, {
    key: "loadDecodedBuffer",
    value: function loadDecodedBuffer(buffer) {
      this.backend.load(buffer);
      this.drawBuffer();
      this.isReady = true;
      this.fireEvent('ready');
    }
    /**
     * Loads audio data from a Blob or File object
     *
     * @param {Blob|File} blob Audio data
     * @example
     */

  }, {
    key: "loadBlob",
    value: function loadBlob(blob) {
      var _this10 = this;

      // Create file reader
      var reader = new FileReader();
      reader.addEventListener('progress', function (e) {
        return _this10.onProgress(e);
      });
      reader.addEventListener('load', function (e) {
        return _this10.loadArrayBuffer(e.target.result);
      });
      reader.addEventListener('error', function () {
        return _this10.fireEvent('error', 'Error reading file');
      });
      reader.readAsArrayBuffer(blob);
      this.empty();
    }
    /**
     * Loads audio and re-renders the waveform.
     *
     * @param {string|HTMLMediaElement} url The url of the audio file or the
     * audio element with the audio
     * @param {number[]|Number.<Array[]>} peaks Wavesurfer does not have to decode
     * the audio to render the waveform if this is specified
     * @param {?string} preload (Use with backend `MediaElement` and `MediaElementWebAudio`)
     * `'none'|'metadata'|'auto'` Preload attribute for the media element
     * @param {?number} duration The duration of the audio. This is used to
     * render the peaks data in the correct size for the audio duration (as
     * befits the current `minPxPerSec` and zoom value) without having to decode
     * the audio.
     * @returns {void}
     * @throws Will throw an error if the `url` argument is empty.
     * @example
     * // uses fetch or media element to load file (depending on backend)
     * wavesurfer.load('http://example.com/demo.wav');
     *
     * // setting preload attribute with media element backend and supplying
     * // peaks
     * wavesurfer.load(
     *   'http://example.com/demo.wav',
     *   [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],
     *   true
     * );
     */

  }, {
    key: "load",
    value: function load(url, peaks, preload, duration) {
      if (!url) {
        throw new Error('url parameter cannot be empty');
      }

      this.empty();

      if (preload) {
        // check whether the preload attribute will be usable and if not log
        // a warning listing the reasons why not and nullify the variable
        var preloadIgnoreReasons = {
          "Preload is not 'auto', 'none' or 'metadata'": ['auto', 'metadata', 'none'].indexOf(preload) === -1,
          'Peaks are not provided': !peaks,
          "Backend is not of type 'MediaElement' or 'MediaElementWebAudio'": ['MediaElement', 'MediaElementWebAudio'].indexOf(this.params.backend) === -1,
          'Url is not of type string': typeof url !== 'string'
        };
        var activeReasons = Object.keys(preloadIgnoreReasons).filter(function (reason) {
          return preloadIgnoreReasons[reason];
        });

        if (activeReasons.length) {
          // eslint-disable-next-line no-console
          console.warn('Preload parameter of wavesurfer.load will be ignored because:\n\t- ' + activeReasons.join('\n\t- ')); // stop invalid values from being used

          preload = null;
        }
      } // loadBuffer(url, peaks, duration) requires that url is a string
      // but users can pass in a HTMLMediaElement to WaveSurfer


      if (this.params.backend === 'WebAudio' && url instanceof HTMLMediaElement) {
        url = url.src;
      }

      switch (this.params.backend) {
        case 'WebAudio':
          return this.loadBuffer(url, peaks, duration);

        case 'MediaElement':
        case 'MediaElementWebAudio':
          return this.loadMediaElement(url, peaks, preload, duration);
      }
    }
    /**
     * Loads audio using Web Audio buffer backend.
     *
     * @private
     * @emits WaveSurfer#waveform-ready
     * @param {string} url URL of audio file
     * @param {number[]|Number.<Array[]>} peaks Peaks data
     * @param {?number} duration Optional duration of audio file
     * @returns {void}
     */

  }, {
    key: "loadBuffer",
    value: function loadBuffer(url, peaks, duration) {
      var _this11 = this;

      var load = function load(action) {
        if (action) {
          _this11.tmpEvents.push(_this11.once('ready', action));
        }

        return _this11.getArrayBuffer(url, function (data) {
          return _this11.loadArrayBuffer(data);
        });
      };

      if (peaks) {
        this.backend.setPeaks(peaks, duration);
        this.drawBuffer();
        this.fireEvent('waveform-ready');
        this.tmpEvents.push(this.once('interaction', load));
      } else {
        return load();
      }
    }
    /**
     * Either create a media element, or load an existing media element.
     *
     * @private
     * @emits WaveSurfer#waveform-ready
     * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an
     * existing HTML5 Audio/Video Element
     * @param {number[]|Number.<Array[]>} peaks Array of peaks. Required to bypass web audio
     * dependency
     * @param {?boolean} preload Set to true if the preload attribute of the
     * audio element should be enabled
     * @param {?number} duration Optional duration of audio file
     */

  }, {
    key: "loadMediaElement",
    value: function loadMediaElement(urlOrElt, peaks, preload, duration) {
      var _this12 = this;

      var url = urlOrElt;

      if (typeof urlOrElt === 'string') {
        this.backend.load(url, this.mediaContainer, peaks, preload);
      } else {
        var elt = urlOrElt;
        this.backend.loadElt(elt, peaks); // If peaks are not provided,
        // url = element.src so we can get peaks with web audio

        url = elt.src;
      }

      this.tmpEvents.push(this.backend.once('canplay', function () {
        // ignore when backend was already destroyed
        if (!_this12.backend.destroyed) {
          _this12.drawBuffer();

          _this12.isReady = true;

          _this12.fireEvent('ready');
        }
      }), this.backend.once('error', function (err) {
        return _this12.fireEvent('error', err);
      })); // If peaks are provided, render them and fire the `waveform-ready` event.

      if (peaks) {
        this.backend.setPeaks(peaks, duration);
        this.drawBuffer();
        this.fireEvent('waveform-ready');
      } // If no pre-decoded peaks are provided, or are provided with
      // forceDecode flag, attempt to download the audio file and decode it
      // with Web Audio.


      if ((!peaks || this.params.forceDecode) && this.backend.supportsWebAudio()) {
        this.getArrayBuffer(url, function (arraybuffer) {
          _this12.decodeArrayBuffer(arraybuffer, function (buffer) {
            _this12.backend.buffer = buffer;

            _this12.backend.setPeaks(null);

            _this12.drawBuffer();

            _this12.fireEvent('waveform-ready');
          });
        });
      }
    }
    /**
     * Decode an array buffer and pass data to a callback
     *
     * @private
     * @param {Object} arraybuffer The array buffer to decode
     * @param {function} callback The function to call on complete
     */

  }, {
    key: "decodeArrayBuffer",
    value: function decodeArrayBuffer(arraybuffer, callback) {
      var _this13 = this;

      if (!this.isDestroyed) {
        this.arraybuffer = arraybuffer;
        this.backend.decodeArrayBuffer(arraybuffer, function (data) {
          // Only use the decoded data if we haven't been destroyed or
          // another decode started in the meantime
          if (!_this13.isDestroyed && _this13.arraybuffer == arraybuffer) {
            callback(data);
            _this13.arraybuffer = null;
          }
        }, function () {
          return _this13.fireEvent('error', 'Error decoding audiobuffer');
        });
      }
    }
    /**
     * Load an array buffer using fetch and pass the result to a callback
     *
     * @param {string} url The URL of the file object
     * @param {function} callback The function to call on complete
     * @returns {util.fetchFile} fetch call
     * @private
     */

  }, {
    key: "getArrayBuffer",
    value: function getArrayBuffer(url, callback) {
      var _this14 = this;

      var options = Object.assign({
        url: url,
        responseType: 'arraybuffer'
      }, this.params.xhr);
      var request = util.fetchFile(options);
      this.currentRequest = request;
      this.tmpEvents.push(request.on('progress', function (e) {
        _this14.onProgress(e);
      }), request.on('success', function (data) {
        callback(data);
        _this14.currentRequest = null;
      }), request.on('error', function (e) {
        _this14.fireEvent('error', e);

        _this14.currentRequest = null;
      }));
      return request;
    }
    /**
     * Called while the audio file is loading
     *
     * @private
     * @param {Event} e Progress event
     * @emits WaveSurfer#loading
     */

  }, {
    key: "onProgress",
    value: function onProgress(e) {
      var percentComplete;

      if (e.lengthComputable) {
        percentComplete = e.loaded / e.total;
      } else {
        // Approximate progress with an asymptotic
        // function, and assume downloads in the 1-3 MB range.
        percentComplete = e.loaded / (e.loaded + 1000000);
      }

      this.fireEvent('loading', Math.round(percentComplete * 100), e.target);
    }
    /**
     * Exports PCM data into a JSON array and optionally opens in a new window
     * as valid JSON Blob instance.
     *
     * @param {number} length=1024 The scale in which to export the peaks
     * @param {number} accuracy=10000
     * @param {?boolean} noWindow Set to true to disable opening a new
     * window with the JSON
     * @param {number} start Start index
     * @param {number} end End index
     * @return {Promise} Promise that resolves with array of peaks
     */

  }, {
    key: "exportPCM",
    value: function exportPCM(length, accuracy, noWindow, start, end) {
      length = length || 1024;
      start = start || 0;
      accuracy = accuracy || 10000;
      noWindow = noWindow || false;
      var peaks = this.backend.getPeaks(length, start, end);
      var arr = [].map.call(peaks, function (val) {
        return Math.round(val * accuracy) / accuracy;
      });
      return new Promise(function (resolve, reject) {
        if (!noWindow) {
          var blobJSON = new Blob([JSON.stringify(arr)], {
            type: 'application/json;charset=utf-8'
          });
          var objURL = URL.createObjectURL(blobJSON);
          window.open(objURL);
          URL.revokeObjectURL(objURL);
        }

        resolve(arr);
      });
    }
    /**
     * Save waveform image as data URI.
     *
     * The default format is `'image/png'`. Other supported types are
     * `'image/jpeg'` and `'image/webp'`.
     *
     * @param {string} format='image/png' A string indicating the image format.
     * The default format type is `'image/png'`.
     * @param {number} quality=1 A number between 0 and 1 indicating the image
     * quality to use for image formats that use lossy compression such as
     * `'image/jpeg'`` and `'image/webp'`.
     * @param {string} type Image data type to return. Either 'dataURL' (default)
     * or 'blob'.
     * @return {string|string[]|Promise} When using `'dataURL'` type this returns
     * a single data URL or an array of data URLs, one for each canvas. When using
     * `'blob'` type this returns a `Promise` resolving with an array of `Blob`
     * instances, one for each canvas.
     */

  }, {
    key: "exportImage",
    value: function exportImage(format, quality, type) {
      if (!format) {
        format = 'image/png';
      }

      if (!quality) {
        quality = 1;
      }

      if (!type) {
        type = 'dataURL';
      }

      return this.drawer.getImage(format, quality, type);
    }
    /**
     * Cancel any fetch request currently in progress
     */

  }, {
    key: "cancelAjax",
    value: function cancelAjax() {
      if (this.currentRequest && this.currentRequest.controller) {
        // If the current request has a ProgressHandler, then its ReadableStream might need to be cancelled too
        // See: Wavesurfer issue #2042
        // See Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1583815
        if (this.currentRequest._reader) {
          // Ignoring exceptions thrown by call to cancel()
          this.currentRequest._reader.cancel().catch(function (err) {});
        }

        this.currentRequest.controller.abort();
        this.currentRequest = null;
      }
    }
    /**
     * @private
     */

  }, {
    key: "clearTmpEvents",
    value: function clearTmpEvents() {
      this.tmpEvents.forEach(function (e) {
        return e.un();
      });
    }
    /**
     * Display empty waveform.
     */

  }, {
    key: "empty",
    value: function empty() {
      if (!this.backend.isPaused()) {
        this.stop();
        this.backend.disconnectSource();
      }

      this.isReady = false;
      this.cancelAjax();
      this.clearTmpEvents(); // empty drawer

      this.drawer.progress(0);
      this.drawer.setWidth(0);
      this.drawer.drawPeaks({
        length: this.drawer.getWidth()
      }, 0);
    }
    /**
     * Remove events, elements and disconnect WebAudio nodes.
     *
     * @emits WaveSurfer#destroy
     */

  }, {
    key: "destroy",
    value: function destroy() {
      this.destroyAllPlugins();
      this.fireEvent('destroy');
      this.cancelAjax();
      this.clearTmpEvents();
      this.unAll();

      if (this.params.responsive !== false) {
        window.removeEventListener('resize', this._onResize, true);
        window.removeEventListener('orientationchange', this._onResize, true);
      }

      if (this.backend) {
        this.backend.destroy(); // clears memory usage

        this.backend = null;
      }

      if (this.drawer) {
        this.drawer.destroy();
      }

      this.isDestroyed = true;
      this.isReady = false;
      this.arraybuffer = null;
    }
  }], [{
    key: "create",
    value:
    /** @private */

    /** @private */

    /**
     * Instantiate this class, call its `init` function and returns it
     *
     * @param {WavesurferParams} params The wavesurfer parameters
     * @return {Object} WaveSurfer instance
     * @example const wavesurfer = WaveSurfer.create(params);
     */
    function create(params) {
      var wavesurfer = new WaveSurfer(params);
      return wavesurfer.init();
    }
    /**
     * The library version number is available as a static property of the
     * WaveSurfer class
     *
     * @type {String}
     * @example
     * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);
     */

  }]);

  return WaveSurfer;
}(util.Observer);

exports.default = WaveSurfer;
WaveSurfer.VERSION = "5.2.0";
WaveSurfer.util = util;
module.exports = exports.default;

/***/ }),

/***/ "./src/webaudio.js":
/*!*************************!*\
  !*** ./src/webaudio.js ***!
  \*************************/
/***/ ((module, exports, __nested_webpack_require_180241__) => {

"use strict";


function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.default = void 0;

var util = _interopRequireWildcard(__nested_webpack_require_180241__(/*! ./util */ "./src/util/index.js"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

// using constants to prevent someone writing the string wrong
var PLAYING = 'playing';
var PAUSED = 'paused';
var FINISHED = 'finished';
/**
 * WebAudio backend
 *
 * @extends {Observer}
 */

var WebAudio = /*#__PURE__*/function (_util$Observer) {
  _inherits(WebAudio, _util$Observer);

  var _super = _createSuper(WebAudio);

  /**
   * Construct the backend
   *
   * @param {WavesurferParams} params Wavesurfer parameters
   */
  function WebAudio(params) {
    var _this$stateBehaviors, _this$states;

    var _this;

    _classCallCheck(this, WebAudio);

    _this = _super.call(this);
    /** @private */

    _this.audioContext = null;
    _this.offlineAudioContext = null;
    _this.stateBehaviors = (_this$stateBehaviors = {}, _defineProperty(_this$stateBehaviors, PLAYING, {
      init: function init() {
        this.addOnAudioProcess();
      },
      getPlayedPercents: function getPlayedPercents() {
        var duration = this.getDuration();
        return this.getCurrentTime() / duration || 0;
      },
      getCurrentTime: function getCurrentTime() {
        return this.startPosition + this.getPlayedTime();
      }
    }), _defineProperty(_this$stateBehaviors, PAUSED, {
      init: function init() {
        this.removeOnAudioProcess();
      },
      getPlayedPercents: function getPlayedPercents() {
        var duration = this.getDuration();
        return this.getCurrentTime() / duration || 0;
      },
      getCurrentTime: function getCurrentTime() {
        return this.startPosition;
      }
    }), _defineProperty(_this$stateBehaviors, FINISHED, {
      init: function init() {
        this.removeOnAudioProcess();
        this.fireEvent('finish');
      },
      getPlayedPercents: function getPlayedPercents() {
        return 1;
      },
      getCurrentTime: function getCurrentTime() {
        return this.getDuration();
      }
    }), _this$stateBehaviors);
    _this.params = params;
    /** ac: Audio Context instance */

    _this.ac = params.audioContext || (_this.supportsWebAudio() ? _this.getAudioContext() : {});
    /**@private */

    _this.lastPlay = _this.ac.currentTime;
    /** @private */

    _this.startPosition = 0;
    /** @private */

    _this.scheduledPause = null;
    /** @private */

    _this.states = (_this$states = {}, _defineProperty(_this$states, PLAYING, Object.create(_this.stateBehaviors[PLAYING])), _defineProperty(_this$states, PAUSED, Object.create(_this.stateBehaviors[PAUSED])), _defineProperty(_this$states, FINISHED, Object.create(_this.stateBehaviors[FINISHED])), _this$states);
    /** @private */

    _this.buffer = null;
    /** @private */

    _this.filters = [];
    /** gainNode: allows to control audio volume */

    _this.gainNode = null;
    /** @private */

    _this.mergedPeaks = null;
    /** @private */

    _this.offlineAc = null;
    /** @private */

    _this.peaks = null;
    /** @private */

    _this.playbackRate = 1;
    /** analyser: provides audio analysis information */

    _this.analyser = null;
    /** scriptNode: allows processing audio */

    _this.scriptNode = null;
    /** @private */

    _this.source = null;
    /** @private */

    _this.splitPeaks = [];
    /** @private */

    _this.state = null;
    /** @private */

    _this.explicitDuration = params.duration;
    /**
     * Boolean indicating if the backend was destroyed.
     */

    _this.destroyed = false;
    return _this;
  }
  /**
   * Initialise the backend, called in `wavesurfer.createBackend()`
   */


  _createClass(WebAudio, [{
    key: "supportsWebAudio",
    value:
    /** scriptBufferSize: size of the processing buffer */

    /** audioContext: allows to process audio with WebAudio API */

    /** @private */

    /** @private */

    /**
     * Does the browser support this backend
     *
     * @return {boolean} Whether or not this browser supports this backend
     */
    function supportsWebAudio() {
      return !!(window.AudioContext || window.webkitAudioContext);
    }
    /**
     * Get the audio context used by this backend or create one
     *
     * @return {AudioContext} Existing audio context, or creates a new one
     */

  }, {
    key: "getAudioContext",
    value: function getAudioContext() {
      if (!window.WaveSurferAudioContext) {
        window.WaveSurferAudioContext = new (window.AudioContext || window.webkitAudioContext)();
      }

      return window.WaveSurferAudioContext;
    }
    /**
     * Get the offline audio context used by this backend or create one
     *
     * @param {number} sampleRate The sample rate to use
     * @return {OfflineAudioContext} Existing offline audio context, or creates
     * a new one
     */

  }, {
    key: "getOfflineAudioContext",
    value: function getOfflineAudioContext(sampleRate) {
      if (!window.WaveSurferOfflineAudioContext) {
        window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, sampleRate);
      }

      return window.WaveSurferOfflineAudioContext;
    }
  }, {
    key: "init",
    value: function init() {
      this.createVolumeNode();
      this.createScriptNode();
      this.createAnalyserNode();
      this.setState(PAUSED);
      this.setPlaybackRate(this.params.audioRate);
      this.setLength(0);
    }
    /** @private */

  }, {
    key: "disconnectFilters",
    value: function disconnectFilters() {
      if (this.filters) {
        this.filters.forEach(function (filter) {
          filter && filter.disconnect();
        });
        this.filters = null; // Reconnect direct path

        this.analyser.connect(this.gainNode);
      }
    }
    /**
     * @private
     *
     * @param {string} state The new state
     */

  }, {
    key: "setState",
    value: function setState(state) {
      if (this.state !== this.states[state]) {
        this.state = this.states[state];
        this.state.init.call(this);
      }
    }
    /**
     * Unpacked `setFilters()`
     *
     * @param {...AudioNode} filters One or more filters to set
     */

  }, {
    key: "setFilter",
    value: function setFilter() {
      for (var _len = arguments.length, filters = new Array(_len), _key = 0; _key < _len; _key++) {
        filters[_key] = arguments[_key];
      }

      this.setFilters(filters);
    }
    /**
     * Insert custom Web Audio nodes into the graph
     *
     * @param {AudioNode[]} filters Packed filters array
     * @example
     * const lowpass = wavesurfer.backend.ac.createBiquadFilter();
     * wavesurfer.backend.setFilter(lowpass);
     */

  }, {
    key: "setFilters",
    value: function setFilters(filters) {
      // Remove existing filters
      this.disconnectFilters(); // Insert filters if filter array not empty

      if (filters && filters.length) {
        this.filters = filters; // Disconnect direct path before inserting filters

        this.analyser.disconnect(); // Connect each filter in turn

        filters.reduce(function (prev, curr) {
          prev.connect(curr);
          return curr;
        }, this.analyser).connect(this.gainNode);
      }
    }
    /** Create ScriptProcessorNode to process audio */

  }, {
    key: "createScriptNode",
    value: function createScriptNode() {
      if (this.params.audioScriptProcessor) {
        this.scriptNode = this.params.audioScriptProcessor;
      } else {
        if (this.ac.createScriptProcessor) {
          this.scriptNode = this.ac.createScriptProcessor(WebAudio.scriptBufferSize);
        } else {
          this.scriptNode = this.ac.createJavaScriptNode(WebAudio.scriptBufferSize);
        }
      }

      this.scriptNode.connect(this.ac.destination);
    }
    /** @private */

  }, {
    key: "addOnAudioProcess",
    value: function addOnAudioProcess() {
      var _this2 = this;

      this.scriptNode.onaudioprocess = function () {
        var time = _this2.getCurrentTime();

        if (time >= _this2.getDuration()) {
          _this2.setState(FINISHED);

          _this2.fireEvent('pause');
        } else if (time >= _this2.scheduledPause) {
          _this2.pause();
        } else if (_this2.state === _this2.states[PLAYING]) {
          _this2.fireEvent('audioprocess', time);
        }
      };
    }
    /** @private */

  }, {
    key: "removeOnAudioProcess",
    value: function removeOnAudioProcess() {
      this.scriptNode.onaudioprocess = null;
    }
    /** Create analyser node to perform audio analysis */

  }, {
    key: "createAnalyserNode",
    value: function createAnalyserNode() {
      this.analyser = this.ac.createAnalyser();
      this.analyser.connect(this.gainNode);
    }
    /**
     * Create the gain node needed to control the playback volume.
     *
     */

  }, {
    key: "createVolumeNode",
    value: function createVolumeNode() {
      // Create gain node using the AudioContext
      if (this.ac.createGain) {
        this.gainNode = this.ac.createGain();
      } else {
        this.gainNode = this.ac.createGainNode();
      } // Add the gain node to the graph


      this.gainNode.connect(this.ac.destination);
    }
    /**
     * Set the sink id for the media player
     *
     * @param {string} deviceId String value representing audio device id.
     * @returns {Promise} A Promise that resolves to `undefined` when there
     * are no errors.
     */

  }, {
    key: "setSinkId",
    value: function setSinkId(deviceId) {
      if (deviceId) {
        /**
         * The webaudio API doesn't currently support setting the device
         * output. Here we create an HTMLAudioElement, connect the
         * webaudio stream to that element and setSinkId there.
         */
        var audio = new window.Audio();

        if (!audio.setSinkId) {
          return Promise.reject(new Error('setSinkId is not supported in your browser'));
        }

        audio.autoplay = true;
        var dest = this.ac.createMediaStreamDestination();
        this.gainNode.disconnect();
        this.gainNode.connect(dest);
        audio.srcObject = dest.stream;
        return audio.setSinkId(deviceId);
      } else {
        return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
      }
    }
    /**
     * Set the audio volume
     *
     * @param {number} value A floating point value between 0 and 1.
     */

  }, {
    key: "setVolume",
    value: function setVolume(value) {
      this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);
    }
    /**
     * Get the current volume
     *
     * @return {number} value A floating point value between 0 and 1.
     */

  }, {
    key: "getVolume",
    value: function getVolume() {
      return this.gainNode.gain.value;
    }
    /**
     * Decode an array buffer and pass data to a callback
     *
     * @private
     * @param {ArrayBuffer} arraybuffer The array buffer to decode
     * @param {function} callback The function to call on complete.
     * @param {function} errback The function to call on error.
     */

  }, {
    key: "decodeArrayBuffer",
    value: function decodeArrayBuffer(arraybuffer, callback, errback) {
      if (!this.offlineAc) {
        this.offlineAc = this.getOfflineAudioContext(this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100);
      }

      if ('webkitAudioContext' in window) {
        // Safari: no support for Promise-based decodeAudioData enabled
        // Enable it in Safari using the Experimental Features > Modern WebAudio API option
        this.offlineAc.decodeAudioData(arraybuffer, function (data) {
          return callback(data);
        }, errback);
      } else {
        this.offlineAc.decodeAudioData(arraybuffer).then(function (data) {
          return callback(data);
        }).catch(function (err) {
          return errback(err);
        });
      }
    }
    /**
     * Set pre-decoded peaks
     *
     * @param {number[]|Number.<Array[]>} peaks Peaks data
     * @param {?number} duration Explicit duration
     */

  }, {
    key: "setPeaks",
    value: function setPeaks(peaks, duration) {
      if (duration != null) {
        this.explicitDuration = duration;
      }

      this.peaks = peaks;
    }
    /**
     * Set the rendered length (different from the length of the audio)
     *
     * @param {number} length The rendered length
     */

  }, {
    key: "setLength",
    value: function setLength(length) {
      // No resize, we can preserve the cached peaks.
      if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {
        return;
      }

      this.splitPeaks = [];
      this.mergedPeaks = []; // Set the last element of the sparse array so the peak arrays are
      // appropriately sized for other calculations.

      var channels = this.buffer ? this.buffer.numberOfChannels : 1;
      var c;

      for (c = 0; c < channels; c++) {
        this.splitPeaks[c] = [];
        this.splitPeaks[c][2 * (length - 1)] = 0;
        this.splitPeaks[c][2 * (length - 1) + 1] = 0;
      }

      this.mergedPeaks[2 * (length - 1)] = 0;
      this.mergedPeaks[2 * (length - 1) + 1] = 0;
    }
    /**
     * Compute the max and min value of the waveform when broken into <length> subranges.
     *
     * @param {number} length How many subranges to break the waveform into.
     * @param {number} first First sample in the required range.
     * @param {number} last Last sample in the required range.
     * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of arrays of
     * peaks consisting of (max, min) values for each subrange.
     */

  }, {
    key: "getPeaks",
    value: function getPeaks(length, first, last) {
      if (this.peaks) {
        return this.peaks;
      }

      if (!this.buffer) {
        return [];
      }

      first = first || 0;
      last = last || length - 1;
      this.setLength(length);

      if (!this.buffer) {
        return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
      }
      /**
       * The following snippet fixes a buffering data issue on the Safari
       * browser which returned undefined It creates the missing buffer based
       * on 1 channel, 4096 samples and the sampleRate from the current
       * webaudio context 4096 samples seemed to be the best fit for rendering
       * will review this code once a stable version of Safari TP is out
       */


      if (!this.buffer.length) {
        var newBuffer = this.createBuffer(1, 4096, this.sampleRate);
        this.buffer = newBuffer.buffer;
      }

      var sampleSize = this.buffer.length / length;
      var sampleStep = ~~(sampleSize / 10) || 1;
      var channels = this.buffer.numberOfChannels;
      var c;

      for (c = 0; c < channels; c++) {
        var peaks = this.splitPeaks[c];
        var chan = this.buffer.getChannelData(c);
        var i = void 0;

        for (i = first; i <= last; i++) {
          var start = ~~(i * sampleSize);
          var end = ~~(start + sampleSize);
          /**
           * Initialize the max and min to the first sample of this
           * subrange, so that even if the samples are entirely
           * on one side of zero, we still return the true max and
           * min values in the subrange.
           */

          var min = chan[start];
          var max = min;
          var j = void 0;

          for (j = start; j < end; j += sampleStep) {
            var value = chan[j];

            if (value > max) {
              max = value;
            }

            if (value < min) {
              min = value;
            }
          }

          peaks[2 * i] = max;
          peaks[2 * i + 1] = min;

          if (c == 0 || max > this.mergedPeaks[2 * i]) {
            this.mergedPeaks[2 * i] = max;
          }

          if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {
            this.mergedPeaks[2 * i + 1] = min;
          }
        }
      }

      return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
    }
    /**
     * Get the position from 0 to 1
     *
     * @return {number} Position
     */

  }, {
    key: "getPlayedPercents",
    value: function getPlayedPercents() {
      return this.state.getPlayedPercents.call(this);
    }
    /** @private */

  }, {
    key: "disconnectSource",
    value: function disconnectSource() {
      if (this.source) {
        this.source.disconnect();
      }
    }
    /**
     * Destroy all references with WebAudio, disconnecting audio nodes and closing Audio Context
     */

  }, {
    key: "destroyWebAudio",
    value: function destroyWebAudio() {
      this.disconnectFilters();
      this.disconnectSource();
      this.gainNode.disconnect();
      this.scriptNode.disconnect();
      this.analyser.disconnect(); // close the audioContext if closeAudioContext option is set to true

      if (this.params.closeAudioContext) {
        // check if browser supports AudioContext.close()
        if (typeof this.ac.close === 'function' && this.ac.state != 'closed') {
          this.ac.close();
        } // clear the reference to the audiocontext


        this.ac = null; // clear the actual audiocontext, either passed as param or the
        // global singleton

        if (!this.params.audioContext) {
          window.WaveSurferAudioContext = null;
        } else {
          this.params.audioContext = null;
        } // clear the offlineAudioContext


        window.WaveSurferOfflineAudioContext = null;
      }
    }
    /**
     * This is called when wavesurfer is destroyed
     */

  }, {
    key: "destroy",
    value: function destroy() {
      if (!this.isPaused()) {
        this.pause();
      }

      this.unAll();
      this.buffer = null;
      this.destroyed = true;
      this.destroyWebAudio();
    }
    /**
     * Loaded a decoded audio buffer
     *
     * @param {Object} buffer Decoded audio buffer to load
     */

  }, {
    key: "load",
    value: function load(buffer) {
      this.startPosition = 0;
      this.lastPlay = this.ac.currentTime;
      this.buffer = buffer;
      this.createSource();
    }
    /** @private */

  }, {
    key: "createSource",
    value: function createSource() {
      this.disconnectSource();
      this.source = this.ac.createBufferSource(); // adjust for old browsers

      this.source.start = this.source.start || this.source.noteGrainOn;
      this.source.stop = this.source.stop || this.source.noteOff;
      this.setPlaybackRate(this.playbackRate);
      this.source.buffer = this.buffer;
      this.source.connect(this.analyser);
    }
    /**
     * @private
     *
     * some browsers require an explicit call to #resume before they will play back audio
     */

  }, {
    key: "resumeAudioContext",
    value: function resumeAudioContext() {
      if (this.ac.state == 'suspended') {
        this.ac.resume && this.ac.resume();
      }
    }
    /**
     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
     *
     * @return {boolean} Whether or not this backend is currently paused
     */

  }, {
    key: "isPaused",
    value: function isPaused() {
      return this.state !== this.states[PLAYING];
    }
    /**
     * Used by `wavesurfer.getDuration()`
     *
     * @return {number} Duration of loaded buffer
     */

  }, {
    key: "getDuration",
    value: function getDuration() {
      if (this.explicitDuration) {
        return this.explicitDuration;
      }

      if (!this.buffer) {
        return 0;
      }

      return this.buffer.duration;
    }
    /**
     * Used by `wavesurfer.seekTo()`
     *
     * @param {number} start Position to start at in seconds
     * @param {number} end Position to end at in seconds
     * @return {{start: number, end: number}} Object containing start and end
     * positions
     */

  }, {
    key: "seekTo",
    value: function seekTo(start, end) {
      if (!this.buffer) {
        return;
      }

      this.scheduledPause = null;

      if (start == null) {
        start = this.getCurrentTime();

        if (start >= this.getDuration()) {
          start = 0;
        }
      }

      if (end == null) {
        end = this.getDuration();
      }

      this.startPosition = start;
      this.lastPlay = this.ac.currentTime;

      if (this.state === this.states[FINISHED]) {
        this.setState(PAUSED);
      }

      return {
        start: start,
        end: end
      };
    }
    /**
     * Get the playback position in seconds
     *
     * @return {number} The playback position in seconds
     */

  }, {
    key: "getPlayedTime",
    value: function getPlayedTime() {
      return (this.ac.currentTime - this.lastPlay) * this.playbackRate;
    }
    /**
     * Plays the loaded audio region.
     *
     * @param {number} start Start offset in seconds, relative to the beginning
     * of a clip.
     * @param {number} end When to stop relative to the beginning of a clip.
     */

  }, {
    key: "play",
    value: function play(start, end) {
      if (!this.buffer) {
        return;
      } // need to re-create source on each playback


      this.createSource();
      var adjustedTime = this.seekTo(start, end);
      start = adjustedTime.start;
      end = adjustedTime.end;
      this.scheduledPause = end;
      this.source.start(0, start);
      this.resumeAudioContext();
      this.setState(PLAYING);
      this.fireEvent('play');
    }
    /**
     * Pauses the loaded audio.
     */

  }, {
    key: "pause",
    value: function pause() {
      this.scheduledPause = null;
      this.startPosition += this.getPlayedTime();

      try {
        this.source && this.source.stop(0);
      } catch (err) {// Calling stop can throw the following 2 errors:
        // - RangeError (The value specified for when is negative.)
        // - InvalidStateNode (The node has not been started by calling start().)
        // We can safely ignore both errors, because:
        // - The range is surely correct
        // - The node might not have been started yet, in which case we just want to carry on without causing any trouble.
      }

      this.setState(PAUSED);
      this.fireEvent('pause');
    }
    /**
     * Returns the current time in seconds relative to the audio-clip's
     * duration.
     *
     * @return {number} The current time in seconds
     */

  }, {
    key: "getCurrentTime",
    value: function getCurrentTime() {
      return this.state.getCurrentTime.call(this);
    }
    /**
     * Returns the current playback rate. (0=no playback, 1=normal playback)
     *
     * @return {number} The current playback rate
     */

  }, {
    key: "getPlaybackRate",
    value: function getPlaybackRate() {
      return this.playbackRate;
    }
    /**
     * Set the audio source playback rate.
     *
     * @param {number} value The playback rate to use
     */

  }, {
    key: "setPlaybackRate",
    value: function setPlaybackRate(value) {
      this.playbackRate = value || 1;
      this.source && this.source.playbackRate.setValueAtTime(this.playbackRate, this.ac.currentTime);
    }
    /**
     * Set a point in seconds for playback to stop at.
     *
     * @param {number} end Position to end at
     * @version 3.3.0
     */

  }, {
    key: "setPlayEnd",
    value: function setPlayEnd(end) {
      this.scheduledPause = end;
    }
  }]);

  return WebAudio;
}(util.Observer);

exports.default = WebAudio;
WebAudio.scriptBufferSize = 256;
module.exports = exports.default;

/***/ }),

/***/ "./node_modules/debounce/index.js":
/*!****************************************!*\
  !*** ./node_modules/debounce/index.js ***!
  \****************************************/
/***/ ((module) => {

/**
 * Returns a function, that, as long as it continues to be invoked, will not
 * be triggered. The function will be called after it stops being called for
 * N milliseconds. If `immediate` is passed, trigger the function on the
 * leading edge, instead of the trailing. The function also has a property 'clear' 
 * that is a function which will clear the timer to prevent previously scheduled executions. 
 *
 * @source underscore.js
 * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
 * @param {Function} function to wrap
 * @param {Number} timeout in ms (`100`)
 * @param {Boolean} whether to execute at the beginning (`false`)
 * @api public
 */
function debounce(func, wait, immediate){
  var timeout, args, context, timestamp, result;
  if (null == wait) wait = 100;

  function later() {
    var last = Date.now() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        context = args = null;
      }
    }
  };

  var debounced = function(){
    context = this;
    args = arguments;
    timestamp = Date.now();
    var callNow = immediate && !timeout;
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };

  debounced.clear = function() {
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
  };
  
  debounced.flush = function() {
    if (timeout) {
      result = func.apply(context, args);
      context = args = null;
      
      clearTimeout(timeout);
      timeout = null;
    }
  };

  return debounced;
};

// Adds compatibility for ES modules
debounce.debounce = debounce;

module.exports = debounce;


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __nested_webpack_require_210487__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __nested_webpack_require_210487__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	var __nested_webpack_exports__ = __nested_webpack_require_210487__("./src/wavesurfer.js");
/******/ 	
/******/ 	return __nested_webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=wavesurfer.js.map

/***/ }),

/***/ 7361:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

/*
 * Copyright (c) Jupyter Development Team.
 * Distributed under the terms of the Modified BSD License.
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.signalToPromise = signalToPromise;
const coreutils_1 = __webpack_require__(5764);
/**
 * Convert a signal into a promise for the first emitted value.
 *
 * @param signal - The signal we are listening to.
 * @param timeout - Timeout to wait for signal in ms (not timeout if not defined or 0)
 *
 * @returns a Promise that resolves with a `(sender, args)` pair.
 */
function signalToPromise(signal, timeout) {
    const waitForSignal = new coreutils_1.PromiseDelegate();
    function cleanup() {
        signal.disconnect(slot);
    }
    function slot(sender, args) {
        cleanup();
        waitForSignal.resolve([sender, args]);
    }
    signal.connect(slot);
    if ((timeout !== null && timeout !== void 0 ? timeout : 0) > 0) {
        setTimeout(() => {
            cleanup();
            waitForSignal.reject(`Signal not emitted within ${timeout} ms.`);
        }, timeout);
    }
    return waitForSignal.promise;
}
//# sourceMappingURL=signal.js.map

/***/ }),

/***/ 7441:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.validateProperty = validateProperty;
/**
 * Validate a property as being on an object, and optionally
 * of a given type and among a given set of values.
 */
function validateProperty(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
object, name, typeName, values = []) {
    if (!object.hasOwnProperty(name)) {
        throw Error(`Missing property '${name}'`);
    }
    const value = object[name];
    if (typeName !== void 0) {
        let valid = true;
        switch (typeName) {
            case 'array':
                valid = Array.isArray(value);
                break;
            case 'object':
                valid = typeof value !== 'undefined';
                break;
            default:
                valid = typeof value === typeName;
        }
        if (!valid) {
            throw new Error(`Property '${name}' is not of type '${typeName}'`);
        }
        if (values.length > 0) {
            let valid = true;
            switch (typeName) {
                case 'string':
                case 'number':
                case 'boolean':
                    valid = values.includes(value);
                    break;
                default:
                    valid = values.findIndex(v => v === value) >= 0;
                    break;
            }
            if (!valid) {
                throw new Error(`Property '${name}' is not one of the valid values ${JSON.stringify(values)}`);
            }
        }
    }
}
//# sourceMappingURL=validate.js.map

/***/ }),

/***/ 7489:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CommHandler = exports.CommsOverSubshells = void 0;
const coreutils_1 = __webpack_require__(5764);
const disposable_1 = __webpack_require__(7556);
const KernelMessage = __importStar(__webpack_require__(9909));
/**
 * The Comm Over Subshell Enum
 */
var CommsOverSubshells;
(function (CommsOverSubshells) {
    CommsOverSubshells["Disabled"] = "disabled";
    CommsOverSubshells["PerComm"] = "perComm";
    CommsOverSubshells["PerCommTarget"] = "perCommTarget";
})(CommsOverSubshells || (exports.CommsOverSubshells = CommsOverSubshells = {}));
/**
 * Comm channel handler.
 */
class CommHandler extends disposable_1.DisposableDelegate {
    /**
     * Construct a new comm channel.
     */
    constructor(target, id, kernel, disposeCb, commsOverSubshells) {
        super(disposeCb);
        this._subshellStarted = new coreutils_1.PromiseDelegate();
        this._subshellId = null;
        this._target = '';
        this._id = '';
        this._id = id;
        this._target = target;
        this._kernel = kernel;
        // Clean subshell ids upon restart
        this._kernel.statusChanged.connect(() => {
            if (this._kernel.status === 'restarting') {
                this._cleanSubshells();
            }
        });
        this.commsOverSubshells =
            commsOverSubshells !== null && commsOverSubshells !== void 0 ? commsOverSubshells : CommsOverSubshells.PerCommTarget;
    }
    /**
     * The unique id for the comm channel.
     */
    get commId() {
        return this._id;
    }
    /**
     * The target name for the comm channel.
     */
    get targetName() {
        return this._target;
    }
    /**
     * The current subshell id.
     */
    get subshellId() {
        return this._subshellId;
    }
    /**
     * Promise that resolves when the subshell started, if any
     */
    get subshellStarted() {
        return this._subshellStarted.promise;
    }
    /**
     * Whether comms are running on a subshell, or not
     */
    get commsOverSubshells() {
        return this._commsOverSubshells;
    }
    /**
     * Set whether comms are running on subshells, or not
     */
    set commsOverSubshells(value) {
        this._commsOverSubshells = value;
        if (this._commsOverSubshells === CommsOverSubshells.Disabled) {
            this._maybeCloseSubshell();
        }
        else {
            void this._maybeStartSubshell();
        }
    }
    /**
     * Get the callback for a comm close event.
     *
     * #### Notes
     * This is called when the comm is closed from either the server or client.
     *
     * **See also:** [[ICommClose]], [[close]]
     */
    get onClose() {
        return this._onClose;
    }
    /**
     * Set the callback for a comm close event.
     *
     * #### Notes
     * This is called when the comm is closed from either the server or client. If
     * the function returns a promise, and the kernel was closed from the server,
     * kernel message processing will pause until the returned promise is
     * fulfilled.
     *
     * **See also:** [[close]]
     */
    set onClose(cb) {
        this._onClose = cb;
    }
    /**
     * Get the callback for a comm message received event.
     */
    get onMsg() {
        return this._onMsg;
    }
    /**
     * Set the callback for a comm message received event.
     *
     * #### Notes
     * This is called when a comm message is received. If the function returns a
     * promise, kernel message processing will pause until it is fulfilled.
     */
    set onMsg(cb) {
        this._onMsg = cb;
    }
    /**
     * Open a comm with optional data and metadata.
     *
     * #### Notes
     * This sends a `comm_open` message to the server.
     *
     * **See also:** [[ICommOpen]]
     */
    open(data, metadata, buffers = []) {
        if (this.isDisposed || this._kernel.isDisposed) {
            throw new Error('Cannot open');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'comm_open',
            channel: 'shell',
            username: this._kernel.username,
            session: this._kernel.clientId,
            subshellId: this._subshellId || this._kernel.subshellId,
            content: {
                comm_id: this._id,
                target_name: this._target,
                data: data !== null && data !== void 0 ? data : {}
            },
            metadata,
            buffers
        });
        return this._kernel.sendShellMessage(msg, false, true);
    }
    /**
     * Send a `comm_msg` message to the kernel.
     *
     * #### Notes
     * This is a no-op if the comm has been closed.
     *
     * **See also:** [[ICommMsg]]
     */
    send(data, metadata, buffers = [], disposeOnDone = true) {
        if (this.isDisposed || this._kernel.isDisposed) {
            throw new Error('Cannot send');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'comm_msg',
            channel: 'shell',
            username: this._kernel.username,
            session: this._kernel.clientId,
            subshellId: this._subshellId || this._kernel.subshellId,
            content: {
                comm_id: this._id,
                data: data
            },
            metadata,
            buffers
        });
        return this._kernel.sendShellMessage(msg, false, disposeOnDone);
    }
    /**
     * Close the comm.
     *
     * #### Notes
     * This will send a `comm_close` message to the kernel, and call the
     * `onClose` callback if set.
     *
     * This is a no-op if the comm is already closed.
     *
     * **See also:** [[ICommClose]], [[onClose]]
     */
    close(data, metadata, buffers = []) {
        if (this.isDisposed || this._kernel.isDisposed) {
            throw new Error('Cannot close');
        }
        const msg = KernelMessage.createMessage({
            msgType: 'comm_close',
            channel: 'shell',
            username: this._kernel.username,
            session: this._kernel.clientId,
            subshellId: this._subshellId || this._kernel.subshellId,
            content: {
                comm_id: this._id,
                data: data !== null && data !== void 0 ? data : {}
            },
            metadata,
            buffers
        });
        const future = this._kernel.sendShellMessage(msg, false, true);
        const onClose = this._onClose;
        if (onClose) {
            const ioMsg = KernelMessage.createMessage({
                msgType: 'comm_close',
                channel: 'iopub',
                username: this._kernel.username,
                session: this._kernel.clientId,
                subshellId: this._subshellId || this._kernel.subshellId,
                content: {
                    comm_id: this._id,
                    data: data !== null && data !== void 0 ? data : {}
                },
                metadata,
                buffers
            });
            // In the future, we may want to communicate back to the user the possible
            // promise returned from onClose.
            void onClose(ioMsg);
        }
        this.dispose();
        return future;
    }
    dispose() {
        this._maybeCloseSubshell();
        super.dispose();
    }
    _cleanSubshells() {
        CommHandler._commTargetSubShellsId = {};
    }
    async _maybeStartSubshell() {
        await this._kernel.info;
        if (!this._kernel.supportsSubshells) {
            return;
        }
        if (this._commsOverSubshells === CommsOverSubshells.PerComm) {
            // Create subshell
            const replyMsg = await this._kernel.requestCreateSubshell({}).done;
            this._subshellId = replyMsg.content.subshell_id;
            this._subshellStarted.resolve();
            return;
        }
        // One shell per comm-target
        if (CommHandler._commTargetSubShellsId[this._target]) {
            this._subshellId = await CommHandler._commTargetSubShellsId[this._target];
            this._subshellStarted.resolve();
        }
        else {
            // Create subshell
            CommHandler._commTargetSubShellsId[this._target] = this._kernel
                .requestCreateSubshell({})
                .done.then(replyMsg => {
                this._subshellId = replyMsg.content.subshell_id;
                return this._subshellId;
            });
            await CommHandler._commTargetSubShellsId[this._target];
            this._subshellStarted.resolve();
        }
    }
    _maybeCloseSubshell() {
        // Only close subshell if we have one subshell per comm
        if (this._commsOverSubshells !== CommsOverSubshells.PerComm) {
            this._subshellId = null;
            return;
        }
        if (this._subshellId && this._kernel.status !== 'dead') {
            this._kernel.requestDeleteSubshell({ subshell_id: this._subshellId }, true);
        }
        this._subshellId = null;
    }
}
exports.CommHandler = CommHandler;
CommHandler._commTargetSubShellsId = {};
//# sourceMappingURL=comm.js.map

/***/ }),

/***/ 7556:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   DisposableDelegate: () => (/* binding */ DisposableDelegate),
/* harmony export */   DisposableSet: () => (/* binding */ DisposableSet),
/* harmony export */   ObservableDisposableDelegate: () => (/* binding */ ObservableDisposableDelegate),
/* harmony export */   ObservableDisposableSet: () => (/* binding */ ObservableDisposableSet)
/* harmony export */ });
/* harmony import */ var _lumino_signaling__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3992);


// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * @packageDocumentation
 * @module disposable
 */
/**
 * A disposable object which delegates to a callback function.
 */
class DisposableDelegate {
    /**
     * Construct a new disposable delegate.
     *
     * @param fn - The callback function to invoke on dispose.
     */
    constructor(fn) {
        this._fn = fn;
    }
    /**
     * Test whether the delegate has been disposed.
     */
    get isDisposed() {
        return !this._fn;
    }
    /**
     * Dispose of the delegate and invoke the callback function.
     */
    dispose() {
        if (!this._fn) {
            return;
        }
        let fn = this._fn;
        this._fn = null;
        fn();
    }
}
/**
 * An observable disposable object which delegates to a callback function.
 */
class ObservableDisposableDelegate extends DisposableDelegate {
    constructor() {
        super(...arguments);
        this._disposed = new _lumino_signaling__WEBPACK_IMPORTED_MODULE_0__.Signal(this);
    }
    /**
     * A signal emitted when the delegate is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * Dispose of the delegate and invoke the callback function.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        super.dispose();
        this._disposed.emit(undefined);
        _lumino_signaling__WEBPACK_IMPORTED_MODULE_0__.Signal.clearData(this);
    }
}
/**
 * An object which manages a collection of disposable items.
 */
class DisposableSet {
    constructor() {
        this._isDisposed = false;
        this._items = new Set();
    }
    /**
     * Test whether the set has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the set and the items it contains.
     *
     * #### Notes
     * Items are disposed in the order they are added to the set.
     */
    dispose() {
        if (this._isDisposed) {
            return;
        }
        this._isDisposed = true;
        this._items.forEach(item => {
            item.dispose();
        });
        this._items.clear();
    }
    /**
     * Test whether the set contains a specific item.
     *
     * @param item - The item of interest.
     *
     * @returns `true` if the set contains the item, `false` otherwise.
     */
    contains(item) {
        return this._items.has(item);
    }
    /**
     * Add a disposable item to the set.
     *
     * @param item - The item to add to the set.
     *
     * #### Notes
     * If the item is already contained in the set, this is a no-op.
     */
    add(item) {
        this._items.add(item);
    }
    /**
     * Remove a disposable item from the set.
     *
     * @param item - The item to remove from the set.
     *
     * #### Notes
     * If the item is not contained in the set, this is a no-op.
     */
    remove(item) {
        this._items.delete(item);
    }
    /**
     * Remove all items from the set.
     */
    clear() {
        this._items.clear();
    }
}
/**
 * The namespace for the `DisposableSet` class statics.
 */
(function (DisposableSet) {
    /**
     * Create a disposable set from an iterable of items.
     *
     * @param items - The iterable object of interest.
     *
     * @returns A new disposable initialized with the given items.
     */
    function from(items) {
        let set = new DisposableSet();
        for (const item of items) {
            set.add(item);
        }
        return set;
    }
    DisposableSet.from = from;
})(DisposableSet || (DisposableSet = {}));
/**
 * An observable object which manages a collection of disposable items.
 */
class ObservableDisposableSet extends DisposableSet {
    constructor() {
        super(...arguments);
        this._disposed = new _lumino_signaling__WEBPACK_IMPORTED_MODULE_0__.Signal(this);
    }
    /**
     * A signal emitted when the set is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * Dispose of the set and the items it contains.
     *
     * #### Notes
     * Items are disposed in the order they are added to the set.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        super.dispose();
        this._disposed.emit(undefined);
        _lumino_signaling__WEBPACK_IMPORTED_MODULE_0__.Signal.clearData(this);
    }
}
/**
 * The namespace for the `ObservableDisposableSet` class statics.
 */
(function (ObservableDisposableSet) {
    /**
     * Create an observable disposable set from an iterable of items.
     *
     * @param items - The iterable object of interest.
     *
     * @returns A new disposable initialized with the given items.
     */
    function from(items) {
        let set = new ObservableDisposableSet();
        for (const item of items) {
            set.add(item);
        }
        return set;
    }
    ObservableDisposableSet.from = from;
})(ObservableDisposableSet || (ObservableDisposableSet = {}));


//# sourceMappingURL=index.es6.js.map


/***/ }),

/***/ 7570:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SessionAPIClient = exports.SESSION_SERVICE_URL = void 0;
exports.listRunning = listRunning;
exports.getSessionUrl = getSessionUrl;
exports.shutdownSession = shutdownSession;
exports.getSessionModel = getSessionModel;
exports.startSession = startSession;
exports.updateSession = updateSession;
const serverconnection_1 = __webpack_require__(2920);
const coreutils_1 = __webpack_require__(8925);
const validate_1 = __webpack_require__(5684);
/**
 * The url for the session service.
 */
exports.SESSION_SERVICE_URL = 'api/sessions';
/**
 * List the running sessions.
 */
async function listRunning(settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.SESSION_SERVICE_URL);
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    if (!Array.isArray(data)) {
        throw new Error('Invalid Session list');
    }
    data.forEach(m => {
        (0, validate_1.updateLegacySessionModel)(m);
        (0, validate_1.validateModel)(m);
    });
    return data;
}
/**
 * Get a session url.
 */
function getSessionUrl(baseUrl, id) {
    const servicesBase = coreutils_1.URLExt.join(baseUrl, exports.SESSION_SERVICE_URL);
    const result = coreutils_1.URLExt.join(servicesBase, id);
    if (!result.startsWith(servicesBase)) {
        throw new Error('Can only be used for services requests');
    }
    return result;
}
/**
 * Shut down a session by id.
 */
async function shutdownSession(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    var _a;
    const url = getSessionUrl(settings.baseUrl, id);
    const init = { method: 'DELETE' };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status === 404) {
        const data = await response.json();
        const msg = (_a = data.message) !== null && _a !== void 0 ? _a : `The session "${id}"" does not exist on the server`;
        console.warn(msg);
    }
    else if (response.status === 410) {
        throw new serverconnection_1.ServerConnection.ResponseError(response, 'The kernel was deleted but the session was not');
    }
    else if (response.status !== 204) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
}
/**
 * Get a full session model from the server by session id string.
 */
async function getSessionModel(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = getSessionUrl(settings.baseUrl, id);
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.updateLegacySessionModel)(data);
    (0, validate_1.validateModel)(data);
    return data;
}
/**
 * Create a new session, or return an existing session if the session path
 * already exists.
 */
async function startSession(options, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.SESSION_SERVICE_URL);
    const init = {
        method: 'POST',
        body: JSON.stringify(options)
    };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 201) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.updateLegacySessionModel)(data);
    (0, validate_1.validateModel)(data);
    return data;
}
/**
 * Send a PATCH to the server, updating the session path or the kernel.
 */
async function updateSession(model, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = getSessionUrl(settings.baseUrl, model.id);
    const init = {
        method: 'PATCH',
        body: JSON.stringify(model)
    };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.updateLegacySessionModel)(data);
    (0, validate_1.validateModel)(data);
    return data;
}
/**
 * The session API client.
 *
 * #### Notes
 * Use this class to interact with the Jupyter Server Session API.
 * This class adheres to the Jupyter Server API endpoints.
 */
class SessionAPIClient {
    /**
     * Create a new session API client.
     *
     * @param options - The options used to create the client.
     */
    constructor(options) {
        var _a;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * List the running sessions.
     *
     * @returns A promise that resolves with the list of running session models.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async listRunning() {
        return listRunning(this.serverSettings);
    }
    /**
     * Get a session model.
     *
     * @param id - The id of the session of interest.
     *
     * @returns A promise that resolves with the session model.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async getModel(id) {
        return getSessionModel(id, this.serverSettings);
    }
    /**
     * Create a new session.
     *
     * @param options - The options used to create the session.
     *
     * @returns A promise that resolves with the session model.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async startNew(options) {
        return startSession(options, this.serverSettings);
    }
    /**
     * Shut down a session by id.
     *
     * @param id - The id of the session to shut down.
     *
     * @returns A promise that resolves when the session is shut down.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async shutdown(id) {
        return shutdownSession(id, this.serverSettings);
    }
    /**
     * Update a session by id.
     *
     * @param model - The session model to update.
     *
     * @returns A promise that resolves with the updated session model.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/sessions) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async update(model) {
        return updateSession(model, this.serverSettings);
    }
}
exports.SessionAPIClient = SessionAPIClient;
//# sourceMappingURL=restapi.js.map

/***/ }),

/***/ 7668:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SessionAPI = exports.Session = void 0;
const Session = __importStar(__webpack_require__(7240));
exports.Session = Session;
const SessionAPI = __importStar(__webpack_require__(7570));
exports.SessionAPI = SessionAPI;
__exportStar(__webpack_require__(6919), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 7780:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SettingManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const statedb_1 = __webpack_require__(1670);
const serverconnection_1 = __webpack_require__(2920);
/**
 * The url for the lab settings service.
 */
const SERVICE_SETTINGS_URL = 'api/settings';
/**
 * The settings API service manager.
 */
class SettingManager extends statedb_1.DataConnector {
    /**
     * Create a new setting manager.
     */
    constructor(options = {}) {
        var _a;
        super();
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * Fetch a plugin's settings.
     *
     * @param id - The plugin's ID.
     *
     * @returns A promise that resolves if successful.
     */
    async fetch(id) {
        if (!id) {
            throw new Error('Plugin `id` parameter is required for settings fetch.');
        }
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, id);
        const response = await makeRequest(url, {}, serverSettings);
        if (response.status !== 200) {
            const err = await ResponseError.create(response);
            throw err;
        }
        // Assert what type the server response is returning.
        return response.json();
    }
    /**
     * Fetch the list of all plugin setting bundles.
     *
     * @returns A promise that resolves if successful.
     */
    async list(query) {
        var _a, _b, _c, _d;
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, '', query === 'ids');
        const response = await makeRequest(url, {}, serverSettings);
        if (response.status !== 200) {
            throw new ResponseError(response);
        }
        const json = await response.json();
        const ids = (_b = (_a = json === null || json === void 0 ? void 0 : json['settings']) === null || _a === void 0 ? void 0 : _a.map((plugin) => plugin.id)) !== null && _b !== void 0 ? _b : [];
        let values = [];
        if (!query) {
            values =
                (_d = (_c = json === null || json === void 0 ? void 0 : json['settings']) === null || _c === void 0 ? void 0 : _c.map((plugin) => {
                    plugin.data = { composite: {}, user: {} };
                    return plugin;
                })) !== null && _d !== void 0 ? _d : [];
        }
        return { ids, values };
    }
    /**
     * Save a plugin's settings.
     *
     * @param id - The plugin's ID.
     *
     * @param raw - The user setting values as a raw string of JSON with comments.
     *
     * @returns A promise that resolves if successful.
     */
    async save(id, raw) {
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, id);
        // NOTE: 'raw' is JSON5 (not valid JSON), so we encode it as a string in a valid JSON body
        const init = { body: JSON.stringify({ raw }), method: 'PUT' };
        const response = await makeRequest(url, init, serverSettings);
        if (response.status !== 204) {
            throw new ResponseError(response);
        }
    }
}
exports.SettingManager = SettingManager;
/**
 * A namespace for private data.
 */
var Private;
(function (Private) {
    /**
     * Get the url for a plugin's settings.
     */
    function url(base, id, idsOnly) {
        const idsOnlyParam = idsOnly
            ? coreutils_1.URLExt.objectToQueryString({ ids_only: true })
            : '';
        const settingsBase = coreutils_1.URLExt.join(base, SERVICE_SETTINGS_URL);
        const result = coreutils_1.URLExt.join(settingsBase, id);
        if (!result.startsWith(settingsBase)) {
            throw new Error('Can only be used for workspaces requests');
        }
        return `${result}${idsOnlyParam}`;
    }
    Private.url = url;
})(Private || (Private = {}));
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 7882:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'times';
var width = 352;
var height = 512;
var ligatures = [];
var unicode = 'f00d';
var svgPathData = 'M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.GR = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 7883:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/**
 * @packageDocumentation
 * @module services
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
__exportStar(__webpack_require__(3867), exports);
__exportStar(__webpack_require__(2170), exports);
__exportStar(__webpack_require__(5573), exports);
__exportStar(__webpack_require__(8790), exports);
__exportStar(__webpack_require__(9480), exports);
__exportStar(__webpack_require__(973), exports);
__exportStar(__webpack_require__(2946), exports);
__exportStar(__webpack_require__(9740), exports);
__exportStar(__webpack_require__(2920), exports);
__exportStar(__webpack_require__(7668), exports);
__exportStar(__webpack_require__(7780), exports);
__exportStar(__webpack_require__(9040), exports);
__exportStar(__webpack_require__(8125), exports);
__exportStar(__webpack_require__(9191), exports);
__exportStar(__webpack_require__(8053), exports);
__exportStar(__webpack_require__(8683), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 8022:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.IStateDB = void 0;
const coreutils_1 = __webpack_require__(5764);
/**
 * The default state database token.
 */
exports.IStateDB = new coreutils_1.Token('@jupyterlab/coreutils:IStateDB', `A service for the JupyterLab state database.
  Use this if you want to store data that will persist across page loads.
  See "state database" for more information.`);
//# sourceMappingURL=tokens.js.map

/***/ }),

/***/ 8053:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.WorkspaceManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const statedb_1 = __webpack_require__(1670);
const serverconnection_1 = __webpack_require__(2920);
/**
 * The url for the lab workspaces service.
 */
const SERVICE_WORKSPACES_URL = 'api/workspaces';
/**
 * The workspaces API service manager.
 */
class WorkspaceManager extends statedb_1.DataConnector {
    /**
     * Create a new workspace manager.
     */
    constructor(options = {}) {
        var _a;
        super();
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * Fetch a workspace.
     *
     * @param id - The workspace's ID.
     *
     * @returns A promise that resolves if successful.
     */
    async fetch(id) {
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, id);
        const response = await makeRequest(url, {}, serverSettings);
        if (response.status !== 200) {
            const err = await ResponseError.create(response);
            throw err;
        }
        return response.json();
    }
    /**
     * Fetch the list of workspace IDs that exist on the server.
     *
     * @returns A promise that resolves if successful.
     */
    async list() {
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, '');
        const response = await makeRequest(url, {}, serverSettings);
        if (response.status !== 200) {
            const err = await ResponseError.create(response);
            throw err;
        }
        const result = await response.json();
        return result.workspaces;
    }
    /**
     * Remove a workspace from the server.
     *
     * @param id - The workspaces's ID.
     *
     * @returns A promise that resolves if successful.
     */
    async remove(id) {
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, id);
        const init = { method: 'DELETE' };
        const response = await makeRequest(url, init, serverSettings);
        if (response.status !== 204) {
            const err = await ResponseError.create(response);
            throw err;
        }
    }
    /**
     * Save a workspace.
     *
     * @param id - The workspace's ID.
     *
     * @param workspace - The workspace being saved.
     *
     * @returns A promise that resolves if successful.
     */
    async save(id, workspace) {
        const { serverSettings } = this;
        const { baseUrl, appUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const base = baseUrl + appUrl;
        const url = Private.url(base, id);
        const init = { body: JSON.stringify(workspace), method: 'PUT' };
        const response = await makeRequest(url, init, serverSettings);
        if (response.status !== 204) {
            const err = await ResponseError.create(response);
            throw err;
        }
    }
}
exports.WorkspaceManager = WorkspaceManager;
/**
 * A namespace for private data.
 */
var Private;
(function (Private) {
    /**
     * Get the url for a workspace.
     */
    function url(base, id) {
        const workspacesBase = coreutils_1.URLExt.join(base, SERVICE_WORKSPACES_URL);
        const result = coreutils_1.URLExt.join(workspacesBase, id);
        if (!result.startsWith(workspacesBase)) {
            throw new Error('Can only be used for workspaces requests');
        }
        return result;
    }
    Private.url = url;
})(Private || (Private = {}));
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 8079:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'sort-up';
var width = 320;
var height = 512;
var ligatures = [];
var unicode = 'f0de';
var svgPathData = 'M279 224H41c-21.4 0-32.1-25.9-17-41L143 64c9.4-9.4 24.6-9.4 33.9 0l119 119c15.2 15.1 4.5 41-16.9 41z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.Dv = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 8125:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.IWorkspaceManager = exports.IUserManager = exports.ITerminalManager = exports.IServiceManager = exports.ISettingManager = exports.ISessionManager = exports.IServerSettings = exports.INbConvertManager = exports.IKernelSpecManager = exports.IKernelManager = exports.IEventManager = exports.IDefaultDrive = exports.IContentsManager = exports.IConfigSectionManager = exports.IConnectionStatus = void 0;
const coreutils_1 = __webpack_require__(5764);
/**
 * Token providing the application connection status.
 */
exports.IConnectionStatus = new coreutils_1.Token('@jupyterlab/application:IConnectionStatus', 'A service providing the application connection status.');
/**
 * Token providing the config section manager.
 */
exports.IConfigSectionManager = new coreutils_1.Token('@jupyterlab/services:IConfigSectionManager', 'A service providing the config section manager.');
/**
 * The contents manager token.
 */
exports.IContentsManager = new coreutils_1.Token('@jupyterlab/services:IContentsManager', 'The contents manager token.');
/**
 * The default drive token.
 */
exports.IDefaultDrive = new coreutils_1.Token('@jupyterlab/services:IDefaultDrive', 'The default drive for the contents manager.');
/**
 * The event manager token.
 */
exports.IEventManager = new coreutils_1.Token('@jupyterlab/services:IEventManager', 'The event manager token.');
/**
 * The kernel manager token.
 */
exports.IKernelManager = new coreutils_1.Token('@jupyterlab/services:IKernelManager', 'The kernel manager token.');
/**
 * The kernel spec manager token.
 */
exports.IKernelSpecManager = new coreutils_1.Token('@jupyterlab/services:IKernelSpecManager', 'The kernel spec manager token.');
/**
 * The nbconvert manager token.
 */
exports.INbConvertManager = new coreutils_1.Token('@jupyterlab/services:INbConvertManager', 'The nbconvert manager token.');
/**
 * The server settings token.
 */
exports.IServerSettings = new coreutils_1.Token('@jupyterlab/services:IServerSettings', 'The server settings for the application.');
/**
 * The session manager token.
 */
exports.ISessionManager = new coreutils_1.Token('@jupyterlab/services:ISessionManager', 'The session manager token.');
/**
 * The setting manager token.
 */
exports.ISettingManager = new coreutils_1.Token('@jupyterlab/services:ISettingManager', 'The setting manager token.');
/**
 * The default service manager token.
 */
exports.IServiceManager = new coreutils_1.Token('@jupyterlab/services:IServiceManager', 'The service manager for the application.');
/**
 * The terminal manager token.
 */
exports.ITerminalManager = new coreutils_1.Token('@jupyterlab/services:ITerminalManager', 'The terminal manager token.');
/**
 * The user manager token.
 */
exports.IUserManager = new coreutils_1.Token('@jupyterlab/services:IUserManager', 'The user manager token.');
/**
 * The workspace manager token.
 */
exports.IWorkspaceManager = new coreutils_1.Token('@jupyterlab/services:IWorkspaceManager', 'The workspace manager token.');
//# sourceMappingURL=tokens.js.map

/***/ }),

/***/ 8126:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Text = void 0;
/**
 * The namespace for text-related functions.
 */
var Text;
(function (Text) {
    // javascript stores text as utf16 and string indices use "code units",
    // which stores high-codepoint characters as "surrogate pairs",
    // which occupy two indices in the javascript string.
    // We need to translate cursor_pos in the Jupyter protocol (in characters)
    // to js offset (with surrogate pairs taking two spots).
    const HAS_SURROGATES = '𝐚'.length > 1;
    /**
     * Convert a javascript string index into a unicode character offset
     *
     * @param jsIdx - The javascript string index (counting surrogate pairs)
     *
     * @param text - The text in which the offset is calculated
     *
     * @returns The unicode character offset
     */
    function jsIndexToCharIndex(jsIdx, text) {
        if (HAS_SURROGATES) {
            // not using surrogates, nothing to do
            return jsIdx;
        }
        let charIdx = jsIdx;
        for (let i = 0; i + 1 < text.length && i < jsIdx; i++) {
            const charCode = text.charCodeAt(i);
            // check for surrogate pair
            if (charCode >= 0xd800 && charCode <= 0xdbff) {
                const nextCharCode = text.charCodeAt(i + 1);
                if (nextCharCode >= 0xdc00 && nextCharCode <= 0xdfff) {
                    charIdx--;
                    i++;
                }
            }
        }
        return charIdx;
    }
    Text.jsIndexToCharIndex = jsIndexToCharIndex;
    /**
     * Convert a unicode character offset to a javascript string index.
     *
     * @param charIdx - The index in unicode characters
     *
     * @param text - The text in which the offset is calculated
     *
     * @returns The js-native index
     */
    function charIndexToJsIndex(charIdx, text) {
        if (HAS_SURROGATES) {
            // not using surrogates, nothing to do
            return charIdx;
        }
        let jsIdx = charIdx;
        for (let i = 0; i + 1 < text.length && i < jsIdx; i++) {
            const charCode = text.charCodeAt(i);
            // check for surrogate pair
            if (charCode >= 0xd800 && charCode <= 0xdbff) {
                const nextCharCode = text.charCodeAt(i + 1);
                if (nextCharCode >= 0xdc00 && nextCharCode <= 0xdfff) {
                    jsIdx++;
                    i++;
                }
            }
        }
        return jsIdx;
    }
    Text.charIndexToJsIndex = charIndexToJsIndex;
    /**
     * Given a 'snake-case', 'snake_case', 'snake:case', or
     * 'snake case' string, will return the camel case version: 'snakeCase'.
     *
     * @param str the snake-case input string.
     *
     * @param upper default = false. If true, the first letter of the
     * returned string will be capitalized.
     *
     * @returns the camel case version of the input string.
     */
    function camelCase(str, upper = false) {
        return str.replace(/^(\w)|[\s-_:]+(\w)/g, function (match, p1, p2) {
            if (p2) {
                return p2.toUpperCase();
            }
            else {
                return upper ? p1.toUpperCase() : p1.toLowerCase();
            }
        });
    }
    Text.camelCase = camelCase;
    /**
     * Given a string, title case the words in the string.
     *
     * @param str the string to title case.
     *
     * @returns the same string, but with each word capitalized.
     */
    function titleCase(str) {
        return (str || '')
            .toLowerCase()
            .split(' ')
            .map(word => word.charAt(0).toUpperCase() + word.slice(1))
            .join(' ');
    }
    Text.titleCase = titleCase;
})(Text || (exports.Text = Text = {}));
//# sourceMappingURL=text.js.map

/***/ }),

/***/ 8135:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   ArrayExt: () => (/* binding */ ArrayExt),
/* harmony export */   StringExt: () => (/* binding */ StringExt),
/* harmony export */   chain: () => (/* binding */ chain),
/* harmony export */   each: () => (/* binding */ each),
/* harmony export */   empty: () => (/* binding */ empty),
/* harmony export */   enumerate: () => (/* binding */ enumerate),
/* harmony export */   every: () => (/* binding */ every),
/* harmony export */   filter: () => (/* binding */ filter),
/* harmony export */   find: () => (/* binding */ find),
/* harmony export */   findIndex: () => (/* binding */ findIndex),
/* harmony export */   map: () => (/* binding */ map),
/* harmony export */   max: () => (/* binding */ max),
/* harmony export */   min: () => (/* binding */ min),
/* harmony export */   minmax: () => (/* binding */ minmax),
/* harmony export */   once: () => (/* binding */ once),
/* harmony export */   range: () => (/* binding */ range),
/* harmony export */   reduce: () => (/* binding */ reduce),
/* harmony export */   repeat: () => (/* binding */ repeat),
/* harmony export */   retro: () => (/* binding */ retro),
/* harmony export */   some: () => (/* binding */ some),
/* harmony export */   stride: () => (/* binding */ stride),
/* harmony export */   take: () => (/* binding */ take),
/* harmony export */   toArray: () => (/* binding */ toArray),
/* harmony export */   toObject: () => (/* binding */ toObject),
/* harmony export */   topologicSort: () => (/* binding */ topologicSort),
/* harmony export */   zip: () => (/* binding */ zip)
/* harmony export */ });
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * The namespace for array-specific algorithms.
 */
var ArrayExt;
(function (ArrayExt) {
    /**
     * Find the index of the first occurrence of a value in an array.
     *
     * @param array - The array-like object to search.
     *
     * @param value - The value to locate in the array. Values are
     *   compared using strict `===` equality.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the first occurrence of the value, or `-1`
     *   if the value is not found.
     *
     * #### Notes
     * If `stop < start` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = ['one', 'two', 'three', 'four', 'one'];
     * ArrayExt.firstIndexOf(data, 'red');        // -1
     * ArrayExt.firstIndexOf(data, 'one');        // 0
     * ArrayExt.firstIndexOf(data, 'one', 1);     // 4
     * ArrayExt.firstIndexOf(data, 'two', 2);     // -1
     * ArrayExt.firstIndexOf(data, 'two', 2, 1);  // 1
     * ```
     */
    function firstIndexOf(array, value, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return -1;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let span;
        if (stop < start) {
            span = stop + 1 + (n - start);
        }
        else {
            span = stop - start + 1;
        }
        for (let i = 0; i < span; ++i) {
            let j = (start + i) % n;
            if (array[j] === value) {
                return j;
            }
        }
        return -1;
    }
    ArrayExt.firstIndexOf = firstIndexOf;
    /**
     * Find the index of the last occurrence of a value in an array.
     *
     * @param array - The array-like object to search.
     *
     * @param value - The value to locate in the array. Values are
     *   compared using strict `===` equality.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the last occurrence of the value, or `-1`
     *   if the value is not found.
     *
     * #### Notes
     * If `start < stop` the search will wrap at the front of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = ['one', 'two', 'three', 'four', 'one'];
     * ArrayExt.lastIndexOf(data, 'red');        // -1
     * ArrayExt.lastIndexOf(data, 'one');        // 4
     * ArrayExt.lastIndexOf(data, 'one', 1);     // 0
     * ArrayExt.lastIndexOf(data, 'two', 0);     // -1
     * ArrayExt.lastIndexOf(data, 'two', 0, 1);  // 1
     * ```
     */
    function lastIndexOf(array, value, start = -1, stop = 0) {
        let n = array.length;
        if (n === 0) {
            return -1;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let span;
        if (start < stop) {
            span = start + 1 + (n - stop);
        }
        else {
            span = start - stop + 1;
        }
        for (let i = 0; i < span; ++i) {
            let j = (start - i + n) % n;
            if (array[j] === value) {
                return j;
            }
        }
        return -1;
    }
    ArrayExt.lastIndexOf = lastIndexOf;
    /**
     * Find the index of the first value which matches a predicate.
     *
     * @param array - The array-like object to search.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the first matching value, or `-1` if no
     *   matching value is found.
     *
     * #### Notes
     * If `stop < start` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [1, 2, 3, 4, 3, 2, 1];
     * ArrayExt.findFirstIndex(data, isEven);       // 1
     * ArrayExt.findFirstIndex(data, isEven, 4);    // 5
     * ArrayExt.findFirstIndex(data, isEven, 6);    // -1
     * ArrayExt.findFirstIndex(data, isEven, 6, 5); // 1
     * ```
     */
    function findFirstIndex(array, fn, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return -1;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let span;
        if (stop < start) {
            span = stop + 1 + (n - start);
        }
        else {
            span = stop - start + 1;
        }
        for (let i = 0; i < span; ++i) {
            let j = (start + i) % n;
            if (fn(array[j], j)) {
                return j;
            }
        }
        return -1;
    }
    ArrayExt.findFirstIndex = findFirstIndex;
    /**
     * Find the index of the last value which matches a predicate.
     *
     * @param array - The array-like object to search.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the last matching value, or `-1` if no
     *   matching value is found.
     *
     * #### Notes
     * If `start < stop` the search will wrap at the front of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [1, 2, 3, 4, 3, 2, 1];
     * ArrayExt.findLastIndex(data, isEven);        // 5
     * ArrayExt.findLastIndex(data, isEven, 4);     // 3
     * ArrayExt.findLastIndex(data, isEven, 0);     // -1
     * ArrayExt.findLastIndex(data, isEven, 0, 1);  // 5
     * ```
     */
    function findLastIndex(array, fn, start = -1, stop = 0) {
        let n = array.length;
        if (n === 0) {
            return -1;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let d;
        if (start < stop) {
            d = start + 1 + (n - stop);
        }
        else {
            d = start - stop + 1;
        }
        for (let i = 0; i < d; ++i) {
            let j = (start - i + n) % n;
            if (fn(array[j], j)) {
                return j;
            }
        }
        return -1;
    }
    ArrayExt.findLastIndex = findLastIndex;
    /**
     * Find the first value which matches a predicate.
     *
     * @param array - The array-like object to search.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The first matching value, or `undefined` if no matching
     *   value is found.
     *
     * #### Notes
     * If `stop < start` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [1, 2, 3, 4, 3, 2, 1];
     * ArrayExt.findFirstValue(data, isEven);       // 2
     * ArrayExt.findFirstValue(data, isEven, 2);    // 4
     * ArrayExt.findFirstValue(data, isEven, 6);    // undefined
     * ArrayExt.findFirstValue(data, isEven, 6, 5); // 2
     * ```
     */
    function findFirstValue(array, fn, start = 0, stop = -1) {
        let index = findFirstIndex(array, fn, start, stop);
        return index !== -1 ? array[index] : undefined;
    }
    ArrayExt.findFirstValue = findFirstValue;
    /**
     * Find the last value which matches a predicate.
     *
     * @param object - The array-like object to search.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The last matching value, or `undefined` if no matching
     *   value is found.
     *
     * #### Notes
     * If `start < stop` the search will wrap at the front of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [1, 2, 3, 4, 3, 2, 1];
     * ArrayExt.findLastValue(data, isEven);        // 2
     * ArrayExt.findLastValue(data, isEven, 4);     // 4
     * ArrayExt.findLastValue(data, isEven, 0);     // undefined
     * ArrayExt.findLastValue(data, isEven, 0, 1);  // 2
     * ```
     */
    function findLastValue(array, fn, start = -1, stop = 0) {
        let index = findLastIndex(array, fn, start, stop);
        return index !== -1 ? array[index] : undefined;
    }
    ArrayExt.findLastValue = findLastValue;
    /**
     * Find the index of the first element which compares `>=` to a value.
     *
     * @param array - The sorted array-like object to search.
     *
     * @param value - The value to locate in the array.
     *
     * @param fn - The 3-way comparison function to apply to the values.
     *   It should return `< 0` if an element is less than a value, `0` if
     *   an element is equal to a value, or `> 0` if an element is greater
     *   than a value.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the first element which compares `>=` to the
     *   value, or `length` if there is no such element. If the computed
     *   index for `stop` is less than `start`, then the computed index
     *   for `start` is returned.
     *
     * #### Notes
     * The array must already be sorted in ascending order according to
     * the comparison function.
     *
     * #### Complexity
     * Logarithmic.
     *
     * #### Undefined Behavior
     * Searching a range which is not sorted in ascending order.
     *
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function numberCmp(a: number, b: number): number {
     *   return a - b;
     * }
     *
     * let data = [0, 3, 4, 7, 7, 9];
     * ArrayExt.lowerBound(data, 0, numberCmp);   // 0
     * ArrayExt.lowerBound(data, 6, numberCmp);   // 3
     * ArrayExt.lowerBound(data, 7, numberCmp);   // 3
     * ArrayExt.lowerBound(data, -1, numberCmp);  // 0
     * ArrayExt.lowerBound(data, 10, numberCmp);  // 6
     * ```
     */
    function lowerBound(array, value, fn, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return 0;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let begin = start;
        let span = stop - start + 1;
        while (span > 0) {
            let half = span >> 1;
            let middle = begin + half;
            if (fn(array[middle], value) < 0) {
                begin = middle + 1;
                span -= half + 1;
            }
            else {
                span = half;
            }
        }
        return begin;
    }
    ArrayExt.lowerBound = lowerBound;
    /**
     * Find the index of the first element which compares `>` than a value.
     *
     * @param array - The sorted array-like object to search.
     *
     * @param value - The value to locate in the array.
     *
     * @param fn - The 3-way comparison function to apply to the values.
     *   It should return `< 0` if an element is less than a value, `0` if
     *   an element is equal to a value, or `> 0` if an element is greater
     *   than a value.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the first element which compares `>` than the
     *   value, or `length` if there is no such element. If the computed
     *   index for `stop` is less than `start`, then the computed index
     *   for `start` is returned.
     *
     * #### Notes
     * The array must already be sorted in ascending order according to
     * the comparison function.
     *
     * #### Complexity
     * Logarithmic.
     *
     * #### Undefined Behavior
     * Searching a range which is not sorted in ascending order.
     *
     * A `start` or `stop` which is non-integral.
     *
     * Modifying the length of the array while searching.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function numberCmp(a: number, b: number): number {
     *   return a - b;
     * }
     *
     * let data = [0, 3, 4, 7, 7, 9];
     * ArrayExt.upperBound(data, 0, numberCmp);   // 1
     * ArrayExt.upperBound(data, 6, numberCmp);   // 3
     * ArrayExt.upperBound(data, 7, numberCmp);   // 5
     * ArrayExt.upperBound(data, -1, numberCmp);  // 0
     * ArrayExt.upperBound(data, 10, numberCmp);  // 6
     * ```
     */
    function upperBound(array, value, fn, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return 0;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let begin = start;
        let span = stop - start + 1;
        while (span > 0) {
            let half = span >> 1;
            let middle = begin + half;
            if (fn(array[middle], value) > 0) {
                span = half;
            }
            else {
                begin = middle + 1;
                span -= half + 1;
            }
        }
        return begin;
    }
    ArrayExt.upperBound = upperBound;
    /**
     * Test whether two arrays are shallowly equal.
     *
     * @param a - The first array-like object to compare.
     *
     * @param b - The second array-like object to compare.
     *
     * @param fn - The comparison function to apply to the elements. It
     *   should return `true` if the elements are "equal". The default
     *   compares elements using strict `===` equality.
     *
     * @returns Whether the two arrays are shallowly equal.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * Modifying the length of the arrays while comparing.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let d1 = [0, 3, 4, 7, 7, 9];
     * let d2 = [0, 3, 4, 7, 7, 9];
     * let d3 = [42];
     * ArrayExt.shallowEqual(d1, d2);  // true
     * ArrayExt.shallowEqual(d2, d3);  // false
     * ```
     */
    function shallowEqual(a, b, fn) {
        // Check for object identity first.
        if (a === b) {
            return true;
        }
        // Bail early if the lengths are different.
        if (a.length !== b.length) {
            return false;
        }
        // Compare each element for equality.
        for (let i = 0, n = a.length; i < n; ++i) {
            if (fn ? !fn(a[i], b[i]) : a[i] !== b[i]) {
                return false;
            }
        }
        // The array are shallowly equal.
        return true;
    }
    ArrayExt.shallowEqual = shallowEqual;
    /**
     * Create a slice of an array subject to an optional step.
     *
     * @param array - The array-like object of interest.
     *
     * @param options - The options for configuring the slice.
     *
     * @returns A new array with the specified values.
     *
     * @throws An exception if the slice `step` is `0`.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start`, `stop`, or `step` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 3, 4, 7, 7, 9];
     * ArrayExt.slice(data);                         // [0, 3, 4, 7, 7, 9]
     * ArrayExt.slice(data, { start: 2 });           // [4, 7, 7, 9]
     * ArrayExt.slice(data, { start: 0, stop: 4 });  // [0, 3, 4, 7]
     * ArrayExt.slice(data, { step: 2 });            // [0, 4, 7]
     * ArrayExt.slice(data, { step: -1 });           // [9, 7, 7, 4, 3, 0]
     * ```
     */
    function slice(array, options = {}) {
        // Extract the options.
        let { start, stop, step } = options;
        // Set up the `step` value.
        if (step === undefined) {
            step = 1;
        }
        // Validate the step size.
        if (step === 0) {
            throw new Error('Slice `step` cannot be zero.');
        }
        // Look up the length of the array.
        let n = array.length;
        // Set up the `start` value.
        if (start === undefined) {
            start = step < 0 ? n - 1 : 0;
        }
        else if (start < 0) {
            start = Math.max(start + n, step < 0 ? -1 : 0);
        }
        else if (start >= n) {
            start = step < 0 ? n - 1 : n;
        }
        // Set up the `stop` value.
        if (stop === undefined) {
            stop = step < 0 ? -1 : n;
        }
        else if (stop < 0) {
            stop = Math.max(stop + n, step < 0 ? -1 : 0);
        }
        else if (stop >= n) {
            stop = step < 0 ? n - 1 : n;
        }
        // Compute the slice length.
        let length;
        if ((step < 0 && stop >= start) || (step > 0 && start >= stop)) {
            length = 0;
        }
        else if (step < 0) {
            length = Math.floor((stop - start + 1) / step + 1);
        }
        else {
            length = Math.floor((stop - start - 1) / step + 1);
        }
        // Compute the sliced result.
        let result = [];
        for (let i = 0; i < length; ++i) {
            result[i] = array[start + i * step];
        }
        // Return the result.
        return result;
    }
    ArrayExt.slice = slice;
    /**
     * Move an element in an array from one index to another.
     *
     * @param array - The mutable array-like object of interest.
     *
     * @param fromIndex - The index of the element to move. Negative
     *   values are taken as an offset from the end of the array.
     *
     * @param toIndex - The target index of the element. Negative
     *   values are taken as an offset from the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `fromIndex` or `toIndex` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from from '@lumino/algorithm';
     *
     * let data = [0, 1, 2, 3, 4];
     * ArrayExt.move(data, 1, 2);  // [0, 2, 1, 3, 4]
     * ArrayExt.move(data, 4, 2);  // [0, 2, 4, 1, 3]
     * ```
     */
    function move(array, fromIndex, toIndex) {
        let n = array.length;
        if (n <= 1) {
            return;
        }
        if (fromIndex < 0) {
            fromIndex = Math.max(0, fromIndex + n);
        }
        else {
            fromIndex = Math.min(fromIndex, n - 1);
        }
        if (toIndex < 0) {
            toIndex = Math.max(0, toIndex + n);
        }
        else {
            toIndex = Math.min(toIndex, n - 1);
        }
        if (fromIndex === toIndex) {
            return;
        }
        let value = array[fromIndex];
        let d = fromIndex < toIndex ? 1 : -1;
        for (let i = fromIndex; i !== toIndex; i += d) {
            array[i] = array[i + d];
        }
        array[toIndex] = value;
    }
    ArrayExt.move = move;
    /**
     * Reverse an array in-place.
     *
     * @param array - The mutable array-like object of interest.
     *
     * @param start - The index of the first element in the range to be
     *   reversed, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   reversed, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or  `stop` index which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 1, 2, 3, 4];
     * ArrayExt.reverse(data, 1, 3);  // [0, 3, 2, 1, 4]
     * ArrayExt.reverse(data, 3);     // [0, 3, 2, 4, 1]
     * ArrayExt.reverse(data);        // [1, 4, 2, 3, 0]
     * ```
     */
    function reverse(array, start = 0, stop = -1) {
        let n = array.length;
        if (n <= 1) {
            return;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        while (start < stop) {
            let a = array[start];
            let b = array[stop];
            array[start++] = b;
            array[stop--] = a;
        }
    }
    ArrayExt.reverse = reverse;
    /**
     * Rotate the elements of an array in-place.
     *
     * @param array - The mutable array-like object of interest.
     *
     * @param delta - The amount of rotation to apply to the elements. A
     *   positive value will rotate the elements to the left. A negative
     *   value will rotate the elements to the right.
     *
     * @param start - The index of the first element in the range to be
     *   rotated, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   rotated, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `delta`, `start`, or `stop` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 1, 2, 3, 4];
     * ArrayExt.rotate(data, 2);        // [2, 3, 4, 0, 1]
     * ArrayExt.rotate(data, -2);       // [0, 1, 2, 3, 4]
     * ArrayExt.rotate(data, 10);       // [0, 1, 2, 3, 4]
     * ArrayExt.rotate(data, 9);        // [4, 0, 1, 2, 3]
     * ArrayExt.rotate(data, 2, 1, 3);  // [4, 2, 0, 1, 3]
     * ```
     */
    function rotate(array, delta, start = 0, stop = -1) {
        let n = array.length;
        if (n <= 1) {
            return;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        if (start >= stop) {
            return;
        }
        let length = stop - start + 1;
        if (delta > 0) {
            delta = delta % length;
        }
        else if (delta < 0) {
            delta = ((delta % length) + length) % length;
        }
        if (delta === 0) {
            return;
        }
        let pivot = start + delta;
        reverse(array, start, pivot - 1);
        reverse(array, pivot, stop);
        reverse(array, start, stop);
    }
    ArrayExt.rotate = rotate;
    /**
     * Fill an array with a static value.
     *
     * @param array - The mutable array-like object to fill.
     *
     * @param value - The static value to use to fill the array.
     *
     * @param start - The index of the first element in the range to be
     *   filled, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   filled, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * #### Notes
     * If `stop < start` the fill will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * A `start` or `stop` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = ['one', 'two', 'three', 'four'];
     * ArrayExt.fill(data, 'r');        // ['r', 'r', 'r', 'r']
     * ArrayExt.fill(data, 'g', 1);     // ['r', 'g', 'g', 'g']
     * ArrayExt.fill(data, 'b', 2, 3);  // ['r', 'g', 'b', 'b']
     * ArrayExt.fill(data, 'z', 3, 1);  // ['z', 'z', 'b', 'z']
     * ```
     */
    function fill(array, value, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let span;
        if (stop < start) {
            span = stop + 1 + (n - start);
        }
        else {
            span = stop - start + 1;
        }
        for (let i = 0; i < span; ++i) {
            array[(start + i) % n] = value;
        }
    }
    ArrayExt.fill = fill;
    /**
     * Insert a value into an array at a specific index.
     *
     * @param array - The array of interest.
     *
     * @param index - The index at which to insert the value. Negative
     *   values are taken as an offset from the end of the array.
     *
     * @param value - The value to set at the specified index.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * An `index` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 1, 2];
     * ArrayExt.insert(data, 0, -1);  // [-1, 0, 1, 2]
     * ArrayExt.insert(data, 2, 12);  // [-1, 0, 12, 1, 2]
     * ArrayExt.insert(data, -1, 7);  // [-1, 0, 12, 1, 7, 2]
     * ArrayExt.insert(data, 6, 19);  // [-1, 0, 12, 1, 7, 2, 19]
     * ```
     */
    function insert(array, index, value) {
        let n = array.length;
        if (index < 0) {
            index = Math.max(0, index + n);
        }
        else {
            index = Math.min(index, n);
        }
        for (let i = n; i > index; --i) {
            array[i] = array[i - 1];
        }
        array[index] = value;
    }
    ArrayExt.insert = insert;
    /**
     * Remove and return a value at a specific index in an array.
     *
     * @param array - The array of interest.
     *
     * @param index - The index of the value to remove. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The value at the specified index, or `undefined` if the
     *   index is out of range.
     *
     * #### Complexity
     * Linear.
     *
     * #### Undefined Behavior
     * An `index` which is non-integral.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 12, 23, 39, 14, 12, 75];
     * ArrayExt.removeAt(data, 2);   // 23
     * ArrayExt.removeAt(data, -2);  // 12
     * ArrayExt.removeAt(data, 10);  // undefined;
     * ```
     */
    function removeAt(array, index) {
        let n = array.length;
        if (index < 0) {
            index += n;
        }
        if (index < 0 || index >= n) {
            return undefined;
        }
        let value = array[index];
        for (let i = index + 1; i < n; ++i) {
            array[i - 1] = array[i];
        }
        array.length = n - 1;
        return value;
    }
    ArrayExt.removeAt = removeAt;
    /**
     * Remove the first occurrence of a value from an array.
     *
     * @param array - The array of interest.
     *
     * @param value - The value to remove from the array. Values are
     *   compared using strict `===` equality.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the removed value, or `-1` if the value
     *   is not contained in the array.
     *
     * #### Notes
     * If `stop < start` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 12, 23, 39, 14, 12, 75];
     * ArrayExt.removeFirstOf(data, 12);        // 1
     * ArrayExt.removeFirstOf(data, 17);        // -1
     * ArrayExt.removeFirstOf(data, 39, 3);     // -1
     * ArrayExt.removeFirstOf(data, 39, 3, 2);  // 2
     * ```
     */
    function removeFirstOf(array, value, start = 0, stop = -1) {
        let index = firstIndexOf(array, value, start, stop);
        if (index !== -1) {
            removeAt(array, index);
        }
        return index;
    }
    ArrayExt.removeFirstOf = removeFirstOf;
    /**
     * Remove the last occurrence of a value from an array.
     *
     * @param array - The array of interest.
     *
     * @param value - The value to remove from the array. Values are
     *   compared using strict `===` equality.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The index of the removed value, or `-1` if the value
     *   is not contained in the array.
     *
     * #### Notes
     * If `start < stop` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [0, 12, 23, 39, 14, 12, 75];
     * ArrayExt.removeLastOf(data, 12);        // 5
     * ArrayExt.removeLastOf(data, 17);        // -1
     * ArrayExt.removeLastOf(data, 39, 2);     // -1
     * ArrayExt.removeLastOf(data, 39, 2, 3);  // 3
     * ```
     */
    function removeLastOf(array, value, start = -1, stop = 0) {
        let index = lastIndexOf(array, value, start, stop);
        if (index !== -1) {
            removeAt(array, index);
        }
        return index;
    }
    ArrayExt.removeLastOf = removeLastOf;
    /**
     * Remove all occurrences of a value from an array.
     *
     * @param array - The array of interest.
     *
     * @param value - The value to remove from the array. Values are
     *   compared using strict `===` equality.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The number of elements removed from the array.
     *
     * #### Notes
     * If `stop < start` the search will conceptually wrap at the end of
     * the array, however the array will be traversed front-to-back.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * let data = [14, 12, 23, 39, 14, 12, 19, 14];
     * ArrayExt.removeAllOf(data, 12);        // 2
     * ArrayExt.removeAllOf(data, 17);        // 0
     * ArrayExt.removeAllOf(data, 14, 1, 4);  // 1
     * ```
     */
    function removeAllOf(array, value, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return 0;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let count = 0;
        for (let i = 0; i < n; ++i) {
            if (start <= stop && i >= start && i <= stop && array[i] === value) {
                count++;
            }
            else if (stop < start &&
                (i <= stop || i >= start) &&
                array[i] === value) {
                count++;
            }
            else if (count > 0) {
                array[i - count] = array[i];
            }
        }
        if (count > 0) {
            array.length = n - count;
        }
        return count;
    }
    ArrayExt.removeAllOf = removeAllOf;
    /**
     * Remove the first occurrence of a value which matches a predicate.
     *
     * @param array - The array of interest.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The removed `{ index, value }`, which will be `-1` and
     *   `undefined` if the value is not contained in the array.
     *
     * #### Notes
     * If `stop < start` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [0, 12, 23, 39, 14, 12, 75];
     * ArrayExt.removeFirstWhere(data, isEven);     // { index: 0, value: 0 }
     * ArrayExt.removeFirstWhere(data, isEven, 2);  // { index: 3, value: 14 }
     * ArrayExt.removeFirstWhere(data, isEven, 4);  // { index: -1, value: undefined }
     * ```
     */
    function removeFirstWhere(array, fn, start = 0, stop = -1) {
        let value;
        let index = findFirstIndex(array, fn, start, stop);
        if (index !== -1) {
            value = removeAt(array, index);
        }
        return { index, value };
    }
    ArrayExt.removeFirstWhere = removeFirstWhere;
    /**
     * Remove the last occurrence of a value which matches a predicate.
     *
     * @param array - The array of interest.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The removed `{ index, value }`, which will be `-1` and
     *   `undefined` if the value is not contained in the array.
     *
     * #### Notes
     * If `start < stop` the search will wrap at the end of the array.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * let data = [0, 12, 23, 39, 14, 12, 75];
     * ArrayExt.removeLastWhere(data, isEven);        // { index: 5, value: 12 }
     * ArrayExt.removeLastWhere(data, isEven, 2);     // { index: 1, value: 12 }
     * ArrayExt.removeLastWhere(data, isEven, 2, 1);  // { index: -1, value: undefined }
     * ```
     */
    function removeLastWhere(array, fn, start = -1, stop = 0) {
        let value;
        let index = findLastIndex(array, fn, start, stop);
        if (index !== -1) {
            value = removeAt(array, index);
        }
        return { index, value };
    }
    ArrayExt.removeLastWhere = removeLastWhere;
    /**
     * Remove all occurrences of values which match a predicate.
     *
     * @param array - The array of interest.
     *
     * @param fn - The predicate function to apply to the values.
     *
     * @param start - The index of the first element in the range to be
     *   searched, inclusive. The default value is `0`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @param stop - The index of the last element in the range to be
     *   searched, inclusive. The default value is `-1`. Negative values
     *   are taken as an offset from the end of the array.
     *
     * @returns The number of elements removed from the array.
     *
     * #### Notes
     * If `stop < start` the search will conceptually wrap at the end of
     * the array, however the array will be traversed front-to-back.
     *
     * #### Complexity
     * Linear.
     *
     * #### Example
     * ```typescript
     * import { ArrayExt } from '@lumino/algorithm';
     *
     * function isEven(value: number): boolean {
     *   return value % 2 === 0;
     * }
     *
     * function isNegative(value: number): boolean {
     *   return value < 0;
     * }
     *
     * let data = [0, 12, -13, -9, 23, 39, 14, -15, 12, 75];
     * ArrayExt.removeAllWhere(data, isEven);            // 4
     * ArrayExt.removeAllWhere(data, isNegative, 0, 3);  // 2
     * ```
     */
    function removeAllWhere(array, fn, start = 0, stop = -1) {
        let n = array.length;
        if (n === 0) {
            return 0;
        }
        if (start < 0) {
            start = Math.max(0, start + n);
        }
        else {
            start = Math.min(start, n - 1);
        }
        if (stop < 0) {
            stop = Math.max(0, stop + n);
        }
        else {
            stop = Math.min(stop, n - 1);
        }
        let count = 0;
        for (let i = 0; i < n; ++i) {
            if (start <= stop && i >= start && i <= stop && fn(array[i], i)) {
                count++;
            }
            else if (stop < start && (i <= stop || i >= start) && fn(array[i], i)) {
                count++;
            }
            else if (count > 0) {
                array[i - count] = array[i];
            }
        }
        if (count > 0) {
            array.length = n - count;
        }
        return count;
    }
    ArrayExt.removeAllWhere = removeAllWhere;
})(ArrayExt || (ArrayExt = {}));

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Chain together several iterables.
 *
 * @deprecated
 *
 * @param objects - The iterable objects of interest.
 *
 * @returns An iterator which yields the values of the iterables
 *   in the order in which they are supplied.
 *
 * #### Example
 * ```typescript
 * import { chain } from '@lumino/algorithm';
 *
 * let data1 = [1, 2, 3];
 * let data2 = [4, 5, 6];
 *
 * let stream = chain(data1, data2);
 *
 * Array.from(stream);  // [1, 2, 3, 4, 5, 6]
 * ```
 */
function* chain(...objects) {
    for (const object of objects) {
        yield* object;
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Create an empty iterator.
 *
 * @returns A new iterator which yields nothing.
 *
 * #### Example
 * ```typescript
 * import { empty } from '@lumino/algorithm';
 *
 * let stream = empty<number>();
 *
 * Array.from(stream);  // []
 * ```
 */
// eslint-disable-next-line require-yield
function* empty() {
    return;
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Enumerate an iterable object.
 *
 * @param object - The iterable object of interest.
 *
 * @param start - The starting enum value. The default is `0`.
 *
 * @returns An iterator which yields the enumerated values.
 *
 * #### Example
 * ```typescript
 * import { enumerate } from '@lumino/algorithm';
 *
 * let data = ['foo', 'bar', 'baz'];
 *
 * let stream = enumerate(data, 1);
 *
 * Array.from(stream);  // [[1, 'foo'], [2, 'bar'], [3, 'baz']]
 * ```
 */
function* enumerate(object, start = 0) {
    for (const value of object) {
        yield [start++, value];
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Filter an iterable for values which pass a test.
 *
 * @param object - The iterable object of interest.
 *
 * @param fn - The predicate function to invoke for each value.
 *
 * @returns An iterator which yields the values which pass the test.
 *
 * #### Example
 * ```typescript
 * import { filter } from '@lumino/algorithm';
 *
 * let data = [1, 2, 3, 4, 5, 6];
 *
 * let stream = filter(data, value => value % 2 === 0);
 *
 * Array.from(stream);  // [2, 4, 6]
 * ```
 */
function* filter(object, fn) {
    let index = 0;
    for (const value of object) {
        if (fn(value, index++)) {
            yield value;
        }
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Find the first value in an iterable which matches a predicate.
 *
 * @param object - The iterable object to search.
 *
 * @param fn - The predicate function to apply to the values.
 *
 * @returns The first matching value, or `undefined` if no matching
 *   value is found.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { find } from '@lumino/algorithm';
 *
 * interface IAnimal { species: string, name: string };
 *
 * function isCat(value: IAnimal): boolean {
 *   return value.species === 'cat';
 * }
 *
 * let data: IAnimal[] = [
 *   { species: 'dog', name: 'spot' },
 *   { species: 'cat', name: 'fluffy' },
 *   { species: 'alligator', name: 'pocho' }
 * ];
 *
 * find(data, isCat).name;  // 'fluffy'
 * ```
 */
function find(object, fn) {
    let index = 0;
    for (const value of object) {
        if (fn(value, index++)) {
            return value;
        }
    }
    return undefined;
}
/**
 * Find the index of the first value which matches a predicate.
 *
 * @param object - The iterable object to search.
 *
 * @param fn - The predicate function to apply to the values.
 *
 * @returns The index of the first matching value, or `-1` if no
 *   matching value is found.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { findIndex } from '@lumino/algorithm';
 *
 * interface IAnimal { species: string, name: string };
 *
 * function isCat(value: IAnimal): boolean {
 *   return value.species === 'cat';
 * }
 *
 * let data: IAnimal[] = [
 *   { species: 'dog', name: 'spot' },
 *   { species: 'cat', name: 'fluffy' },
 *   { species: 'alligator', name: 'pocho' }
 * ];
 *
 * findIndex(data, isCat);  // 1
 * ```
 */
function findIndex(object, fn) {
    let index = 0;
    for (const value of object) {
        if (fn(value, index++)) {
            return index - 1;
        }
    }
    return -1;
}
/**
 * Find the minimum value in an iterable.
 *
 * @param object - The iterable object to search.
 *
 * @param fn - The 3-way comparison function to apply to the values.
 *   It should return `< 0` if the first value is less than the second.
 *   `0` if the values are equivalent, or `> 0` if the first value is
 *   greater than the second.
 *
 * @returns The minimum value in the iterable. If multiple values are
 *   equivalent to the minimum, the left-most value is returned. If
 *   the iterable is empty, this returns `undefined`.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { min } from '@lumino/algorithm';
 *
 * function numberCmp(a: number, b: number): number {
 *   return a - b;
 * }
 *
 * min([7, 4, 0, 3, 9, 4], numberCmp);  // 0
 * ```
 */
function min(object, fn) {
    let result = undefined;
    for (const value of object) {
        if (result === undefined) {
            result = value;
            continue;
        }
        if (fn(value, result) < 0) {
            result = value;
        }
    }
    return result;
}
/**
 * Find the maximum value in an iterable.
 *
 * @param object - The iterable object to search.
 *
 * @param fn - The 3-way comparison function to apply to the values.
 *   It should return `< 0` if the first value is less than the second.
 *   `0` if the values are equivalent, or `> 0` if the first value is
 *   greater than the second.
 *
 * @returns The maximum value in the iterable. If multiple values are
 *   equivalent to the maximum, the left-most value is returned. If
 *   the iterable is empty, this returns `undefined`.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { max } from '@lumino/algorithm';
 *
 * function numberCmp(a: number, b: number): number {
 *   return a - b;
 * }
 *
 * max([7, 4, 0, 3, 9, 4], numberCmp);  // 9
 * ```
 */
function max(object, fn) {
    let result = undefined;
    for (const value of object) {
        if (result === undefined) {
            result = value;
            continue;
        }
        if (fn(value, result) > 0) {
            result = value;
        }
    }
    return result;
}
/**
 * Find the minimum and maximum values in an iterable.
 *
 * @param object - The iterable object to search.
 *
 * @param fn - The 3-way comparison function to apply to the values.
 *   It should return `< 0` if the first value is less than the second.
 *   `0` if the values are equivalent, or `> 0` if the first value is
 *   greater than the second.
 *
 * @returns A 2-tuple of the `[min, max]` values in the iterable. If
 *   multiple values are equivalent, the left-most values are returned.
 *   If the iterable is empty, this returns `undefined`.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { minmax } from '@lumino/algorithm';
 *
 * function numberCmp(a: number, b: number): number {
 *   return a - b;
 * }
 *
 * minmax([7, 4, 0, 3, 9, 4], numberCmp);  // [0, 9]
 * ```
 */
function minmax(object, fn) {
    let empty = true;
    let vmin;
    let vmax;
    for (const value of object) {
        if (empty) {
            vmin = value;
            vmax = value;
            empty = false;
        }
        else if (fn(value, vmin) < 0) {
            vmin = value;
        }
        else if (fn(value, vmax) > 0) {
            vmax = value;
        }
    }
    return empty ? undefined : [vmin, vmax];
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Create an array from an iterable of values.
 *
 * @deprecated
 *
 * @param object - The iterable object of interest.
 *
 * @returns A new array of values from the given object.
 *
 * #### Example
 * ```typescript
 * import { toArray } from '@lumino/algorithm';
 *
 * let stream = [1, 2, 3, 4, 5, 6][Symbol.iterator]();
 *
 * toArray(stream);  // [1, 2, 3, 4, 5, 6];
 * ```
 */
function toArray(object) {
    return Array.from(object);
}
/**
 * Create an object from an iterable of key/value pairs.
 *
 * @param object - The iterable object of interest.
 *
 * @returns A new object mapping keys to values.
 *
 * #### Example
 * ```typescript
 * import { toObject } from '@lumino/algorithm';
 *
 * let data: [string, number][] = [['one', 1], ['two', 2], ['three', 3]];
 *
 * toObject(data);  // { one: 1, two: 2, three: 3 }
 * ```
 */
function toObject(object) {
    const result = {};
    for (const [key, value] of object) {
        result[key] = value;
    }
    return result;
}
/**
 * Invoke a function for each value in an iterable.
 *
 * @deprecated
 *
 * @param object - The iterable object of interest.
 *
 * @param fn - The callback function to invoke for each value.
 *
 * #### Notes
 * Iteration can be terminated early by returning `false` from the
 * callback function.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { each } from '@lumino/algorithm';
 *
 * let data = [5, 7, 0, -2, 9];
 *
 * each(data, value => { console.log(value); });
 * ```
 */
function each(object, fn) {
    let index = 0;
    for (const value of object) {
        if (false === fn(value, index++)) {
            return;
        }
    }
}
/**
 * Test whether all values in an iterable satisfy a predicate.
 *
 * @param object - The iterable object of interest.
 *
 * @param fn - The predicate function to invoke for each value.
 *
 * @returns `true` if all values pass the test, `false` otherwise.
 *
 * #### Notes
 * Iteration terminates on the first `false` predicate result.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { every } from '@lumino/algorithm';
 *
 * let data = [5, 7, 1];
 *
 * every(data, value => value % 2 === 0);  // false
 * every(data, value => value % 2 === 1);  // true
 * ```
 */
function every(object, fn) {
    let index = 0;
    for (const value of object) {
        if (false === fn(value, index++)) {
            return false;
        }
    }
    return true;
}
/**
 * Test whether any value in an iterable satisfies a predicate.
 *
 * @param object - The iterable object of interest.
 *
 * @param fn - The predicate function to invoke for each value.
 *
 * @returns `true` if any value passes the test, `false` otherwise.
 *
 * #### Notes
 * Iteration terminates on the first `true` predicate result.
 *
 * #### Complexity
 * Linear.
 *
 * #### Example
 * ```typescript
 * import { some } from '@lumino/algorithm';
 *
 * let data = [5, 7, 1];
 *
 * some(data, value => value === 7);  // true
 * some(data, value => value === 3);  // false
 * ```
 */
function some(object, fn) {
    let index = 0;
    for (const value of object) {
        if (fn(value, index++)) {
            return true;
        }
    }
    return false;
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Transform the values of an iterable with a mapping function.
 *
 * @param object - The iterable object of interest.
 *
 * @param fn - The mapping function to invoke for each value.
 *
 * @returns An iterator which yields the transformed values.
 *
 * #### Example
 * ```typescript
 * import { map } from '@lumino/algorithm';
 *
 * let data = [1, 2, 3];
 *
 * let stream = map(data, value => value * 2);
 *
 * Array.from(stream);  // [2, 4, 6]
 * ```
 */
function* map(object, fn) {
    let index = 0;
    for (const value of object) {
        yield fn(value, index++);
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Create an iterator of evenly spaced values.
 *
 * @param start - The starting value for the range, inclusive.
 *
 * @param stop - The stopping value for the range, exclusive.
 *
 * @param step - The distance between each value.
 *
 * @returns An iterator which produces evenly spaced values.
 *
 * #### Notes
 * In the single argument form of `range(stop)`, `start` defaults to
 * `0` and `step` defaults to `1`.
 *
 * In the two argument form of `range(start, stop)`, `step` defaults
 * to `1`.
 *
 * #### Example
 * ```typescript
 * import { range } from '@lumino/algorithm';
 *
 * let stream = range(2, 4);
 *
 * Array.from(stream);  // [2, 3]
 * ```
 */
function* range(start, stop, step) {
    if (stop === undefined) {
        stop = start;
        start = 0;
        step = 1;
    }
    else if (step === undefined) {
        step = 1;
    }
    const length = Private.rangeLength(start, stop, step);
    for (let index = 0; index < length; index++) {
        yield start + step * index;
    }
}
/**
 * The namespace for the module implementation details.
 */
var Private;
(function (Private) {
    /**
     * Compute the effective length of a range.
     *
     * @param start - The starting value for the range, inclusive.
     *
     * @param stop - The stopping value for the range, exclusive.
     *
     * @param step - The distance between each value.
     *
     * @returns The number of steps need to traverse the range.
     */
    function rangeLength(start, stop, step) {
        if (step === 0) {
            return Infinity;
        }
        if (start > stop && step > 0) {
            return 0;
        }
        if (start < stop && step < 0) {
            return 0;
        }
        return Math.ceil((stop - start) / step);
    }
    Private.rangeLength = rangeLength;
})(Private || (Private = {}));

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
function reduce(object, fn, initial) {
    // Setup the iterator and fetch the first value.
    const it = object[Symbol.iterator]();
    let index = 0;
    let first = it.next();
    // An empty iterator and no initial value is an error.
    if (first.done && initial === undefined) {
        throw new TypeError('Reduce of empty iterable with no initial value.');
    }
    // If the iterator is empty, return the initial value.
    if (first.done) {
        return initial;
    }
    // If the iterator has a single item and no initial value, the
    // reducer is not invoked and the first item is the return value.
    let second = it.next();
    if (second.done && initial === undefined) {
        return first.value;
    }
    // If iterator has a single item and an initial value is provided,
    // the reducer is invoked and that result is the return value.
    if (second.done) {
        return fn(initial, first.value, index++);
    }
    // Setup the initial accumlated value.
    let accumulator;
    if (initial === undefined) {
        accumulator = fn(first.value, second.value, index++);
    }
    else {
        accumulator = fn(fn(initial, first.value, index++), second.value, index++);
    }
    // Iterate the rest of the values, updating the accumulator.
    let next;
    while (!(next = it.next()).done) {
        accumulator = fn(accumulator, next.value, index++);
    }
    // Return the final accumulated value.
    return accumulator;
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Create an iterator which repeats a value a number of times.
 *
 * @deprecated
 *
 * @param value - The value to repeat.
 *
 * @param count - The number of times to repeat the value.
 *
 * @returns A new iterator which repeats the specified value.
 *
 * #### Example
 * ```typescript
 * import { repeat } from '@lumino/algorithm';
 *
 * let stream = repeat(7, 3);
 *
 * Array.from(stream);  // [7, 7, 7]
 * ```
 */
function* repeat(value, count) {
    while (0 < count--) {
        yield value;
    }
}
/**
 * Create an iterator which yields a value a single time.
 *
 * @deprecated
 *
 * @param value - The value to wrap in an iterator.
 *
 * @returns A new iterator which yields the value a single time.
 *
 * #### Example
 * ```typescript
 * import { once } from '@lumino/algorithm';
 *
 * let stream = once(7);
 *
 * Array.from(stream);  // [7]
 * ```
 */
function* once(value) {
    yield value;
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Create an iterator for a retroable object.
 *
 * @param object - The retroable or array-like object of interest.
 *
 * @returns An iterator which traverses the object's values in reverse.
 *
 * #### Example
 * ```typescript
 * import { retro } from '@lumino/algorithm';
 *
 * let data = [1, 2, 3, 4, 5, 6];
 *
 * let stream = retro(data);
 *
 * Array.from(stream);  // [6, 5, 4, 3, 2, 1]
 * ```
 */
function* retro(object) {
    if (typeof object.retro === 'function') {
        yield* object.retro();
    }
    else {
        for (let index = object.length - 1; index > -1; index--) {
            yield object[index];
        }
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Topologically sort an iterable of edges.
 *
 * @param edges - The iterable object of edges to sort.
 *   An edge is represented as a 2-tuple of `[fromNode, toNode]`.
 *
 * @returns The topologically sorted array of nodes.
 *
 * #### Notes
 * If a cycle is present in the graph, the cycle will be ignored and
 * the return value will be only approximately sorted.
 *
 * #### Example
 * ```typescript
 * import { topologicSort } from '@lumino/algorithm';
 *
 * let data = [
 *   ['d', 'e'],
 *   ['c', 'd'],
 *   ['a', 'b'],
 *   ['b', 'c']
 * ];
 *
 * topologicSort(data);  // ['a', 'b', 'c', 'd', 'e']
 * ```
 */
function topologicSort(edges) {
    // Setup the shared sorting state.
    let sorted = [];
    let visited = new Set();
    let graph = new Map();
    // Add the edges to the graph.
    for (const edge of edges) {
        addEdge(edge);
    }
    // Visit each node in the graph.
    for (const [k] of graph) {
        visit(k);
    }
    // Return the sorted results.
    return sorted;
    // Add an edge to the graph.
    function addEdge(edge) {
        let [fromNode, toNode] = edge;
        let children = graph.get(toNode);
        if (children) {
            children.push(fromNode);
        }
        else {
            graph.set(toNode, [fromNode]);
        }
    }
    // Recursively visit the node.
    function visit(node) {
        if (visited.has(node)) {
            return;
        }
        visited.add(node);
        let children = graph.get(node);
        if (children) {
            for (const child of children) {
                visit(child);
            }
        }
        sorted.push(node);
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Iterate over an iterable using a stepped increment.
 *
 * @param object - The iterable object of interest.
 *
 * @param step - The distance to step on each iteration. A value
 *   of less than `1` will behave the same as a value of `1`.
 *
 * @returns An iterator which traverses the iterable step-wise.
 *
 * #### Example
 * ```typescript
 * import { stride } from '@lumino/algorithm';
 *
 * let data = [1, 2, 3, 4, 5, 6];
 *
 * let stream = stride(data, 2);
 *
 * Array.from(stream);  // [1, 3, 5];
 * ```
 */
function* stride(object, step) {
    let count = 0;
    for (const value of object) {
        if (0 === count++ % step) {
            yield value;
        }
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * The namespace for string-specific algorithms.
 */
var StringExt;
(function (StringExt) {
    /**
     * Find the indices of characters in a source text.
     *
     * @param source - The source text which should be searched.
     *
     * @param query - The characters to locate in the source text.
     *
     * @param start - The index to start the search.
     *
     * @returns The matched indices, or `null` if there is no match.
     *
     * #### Complexity
     * Linear on `sourceText`.
     *
     * #### Notes
     * In order for there to be a match, all of the characters in `query`
     * **must** appear in `source` in the order given by `query`.
     *
     * Characters are matched using strict `===` equality.
     */
    function findIndices(source, query, start = 0) {
        let indices = new Array(query.length);
        for (let i = 0, j = start, n = query.length; i < n; ++i, ++j) {
            j = source.indexOf(query[i], j);
            if (j === -1) {
                return null;
            }
            indices[i] = j;
        }
        return indices;
    }
    StringExt.findIndices = findIndices;
    /**
     * A string matcher which uses a sum-of-squares algorithm.
     *
     * @param source - The source text which should be searched.
     *
     * @param query - The characters to locate in the source text.
     *
     * @param start - The index to start the search.
     *
     * @returns The match result, or `null` if there is no match.
     *   A lower `score` represents a stronger match.
     *
     * #### Complexity
     * Linear on `sourceText`.
     *
     * #### Notes
     * This scoring algorithm uses a sum-of-squares approach to determine
     * the score. In order for there to be a match, all of the characters
     * in `query` **must** appear in `source` in order. The index of each
     * matching character is squared and added to the score. This means
     * that early and consecutive character matches are preferred, while
     * late matches are heavily penalized.
     */
    function matchSumOfSquares(source, query, start = 0) {
        let indices = findIndices(source, query, start);
        if (!indices) {
            return null;
        }
        let score = 0;
        for (let i = 0, n = indices.length; i < n; ++i) {
            let j = indices[i] - start;
            score += j * j;
        }
        return { score, indices };
    }
    StringExt.matchSumOfSquares = matchSumOfSquares;
    /**
     * A string matcher which uses a sum-of-deltas algorithm.
     *
     * @param source - The source text which should be searched.
     *
     * @param query - The characters to locate in the source text.
     *
     * @param start - The index to start the search.
     *
     * @returns The match result, or `null` if there is no match.
     *   A lower `score` represents a stronger match.
     *
     * #### Complexity
     * Linear on `sourceText`.
     *
     * #### Notes
     * This scoring algorithm uses a sum-of-deltas approach to determine
     * the score. In order for there to be a match, all of the characters
     * in `query` **must** appear in `source` in order. The delta between
     * the indices are summed to create the score. This means that groups
     * of matched characters are preferred, while fragmented matches are
     * penalized.
     */
    function matchSumOfDeltas(source, query, start = 0) {
        let indices = findIndices(source, query, start);
        if (!indices) {
            return null;
        }
        let score = 0;
        let last = start - 1;
        for (let i = 0, n = indices.length; i < n; ++i) {
            let j = indices[i];
            score += j - last - 1;
            last = j;
        }
        return { score, indices };
    }
    StringExt.matchSumOfDeltas = matchSumOfDeltas;
    /**
     * Highlight the matched characters of a source text.
     *
     * @param source - The text which should be highlighted.
     *
     * @param indices - The indices of the matched characters. They must
     *   appear in increasing order and must be in bounds of the source.
     *
     * @param fn - The function to apply to the matched chunks.
     *
     * @returns An array of unmatched and highlighted chunks.
     */
    function highlight(source, indices, fn) {
        // Set up the result array.
        let result = [];
        // Set up the counter variables.
        let k = 0;
        let last = 0;
        let n = indices.length;
        // Iterator over each index.
        while (k < n) {
            // Set up the chunk indices.
            let i = indices[k];
            let j = indices[k];
            // Advance the right chunk index until it's non-contiguous.
            while (++k < n && indices[k] === j + 1) {
                j++;
            }
            // Extract the unmatched text.
            if (last < i) {
                result.push(source.slice(last, i));
            }
            // Extract and highlight the matched text.
            if (i < j + 1) {
                result.push(fn(source.slice(i, j + 1)));
            }
            // Update the last visited index.
            last = j + 1;
        }
        // Extract any remaining unmatched text.
        if (last < source.length) {
            result.push(source.slice(last));
        }
        // Return the highlighted result.
        return result;
    }
    StringExt.highlight = highlight;
    /**
     * A 3-way string comparison function.
     *
     * @param a - The first string of interest.
     *
     * @param b - The second string of interest.
     *
     * @returns `-1` if `a < b`, else `1` if `a > b`, else `0`.
     */
    function cmp(a, b) {
        return a < b ? -1 : a > b ? 1 : 0;
    }
    StringExt.cmp = cmp;
})(StringExt || (StringExt = {}));

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Take a fixed number of items from an iterable.
 *
 * @param object - The iterable object of interest.
 *
 * @param count - The number of items to take from the iterable.
 *
 * @returns An iterator which yields the specified number of items
 *   from the source iterable.
 *
 * #### Notes
 * The returned iterator will exhaust early if the source iterable
 * contains an insufficient number of items.
 *
 * #### Example
 * ```typescript
 * import { take } from '@lumino/algorithm';
 *
 * let stream = take([5, 4, 3, 2, 1, 0, -1], 3);
 *
 * Array.from(stream);  // [5, 4, 3]
 * ```
 */
function* take(object, count) {
    if (count < 1) {
        return;
    }
    const it = object[Symbol.iterator]();
    let item;
    while (0 < count-- && !(item = it.next()).done) {
        yield item.value;
    }
}

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/**
 * Iterate several iterables in lockstep.
 *
 * @param objects - The iterable objects of interest.
 *
 * @returns An iterator which yields successive tuples of values where
 *   each value is taken in turn from the provided iterables. It will
 *   be as long as the shortest provided iterable.
 *
 * #### Example
 * ```typescript
 * import { zip } from '@lumino/algorithm';
 *
 * let data1 = [1, 2, 3];
 * let data2 = [4, 5, 6];
 *
 * let stream = zip(data1, data2);
 *
 * Array.from(stream);  // [[1, 4], [2, 5], [3, 6]]
 * ```
 */
function* zip(...objects) {
    const iters = objects.map(obj => obj[Symbol.iterator]());
    let tuple = iters.map(it => it.next());
    for (; every(tuple, item => !item.done); tuple = iters.map(it => it.next())) {
        yield tuple.map(item => item.value);
    }
}


//# sourceMappingURL=index.es6.js.map


/***/ }),

/***/ 8235:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.KernelAPIClient = exports.KERNEL_SERVICE_URL = void 0;
exports.listRunning = listRunning;
exports.startNew = startNew;
exports.restartKernel = restartKernel;
exports.interruptKernel = interruptKernel;
exports.shutdownKernel = shutdownKernel;
exports.getKernelModel = getKernelModel;
const serverconnection_1 = __webpack_require__(2920);
const coreutils_1 = __webpack_require__(8925);
const validate_1 = __webpack_require__(5855);
/**
 * The url for the kernel service.
 */
exports.KERNEL_SERVICE_URL = 'api/kernels';
/**
 * Fetch the running kernels.
 *
 * @param settings - The optional server settings.
 *
 * @returns A promise that resolves with the list of running kernels.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response and rejected otherwise.
 */
async function listRunning(settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL);
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.validateModels)(data);
    return data;
}
/**
 * Start a new kernel.
 *
 * @param options - The options used to create the kernel.
 *
 * @returns A promise that resolves with a kernel connection object.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response and rejected otherwise.
 */
async function startNew(options = {}, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL);
    const init = {
        method: 'POST',
        body: JSON.stringify(options)
    };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 201) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.validateModel)(data);
    return data;
}
/**
 * Restart a kernel.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response (and thus after a restart) and rejected otherwise.
 */
async function restartKernel(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL, encodeURIComponent(id), 'restart');
    const init = { method: 'POST' };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.validateModel)(data);
}
/**
 * Interrupt a kernel.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response and rejected otherwise.
 */
async function interruptKernel(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL, encodeURIComponent(id), 'interrupt');
    const init = { method: 'POST' };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status !== 204) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
}
/**
 * Shut down a kernel.
 *
 * @param id - The id of the running kernel.
 *
 * @param settings - The server settings for the request.
 *
 * @returns A promise that resolves when the kernel is shut down.
 *
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response and rejected otherwise.
 */
async function shutdownKernel(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL, encodeURIComponent(id));
    const init = { method: 'DELETE' };
    const response = await serverconnection_1.ServerConnection.makeRequest(url, init, settings);
    if (response.status === 404) {
        const msg = `The kernel "${id}" does not exist on the server`;
        console.warn(msg);
    }
    else if (response.status !== 204) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
}
/**
 * Get a full kernel model from the server by kernel id string.
 *
 * #### Notes
 * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
 *
 * The promise is fulfilled on a valid response and rejected otherwise.
 */
async function getKernelModel(id, settings = serverconnection_1.ServerConnection.makeSettings()) {
    const url = coreutils_1.URLExt.join(settings.baseUrl, exports.KERNEL_SERVICE_URL, encodeURIComponent(id));
    const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, settings);
    if (response.status === 404) {
        return undefined;
    }
    else if (response.status !== 200) {
        const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
        throw err;
    }
    const data = await response.json();
    (0, validate_1.validateModel)(data);
    return data;
}
/**
 * The kernel API client.
 *
 * #### Notes
 * Use this class to interact with the Jupyter Server Kernel API.
 * This class adheres to the Jupyter Server API endpoints.
 */
class KernelAPIClient {
    /**
     * Create a new kernel API client.
     *
     * @param options - The options used to create the client.
     */
    constructor(options = {}) {
        var _a;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * List the running kernels.
     *
     * @returns A promise that resolves with the list of running kernel models.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async listRunning() {
        return listRunning(this.serverSettings);
    }
    /**
     * Get a kernel model.
     *
     * @param id - The id of the kernel of interest.
     *
     * @returns A promise that resolves with the kernel model.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     * If the kernel does not exist on the server, the promise is resolved with `undefined`.
     */
    async getModel(id) {
        return getKernelModel(id, this.serverSettings);
    }
    /**
     * Start a new kernel.
     *
     * @param options - The options used to create the kernel.
     *
     * @returns A promise that resolves with the kernel model.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async startNew(options = {}) {
        return startNew(options, this.serverSettings);
    }
    /**
     * Restart a kernel.
     *
     * @param id - The id of the kernel to restart.
     *
     * @returns A promise that resolves when the kernel is restarted.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async restart(id) {
        return restartKernel(id, this.serverSettings);
    }
    /**
     * Interrupt a kernel.
     *
     * @param id - The id of the kernel to interrupt.
     *
     * @returns A promise that resolves when the kernel is interrupted.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async interrupt(id) {
        return interruptKernel(id, this.serverSettings);
    }
    /**
     * Shut down a kernel by id.
     *
     * @param id - The id of the kernel to shut down.
     *
     * @returns A promise that resolves when the kernel is shut down.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/kernels) and validates the response model.
     *
     * The promise is fulfilled on a valid response and rejected otherwise.
     */
    async shutdown(id) {
        return shutdownKernel(id, this.serverSettings);
    }
}
exports.KernelAPIClient = KernelAPIClient;
//# sourceMappingURL=restapi.js.map

/***/ }),

/***/ 8317:
/***/ (function(module) {

/*!
 * html2canvas 1.4.1 <https://html2canvas.hertzen.com>
 * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
 * Released under MIT License
 */
(function (global, factory) {
     true ? module.exports = factory() :
    0;
}(this, (function () { 'use strict';

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */

    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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };

    function __extends(d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }

    var __assign = function() {
        __assign = Object.assign || function __assign(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };

    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }

    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f) throw new TypeError("Generator is already executing.");
            while (_) try {
                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                if (y = 0, t) op = [op[0] & 2, t.value];
                switch (op[0]) {
                    case 0: case 1: t = op; break;
                    case 4: _.label++; return { value: op[1], done: false };
                    case 5: _.label++; y = op[1]; op = [0]; continue;
                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
                    default:
                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                        if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                        if (t[2]) _.ops.pop();
                        _.trys.pop(); continue;
                }
                op = body.call(thisArg, _);
            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
        }
    }

    function __spreadArray(to, from, pack) {
        if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
            if (ar || !(i in from)) {
                if (!ar) ar = Array.prototype.slice.call(from, 0, i);
                ar[i] = from[i];
            }
        }
        return to.concat(ar || from);
    }

    var Bounds = /** @class */ (function () {
        function Bounds(left, top, width, height) {
            this.left = left;
            this.top = top;
            this.width = width;
            this.height = height;
        }
        Bounds.prototype.add = function (x, y, w, h) {
            return new Bounds(this.left + x, this.top + y, this.width + w, this.height + h);
        };
        Bounds.fromClientRect = function (context, clientRect) {
            return new Bounds(clientRect.left + context.windowBounds.left, clientRect.top + context.windowBounds.top, clientRect.width, clientRect.height);
        };
        Bounds.fromDOMRectList = function (context, domRectList) {
            var domRect = Array.from(domRectList).find(function (rect) { return rect.width !== 0; });
            return domRect
                ? new Bounds(domRect.left + context.windowBounds.left, domRect.top + context.windowBounds.top, domRect.width, domRect.height)
                : Bounds.EMPTY;
        };
        Bounds.EMPTY = new Bounds(0, 0, 0, 0);
        return Bounds;
    }());
    var parseBounds = function (context, node) {
        return Bounds.fromClientRect(context, node.getBoundingClientRect());
    };
    var parseDocumentSize = function (document) {
        var body = document.body;
        var documentElement = document.documentElement;
        if (!body || !documentElement) {
            throw new Error("Unable to get document size");
        }
        var width = Math.max(Math.max(body.scrollWidth, documentElement.scrollWidth), Math.max(body.offsetWidth, documentElement.offsetWidth), Math.max(body.clientWidth, documentElement.clientWidth));
        var height = Math.max(Math.max(body.scrollHeight, documentElement.scrollHeight), Math.max(body.offsetHeight, documentElement.offsetHeight), Math.max(body.clientHeight, documentElement.clientHeight));
        return new Bounds(0, 0, width, height);
    };

    /*
     * css-line-break 2.1.0 <https://github.com/niklasvh/css-line-break#readme>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var toCodePoints$1 = function (str) {
        var codePoints = [];
        var i = 0;
        var length = str.length;
        while (i < length) {
            var value = str.charCodeAt(i++);
            if (value >= 0xd800 && value <= 0xdbff && i < length) {
                var extra = str.charCodeAt(i++);
                if ((extra & 0xfc00) === 0xdc00) {
                    codePoints.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
                }
                else {
                    codePoints.push(value);
                    i--;
                }
            }
            else {
                codePoints.push(value);
            }
        }
        return codePoints;
    };
    var fromCodePoint$1 = function () {
        var codePoints = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            codePoints[_i] = arguments[_i];
        }
        if (String.fromCodePoint) {
            return String.fromCodePoint.apply(String, codePoints);
        }
        var length = codePoints.length;
        if (!length) {
            return '';
        }
        var codeUnits = [];
        var index = -1;
        var result = '';
        while (++index < length) {
            var codePoint = codePoints[index];
            if (codePoint <= 0xffff) {
                codeUnits.push(codePoint);
            }
            else {
                codePoint -= 0x10000;
                codeUnits.push((codePoint >> 10) + 0xd800, (codePoint % 0x400) + 0xdc00);
            }
            if (index + 1 === length || codeUnits.length > 0x4000) {
                result += String.fromCharCode.apply(String, codeUnits);
                codeUnits.length = 0;
            }
        }
        return result;
    };
    var chars$2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // Use a lookup table to find the index.
    var lookup$2 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
    for (var i$2 = 0; i$2 < chars$2.length; i$2++) {
        lookup$2[chars$2.charCodeAt(i$2)] = i$2;
    }

    /*
     * utrie 1.0.2 <https://github.com/niklasvh/utrie>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var chars$1$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // Use a lookup table to find the index.
    var lookup$1$1 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
    for (var i$1$1 = 0; i$1$1 < chars$1$1.length; i$1$1++) {
        lookup$1$1[chars$1$1.charCodeAt(i$1$1)] = i$1$1;
    }
    var decode$1 = function (base64) {
        var bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;
        if (base64[base64.length - 1] === '=') {
            bufferLength--;
            if (base64[base64.length - 2] === '=') {
                bufferLength--;
            }
        }
        var buffer = typeof ArrayBuffer !== 'undefined' &&
            typeof Uint8Array !== 'undefined' &&
            typeof Uint8Array.prototype.slice !== 'undefined'
            ? new ArrayBuffer(bufferLength)
            : new Array(bufferLength);
        var bytes = Array.isArray(buffer) ? buffer : new Uint8Array(buffer);
        for (i = 0; i < len; i += 4) {
            encoded1 = lookup$1$1[base64.charCodeAt(i)];
            encoded2 = lookup$1$1[base64.charCodeAt(i + 1)];
            encoded3 = lookup$1$1[base64.charCodeAt(i + 2)];
            encoded4 = lookup$1$1[base64.charCodeAt(i + 3)];
            bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
            bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
            bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
        }
        return buffer;
    };
    var polyUint16Array$1 = function (buffer) {
        var length = buffer.length;
        var bytes = [];
        for (var i = 0; i < length; i += 2) {
            bytes.push((buffer[i + 1] << 8) | buffer[i]);
        }
        return bytes;
    };
    var polyUint32Array$1 = function (buffer) {
        var length = buffer.length;
        var bytes = [];
        for (var i = 0; i < length; i += 4) {
            bytes.push((buffer[i + 3] << 24) | (buffer[i + 2] << 16) | (buffer[i + 1] << 8) | buffer[i]);
        }
        return bytes;
    };

    /** Shift size for getting the index-2 table offset. */
    var UTRIE2_SHIFT_2$1 = 5;
    /** Shift size for getting the index-1 table offset. */
    var UTRIE2_SHIFT_1$1 = 6 + 5;
    /**
     * Shift size for shifting left the index array values.
     * Increases possible data size with 16-bit index values at the cost
     * of compactability.
     * This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY.
     */
    var UTRIE2_INDEX_SHIFT$1 = 2;
    /**
     * Difference between the two shift sizes,
     * for getting an index-1 offset from an index-2 offset. 6=11-5
     */
    var UTRIE2_SHIFT_1_2$1 = UTRIE2_SHIFT_1$1 - UTRIE2_SHIFT_2$1;
    /**
     * The part of the index-2 table for U+D800..U+DBFF stores values for
     * lead surrogate code _units_ not code _points_.
     * Values for lead surrogate code _points_ are indexed with this portion of the table.
     * Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.)
     */
    var UTRIE2_LSCP_INDEX_2_OFFSET$1 = 0x10000 >> UTRIE2_SHIFT_2$1;
    /** Number of entries in a data block. 32=0x20 */
    var UTRIE2_DATA_BLOCK_LENGTH$1 = 1 << UTRIE2_SHIFT_2$1;
    /** Mask for getting the lower bits for the in-data-block offset. */
    var UTRIE2_DATA_MASK$1 = UTRIE2_DATA_BLOCK_LENGTH$1 - 1;
    var UTRIE2_LSCP_INDEX_2_LENGTH$1 = 0x400 >> UTRIE2_SHIFT_2$1;
    /** Count the lengths of both BMP pieces. 2080=0x820 */
    var UTRIE2_INDEX_2_BMP_LENGTH$1 = UTRIE2_LSCP_INDEX_2_OFFSET$1 + UTRIE2_LSCP_INDEX_2_LENGTH$1;
    /**
     * The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.
     * Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2.
     */
    var UTRIE2_UTF8_2B_INDEX_2_OFFSET$1 = UTRIE2_INDEX_2_BMP_LENGTH$1;
    var UTRIE2_UTF8_2B_INDEX_2_LENGTH$1 = 0x800 >> 6; /* U+0800 is the first code point after 2-byte UTF-8 */
    /**
     * The index-1 table, only used for supplementary code points, at offset 2112=0x840.
     * Variable length, for code points up to highStart, where the last single-value range starts.
     * Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1.
     * (For 0x100000 supplementary code points U+10000..U+10ffff.)
     *
     * The part of the index-2 table for supplementary code points starts
     * after this index-1 table.
     *
     * Both the index-1 table and the following part of the index-2 table
     * are omitted completely if there is only BMP data.
     */
    var UTRIE2_INDEX_1_OFFSET$1 = UTRIE2_UTF8_2B_INDEX_2_OFFSET$1 + UTRIE2_UTF8_2B_INDEX_2_LENGTH$1;
    /**
     * Number of index-1 entries for the BMP. 32=0x20
     * This part of the index-1 table is omitted from the serialized form.
     */
    var UTRIE2_OMITTED_BMP_INDEX_1_LENGTH$1 = 0x10000 >> UTRIE2_SHIFT_1$1;
    /** Number of entries in an index-2 block. 64=0x40 */
    var UTRIE2_INDEX_2_BLOCK_LENGTH$1 = 1 << UTRIE2_SHIFT_1_2$1;
    /** Mask for getting the lower bits for the in-index-2-block offset. */
    var UTRIE2_INDEX_2_MASK$1 = UTRIE2_INDEX_2_BLOCK_LENGTH$1 - 1;
    var slice16$1 = function (view, start, end) {
        if (view.slice) {
            return view.slice(start, end);
        }
        return new Uint16Array(Array.prototype.slice.call(view, start, end));
    };
    var slice32$1 = function (view, start, end) {
        if (view.slice) {
            return view.slice(start, end);
        }
        return new Uint32Array(Array.prototype.slice.call(view, start, end));
    };
    var createTrieFromBase64$1 = function (base64, _byteLength) {
        var buffer = decode$1(base64);
        var view32 = Array.isArray(buffer) ? polyUint32Array$1(buffer) : new Uint32Array(buffer);
        var view16 = Array.isArray(buffer) ? polyUint16Array$1(buffer) : new Uint16Array(buffer);
        var headerLength = 24;
        var index = slice16$1(view16, headerLength / 2, view32[4] / 2);
        var data = view32[5] === 2
            ? slice16$1(view16, (headerLength + view32[4]) / 2)
            : slice32$1(view32, Math.ceil((headerLength + view32[4]) / 4));
        return new Trie$1(view32[0], view32[1], view32[2], view32[3], index, data);
    };
    var Trie$1 = /** @class */ (function () {
        function Trie(initialValue, errorValue, highStart, highValueIndex, index, data) {
            this.initialValue = initialValue;
            this.errorValue = errorValue;
            this.highStart = highStart;
            this.highValueIndex = highValueIndex;
            this.index = index;
            this.data = data;
        }
        /**
         * Get the value for a code point as stored in the Trie.
         *
         * @param codePoint the code point
         * @return the value
         */
        Trie.prototype.get = function (codePoint) {
            var ix;
            if (codePoint >= 0) {
                if (codePoint < 0x0d800 || (codePoint > 0x0dbff && codePoint <= 0x0ffff)) {
                    // Ordinary BMP code point, excluding leading surrogates.
                    // BMP uses a single level lookup.  BMP index starts at offset 0 in the Trie2 index.
                    // 16 bit data is stored in the index array itself.
                    ix = this.index[codePoint >> UTRIE2_SHIFT_2$1];
                    ix = (ix << UTRIE2_INDEX_SHIFT$1) + (codePoint & UTRIE2_DATA_MASK$1);
                    return this.data[ix];
                }
                if (codePoint <= 0xffff) {
                    // Lead Surrogate Code Point.  A Separate index section is stored for
                    // lead surrogate code units and code points.
                    //   The main index has the code unit data.
                    //   For this function, we need the code point data.
                    // Note: this expression could be refactored for slightly improved efficiency, but
                    //       surrogate code points will be so rare in practice that it's not worth it.
                    ix = this.index[UTRIE2_LSCP_INDEX_2_OFFSET$1 + ((codePoint - 0xd800) >> UTRIE2_SHIFT_2$1)];
                    ix = (ix << UTRIE2_INDEX_SHIFT$1) + (codePoint & UTRIE2_DATA_MASK$1);
                    return this.data[ix];
                }
                if (codePoint < this.highStart) {
                    // Supplemental code point, use two-level lookup.
                    ix = UTRIE2_INDEX_1_OFFSET$1 - UTRIE2_OMITTED_BMP_INDEX_1_LENGTH$1 + (codePoint >> UTRIE2_SHIFT_1$1);
                    ix = this.index[ix];
                    ix += (codePoint >> UTRIE2_SHIFT_2$1) & UTRIE2_INDEX_2_MASK$1;
                    ix = this.index[ix];
                    ix = (ix << UTRIE2_INDEX_SHIFT$1) + (codePoint & UTRIE2_DATA_MASK$1);
                    return this.data[ix];
                }
                if (codePoint <= 0x10ffff) {
                    return this.data[this.highValueIndex];
                }
            }
            // Fall through.  The code point is outside of the legal range of 0..0x10ffff.
            return this.errorValue;
        };
        return Trie;
    }());

    /*
     * base64-arraybuffer 1.0.2 <https://github.com/niklasvh/base64-arraybuffer>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var chars$3 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // Use a lookup table to find the index.
    var lookup$3 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
    for (var i$3 = 0; i$3 < chars$3.length; i$3++) {
        lookup$3[chars$3.charCodeAt(i$3)] = i$3;
    }

    var base64$1 = ' ';

    var LETTER_NUMBER_MODIFIER = 50;
    // Non-tailorable Line Breaking Classes
    var BK = 1; //  Cause a line break (after)
    var CR$1 = 2; //  Cause a line break (after), except between CR and LF
    var LF$1 = 3; //  Cause a line break (after)
    var CM = 4; //  Prohibit a line break between the character and the preceding character
    var NL = 5; //  Cause a line break (after)
    var WJ = 7; //  Prohibit line breaks before and after
    var ZW = 8; //  Provide a break opportunity
    var GL = 9; //  Prohibit line breaks before and after
    var SP = 10; // Enable indirect line breaks
    var ZWJ$1 = 11; // Prohibit line breaks within joiner sequences
    // Break Opportunities
    var B2 = 12; //  Provide a line break opportunity before and after the character
    var BA = 13; //  Generally provide a line break opportunity after the character
    var BB = 14; //  Generally provide a line break opportunity before the character
    var HY = 15; //  Provide a line break opportunity after the character, except in numeric context
    var CB = 16; //   Provide a line break opportunity contingent on additional information
    // Characters Prohibiting Certain Breaks
    var CL = 17; //  Prohibit line breaks before
    var CP = 18; //  Prohibit line breaks before
    var EX = 19; //  Prohibit line breaks before
    var IN = 20; //  Allow only indirect line breaks between pairs
    var NS = 21; //  Allow only indirect line breaks before
    var OP = 22; //  Prohibit line breaks after
    var QU = 23; //  Act like they are both opening and closing
    // Numeric Context
    var IS = 24; //  Prevent breaks after any and before numeric
    var NU = 25; //  Form numeric expressions for line breaking purposes
    var PO = 26; //  Do not break following a numeric expression
    var PR = 27; //  Do not break in front of a numeric expression
    var SY = 28; //  Prevent a break before; and allow a break after
    // Other Characters
    var AI = 29; //  Act like AL when the resolvedEAW is N; otherwise; act as ID
    var AL = 30; //  Are alphabetic characters or symbols that are used with alphabetic characters
    var CJ = 31; //  Treat as NS or ID for strict or normal breaking.
    var EB = 32; //  Do not break from following Emoji Modifier
    var EM = 33; //  Do not break from preceding Emoji Base
    var H2 = 34; //  Form Korean syllable blocks
    var H3 = 35; //  Form Korean syllable blocks
    var HL = 36; //  Do not break around a following hyphen; otherwise act as Alphabetic
    var ID = 37; //  Break before or after; except in some numeric context
    var JL = 38; //  Form Korean syllable blocks
    var JV = 39; //  Form Korean syllable blocks
    var JT = 40; //  Form Korean syllable blocks
    var RI$1 = 41; //  Keep pairs together. For pairs; break before and after other classes
    var SA = 42; //  Provide a line break opportunity contingent on additional, language-specific context analysis
    var XX = 43; //  Have as yet unknown line breaking behavior or unassigned code positions
    var ea_OP = [0x2329, 0xff08];
    var BREAK_MANDATORY = '!';
    var BREAK_NOT_ALLOWED$1 = '×';
    var BREAK_ALLOWED$1 = '÷';
    var UnicodeTrie$1 = createTrieFromBase64$1(base64$1);
    var ALPHABETICS = [AL, HL];
    var HARD_LINE_BREAKS = [BK, CR$1, LF$1, NL];
    var SPACE$1 = [SP, ZW];
    var PREFIX_POSTFIX = [PR, PO];
    var LINE_BREAKS = HARD_LINE_BREAKS.concat(SPACE$1);
    var KOREAN_SYLLABLE_BLOCK = [JL, JV, JT, H2, H3];
    var HYPHEN = [HY, BA];
    var codePointsToCharacterClasses = function (codePoints, lineBreak) {
        if (lineBreak === void 0) { lineBreak = 'strict'; }
        var types = [];
        var indices = [];
        var categories = [];
        codePoints.forEach(function (codePoint, index) {
            var classType = UnicodeTrie$1.get(codePoint);
            if (classType > LETTER_NUMBER_MODIFIER) {
                categories.push(true);
                classType -= LETTER_NUMBER_MODIFIER;
            }
            else {
                categories.push(false);
            }
            if (['normal', 'auto', 'loose'].indexOf(lineBreak) !== -1) {
                // U+2010, – U+2013, 〜 U+301C, ゠ U+30A0
                if ([0x2010, 0x2013, 0x301c, 0x30a0].indexOf(codePoint) !== -1) {
                    indices.push(index);
                    return types.push(CB);
                }
            }
            if (classType === CM || classType === ZWJ$1) {
                // LB10 Treat any remaining combining mark or ZWJ as AL.
                if (index === 0) {
                    indices.push(index);
                    return types.push(AL);
                }
                // LB9 Do not break a combining character sequence; treat it as if it has the line breaking class of
                // the base character in all of the following rules. Treat ZWJ as if it were CM.
                var prev = types[index - 1];
                if (LINE_BREAKS.indexOf(prev) === -1) {
                    indices.push(indices[index - 1]);
                    return types.push(prev);
                }
                indices.push(index);
                return types.push(AL);
            }
            indices.push(index);
            if (classType === CJ) {
                return types.push(lineBreak === 'strict' ? NS : ID);
            }
            if (classType === SA) {
                return types.push(AL);
            }
            if (classType === AI) {
                return types.push(AL);
            }
            // For supplementary characters, a useful default is to treat characters in the range 10000..1FFFD as AL
            // and characters in the ranges 20000..2FFFD and 30000..3FFFD as ID, until the implementation can be revised
            // to take into account the actual line breaking properties for these characters.
            if (classType === XX) {
                if ((codePoint >= 0x20000 && codePoint <= 0x2fffd) || (codePoint >= 0x30000 && codePoint <= 0x3fffd)) {
                    return types.push(ID);
                }
                else {
                    return types.push(AL);
                }
            }
            types.push(classType);
        });
        return [indices, types, categories];
    };
    var isAdjacentWithSpaceIgnored = function (a, b, currentIndex, classTypes) {
        var current = classTypes[currentIndex];
        if (Array.isArray(a) ? a.indexOf(current) !== -1 : a === current) {
            var i = currentIndex;
            while (i <= classTypes.length) {
                i++;
                var next = classTypes[i];
                if (next === b) {
                    return true;
                }
                if (next !== SP) {
                    break;
                }
            }
        }
        if (current === SP) {
            var i = currentIndex;
            while (i > 0) {
                i--;
                var prev = classTypes[i];
                if (Array.isArray(a) ? a.indexOf(prev) !== -1 : a === prev) {
                    var n = currentIndex;
                    while (n <= classTypes.length) {
                        n++;
                        var next = classTypes[n];
                        if (next === b) {
                            return true;
                        }
                        if (next !== SP) {
                            break;
                        }
                    }
                }
                if (prev !== SP) {
                    break;
                }
            }
        }
        return false;
    };
    var previousNonSpaceClassType = function (currentIndex, classTypes) {
        var i = currentIndex;
        while (i >= 0) {
            var type = classTypes[i];
            if (type === SP) {
                i--;
            }
            else {
                return type;
            }
        }
        return 0;
    };
    var _lineBreakAtIndex = function (codePoints, classTypes, indicies, index, forbiddenBreaks) {
        if (indicies[index] === 0) {
            return BREAK_NOT_ALLOWED$1;
        }
        var currentIndex = index - 1;
        if (Array.isArray(forbiddenBreaks) && forbiddenBreaks[currentIndex] === true) {
            return BREAK_NOT_ALLOWED$1;
        }
        var beforeIndex = currentIndex - 1;
        var afterIndex = currentIndex + 1;
        var current = classTypes[currentIndex];
        // LB4 Always break after hard line breaks.
        // LB5 Treat CR followed by LF, as well as CR, LF, and NL as hard line breaks.
        var before = beforeIndex >= 0 ? classTypes[beforeIndex] : 0;
        var next = classTypes[afterIndex];
        if (current === CR$1 && next === LF$1) {
            return BREAK_NOT_ALLOWED$1;
        }
        if (HARD_LINE_BREAKS.indexOf(current) !== -1) {
            return BREAK_MANDATORY;
        }
        // LB6 Do not break before hard line breaks.
        if (HARD_LINE_BREAKS.indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB7 Do not break before spaces or zero width space.
        if (SPACE$1.indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB8 Break before any character following a zero-width space, even if one or more spaces intervene.
        if (previousNonSpaceClassType(currentIndex, classTypes) === ZW) {
            return BREAK_ALLOWED$1;
        }
        // LB8a Do not break after a zero width joiner.
        if (UnicodeTrie$1.get(codePoints[currentIndex]) === ZWJ$1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // zwj emojis
        if ((current === EB || current === EM) && UnicodeTrie$1.get(codePoints[afterIndex]) === ZWJ$1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB11 Do not break before or after Word joiner and related characters.
        if (current === WJ || next === WJ) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB12 Do not break after NBSP and related characters.
        if (current === GL) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB12a Do not break before NBSP and related characters, except after spaces and hyphens.
        if ([SP, BA, HY].indexOf(current) === -1 && next === GL) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB13 Do not break before ‘]’ or ‘!’ or ‘;’ or ‘/’, even after spaces.
        if ([CL, CP, EX, IS, SY].indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB14 Do not break after ‘[’, even after spaces.
        if (previousNonSpaceClassType(currentIndex, classTypes) === OP) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB15 Do not break within ‘”[’, even with intervening spaces.
        if (isAdjacentWithSpaceIgnored(QU, OP, currentIndex, classTypes)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB16 Do not break between closing punctuation and a nonstarter (lb=NS), even with intervening spaces.
        if (isAdjacentWithSpaceIgnored([CL, CP], NS, currentIndex, classTypes)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB17 Do not break within ‘——’, even with intervening spaces.
        if (isAdjacentWithSpaceIgnored(B2, B2, currentIndex, classTypes)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB18 Break after spaces.
        if (current === SP) {
            return BREAK_ALLOWED$1;
        }
        // LB19 Do not break before or after quotation marks, such as ‘ ” ’.
        if (current === QU || next === QU) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB20 Break before and after unresolved CB.
        if (next === CB || current === CB) {
            return BREAK_ALLOWED$1;
        }
        // LB21 Do not break before hyphen-minus, other hyphens, fixed-width spaces, small kana, and other non-starters, or after acute accents.
        if ([BA, HY, NS].indexOf(next) !== -1 || current === BB) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB21a Don't break after Hebrew + Hyphen.
        if (before === HL && HYPHEN.indexOf(current) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB21b Don’t break between Solidus and Hebrew letters.
        if (current === SY && next === HL) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB22 Do not break before ellipsis.
        if (next === IN) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB23 Do not break between digits and letters.
        if ((ALPHABETICS.indexOf(next) !== -1 && current === NU) || (ALPHABETICS.indexOf(current) !== -1 && next === NU)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB23a Do not break between numeric prefixes and ideographs, or between ideographs and numeric postfixes.
        if ((current === PR && [ID, EB, EM].indexOf(next) !== -1) ||
            ([ID, EB, EM].indexOf(current) !== -1 && next === PO)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB24 Do not break between numeric prefix/postfix and letters, or between letters and prefix/postfix.
        if ((ALPHABETICS.indexOf(current) !== -1 && PREFIX_POSTFIX.indexOf(next) !== -1) ||
            (PREFIX_POSTFIX.indexOf(current) !== -1 && ALPHABETICS.indexOf(next) !== -1)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB25 Do not break between the following pairs of classes relevant to numbers:
        if (
        // (PR | PO) × ( OP | HY )? NU
        ([PR, PO].indexOf(current) !== -1 &&
            (next === NU || ([OP, HY].indexOf(next) !== -1 && classTypes[afterIndex + 1] === NU))) ||
            // ( OP | HY ) × NU
            ([OP, HY].indexOf(current) !== -1 && next === NU) ||
            // NU ×	(NU | SY | IS)
            (current === NU && [NU, SY, IS].indexOf(next) !== -1)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // NU (NU | SY | IS)* × (NU | SY | IS | CL | CP)
        if ([NU, SY, IS, CL, CP].indexOf(next) !== -1) {
            var prevIndex = currentIndex;
            while (prevIndex >= 0) {
                var type = classTypes[prevIndex];
                if (type === NU) {
                    return BREAK_NOT_ALLOWED$1;
                }
                else if ([SY, IS].indexOf(type) !== -1) {
                    prevIndex--;
                }
                else {
                    break;
                }
            }
        }
        // NU (NU | SY | IS)* (CL | CP)? × (PO | PR))
        if ([PR, PO].indexOf(next) !== -1) {
            var prevIndex = [CL, CP].indexOf(current) !== -1 ? beforeIndex : currentIndex;
            while (prevIndex >= 0) {
                var type = classTypes[prevIndex];
                if (type === NU) {
                    return BREAK_NOT_ALLOWED$1;
                }
                else if ([SY, IS].indexOf(type) !== -1) {
                    prevIndex--;
                }
                else {
                    break;
                }
            }
        }
        // LB26 Do not break a Korean syllable.
        if ((JL === current && [JL, JV, H2, H3].indexOf(next) !== -1) ||
            ([JV, H2].indexOf(current) !== -1 && [JV, JT].indexOf(next) !== -1) ||
            ([JT, H3].indexOf(current) !== -1 && next === JT)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB27 Treat a Korean Syllable Block the same as ID.
        if ((KOREAN_SYLLABLE_BLOCK.indexOf(current) !== -1 && [IN, PO].indexOf(next) !== -1) ||
            (KOREAN_SYLLABLE_BLOCK.indexOf(next) !== -1 && current === PR)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB28 Do not break between alphabetics (“at”).
        if (ALPHABETICS.indexOf(current) !== -1 && ALPHABETICS.indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB29 Do not break between numeric punctuation and alphabetics (“e.g.”).
        if (current === IS && ALPHABETICS.indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB30 Do not break between letters, numbers, or ordinary symbols and opening or closing parentheses.
        if ((ALPHABETICS.concat(NU).indexOf(current) !== -1 &&
            next === OP &&
            ea_OP.indexOf(codePoints[afterIndex]) === -1) ||
            (ALPHABETICS.concat(NU).indexOf(next) !== -1 && current === CP)) {
            return BREAK_NOT_ALLOWED$1;
        }
        // LB30a Break between two regional indicator symbols if and only if there are an even number of regional
        // indicators preceding the position of the break.
        if (current === RI$1 && next === RI$1) {
            var i = indicies[currentIndex];
            var count = 1;
            while (i > 0) {
                i--;
                if (classTypes[i] === RI$1) {
                    count++;
                }
                else {
                    break;
                }
            }
            if (count % 2 !== 0) {
                return BREAK_NOT_ALLOWED$1;
            }
        }
        // LB30b Do not break between an emoji base and an emoji modifier.
        if (current === EB && next === EM) {
            return BREAK_NOT_ALLOWED$1;
        }
        return BREAK_ALLOWED$1;
    };
    var cssFormattedClasses = function (codePoints, options) {
        if (!options) {
            options = { lineBreak: 'normal', wordBreak: 'normal' };
        }
        var _a = codePointsToCharacterClasses(codePoints, options.lineBreak), indicies = _a[0], classTypes = _a[1], isLetterNumber = _a[2];
        if (options.wordBreak === 'break-all' || options.wordBreak === 'break-word') {
            classTypes = classTypes.map(function (type) { return ([NU, AL, SA].indexOf(type) !== -1 ? ID : type); });
        }
        var forbiddenBreakpoints = options.wordBreak === 'keep-all'
            ? isLetterNumber.map(function (letterNumber, i) {
                return letterNumber && codePoints[i] >= 0x4e00 && codePoints[i] <= 0x9fff;
            })
            : undefined;
        return [indicies, classTypes, forbiddenBreakpoints];
    };
    var Break = /** @class */ (function () {
        function Break(codePoints, lineBreak, start, end) {
            this.codePoints = codePoints;
            this.required = lineBreak === BREAK_MANDATORY;
            this.start = start;
            this.end = end;
        }
        Break.prototype.slice = function () {
            return fromCodePoint$1.apply(void 0, this.codePoints.slice(this.start, this.end));
        };
        return Break;
    }());
    var LineBreaker = function (str, options) {
        var codePoints = toCodePoints$1(str);
        var _a = cssFormattedClasses(codePoints, options), indicies = _a[0], classTypes = _a[1], forbiddenBreakpoints = _a[2];
        var length = codePoints.length;
        var lastEnd = 0;
        var nextIndex = 0;
        return {
            next: function () {
                if (nextIndex >= length) {
                    return { done: true, value: null };
                }
                var lineBreak = BREAK_NOT_ALLOWED$1;
                while (nextIndex < length &&
                    (lineBreak = _lineBreakAtIndex(codePoints, classTypes, indicies, ++nextIndex, forbiddenBreakpoints)) ===
                        BREAK_NOT_ALLOWED$1) { }
                if (lineBreak !== BREAK_NOT_ALLOWED$1 || nextIndex === length) {
                    var value = new Break(codePoints, lineBreak, lastEnd, nextIndex);
                    lastEnd = nextIndex;
                    return { value: value, done: false };
                }
                return { done: true, value: null };
            },
        };
    };

    // https://www.w3.org/TR/css-syntax-3
    var FLAG_UNRESTRICTED = 1 << 0;
    var FLAG_ID = 1 << 1;
    var FLAG_INTEGER = 1 << 2;
    var FLAG_NUMBER = 1 << 3;
    var LINE_FEED = 0x000a;
    var SOLIDUS = 0x002f;
    var REVERSE_SOLIDUS = 0x005c;
    var CHARACTER_TABULATION = 0x0009;
    var SPACE = 0x0020;
    var QUOTATION_MARK = 0x0022;
    var EQUALS_SIGN = 0x003d;
    var NUMBER_SIGN = 0x0023;
    var DOLLAR_SIGN = 0x0024;
    var PERCENTAGE_SIGN = 0x0025;
    var APOSTROPHE = 0x0027;
    var LEFT_PARENTHESIS = 0x0028;
    var RIGHT_PARENTHESIS = 0x0029;
    var LOW_LINE = 0x005f;
    var HYPHEN_MINUS = 0x002d;
    var EXCLAMATION_MARK = 0x0021;
    var LESS_THAN_SIGN = 0x003c;
    var GREATER_THAN_SIGN = 0x003e;
    var COMMERCIAL_AT = 0x0040;
    var LEFT_SQUARE_BRACKET = 0x005b;
    var RIGHT_SQUARE_BRACKET = 0x005d;
    var CIRCUMFLEX_ACCENT = 0x003d;
    var LEFT_CURLY_BRACKET = 0x007b;
    var QUESTION_MARK = 0x003f;
    var RIGHT_CURLY_BRACKET = 0x007d;
    var VERTICAL_LINE = 0x007c;
    var TILDE = 0x007e;
    var CONTROL = 0x0080;
    var REPLACEMENT_CHARACTER = 0xfffd;
    var ASTERISK = 0x002a;
    var PLUS_SIGN = 0x002b;
    var COMMA = 0x002c;
    var COLON = 0x003a;
    var SEMICOLON = 0x003b;
    var FULL_STOP = 0x002e;
    var NULL = 0x0000;
    var BACKSPACE = 0x0008;
    var LINE_TABULATION = 0x000b;
    var SHIFT_OUT = 0x000e;
    var INFORMATION_SEPARATOR_ONE = 0x001f;
    var DELETE = 0x007f;
    var EOF = -1;
    var ZERO = 0x0030;
    var a = 0x0061;
    var e = 0x0065;
    var f = 0x0066;
    var u = 0x0075;
    var z = 0x007a;
    var A = 0x0041;
    var E = 0x0045;
    var F = 0x0046;
    var U = 0x0055;
    var Z = 0x005a;
    var isDigit = function (codePoint) { return codePoint >= ZERO && codePoint <= 0x0039; };
    var isSurrogateCodePoint = function (codePoint) { return codePoint >= 0xd800 && codePoint <= 0xdfff; };
    var isHex = function (codePoint) {
        return isDigit(codePoint) || (codePoint >= A && codePoint <= F) || (codePoint >= a && codePoint <= f);
    };
    var isLowerCaseLetter = function (codePoint) { return codePoint >= a && codePoint <= z; };
    var isUpperCaseLetter = function (codePoint) { return codePoint >= A && codePoint <= Z; };
    var isLetter = function (codePoint) { return isLowerCaseLetter(codePoint) || isUpperCaseLetter(codePoint); };
    var isNonASCIICodePoint = function (codePoint) { return codePoint >= CONTROL; };
    var isWhiteSpace = function (codePoint) {
        return codePoint === LINE_FEED || codePoint === CHARACTER_TABULATION || codePoint === SPACE;
    };
    var isNameStartCodePoint = function (codePoint) {
        return isLetter(codePoint) || isNonASCIICodePoint(codePoint) || codePoint === LOW_LINE;
    };
    var isNameCodePoint = function (codePoint) {
        return isNameStartCodePoint(codePoint) || isDigit(codePoint) || codePoint === HYPHEN_MINUS;
    };
    var isNonPrintableCodePoint = function (codePoint) {
        return ((codePoint >= NULL && codePoint <= BACKSPACE) ||
            codePoint === LINE_TABULATION ||
            (codePoint >= SHIFT_OUT && codePoint <= INFORMATION_SEPARATOR_ONE) ||
            codePoint === DELETE);
    };
    var isValidEscape = function (c1, c2) {
        if (c1 !== REVERSE_SOLIDUS) {
            return false;
        }
        return c2 !== LINE_FEED;
    };
    var isIdentifierStart = function (c1, c2, c3) {
        if (c1 === HYPHEN_MINUS) {
            return isNameStartCodePoint(c2) || isValidEscape(c2, c3);
        }
        else if (isNameStartCodePoint(c1)) {
            return true;
        }
        else if (c1 === REVERSE_SOLIDUS && isValidEscape(c1, c2)) {
            return true;
        }
        return false;
    };
    var isNumberStart = function (c1, c2, c3) {
        if (c1 === PLUS_SIGN || c1 === HYPHEN_MINUS) {
            if (isDigit(c2)) {
                return true;
            }
            return c2 === FULL_STOP && isDigit(c3);
        }
        if (c1 === FULL_STOP) {
            return isDigit(c2);
        }
        return isDigit(c1);
    };
    var stringToNumber = function (codePoints) {
        var c = 0;
        var sign = 1;
        if (codePoints[c] === PLUS_SIGN || codePoints[c] === HYPHEN_MINUS) {
            if (codePoints[c] === HYPHEN_MINUS) {
                sign = -1;
            }
            c++;
        }
        var integers = [];
        while (isDigit(codePoints[c])) {
            integers.push(codePoints[c++]);
        }
        var int = integers.length ? parseInt(fromCodePoint$1.apply(void 0, integers), 10) : 0;
        if (codePoints[c] === FULL_STOP) {
            c++;
        }
        var fraction = [];
        while (isDigit(codePoints[c])) {
            fraction.push(codePoints[c++]);
        }
        var fracd = fraction.length;
        var frac = fracd ? parseInt(fromCodePoint$1.apply(void 0, fraction), 10) : 0;
        if (codePoints[c] === E || codePoints[c] === e) {
            c++;
        }
        var expsign = 1;
        if (codePoints[c] === PLUS_SIGN || codePoints[c] === HYPHEN_MINUS) {
            if (codePoints[c] === HYPHEN_MINUS) {
                expsign = -1;
            }
            c++;
        }
        var exponent = [];
        while (isDigit(codePoints[c])) {
            exponent.push(codePoints[c++]);
        }
        var exp = exponent.length ? parseInt(fromCodePoint$1.apply(void 0, exponent), 10) : 0;
        return sign * (int + frac * Math.pow(10, -fracd)) * Math.pow(10, expsign * exp);
    };
    var LEFT_PARENTHESIS_TOKEN = {
        type: 2 /* LEFT_PARENTHESIS_TOKEN */
    };
    var RIGHT_PARENTHESIS_TOKEN = {
        type: 3 /* RIGHT_PARENTHESIS_TOKEN */
    };
    var COMMA_TOKEN = { type: 4 /* COMMA_TOKEN */ };
    var SUFFIX_MATCH_TOKEN = { type: 13 /* SUFFIX_MATCH_TOKEN */ };
    var PREFIX_MATCH_TOKEN = { type: 8 /* PREFIX_MATCH_TOKEN */ };
    var COLUMN_TOKEN = { type: 21 /* COLUMN_TOKEN */ };
    var DASH_MATCH_TOKEN = { type: 9 /* DASH_MATCH_TOKEN */ };
    var INCLUDE_MATCH_TOKEN = { type: 10 /* INCLUDE_MATCH_TOKEN */ };
    var LEFT_CURLY_BRACKET_TOKEN = {
        type: 11 /* LEFT_CURLY_BRACKET_TOKEN */
    };
    var RIGHT_CURLY_BRACKET_TOKEN = {
        type: 12 /* RIGHT_CURLY_BRACKET_TOKEN */
    };
    var SUBSTRING_MATCH_TOKEN = { type: 14 /* SUBSTRING_MATCH_TOKEN */ };
    var BAD_URL_TOKEN = { type: 23 /* BAD_URL_TOKEN */ };
    var BAD_STRING_TOKEN = { type: 1 /* BAD_STRING_TOKEN */ };
    var CDO_TOKEN = { type: 25 /* CDO_TOKEN */ };
    var CDC_TOKEN = { type: 24 /* CDC_TOKEN */ };
    var COLON_TOKEN = { type: 26 /* COLON_TOKEN */ };
    var SEMICOLON_TOKEN = { type: 27 /* SEMICOLON_TOKEN */ };
    var LEFT_SQUARE_BRACKET_TOKEN = {
        type: 28 /* LEFT_SQUARE_BRACKET_TOKEN */
    };
    var RIGHT_SQUARE_BRACKET_TOKEN = {
        type: 29 /* RIGHT_SQUARE_BRACKET_TOKEN */
    };
    var WHITESPACE_TOKEN = { type: 31 /* WHITESPACE_TOKEN */ };
    var EOF_TOKEN = { type: 32 /* EOF_TOKEN */ };
    var Tokenizer = /** @class */ (function () {
        function Tokenizer() {
            this._value = [];
        }
        Tokenizer.prototype.write = function (chunk) {
            this._value = this._value.concat(toCodePoints$1(chunk));
        };
        Tokenizer.prototype.read = function () {
            var tokens = [];
            var token = this.consumeToken();
            while (token !== EOF_TOKEN) {
                tokens.push(token);
                token = this.consumeToken();
            }
            return tokens;
        };
        Tokenizer.prototype.consumeToken = function () {
            var codePoint = this.consumeCodePoint();
            switch (codePoint) {
                case QUOTATION_MARK:
                    return this.consumeStringToken(QUOTATION_MARK);
                case NUMBER_SIGN:
                    var c1 = this.peekCodePoint(0);
                    var c2 = this.peekCodePoint(1);
                    var c3 = this.peekCodePoint(2);
                    if (isNameCodePoint(c1) || isValidEscape(c2, c3)) {
                        var flags = isIdentifierStart(c1, c2, c3) ? FLAG_ID : FLAG_UNRESTRICTED;
                        var value = this.consumeName();
                        return { type: 5 /* HASH_TOKEN */, value: value, flags: flags };
                    }
                    break;
                case DOLLAR_SIGN:
                    if (this.peekCodePoint(0) === EQUALS_SIGN) {
                        this.consumeCodePoint();
                        return SUFFIX_MATCH_TOKEN;
                    }
                    break;
                case APOSTROPHE:
                    return this.consumeStringToken(APOSTROPHE);
                case LEFT_PARENTHESIS:
                    return LEFT_PARENTHESIS_TOKEN;
                case RIGHT_PARENTHESIS:
                    return RIGHT_PARENTHESIS_TOKEN;
                case ASTERISK:
                    if (this.peekCodePoint(0) === EQUALS_SIGN) {
                        this.consumeCodePoint();
                        return SUBSTRING_MATCH_TOKEN;
                    }
                    break;
                case PLUS_SIGN:
                    if (isNumberStart(codePoint, this.peekCodePoint(0), this.peekCodePoint(1))) {
                        this.reconsumeCodePoint(codePoint);
                        return this.consumeNumericToken();
                    }
                    break;
                case COMMA:
                    return COMMA_TOKEN;
                case HYPHEN_MINUS:
                    var e1 = codePoint;
                    var e2 = this.peekCodePoint(0);
                    var e3 = this.peekCodePoint(1);
                    if (isNumberStart(e1, e2, e3)) {
                        this.reconsumeCodePoint(codePoint);
                        return this.consumeNumericToken();
                    }
                    if (isIdentifierStart(e1, e2, e3)) {
                        this.reconsumeCodePoint(codePoint);
                        return this.consumeIdentLikeToken();
                    }
                    if (e2 === HYPHEN_MINUS && e3 === GREATER_THAN_SIGN) {
                        this.consumeCodePoint();
                        this.consumeCodePoint();
                        return CDC_TOKEN;
                    }
                    break;
                case FULL_STOP:
                    if (isNumberStart(codePoint, this.peekCodePoint(0), this.peekCodePoint(1))) {
                        this.reconsumeCodePoint(codePoint);
                        return this.consumeNumericToken();
                    }
                    break;
                case SOLIDUS:
                    if (this.peekCodePoint(0) === ASTERISK) {
                        this.consumeCodePoint();
                        while (true) {
                            var c = this.consumeCodePoint();
                            if (c === ASTERISK) {
                                c = this.consumeCodePoint();
                                if (c === SOLIDUS) {
                                    return this.consumeToken();
                                }
                            }
                            if (c === EOF) {
                                return this.consumeToken();
                            }
                        }
                    }
                    break;
                case COLON:
                    return COLON_TOKEN;
                case SEMICOLON:
                    return SEMICOLON_TOKEN;
                case LESS_THAN_SIGN:
                    if (this.peekCodePoint(0) === EXCLAMATION_MARK &&
                        this.peekCodePoint(1) === HYPHEN_MINUS &&
                        this.peekCodePoint(2) === HYPHEN_MINUS) {
                        this.consumeCodePoint();
                        this.consumeCodePoint();
                        return CDO_TOKEN;
                    }
                    break;
                case COMMERCIAL_AT:
                    var a1 = this.peekCodePoint(0);
                    var a2 = this.peekCodePoint(1);
                    var a3 = this.peekCodePoint(2);
                    if (isIdentifierStart(a1, a2, a3)) {
                        var value = this.consumeName();
                        return { type: 7 /* AT_KEYWORD_TOKEN */, value: value };
                    }
                    break;
                case LEFT_SQUARE_BRACKET:
                    return LEFT_SQUARE_BRACKET_TOKEN;
                case REVERSE_SOLIDUS:
                    if (isValidEscape(codePoint, this.peekCodePoint(0))) {
                        this.reconsumeCodePoint(codePoint);
                        return this.consumeIdentLikeToken();
                    }
                    break;
                case RIGHT_SQUARE_BRACKET:
                    return RIGHT_SQUARE_BRACKET_TOKEN;
                case CIRCUMFLEX_ACCENT:
                    if (this.peekCodePoint(0) === EQUALS_SIGN) {
                        this.consumeCodePoint();
                        return PREFIX_MATCH_TOKEN;
                    }
                    break;
                case LEFT_CURLY_BRACKET:
                    return LEFT_CURLY_BRACKET_TOKEN;
                case RIGHT_CURLY_BRACKET:
                    return RIGHT_CURLY_BRACKET_TOKEN;
                case u:
                case U:
                    var u1 = this.peekCodePoint(0);
                    var u2 = this.peekCodePoint(1);
                    if (u1 === PLUS_SIGN && (isHex(u2) || u2 === QUESTION_MARK)) {
                        this.consumeCodePoint();
                        this.consumeUnicodeRangeToken();
                    }
                    this.reconsumeCodePoint(codePoint);
                    return this.consumeIdentLikeToken();
                case VERTICAL_LINE:
                    if (this.peekCodePoint(0) === EQUALS_SIGN) {
                        this.consumeCodePoint();
                        return DASH_MATCH_TOKEN;
                    }
                    if (this.peekCodePoint(0) === VERTICAL_LINE) {
                        this.consumeCodePoint();
                        return COLUMN_TOKEN;
                    }
                    break;
                case TILDE:
                    if (this.peekCodePoint(0) === EQUALS_SIGN) {
                        this.consumeCodePoint();
                        return INCLUDE_MATCH_TOKEN;
                    }
                    break;
                case EOF:
                    return EOF_TOKEN;
            }
            if (isWhiteSpace(codePoint)) {
                this.consumeWhiteSpace();
                return WHITESPACE_TOKEN;
            }
            if (isDigit(codePoint)) {
                this.reconsumeCodePoint(codePoint);
                return this.consumeNumericToken();
            }
            if (isNameStartCodePoint(codePoint)) {
                this.reconsumeCodePoint(codePoint);
                return this.consumeIdentLikeToken();
            }
            return { type: 6 /* DELIM_TOKEN */, value: fromCodePoint$1(codePoint) };
        };
        Tokenizer.prototype.consumeCodePoint = function () {
            var value = this._value.shift();
            return typeof value === 'undefined' ? -1 : value;
        };
        Tokenizer.prototype.reconsumeCodePoint = function (codePoint) {
            this._value.unshift(codePoint);
        };
        Tokenizer.prototype.peekCodePoint = function (delta) {
            if (delta >= this._value.length) {
                return -1;
            }
            return this._value[delta];
        };
        Tokenizer.prototype.consumeUnicodeRangeToken = function () {
            var digits = [];
            var codePoint = this.consumeCodePoint();
            while (isHex(codePoint) && digits.length < 6) {
                digits.push(codePoint);
                codePoint = this.consumeCodePoint();
            }
            var questionMarks = false;
            while (codePoint === QUESTION_MARK && digits.length < 6) {
                digits.push(codePoint);
                codePoint = this.consumeCodePoint();
                questionMarks = true;
            }
            if (questionMarks) {
                var start_1 = parseInt(fromCodePoint$1.apply(void 0, digits.map(function (digit) { return (digit === QUESTION_MARK ? ZERO : digit); })), 16);
                var end = parseInt(fromCodePoint$1.apply(void 0, digits.map(function (digit) { return (digit === QUESTION_MARK ? F : digit); })), 16);
                return { type: 30 /* UNICODE_RANGE_TOKEN */, start: start_1, end: end };
            }
            var start = parseInt(fromCodePoint$1.apply(void 0, digits), 16);
            if (this.peekCodePoint(0) === HYPHEN_MINUS && isHex(this.peekCodePoint(1))) {
                this.consumeCodePoint();
                codePoint = this.consumeCodePoint();
                var endDigits = [];
                while (isHex(codePoint) && endDigits.length < 6) {
                    endDigits.push(codePoint);
                    codePoint = this.consumeCodePoint();
                }
                var end = parseInt(fromCodePoint$1.apply(void 0, endDigits), 16);
                return { type: 30 /* UNICODE_RANGE_TOKEN */, start: start, end: end };
            }
            else {
                return { type: 30 /* UNICODE_RANGE_TOKEN */, start: start, end: start };
            }
        };
        Tokenizer.prototype.consumeIdentLikeToken = function () {
            var value = this.consumeName();
            if (value.toLowerCase() === 'url' && this.peekCodePoint(0) === LEFT_PARENTHESIS) {
                this.consumeCodePoint();
                return this.consumeUrlToken();
            }
            else if (this.peekCodePoint(0) === LEFT_PARENTHESIS) {
                this.consumeCodePoint();
                return { type: 19 /* FUNCTION_TOKEN */, value: value };
            }
            return { type: 20 /* IDENT_TOKEN */, value: value };
        };
        Tokenizer.prototype.consumeUrlToken = function () {
            var value = [];
            this.consumeWhiteSpace();
            if (this.peekCodePoint(0) === EOF) {
                return { type: 22 /* URL_TOKEN */, value: '' };
            }
            var next = this.peekCodePoint(0);
            if (next === APOSTROPHE || next === QUOTATION_MARK) {
                var stringToken = this.consumeStringToken(this.consumeCodePoint());
                if (stringToken.type === 0 /* STRING_TOKEN */) {
                    this.consumeWhiteSpace();
                    if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) {
                        this.consumeCodePoint();
                        return { type: 22 /* URL_TOKEN */, value: stringToken.value };
                    }
                }
                this.consumeBadUrlRemnants();
                return BAD_URL_TOKEN;
            }
            while (true) {
                var codePoint = this.consumeCodePoint();
                if (codePoint === EOF || codePoint === RIGHT_PARENTHESIS) {
                    return { type: 22 /* URL_TOKEN */, value: fromCodePoint$1.apply(void 0, value) };
                }
                else if (isWhiteSpace(codePoint)) {
                    this.consumeWhiteSpace();
                    if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) {
                        this.consumeCodePoint();
                        return { type: 22 /* URL_TOKEN */, value: fromCodePoint$1.apply(void 0, value) };
                    }
                    this.consumeBadUrlRemnants();
                    return BAD_URL_TOKEN;
                }
                else if (codePoint === QUOTATION_MARK ||
                    codePoint === APOSTROPHE ||
                    codePoint === LEFT_PARENTHESIS ||
                    isNonPrintableCodePoint(codePoint)) {
                    this.consumeBadUrlRemnants();
                    return BAD_URL_TOKEN;
                }
                else if (codePoint === REVERSE_SOLIDUS) {
                    if (isValidEscape(codePoint, this.peekCodePoint(0))) {
                        value.push(this.consumeEscapedCodePoint());
                    }
                    else {
                        this.consumeBadUrlRemnants();
                        return BAD_URL_TOKEN;
                    }
                }
                else {
                    value.push(codePoint);
                }
            }
        };
        Tokenizer.prototype.consumeWhiteSpace = function () {
            while (isWhiteSpace(this.peekCodePoint(0))) {
                this.consumeCodePoint();
            }
        };
        Tokenizer.prototype.consumeBadUrlRemnants = function () {
            while (true) {
                var codePoint = this.consumeCodePoint();
                if (codePoint === RIGHT_PARENTHESIS || codePoint === EOF) {
                    return;
                }
                if (isValidEscape(codePoint, this.peekCodePoint(0))) {
                    this.consumeEscapedCodePoint();
                }
            }
        };
        Tokenizer.prototype.consumeStringSlice = function (count) {
            var SLICE_STACK_SIZE = 50000;
            var value = '';
            while (count > 0) {
                var amount = Math.min(SLICE_STACK_SIZE, count);
                value += fromCodePoint$1.apply(void 0, this._value.splice(0, amount));
                count -= amount;
            }
            this._value.shift();
            return value;
        };
        Tokenizer.prototype.consumeStringToken = function (endingCodePoint) {
            var value = '';
            var i = 0;
            do {
                var codePoint = this._value[i];
                if (codePoint === EOF || codePoint === undefined || codePoint === endingCodePoint) {
                    value += this.consumeStringSlice(i);
                    return { type: 0 /* STRING_TOKEN */, value: value };
                }
                if (codePoint === LINE_FEED) {
                    this._value.splice(0, i);
                    return BAD_STRING_TOKEN;
                }
                if (codePoint === REVERSE_SOLIDUS) {
                    var next = this._value[i + 1];
                    if (next !== EOF && next !== undefined) {
                        if (next === LINE_FEED) {
                            value += this.consumeStringSlice(i);
                            i = -1;
                            this._value.shift();
                        }
                        else if (isValidEscape(codePoint, next)) {
                            value += this.consumeStringSlice(i);
                            value += fromCodePoint$1(this.consumeEscapedCodePoint());
                            i = -1;
                        }
                    }
                }
                i++;
            } while (true);
        };
        Tokenizer.prototype.consumeNumber = function () {
            var repr = [];
            var type = FLAG_INTEGER;
            var c1 = this.peekCodePoint(0);
            if (c1 === PLUS_SIGN || c1 === HYPHEN_MINUS) {
                repr.push(this.consumeCodePoint());
            }
            while (isDigit(this.peekCodePoint(0))) {
                repr.push(this.consumeCodePoint());
            }
            c1 = this.peekCodePoint(0);
            var c2 = this.peekCodePoint(1);
            if (c1 === FULL_STOP && isDigit(c2)) {
                repr.push(this.consumeCodePoint(), this.consumeCodePoint());
                type = FLAG_NUMBER;
                while (isDigit(this.peekCodePoint(0))) {
                    repr.push(this.consumeCodePoint());
                }
            }
            c1 = this.peekCodePoint(0);
            c2 = this.peekCodePoint(1);
            var c3 = this.peekCodePoint(2);
            if ((c1 === E || c1 === e) && (((c2 === PLUS_SIGN || c2 === HYPHEN_MINUS) && isDigit(c3)) || isDigit(c2))) {
                repr.push(this.consumeCodePoint(), this.consumeCodePoint());
                type = FLAG_NUMBER;
                while (isDigit(this.peekCodePoint(0))) {
                    repr.push(this.consumeCodePoint());
                }
            }
            return [stringToNumber(repr), type];
        };
        Tokenizer.prototype.consumeNumericToken = function () {
            var _a = this.consumeNumber(), number = _a[0], flags = _a[1];
            var c1 = this.peekCodePoint(0);
            var c2 = this.peekCodePoint(1);
            var c3 = this.peekCodePoint(2);
            if (isIdentifierStart(c1, c2, c3)) {
                var unit = this.consumeName();
                return { type: 15 /* DIMENSION_TOKEN */, number: number, flags: flags, unit: unit };
            }
            if (c1 === PERCENTAGE_SIGN) {
                this.consumeCodePoint();
                return { type: 16 /* PERCENTAGE_TOKEN */, number: number, flags: flags };
            }
            return { type: 17 /* NUMBER_TOKEN */, number: number, flags: flags };
        };
        Tokenizer.prototype.consumeEscapedCodePoint = function () {
            var codePoint = this.consumeCodePoint();
            if (isHex(codePoint)) {
                var hex = fromCodePoint$1(codePoint);
                while (isHex(this.peekCodePoint(0)) && hex.length < 6) {
                    hex += fromCodePoint$1(this.consumeCodePoint());
                }
                if (isWhiteSpace(this.peekCodePoint(0))) {
                    this.consumeCodePoint();
                }
                var hexCodePoint = parseInt(hex, 16);
                if (hexCodePoint === 0 || isSurrogateCodePoint(hexCodePoint) || hexCodePoint > 0x10ffff) {
                    return REPLACEMENT_CHARACTER;
                }
                return hexCodePoint;
            }
            if (codePoint === EOF) {
                return REPLACEMENT_CHARACTER;
            }
            return codePoint;
        };
        Tokenizer.prototype.consumeName = function () {
            var result = '';
            while (true) {
                var codePoint = this.consumeCodePoint();
                if (isNameCodePoint(codePoint)) {
                    result += fromCodePoint$1(codePoint);
                }
                else if (isValidEscape(codePoint, this.peekCodePoint(0))) {
                    result += fromCodePoint$1(this.consumeEscapedCodePoint());
                }
                else {
                    this.reconsumeCodePoint(codePoint);
                    return result;
                }
            }
        };
        return Tokenizer;
    }());

    var Parser = /** @class */ (function () {
        function Parser(tokens) {
            this._tokens = tokens;
        }
        Parser.create = function (value) {
            var tokenizer = new Tokenizer();
            tokenizer.write(value);
            return new Parser(tokenizer.read());
        };
        Parser.parseValue = function (value) {
            return Parser.create(value).parseComponentValue();
        };
        Parser.parseValues = function (value) {
            return Parser.create(value).parseComponentValues();
        };
        Parser.prototype.parseComponentValue = function () {
            var token = this.consumeToken();
            while (token.type === 31 /* WHITESPACE_TOKEN */) {
                token = this.consumeToken();
            }
            if (token.type === 32 /* EOF_TOKEN */) {
                throw new SyntaxError("Error parsing CSS component value, unexpected EOF");
            }
            this.reconsumeToken(token);
            var value = this.consumeComponentValue();
            do {
                token = this.consumeToken();
            } while (token.type === 31 /* WHITESPACE_TOKEN */);
            if (token.type === 32 /* EOF_TOKEN */) {
                return value;
            }
            throw new SyntaxError("Error parsing CSS component value, multiple values found when expecting only one");
        };
        Parser.prototype.parseComponentValues = function () {
            var values = [];
            while (true) {
                var value = this.consumeComponentValue();
                if (value.type === 32 /* EOF_TOKEN */) {
                    return values;
                }
                values.push(value);
                values.push();
            }
        };
        Parser.prototype.consumeComponentValue = function () {
            var token = this.consumeToken();
            switch (token.type) {
                case 11 /* LEFT_CURLY_BRACKET_TOKEN */:
                case 28 /* LEFT_SQUARE_BRACKET_TOKEN */:
                case 2 /* LEFT_PARENTHESIS_TOKEN */:
                    return this.consumeSimpleBlock(token.type);
                case 19 /* FUNCTION_TOKEN */:
                    return this.consumeFunction(token);
            }
            return token;
        };
        Parser.prototype.consumeSimpleBlock = function (type) {
            var block = { type: type, values: [] };
            var token = this.consumeToken();
            while (true) {
                if (token.type === 32 /* EOF_TOKEN */ || isEndingTokenFor(token, type)) {
                    return block;
                }
                this.reconsumeToken(token);
                block.values.push(this.consumeComponentValue());
                token = this.consumeToken();
            }
        };
        Parser.prototype.consumeFunction = function (functionToken) {
            var cssFunction = {
                name: functionToken.value,
                values: [],
                type: 18 /* FUNCTION */
            };
            while (true) {
                var token = this.consumeToken();
                if (token.type === 32 /* EOF_TOKEN */ || token.type === 3 /* RIGHT_PARENTHESIS_TOKEN */) {
                    return cssFunction;
                }
                this.reconsumeToken(token);
                cssFunction.values.push(this.consumeComponentValue());
            }
        };
        Parser.prototype.consumeToken = function () {
            var token = this._tokens.shift();
            return typeof token === 'undefined' ? EOF_TOKEN : token;
        };
        Parser.prototype.reconsumeToken = function (token) {
            this._tokens.unshift(token);
        };
        return Parser;
    }());
    var isDimensionToken = function (token) { return token.type === 15 /* DIMENSION_TOKEN */; };
    var isNumberToken = function (token) { return token.type === 17 /* NUMBER_TOKEN */; };
    var isIdentToken = function (token) { return token.type === 20 /* IDENT_TOKEN */; };
    var isStringToken = function (token) { return token.type === 0 /* STRING_TOKEN */; };
    var isIdentWithValue = function (token, value) {
        return isIdentToken(token) && token.value === value;
    };
    var nonWhiteSpace = function (token) { return token.type !== 31 /* WHITESPACE_TOKEN */; };
    var nonFunctionArgSeparator = function (token) {
        return token.type !== 31 /* WHITESPACE_TOKEN */ && token.type !== 4 /* COMMA_TOKEN */;
    };
    var parseFunctionArgs = function (tokens) {
        var args = [];
        var arg = [];
        tokens.forEach(function (token) {
            if (token.type === 4 /* COMMA_TOKEN */) {
                if (arg.length === 0) {
                    throw new Error("Error parsing function args, zero tokens for arg");
                }
                args.push(arg);
                arg = [];
                return;
            }
            if (token.type !== 31 /* WHITESPACE_TOKEN */) {
                arg.push(token);
            }
        });
        if (arg.length) {
            args.push(arg);
        }
        return args;
    };
    var isEndingTokenFor = function (token, type) {
        if (type === 11 /* LEFT_CURLY_BRACKET_TOKEN */ && token.type === 12 /* RIGHT_CURLY_BRACKET_TOKEN */) {
            return true;
        }
        if (type === 28 /* LEFT_SQUARE_BRACKET_TOKEN */ && token.type === 29 /* RIGHT_SQUARE_BRACKET_TOKEN */) {
            return true;
        }
        return type === 2 /* LEFT_PARENTHESIS_TOKEN */ && token.type === 3 /* RIGHT_PARENTHESIS_TOKEN */;
    };

    var isLength = function (token) {
        return token.type === 17 /* NUMBER_TOKEN */ || token.type === 15 /* DIMENSION_TOKEN */;
    };

    var isLengthPercentage = function (token) {
        return token.type === 16 /* PERCENTAGE_TOKEN */ || isLength(token);
    };
    var parseLengthPercentageTuple = function (tokens) {
        return tokens.length > 1 ? [tokens[0], tokens[1]] : [tokens[0]];
    };
    var ZERO_LENGTH = {
        type: 17 /* NUMBER_TOKEN */,
        number: 0,
        flags: FLAG_INTEGER
    };
    var FIFTY_PERCENT = {
        type: 16 /* PERCENTAGE_TOKEN */,
        number: 50,
        flags: FLAG_INTEGER
    };
    var HUNDRED_PERCENT = {
        type: 16 /* PERCENTAGE_TOKEN */,
        number: 100,
        flags: FLAG_INTEGER
    };
    var getAbsoluteValueForTuple = function (tuple, width, height) {
        var x = tuple[0], y = tuple[1];
        return [getAbsoluteValue(x, width), getAbsoluteValue(typeof y !== 'undefined' ? y : x, height)];
    };
    var getAbsoluteValue = function (token, parent) {
        if (token.type === 16 /* PERCENTAGE_TOKEN */) {
            return (token.number / 100) * parent;
        }
        if (isDimensionToken(token)) {
            switch (token.unit) {
                case 'rem':
                case 'em':
                    return 16 * token.number; // TODO use correct font-size
                case 'px':
                default:
                    return token.number;
            }
        }
        return token.number;
    };

    var DEG = 'deg';
    var GRAD = 'grad';
    var RAD = 'rad';
    var TURN = 'turn';
    var angle = {
        name: 'angle',
        parse: function (_context, value) {
            if (value.type === 15 /* DIMENSION_TOKEN */) {
                switch (value.unit) {
                    case DEG:
                        return (Math.PI * value.number) / 180;
                    case GRAD:
                        return (Math.PI / 200) * value.number;
                    case RAD:
                        return value.number;
                    case TURN:
                        return Math.PI * 2 * value.number;
                }
            }
            throw new Error("Unsupported angle type");
        }
    };
    var isAngle = function (value) {
        if (value.type === 15 /* DIMENSION_TOKEN */) {
            if (value.unit === DEG || value.unit === GRAD || value.unit === RAD || value.unit === TURN) {
                return true;
            }
        }
        return false;
    };
    var parseNamedSide = function (tokens) {
        var sideOrCorner = tokens
            .filter(isIdentToken)
            .map(function (ident) { return ident.value; })
            .join(' ');
        switch (sideOrCorner) {
            case 'to bottom right':
            case 'to right bottom':
            case 'left top':
            case 'top left':
                return [ZERO_LENGTH, ZERO_LENGTH];
            case 'to top':
            case 'bottom':
                return deg(0);
            case 'to bottom left':
            case 'to left bottom':
            case 'right top':
            case 'top right':
                return [ZERO_LENGTH, HUNDRED_PERCENT];
            case 'to right':
            case 'left':
                return deg(90);
            case 'to top left':
            case 'to left top':
            case 'right bottom':
            case 'bottom right':
                return [HUNDRED_PERCENT, HUNDRED_PERCENT];
            case 'to bottom':
            case 'top':
                return deg(180);
            case 'to top right':
            case 'to right top':
            case 'left bottom':
            case 'bottom left':
                return [HUNDRED_PERCENT, ZERO_LENGTH];
            case 'to left':
            case 'right':
                return deg(270);
        }
        return 0;
    };
    var deg = function (deg) { return (Math.PI * deg) / 180; };

    var color$1 = {
        name: 'color',
        parse: function (context, value) {
            if (value.type === 18 /* FUNCTION */) {
                var colorFunction = SUPPORTED_COLOR_FUNCTIONS[value.name];
                if (typeof colorFunction === 'undefined') {
                    throw new Error("Attempting to parse an unsupported color function \"" + value.name + "\"");
                }
                return colorFunction(context, value.values);
            }
            if (value.type === 5 /* HASH_TOKEN */) {
                if (value.value.length === 3) {
                    var r = value.value.substring(0, 1);
                    var g = value.value.substring(1, 2);
                    var b = value.value.substring(2, 3);
                    return pack(parseInt(r + r, 16), parseInt(g + g, 16), parseInt(b + b, 16), 1);
                }
                if (value.value.length === 4) {
                    var r = value.value.substring(0, 1);
                    var g = value.value.substring(1, 2);
                    var b = value.value.substring(2, 3);
                    var a = value.value.substring(3, 4);
                    return pack(parseInt(r + r, 16), parseInt(g + g, 16), parseInt(b + b, 16), parseInt(a + a, 16) / 255);
                }
                if (value.value.length === 6) {
                    var r = value.value.substring(0, 2);
                    var g = value.value.substring(2, 4);
                    var b = value.value.substring(4, 6);
                    return pack(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1);
                }
                if (value.value.length === 8) {
                    var r = value.value.substring(0, 2);
                    var g = value.value.substring(2, 4);
                    var b = value.value.substring(4, 6);
                    var a = value.value.substring(6, 8);
                    return pack(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), parseInt(a, 16) / 255);
                }
            }
            if (value.type === 20 /* IDENT_TOKEN */) {
                var namedColor = COLORS[value.value.toUpperCase()];
                if (typeof namedColor !== 'undefined') {
                    return namedColor;
                }
            }
            return COLORS.TRANSPARENT;
        }
    };
    var isTransparent = function (color) { return (0xff & color) === 0; };
    var asString = function (color) {
        var alpha = 0xff & color;
        var blue = 0xff & (color >> 8);
        var green = 0xff & (color >> 16);
        var red = 0xff & (color >> 24);
        return alpha < 255 ? "rgba(" + red + "," + green + "," + blue + "," + alpha / 255 + ")" : "rgb(" + red + "," + green + "," + blue + ")";
    };
    var pack = function (r, g, b, a) {
        return ((r << 24) | (g << 16) | (b << 8) | (Math.round(a * 255) << 0)) >>> 0;
    };
    var getTokenColorValue = function (token, i) {
        if (token.type === 17 /* NUMBER_TOKEN */) {
            return token.number;
        }
        if (token.type === 16 /* PERCENTAGE_TOKEN */) {
            var max = i === 3 ? 1 : 255;
            return i === 3 ? (token.number / 100) * max : Math.round((token.number / 100) * max);
        }
        return 0;
    };
    var rgb = function (_context, args) {
        var tokens = args.filter(nonFunctionArgSeparator);
        if (tokens.length === 3) {
            var _a = tokens.map(getTokenColorValue), r = _a[0], g = _a[1], b = _a[2];
            return pack(r, g, b, 1);
        }
        if (tokens.length === 4) {
            var _b = tokens.map(getTokenColorValue), r = _b[0], g = _b[1], b = _b[2], a = _b[3];
            return pack(r, g, b, a);
        }
        return 0;
    };
    function hue2rgb(t1, t2, hue) {
        if (hue < 0) {
            hue += 1;
        }
        if (hue >= 1) {
            hue -= 1;
        }
        if (hue < 1 / 6) {
            return (t2 - t1) * hue * 6 + t1;
        }
        else if (hue < 1 / 2) {
            return t2;
        }
        else if (hue < 2 / 3) {
            return (t2 - t1) * 6 * (2 / 3 - hue) + t1;
        }
        else {
            return t1;
        }
    }
    var hsl = function (context, args) {
        var tokens = args.filter(nonFunctionArgSeparator);
        var hue = tokens[0], saturation = tokens[1], lightness = tokens[2], alpha = tokens[3];
        var h = (hue.type === 17 /* NUMBER_TOKEN */ ? deg(hue.number) : angle.parse(context, hue)) / (Math.PI * 2);
        var s = isLengthPercentage(saturation) ? saturation.number / 100 : 0;
        var l = isLengthPercentage(lightness) ? lightness.number / 100 : 0;
        var a = typeof alpha !== 'undefined' && isLengthPercentage(alpha) ? getAbsoluteValue(alpha, 1) : 1;
        if (s === 0) {
            return pack(l * 255, l * 255, l * 255, 1);
        }
        var t2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
        var t1 = l * 2 - t2;
        var r = hue2rgb(t1, t2, h + 1 / 3);
        var g = hue2rgb(t1, t2, h);
        var b = hue2rgb(t1, t2, h - 1 / 3);
        return pack(r * 255, g * 255, b * 255, a);
    };
    var SUPPORTED_COLOR_FUNCTIONS = {
        hsl: hsl,
        hsla: hsl,
        rgb: rgb,
        rgba: rgb
    };
    var parseColor = function (context, value) {
        return color$1.parse(context, Parser.create(value).parseComponentValue());
    };
    var COLORS = {
        ALICEBLUE: 0xf0f8ffff,
        ANTIQUEWHITE: 0xfaebd7ff,
        AQUA: 0x00ffffff,
        AQUAMARINE: 0x7fffd4ff,
        AZURE: 0xf0ffffff,
        BEIGE: 0xf5f5dcff,
        BISQUE: 0xffe4c4ff,
        BLACK: 0x000000ff,
        BLANCHEDALMOND: 0xffebcdff,
        BLUE: 0x0000ffff,
        BLUEVIOLET: 0x8a2be2ff,
        BROWN: 0xa52a2aff,
        BURLYWOOD: 0xdeb887ff,
        CADETBLUE: 0x5f9ea0ff,
        CHARTREUSE: 0x7fff00ff,
        CHOCOLATE: 0xd2691eff,
        CORAL: 0xff7f50ff,
        CORNFLOWERBLUE: 0x6495edff,
        CORNSILK: 0xfff8dcff,
        CRIMSON: 0xdc143cff,
        CYAN: 0x00ffffff,
        DARKBLUE: 0x00008bff,
        DARKCYAN: 0x008b8bff,
        DARKGOLDENROD: 0xb886bbff,
        DARKGRAY: 0xa9a9a9ff,
        DARKGREEN: 0x006400ff,
        DARKGREY: 0xa9a9a9ff,
        DARKKHAKI: 0xbdb76bff,
        DARKMAGENTA: 0x8b008bff,
        DARKOLIVEGREEN: 0x556b2fff,
        DARKORANGE: 0xff8c00ff,
        DARKORCHID: 0x9932ccff,
        DARKRED: 0x8b0000ff,
        DARKSALMON: 0xe9967aff,
        DARKSEAGREEN: 0x8fbc8fff,
        DARKSLATEBLUE: 0x483d8bff,
        DARKSLATEGRAY: 0x2f4f4fff,
        DARKSLATEGREY: 0x2f4f4fff,
        DARKTURQUOISE: 0x00ced1ff,
        DARKVIOLET: 0x9400d3ff,
        DEEPPINK: 0xff1493ff,
        DEEPSKYBLUE: 0x00bfffff,
        DIMGRAY: 0x696969ff,
        DIMGREY: 0x696969ff,
        DODGERBLUE: 0x1e90ffff,
        FIREBRICK: 0xb22222ff,
        FLORALWHITE: 0xfffaf0ff,
        FORESTGREEN: 0x228b22ff,
        FUCHSIA: 0xff00ffff,
        GAINSBORO: 0xdcdcdcff,
        GHOSTWHITE: 0xf8f8ffff,
        GOLD: 0xffd700ff,
        GOLDENROD: 0xdaa520ff,
        GRAY: 0x808080ff,
        GREEN: 0x008000ff,
        GREENYELLOW: 0xadff2fff,
        GREY: 0x808080ff,
        HONEYDEW: 0xf0fff0ff,
        HOTPINK: 0xff69b4ff,
        INDIANRED: 0xcd5c5cff,
        INDIGO: 0x4b0082ff,
        IVORY: 0xfffff0ff,
        KHAKI: 0xf0e68cff,
        LAVENDER: 0xe6e6faff,
        LAVENDERBLUSH: 0xfff0f5ff,
        LAWNGREEN: 0x7cfc00ff,
        LEMONCHIFFON: 0xfffacdff,
        LIGHTBLUE: 0xadd8e6ff,
        LIGHTCORAL: 0xf08080ff,
        LIGHTCYAN: 0xe0ffffff,
        LIGHTGOLDENRODYELLOW: 0xfafad2ff,
        LIGHTGRAY: 0xd3d3d3ff,
        LIGHTGREEN: 0x90ee90ff,
        LIGHTGREY: 0xd3d3d3ff,
        LIGHTPINK: 0xffb6c1ff,
        LIGHTSALMON: 0xffa07aff,
        LIGHTSEAGREEN: 0x20b2aaff,
        LIGHTSKYBLUE: 0x87cefaff,
        LIGHTSLATEGRAY: 0x778899ff,
        LIGHTSLATEGREY: 0x778899ff,
        LIGHTSTEELBLUE: 0xb0c4deff,
        LIGHTYELLOW: 0xffffe0ff,
        LIME: 0x00ff00ff,
        LIMEGREEN: 0x32cd32ff,
        LINEN: 0xfaf0e6ff,
        MAGENTA: 0xff00ffff,
        MAROON: 0x800000ff,
        MEDIUMAQUAMARINE: 0x66cdaaff,
        MEDIUMBLUE: 0x0000cdff,
        MEDIUMORCHID: 0xba55d3ff,
        MEDIUMPURPLE: 0x9370dbff,
        MEDIUMSEAGREEN: 0x3cb371ff,
        MEDIUMSLATEBLUE: 0x7b68eeff,
        MEDIUMSPRINGGREEN: 0x00fa9aff,
        MEDIUMTURQUOISE: 0x48d1ccff,
        MEDIUMVIOLETRED: 0xc71585ff,
        MIDNIGHTBLUE: 0x191970ff,
        MINTCREAM: 0xf5fffaff,
        MISTYROSE: 0xffe4e1ff,
        MOCCASIN: 0xffe4b5ff,
        NAVAJOWHITE: 0xffdeadff,
        NAVY: 0x000080ff,
        OLDLACE: 0xfdf5e6ff,
        OLIVE: 0x808000ff,
        OLIVEDRAB: 0x6b8e23ff,
        ORANGE: 0xffa500ff,
        ORANGERED: 0xff4500ff,
        ORCHID: 0xda70d6ff,
        PALEGOLDENROD: 0xeee8aaff,
        PALEGREEN: 0x98fb98ff,
        PALETURQUOISE: 0xafeeeeff,
        PALEVIOLETRED: 0xdb7093ff,
        PAPAYAWHIP: 0xffefd5ff,
        PEACHPUFF: 0xffdab9ff,
        PERU: 0xcd853fff,
        PINK: 0xffc0cbff,
        PLUM: 0xdda0ddff,
        POWDERBLUE: 0xb0e0e6ff,
        PURPLE: 0x800080ff,
        REBECCAPURPLE: 0x663399ff,
        RED: 0xff0000ff,
        ROSYBROWN: 0xbc8f8fff,
        ROYALBLUE: 0x4169e1ff,
        SADDLEBROWN: 0x8b4513ff,
        SALMON: 0xfa8072ff,
        SANDYBROWN: 0xf4a460ff,
        SEAGREEN: 0x2e8b57ff,
        SEASHELL: 0xfff5eeff,
        SIENNA: 0xa0522dff,
        SILVER: 0xc0c0c0ff,
        SKYBLUE: 0x87ceebff,
        SLATEBLUE: 0x6a5acdff,
        SLATEGRAY: 0x708090ff,
        SLATEGREY: 0x708090ff,
        SNOW: 0xfffafaff,
        SPRINGGREEN: 0x00ff7fff,
        STEELBLUE: 0x4682b4ff,
        TAN: 0xd2b48cff,
        TEAL: 0x008080ff,
        THISTLE: 0xd8bfd8ff,
        TOMATO: 0xff6347ff,
        TRANSPARENT: 0x00000000,
        TURQUOISE: 0x40e0d0ff,
        VIOLET: 0xee82eeff,
        WHEAT: 0xf5deb3ff,
        WHITE: 0xffffffff,
        WHITESMOKE: 0xf5f5f5ff,
        YELLOW: 0xffff00ff,
        YELLOWGREEN: 0x9acd32ff
    };

    var backgroundClip = {
        name: 'background-clip',
        initialValue: 'border-box',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return tokens.map(function (token) {
                if (isIdentToken(token)) {
                    switch (token.value) {
                        case 'padding-box':
                            return 1 /* PADDING_BOX */;
                        case 'content-box':
                            return 2 /* CONTENT_BOX */;
                    }
                }
                return 0 /* BORDER_BOX */;
            });
        }
    };

    var backgroundColor = {
        name: "background-color",
        initialValue: 'transparent',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'color'
    };

    var parseColorStop = function (context, args) {
        var color = color$1.parse(context, args[0]);
        var stop = args[1];
        return stop && isLengthPercentage(stop) ? { color: color, stop: stop } : { color: color, stop: null };
    };
    var processColorStops = function (stops, lineLength) {
        var first = stops[0];
        var last = stops[stops.length - 1];
        if (first.stop === null) {
            first.stop = ZERO_LENGTH;
        }
        if (last.stop === null) {
            last.stop = HUNDRED_PERCENT;
        }
        var processStops = [];
        var previous = 0;
        for (var i = 0; i < stops.length; i++) {
            var stop_1 = stops[i].stop;
            if (stop_1 !== null) {
                var absoluteValue = getAbsoluteValue(stop_1, lineLength);
                if (absoluteValue > previous) {
                    processStops.push(absoluteValue);
                }
                else {
                    processStops.push(previous);
                }
                previous = absoluteValue;
            }
            else {
                processStops.push(null);
            }
        }
        var gapBegin = null;
        for (var i = 0; i < processStops.length; i++) {
            var stop_2 = processStops[i];
            if (stop_2 === null) {
                if (gapBegin === null) {
                    gapBegin = i;
                }
            }
            else if (gapBegin !== null) {
                var gapLength = i - gapBegin;
                var beforeGap = processStops[gapBegin - 1];
                var gapValue = (stop_2 - beforeGap) / (gapLength + 1);
                for (var g = 1; g <= gapLength; g++) {
                    processStops[gapBegin + g - 1] = gapValue * g;
                }
                gapBegin = null;
            }
        }
        return stops.map(function (_a, i) {
            var color = _a.color;
            return { color: color, stop: Math.max(Math.min(1, processStops[i] / lineLength), 0) };
        });
    };
    var getAngleFromCorner = function (corner, width, height) {
        var centerX = width / 2;
        var centerY = height / 2;
        var x = getAbsoluteValue(corner[0], width) - centerX;
        var y = centerY - getAbsoluteValue(corner[1], height);
        return (Math.atan2(y, x) + Math.PI * 2) % (Math.PI * 2);
    };
    var calculateGradientDirection = function (angle, width, height) {
        var radian = typeof angle === 'number' ? angle : getAngleFromCorner(angle, width, height);
        var lineLength = Math.abs(width * Math.sin(radian)) + Math.abs(height * Math.cos(radian));
        var halfWidth = width / 2;
        var halfHeight = height / 2;
        var halfLineLength = lineLength / 2;
        var yDiff = Math.sin(radian - Math.PI / 2) * halfLineLength;
        var xDiff = Math.cos(radian - Math.PI / 2) * halfLineLength;
        return [lineLength, halfWidth - xDiff, halfWidth + xDiff, halfHeight - yDiff, halfHeight + yDiff];
    };
    var distance = function (a, b) { return Math.sqrt(a * a + b * b); };
    var findCorner = function (width, height, x, y, closest) {
        var corners = [
            [0, 0],
            [0, height],
            [width, 0],
            [width, height]
        ];
        return corners.reduce(function (stat, corner) {
            var cx = corner[0], cy = corner[1];
            var d = distance(x - cx, y - cy);
            if (closest ? d < stat.optimumDistance : d > stat.optimumDistance) {
                return {
                    optimumCorner: corner,
                    optimumDistance: d
                };
            }
            return stat;
        }, {
            optimumDistance: closest ? Infinity : -Infinity,
            optimumCorner: null
        }).optimumCorner;
    };
    var calculateRadius = function (gradient, x, y, width, height) {
        var rx = 0;
        var ry = 0;
        switch (gradient.size) {
            case 0 /* CLOSEST_SIDE */:
                // The ending shape is sized so that that it exactly meets the side of the gradient box closest to the gradient’s center.
                // If the shape is an ellipse, it exactly meets the closest side in each dimension.
                if (gradient.shape === 0 /* CIRCLE */) {
                    rx = ry = Math.min(Math.abs(x), Math.abs(x - width), Math.abs(y), Math.abs(y - height));
                }
                else if (gradient.shape === 1 /* ELLIPSE */) {
                    rx = Math.min(Math.abs(x), Math.abs(x - width));
                    ry = Math.min(Math.abs(y), Math.abs(y - height));
                }
                break;
            case 2 /* CLOSEST_CORNER */:
                // The ending shape is sized so that that it passes through the corner of the gradient box closest to the gradient’s center.
                // If the shape is an ellipse, the ending shape is given the same aspect-ratio it would have if closest-side were specified.
                if (gradient.shape === 0 /* CIRCLE */) {
                    rx = ry = Math.min(distance(x, y), distance(x, y - height), distance(x - width, y), distance(x - width, y - height));
                }
                else if (gradient.shape === 1 /* ELLIPSE */) {
                    // Compute the ratio ry/rx (which is to be the same as for "closest-side")
                    var c = Math.min(Math.abs(y), Math.abs(y - height)) / Math.min(Math.abs(x), Math.abs(x - width));
                    var _a = findCorner(width, height, x, y, true), cx = _a[0], cy = _a[1];
                    rx = distance(cx - x, (cy - y) / c);
                    ry = c * rx;
                }
                break;
            case 1 /* FARTHEST_SIDE */:
                // Same as closest-side, except the ending shape is sized based on the farthest side(s)
                if (gradient.shape === 0 /* CIRCLE */) {
                    rx = ry = Math.max(Math.abs(x), Math.abs(x - width), Math.abs(y), Math.abs(y - height));
                }
                else if (gradient.shape === 1 /* ELLIPSE */) {
                    rx = Math.max(Math.abs(x), Math.abs(x - width));
                    ry = Math.max(Math.abs(y), Math.abs(y - height));
                }
                break;
            case 3 /* FARTHEST_CORNER */:
                // Same as closest-corner, except the ending shape is sized based on the farthest corner.
                // If the shape is an ellipse, the ending shape is given the same aspect ratio it would have if farthest-side were specified.
                if (gradient.shape === 0 /* CIRCLE */) {
                    rx = ry = Math.max(distance(x, y), distance(x, y - height), distance(x - width, y), distance(x - width, y - height));
                }
                else if (gradient.shape === 1 /* ELLIPSE */) {
                    // Compute the ratio ry/rx (which is to be the same as for "farthest-side")
                    var c = Math.max(Math.abs(y), Math.abs(y - height)) / Math.max(Math.abs(x), Math.abs(x - width));
                    var _b = findCorner(width, height, x, y, false), cx = _b[0], cy = _b[1];
                    rx = distance(cx - x, (cy - y) / c);
                    ry = c * rx;
                }
                break;
        }
        if (Array.isArray(gradient.size)) {
            rx = getAbsoluteValue(gradient.size[0], width);
            ry = gradient.size.length === 2 ? getAbsoluteValue(gradient.size[1], height) : rx;
        }
        return [rx, ry];
    };

    var linearGradient = function (context, tokens) {
        var angle$1 = deg(180);
        var stops = [];
        parseFunctionArgs(tokens).forEach(function (arg, i) {
            if (i === 0) {
                var firstToken = arg[0];
                if (firstToken.type === 20 /* IDENT_TOKEN */ && firstToken.value === 'to') {
                    angle$1 = parseNamedSide(arg);
                    return;
                }
                else if (isAngle(firstToken)) {
                    angle$1 = angle.parse(context, firstToken);
                    return;
                }
            }
            var colorStop = parseColorStop(context, arg);
            stops.push(colorStop);
        });
        return { angle: angle$1, stops: stops, type: 1 /* LINEAR_GRADIENT */ };
    };

    var prefixLinearGradient = function (context, tokens) {
        var angle$1 = deg(180);
        var stops = [];
        parseFunctionArgs(tokens).forEach(function (arg, i) {
            if (i === 0) {
                var firstToken = arg[0];
                if (firstToken.type === 20 /* IDENT_TOKEN */ &&
                    ['top', 'left', 'right', 'bottom'].indexOf(firstToken.value) !== -1) {
                    angle$1 = parseNamedSide(arg);
                    return;
                }
                else if (isAngle(firstToken)) {
                    angle$1 = (angle.parse(context, firstToken) + deg(270)) % deg(360);
                    return;
                }
            }
            var colorStop = parseColorStop(context, arg);
            stops.push(colorStop);
        });
        return {
            angle: angle$1,
            stops: stops,
            type: 1 /* LINEAR_GRADIENT */
        };
    };

    var webkitGradient = function (context, tokens) {
        var angle = deg(180);
        var stops = [];
        var type = 1 /* LINEAR_GRADIENT */;
        var shape = 0 /* CIRCLE */;
        var size = 3 /* FARTHEST_CORNER */;
        var position = [];
        parseFunctionArgs(tokens).forEach(function (arg, i) {
            var firstToken = arg[0];
            if (i === 0) {
                if (isIdentToken(firstToken) && firstToken.value === 'linear') {
                    type = 1 /* LINEAR_GRADIENT */;
                    return;
                }
                else if (isIdentToken(firstToken) && firstToken.value === 'radial') {
                    type = 2 /* RADIAL_GRADIENT */;
                    return;
                }
            }
            if (firstToken.type === 18 /* FUNCTION */) {
                if (firstToken.name === 'from') {
                    var color = color$1.parse(context, firstToken.values[0]);
                    stops.push({ stop: ZERO_LENGTH, color: color });
                }
                else if (firstToken.name === 'to') {
                    var color = color$1.parse(context, firstToken.values[0]);
                    stops.push({ stop: HUNDRED_PERCENT, color: color });
                }
                else if (firstToken.name === 'color-stop') {
                    var values = firstToken.values.filter(nonFunctionArgSeparator);
                    if (values.length === 2) {
                        var color = color$1.parse(context, values[1]);
                        var stop_1 = values[0];
                        if (isNumberToken(stop_1)) {
                            stops.push({
                                stop: { type: 16 /* PERCENTAGE_TOKEN */, number: stop_1.number * 100, flags: stop_1.flags },
                                color: color
                            });
                        }
                    }
                }
            }
        });
        return type === 1 /* LINEAR_GRADIENT */
            ? {
                angle: (angle + deg(180)) % deg(360),
                stops: stops,
                type: type
            }
            : { size: size, shape: shape, stops: stops, position: position, type: type };
    };

    var CLOSEST_SIDE = 'closest-side';
    var FARTHEST_SIDE = 'farthest-side';
    var CLOSEST_CORNER = 'closest-corner';
    var FARTHEST_CORNER = 'farthest-corner';
    var CIRCLE = 'circle';
    var ELLIPSE = 'ellipse';
    var COVER = 'cover';
    var CONTAIN = 'contain';
    var radialGradient = function (context, tokens) {
        var shape = 0 /* CIRCLE */;
        var size = 3 /* FARTHEST_CORNER */;
        var stops = [];
        var position = [];
        parseFunctionArgs(tokens).forEach(function (arg, i) {
            var isColorStop = true;
            if (i === 0) {
                var isAtPosition_1 = false;
                isColorStop = arg.reduce(function (acc, token) {
                    if (isAtPosition_1) {
                        if (isIdentToken(token)) {
                            switch (token.value) {
                                case 'center':
                                    position.push(FIFTY_PERCENT);
                                    return acc;
                                case 'top':
                                case 'left':
                                    position.push(ZERO_LENGTH);
                                    return acc;
                                case 'right':
                                case 'bottom':
                                    position.push(HUNDRED_PERCENT);
                                    return acc;
                            }
                        }
                        else if (isLengthPercentage(token) || isLength(token)) {
                            position.push(token);
                        }
                    }
                    else if (isIdentToken(token)) {
                        switch (token.value) {
                            case CIRCLE:
                                shape = 0 /* CIRCLE */;
                                return false;
                            case ELLIPSE:
                                shape = 1 /* ELLIPSE */;
                                return false;
                            case 'at':
                                isAtPosition_1 = true;
                                return false;
                            case CLOSEST_SIDE:
                                size = 0 /* CLOSEST_SIDE */;
                                return false;
                            case COVER:
                            case FARTHEST_SIDE:
                                size = 1 /* FARTHEST_SIDE */;
                                return false;
                            case CONTAIN:
                            case CLOSEST_CORNER:
                                size = 2 /* CLOSEST_CORNER */;
                                return false;
                            case FARTHEST_CORNER:
                                size = 3 /* FARTHEST_CORNER */;
                                return false;
                        }
                    }
                    else if (isLength(token) || isLengthPercentage(token)) {
                        if (!Array.isArray(size)) {
                            size = [];
                        }
                        size.push(token);
                        return false;
                    }
                    return acc;
                }, isColorStop);
            }
            if (isColorStop) {
                var colorStop = parseColorStop(context, arg);
                stops.push(colorStop);
            }
        });
        return { size: size, shape: shape, stops: stops, position: position, type: 2 /* RADIAL_GRADIENT */ };
    };

    var prefixRadialGradient = function (context, tokens) {
        var shape = 0 /* CIRCLE */;
        var size = 3 /* FARTHEST_CORNER */;
        var stops = [];
        var position = [];
        parseFunctionArgs(tokens).forEach(function (arg, i) {
            var isColorStop = true;
            if (i === 0) {
                isColorStop = arg.reduce(function (acc, token) {
                    if (isIdentToken(token)) {
                        switch (token.value) {
                            case 'center':
                                position.push(FIFTY_PERCENT);
                                return false;
                            case 'top':
                            case 'left':
                                position.push(ZERO_LENGTH);
                                return false;
                            case 'right':
                            case 'bottom':
                                position.push(HUNDRED_PERCENT);
                                return false;
                        }
                    }
                    else if (isLengthPercentage(token) || isLength(token)) {
                        position.push(token);
                        return false;
                    }
                    return acc;
                }, isColorStop);
            }
            else if (i === 1) {
                isColorStop = arg.reduce(function (acc, token) {
                    if (isIdentToken(token)) {
                        switch (token.value) {
                            case CIRCLE:
                                shape = 0 /* CIRCLE */;
                                return false;
                            case ELLIPSE:
                                shape = 1 /* ELLIPSE */;
                                return false;
                            case CONTAIN:
                            case CLOSEST_SIDE:
                                size = 0 /* CLOSEST_SIDE */;
                                return false;
                            case FARTHEST_SIDE:
                                size = 1 /* FARTHEST_SIDE */;
                                return false;
                            case CLOSEST_CORNER:
                                size = 2 /* CLOSEST_CORNER */;
                                return false;
                            case COVER:
                            case FARTHEST_CORNER:
                                size = 3 /* FARTHEST_CORNER */;
                                return false;
                        }
                    }
                    else if (isLength(token) || isLengthPercentage(token)) {
                        if (!Array.isArray(size)) {
                            size = [];
                        }
                        size.push(token);
                        return false;
                    }
                    return acc;
                }, isColorStop);
            }
            if (isColorStop) {
                var colorStop = parseColorStop(context, arg);
                stops.push(colorStop);
            }
        });
        return { size: size, shape: shape, stops: stops, position: position, type: 2 /* RADIAL_GRADIENT */ };
    };

    var isLinearGradient = function (background) {
        return background.type === 1 /* LINEAR_GRADIENT */;
    };
    var isRadialGradient = function (background) {
        return background.type === 2 /* RADIAL_GRADIENT */;
    };
    var image = {
        name: 'image',
        parse: function (context, value) {
            if (value.type === 22 /* URL_TOKEN */) {
                var image_1 = { url: value.value, type: 0 /* URL */ };
                context.cache.addImage(value.value);
                return image_1;
            }
            if (value.type === 18 /* FUNCTION */) {
                var imageFunction = SUPPORTED_IMAGE_FUNCTIONS[value.name];
                if (typeof imageFunction === 'undefined') {
                    throw new Error("Attempting to parse an unsupported image function \"" + value.name + "\"");
                }
                return imageFunction(context, value.values);
            }
            throw new Error("Unsupported image type " + value.type);
        }
    };
    function isSupportedImage(value) {
        return (!(value.type === 20 /* IDENT_TOKEN */ && value.value === 'none') &&
            (value.type !== 18 /* FUNCTION */ || !!SUPPORTED_IMAGE_FUNCTIONS[value.name]));
    }
    var SUPPORTED_IMAGE_FUNCTIONS = {
        'linear-gradient': linearGradient,
        '-moz-linear-gradient': prefixLinearGradient,
        '-ms-linear-gradient': prefixLinearGradient,
        '-o-linear-gradient': prefixLinearGradient,
        '-webkit-linear-gradient': prefixLinearGradient,
        'radial-gradient': radialGradient,
        '-moz-radial-gradient': prefixRadialGradient,
        '-ms-radial-gradient': prefixRadialGradient,
        '-o-radial-gradient': prefixRadialGradient,
        '-webkit-radial-gradient': prefixRadialGradient,
        '-webkit-gradient': webkitGradient
    };

    var backgroundImage = {
        name: 'background-image',
        initialValue: 'none',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (context, tokens) {
            if (tokens.length === 0) {
                return [];
            }
            var first = tokens[0];
            if (first.type === 20 /* IDENT_TOKEN */ && first.value === 'none') {
                return [];
            }
            return tokens
                .filter(function (value) { return nonFunctionArgSeparator(value) && isSupportedImage(value); })
                .map(function (value) { return image.parse(context, value); });
        }
    };

    var backgroundOrigin = {
        name: 'background-origin',
        initialValue: 'border-box',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return tokens.map(function (token) {
                if (isIdentToken(token)) {
                    switch (token.value) {
                        case 'padding-box':
                            return 1 /* PADDING_BOX */;
                        case 'content-box':
                            return 2 /* CONTENT_BOX */;
                    }
                }
                return 0 /* BORDER_BOX */;
            });
        }
    };

    var backgroundPosition = {
        name: 'background-position',
        initialValue: '0% 0%',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (_context, tokens) {
            return parseFunctionArgs(tokens)
                .map(function (values) { return values.filter(isLengthPercentage); })
                .map(parseLengthPercentageTuple);
        }
    };

    var backgroundRepeat = {
        name: 'background-repeat',
        initialValue: 'repeat',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return parseFunctionArgs(tokens)
                .map(function (values) {
                return values
                    .filter(isIdentToken)
                    .map(function (token) { return token.value; })
                    .join(' ');
            })
                .map(parseBackgroundRepeat);
        }
    };
    var parseBackgroundRepeat = function (value) {
        switch (value) {
            case 'no-repeat':
                return 1 /* NO_REPEAT */;
            case 'repeat-x':
            case 'repeat no-repeat':
                return 2 /* REPEAT_X */;
            case 'repeat-y':
            case 'no-repeat repeat':
                return 3 /* REPEAT_Y */;
            case 'repeat':
            default:
                return 0 /* REPEAT */;
        }
    };

    var BACKGROUND_SIZE;
    (function (BACKGROUND_SIZE) {
        BACKGROUND_SIZE["AUTO"] = "auto";
        BACKGROUND_SIZE["CONTAIN"] = "contain";
        BACKGROUND_SIZE["COVER"] = "cover";
    })(BACKGROUND_SIZE || (BACKGROUND_SIZE = {}));
    var backgroundSize = {
        name: 'background-size',
        initialValue: '0',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return parseFunctionArgs(tokens).map(function (values) { return values.filter(isBackgroundSizeInfoToken); });
        }
    };
    var isBackgroundSizeInfoToken = function (value) {
        return isIdentToken(value) || isLengthPercentage(value);
    };

    var borderColorForSide = function (side) { return ({
        name: "border-" + side + "-color",
        initialValue: 'transparent',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'color'
    }); };
    var borderTopColor = borderColorForSide('top');
    var borderRightColor = borderColorForSide('right');
    var borderBottomColor = borderColorForSide('bottom');
    var borderLeftColor = borderColorForSide('left');

    var borderRadiusForSide = function (side) { return ({
        name: "border-radius-" + side,
        initialValue: '0 0',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return parseLengthPercentageTuple(tokens.filter(isLengthPercentage));
        }
    }); };
    var borderTopLeftRadius = borderRadiusForSide('top-left');
    var borderTopRightRadius = borderRadiusForSide('top-right');
    var borderBottomRightRadius = borderRadiusForSide('bottom-right');
    var borderBottomLeftRadius = borderRadiusForSide('bottom-left');

    var borderStyleForSide = function (side) { return ({
        name: "border-" + side + "-style",
        initialValue: 'solid',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, style) {
            switch (style) {
                case 'none':
                    return 0 /* NONE */;
                case 'dashed':
                    return 2 /* DASHED */;
                case 'dotted':
                    return 3 /* DOTTED */;
                case 'double':
                    return 4 /* DOUBLE */;
            }
            return 1 /* SOLID */;
        }
    }); };
    var borderTopStyle = borderStyleForSide('top');
    var borderRightStyle = borderStyleForSide('right');
    var borderBottomStyle = borderStyleForSide('bottom');
    var borderLeftStyle = borderStyleForSide('left');

    var borderWidthForSide = function (side) { return ({
        name: "border-" + side + "-width",
        initialValue: '0',
        type: 0 /* VALUE */,
        prefix: false,
        parse: function (_context, token) {
            if (isDimensionToken(token)) {
                return token.number;
            }
            return 0;
        }
    }); };
    var borderTopWidth = borderWidthForSide('top');
    var borderRightWidth = borderWidthForSide('right');
    var borderBottomWidth = borderWidthForSide('bottom');
    var borderLeftWidth = borderWidthForSide('left');

    var color = {
        name: "color",
        initialValue: 'transparent',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'color'
    };

    var direction = {
        name: 'direction',
        initialValue: 'ltr',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, direction) {
            switch (direction) {
                case 'rtl':
                    return 1 /* RTL */;
                case 'ltr':
                default:
                    return 0 /* LTR */;
            }
        }
    };

    var display = {
        name: 'display',
        initialValue: 'inline-block',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return tokens.filter(isIdentToken).reduce(function (bit, token) {
                return bit | parseDisplayValue(token.value);
            }, 0 /* NONE */);
        }
    };
    var parseDisplayValue = function (display) {
        switch (display) {
            case 'block':
            case '-webkit-box':
                return 2 /* BLOCK */;
            case 'inline':
                return 4 /* INLINE */;
            case 'run-in':
                return 8 /* RUN_IN */;
            case 'flow':
                return 16 /* FLOW */;
            case 'flow-root':
                return 32 /* FLOW_ROOT */;
            case 'table':
                return 64 /* TABLE */;
            case 'flex':
            case '-webkit-flex':
                return 128 /* FLEX */;
            case 'grid':
            case '-ms-grid':
                return 256 /* GRID */;
            case 'ruby':
                return 512 /* RUBY */;
            case 'subgrid':
                return 1024 /* SUBGRID */;
            case 'list-item':
                return 2048 /* LIST_ITEM */;
            case 'table-row-group':
                return 4096 /* TABLE_ROW_GROUP */;
            case 'table-header-group':
                return 8192 /* TABLE_HEADER_GROUP */;
            case 'table-footer-group':
                return 16384 /* TABLE_FOOTER_GROUP */;
            case 'table-row':
                return 32768 /* TABLE_ROW */;
            case 'table-cell':
                return 65536 /* TABLE_CELL */;
            case 'table-column-group':
                return 131072 /* TABLE_COLUMN_GROUP */;
            case 'table-column':
                return 262144 /* TABLE_COLUMN */;
            case 'table-caption':
                return 524288 /* TABLE_CAPTION */;
            case 'ruby-base':
                return 1048576 /* RUBY_BASE */;
            case 'ruby-text':
                return 2097152 /* RUBY_TEXT */;
            case 'ruby-base-container':
                return 4194304 /* RUBY_BASE_CONTAINER */;
            case 'ruby-text-container':
                return 8388608 /* RUBY_TEXT_CONTAINER */;
            case 'contents':
                return 16777216 /* CONTENTS */;
            case 'inline-block':
                return 33554432 /* INLINE_BLOCK */;
            case 'inline-list-item':
                return 67108864 /* INLINE_LIST_ITEM */;
            case 'inline-table':
                return 134217728 /* INLINE_TABLE */;
            case 'inline-flex':
                return 268435456 /* INLINE_FLEX */;
            case 'inline-grid':
                return 536870912 /* INLINE_GRID */;
        }
        return 0 /* NONE */;
    };

    var float = {
        name: 'float',
        initialValue: 'none',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, float) {
            switch (float) {
                case 'left':
                    return 1 /* LEFT */;
                case 'right':
                    return 2 /* RIGHT */;
                case 'inline-start':
                    return 3 /* INLINE_START */;
                case 'inline-end':
                    return 4 /* INLINE_END */;
            }
            return 0 /* NONE */;
        }
    };

    var letterSpacing = {
        name: 'letter-spacing',
        initialValue: '0',
        prefix: false,
        type: 0 /* VALUE */,
        parse: function (_context, token) {
            if (token.type === 20 /* IDENT_TOKEN */ && token.value === 'normal') {
                return 0;
            }
            if (token.type === 17 /* NUMBER_TOKEN */) {
                return token.number;
            }
            if (token.type === 15 /* DIMENSION_TOKEN */) {
                return token.number;
            }
            return 0;
        }
    };

    var LINE_BREAK;
    (function (LINE_BREAK) {
        LINE_BREAK["NORMAL"] = "normal";
        LINE_BREAK["STRICT"] = "strict";
    })(LINE_BREAK || (LINE_BREAK = {}));
    var lineBreak = {
        name: 'line-break',
        initialValue: 'normal',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, lineBreak) {
            switch (lineBreak) {
                case 'strict':
                    return LINE_BREAK.STRICT;
                case 'normal':
                default:
                    return LINE_BREAK.NORMAL;
            }
        }
    };

    var lineHeight = {
        name: 'line-height',
        initialValue: 'normal',
        prefix: false,
        type: 4 /* TOKEN_VALUE */
    };
    var computeLineHeight = function (token, fontSize) {
        if (isIdentToken(token) && token.value === 'normal') {
            return 1.2 * fontSize;
        }
        else if (token.type === 17 /* NUMBER_TOKEN */) {
            return fontSize * token.number;
        }
        else if (isLengthPercentage(token)) {
            return getAbsoluteValue(token, fontSize);
        }
        return fontSize;
    };

    var listStyleImage = {
        name: 'list-style-image',
        initialValue: 'none',
        type: 0 /* VALUE */,
        prefix: false,
        parse: function (context, token) {
            if (token.type === 20 /* IDENT_TOKEN */ && token.value === 'none') {
                return null;
            }
            return image.parse(context, token);
        }
    };

    var listStylePosition = {
        name: 'list-style-position',
        initialValue: 'outside',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, position) {
            switch (position) {
                case 'inside':
                    return 0 /* INSIDE */;
                case 'outside':
                default:
                    return 1 /* OUTSIDE */;
            }
        }
    };

    var listStyleType = {
        name: 'list-style-type',
        initialValue: 'none',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, type) {
            switch (type) {
                case 'disc':
                    return 0 /* DISC */;
                case 'circle':
                    return 1 /* CIRCLE */;
                case 'square':
                    return 2 /* SQUARE */;
                case 'decimal':
                    return 3 /* DECIMAL */;
                case 'cjk-decimal':
                    return 4 /* CJK_DECIMAL */;
                case 'decimal-leading-zero':
                    return 5 /* DECIMAL_LEADING_ZERO */;
                case 'lower-roman':
                    return 6 /* LOWER_ROMAN */;
                case 'upper-roman':
                    return 7 /* UPPER_ROMAN */;
                case 'lower-greek':
                    return 8 /* LOWER_GREEK */;
                case 'lower-alpha':
                    return 9 /* LOWER_ALPHA */;
                case 'upper-alpha':
                    return 10 /* UPPER_ALPHA */;
                case 'arabic-indic':
                    return 11 /* ARABIC_INDIC */;
                case 'armenian':
                    return 12 /* ARMENIAN */;
                case 'bengali':
                    return 13 /* BENGALI */;
                case 'cambodian':
                    return 14 /* CAMBODIAN */;
                case 'cjk-earthly-branch':
                    return 15 /* CJK_EARTHLY_BRANCH */;
                case 'cjk-heavenly-stem':
                    return 16 /* CJK_HEAVENLY_STEM */;
                case 'cjk-ideographic':
                    return 17 /* CJK_IDEOGRAPHIC */;
                case 'devanagari':
                    return 18 /* DEVANAGARI */;
                case 'ethiopic-numeric':
                    return 19 /* ETHIOPIC_NUMERIC */;
                case 'georgian':
                    return 20 /* GEORGIAN */;
                case 'gujarati':
                    return 21 /* GUJARATI */;
                case 'gurmukhi':
                    return 22 /* GURMUKHI */;
                case 'hebrew':
                    return 22 /* HEBREW */;
                case 'hiragana':
                    return 23 /* HIRAGANA */;
                case 'hiragana-iroha':
                    return 24 /* HIRAGANA_IROHA */;
                case 'japanese-formal':
                    return 25 /* JAPANESE_FORMAL */;
                case 'japanese-informal':
                    return 26 /* JAPANESE_INFORMAL */;
                case 'kannada':
                    return 27 /* KANNADA */;
                case 'katakana':
                    return 28 /* KATAKANA */;
                case 'katakana-iroha':
                    return 29 /* KATAKANA_IROHA */;
                case 'khmer':
                    return 30 /* KHMER */;
                case 'korean-hangul-formal':
                    return 31 /* KOREAN_HANGUL_FORMAL */;
                case 'korean-hanja-formal':
                    return 32 /* KOREAN_HANJA_FORMAL */;
                case 'korean-hanja-informal':
                    return 33 /* KOREAN_HANJA_INFORMAL */;
                case 'lao':
                    return 34 /* LAO */;
                case 'lower-armenian':
                    return 35 /* LOWER_ARMENIAN */;
                case 'malayalam':
                    return 36 /* MALAYALAM */;
                case 'mongolian':
                    return 37 /* MONGOLIAN */;
                case 'myanmar':
                    return 38 /* MYANMAR */;
                case 'oriya':
                    return 39 /* ORIYA */;
                case 'persian':
                    return 40 /* PERSIAN */;
                case 'simp-chinese-formal':
                    return 41 /* SIMP_CHINESE_FORMAL */;
                case 'simp-chinese-informal':
                    return 42 /* SIMP_CHINESE_INFORMAL */;
                case 'tamil':
                    return 43 /* TAMIL */;
                case 'telugu':
                    return 44 /* TELUGU */;
                case 'thai':
                    return 45 /* THAI */;
                case 'tibetan':
                    return 46 /* TIBETAN */;
                case 'trad-chinese-formal':
                    return 47 /* TRAD_CHINESE_FORMAL */;
                case 'trad-chinese-informal':
                    return 48 /* TRAD_CHINESE_INFORMAL */;
                case 'upper-armenian':
                    return 49 /* UPPER_ARMENIAN */;
                case 'disclosure-open':
                    return 50 /* DISCLOSURE_OPEN */;
                case 'disclosure-closed':
                    return 51 /* DISCLOSURE_CLOSED */;
                case 'none':
                default:
                    return -1 /* NONE */;
            }
        }
    };

    var marginForSide = function (side) { return ({
        name: "margin-" + side,
        initialValue: '0',
        prefix: false,
        type: 4 /* TOKEN_VALUE */
    }); };
    var marginTop = marginForSide('top');
    var marginRight = marginForSide('right');
    var marginBottom = marginForSide('bottom');
    var marginLeft = marginForSide('left');

    var overflow = {
        name: 'overflow',
        initialValue: 'visible',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return tokens.filter(isIdentToken).map(function (overflow) {
                switch (overflow.value) {
                    case 'hidden':
                        return 1 /* HIDDEN */;
                    case 'scroll':
                        return 2 /* SCROLL */;
                    case 'clip':
                        return 3 /* CLIP */;
                    case 'auto':
                        return 4 /* AUTO */;
                    case 'visible':
                    default:
                        return 0 /* VISIBLE */;
                }
            });
        }
    };

    var overflowWrap = {
        name: 'overflow-wrap',
        initialValue: 'normal',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, overflow) {
            switch (overflow) {
                case 'break-word':
                    return "break-word" /* BREAK_WORD */;
                case 'normal':
                default:
                    return "normal" /* NORMAL */;
            }
        }
    };

    var paddingForSide = function (side) { return ({
        name: "padding-" + side,
        initialValue: '0',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'length-percentage'
    }); };
    var paddingTop = paddingForSide('top');
    var paddingRight = paddingForSide('right');
    var paddingBottom = paddingForSide('bottom');
    var paddingLeft = paddingForSide('left');

    var textAlign = {
        name: 'text-align',
        initialValue: 'left',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, textAlign) {
            switch (textAlign) {
                case 'right':
                    return 2 /* RIGHT */;
                case 'center':
                case 'justify':
                    return 1 /* CENTER */;
                case 'left':
                default:
                    return 0 /* LEFT */;
            }
        }
    };

    var position = {
        name: 'position',
        initialValue: 'static',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, position) {
            switch (position) {
                case 'relative':
                    return 1 /* RELATIVE */;
                case 'absolute':
                    return 2 /* ABSOLUTE */;
                case 'fixed':
                    return 3 /* FIXED */;
                case 'sticky':
                    return 4 /* STICKY */;
            }
            return 0 /* STATIC */;
        }
    };

    var textShadow = {
        name: 'text-shadow',
        initialValue: 'none',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (context, tokens) {
            if (tokens.length === 1 && isIdentWithValue(tokens[0], 'none')) {
                return [];
            }
            return parseFunctionArgs(tokens).map(function (values) {
                var shadow = {
                    color: COLORS.TRANSPARENT,
                    offsetX: ZERO_LENGTH,
                    offsetY: ZERO_LENGTH,
                    blur: ZERO_LENGTH
                };
                var c = 0;
                for (var i = 0; i < values.length; i++) {
                    var token = values[i];
                    if (isLength(token)) {
                        if (c === 0) {
                            shadow.offsetX = token;
                        }
                        else if (c === 1) {
                            shadow.offsetY = token;
                        }
                        else {
                            shadow.blur = token;
                        }
                        c++;
                    }
                    else {
                        shadow.color = color$1.parse(context, token);
                    }
                }
                return shadow;
            });
        }
    };

    var textTransform = {
        name: 'text-transform',
        initialValue: 'none',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, textTransform) {
            switch (textTransform) {
                case 'uppercase':
                    return 2 /* UPPERCASE */;
                case 'lowercase':
                    return 1 /* LOWERCASE */;
                case 'capitalize':
                    return 3 /* CAPITALIZE */;
            }
            return 0 /* NONE */;
        }
    };

    var transform$1 = {
        name: 'transform',
        initialValue: 'none',
        prefix: true,
        type: 0 /* VALUE */,
        parse: function (_context, token) {
            if (token.type === 20 /* IDENT_TOKEN */ && token.value === 'none') {
                return null;
            }
            if (token.type === 18 /* FUNCTION */) {
                var transformFunction = SUPPORTED_TRANSFORM_FUNCTIONS[token.name];
                if (typeof transformFunction === 'undefined') {
                    throw new Error("Attempting to parse an unsupported transform function \"" + token.name + "\"");
                }
                return transformFunction(token.values);
            }
            return null;
        }
    };
    var matrix = function (args) {
        var values = args.filter(function (arg) { return arg.type === 17 /* NUMBER_TOKEN */; }).map(function (arg) { return arg.number; });
        return values.length === 6 ? values : null;
    };
    // doesn't support 3D transforms at the moment
    var matrix3d = function (args) {
        var values = args.filter(function (arg) { return arg.type === 17 /* NUMBER_TOKEN */; }).map(function (arg) { return arg.number; });
        var a1 = values[0], b1 = values[1]; values[2]; values[3]; var a2 = values[4], b2 = values[5]; values[6]; values[7]; values[8]; values[9]; values[10]; values[11]; var a4 = values[12], b4 = values[13]; values[14]; values[15];
        return values.length === 16 ? [a1, b1, a2, b2, a4, b4] : null;
    };
    var SUPPORTED_TRANSFORM_FUNCTIONS = {
        matrix: matrix,
        matrix3d: matrix3d
    };

    var DEFAULT_VALUE = {
        type: 16 /* PERCENTAGE_TOKEN */,
        number: 50,
        flags: FLAG_INTEGER
    };
    var DEFAULT = [DEFAULT_VALUE, DEFAULT_VALUE];
    var transformOrigin = {
        name: 'transform-origin',
        initialValue: '50% 50%',
        prefix: true,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            var origins = tokens.filter(isLengthPercentage);
            if (origins.length !== 2) {
                return DEFAULT;
            }
            return [origins[0], origins[1]];
        }
    };

    var visibility = {
        name: 'visible',
        initialValue: 'none',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, visibility) {
            switch (visibility) {
                case 'hidden':
                    return 1 /* HIDDEN */;
                case 'collapse':
                    return 2 /* COLLAPSE */;
                case 'visible':
                default:
                    return 0 /* VISIBLE */;
            }
        }
    };

    var WORD_BREAK;
    (function (WORD_BREAK) {
        WORD_BREAK["NORMAL"] = "normal";
        WORD_BREAK["BREAK_ALL"] = "break-all";
        WORD_BREAK["KEEP_ALL"] = "keep-all";
    })(WORD_BREAK || (WORD_BREAK = {}));
    var wordBreak = {
        name: 'word-break',
        initialValue: 'normal',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, wordBreak) {
            switch (wordBreak) {
                case 'break-all':
                    return WORD_BREAK.BREAK_ALL;
                case 'keep-all':
                    return WORD_BREAK.KEEP_ALL;
                case 'normal':
                default:
                    return WORD_BREAK.NORMAL;
            }
        }
    };

    var zIndex = {
        name: 'z-index',
        initialValue: 'auto',
        prefix: false,
        type: 0 /* VALUE */,
        parse: function (_context, token) {
            if (token.type === 20 /* IDENT_TOKEN */) {
                return { auto: true, order: 0 };
            }
            if (isNumberToken(token)) {
                return { auto: false, order: token.number };
            }
            throw new Error("Invalid z-index number parsed");
        }
    };

    var time = {
        name: 'time',
        parse: function (_context, value) {
            if (value.type === 15 /* DIMENSION_TOKEN */) {
                switch (value.unit.toLowerCase()) {
                    case 's':
                        return 1000 * value.number;
                    case 'ms':
                        return value.number;
                }
            }
            throw new Error("Unsupported time type");
        }
    };

    var opacity = {
        name: 'opacity',
        initialValue: '1',
        type: 0 /* VALUE */,
        prefix: false,
        parse: function (_context, token) {
            if (isNumberToken(token)) {
                return token.number;
            }
            return 1;
        }
    };

    var textDecorationColor = {
        name: "text-decoration-color",
        initialValue: 'transparent',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'color'
    };

    var textDecorationLine = {
        name: 'text-decoration-line',
        initialValue: 'none',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            return tokens
                .filter(isIdentToken)
                .map(function (token) {
                switch (token.value) {
                    case 'underline':
                        return 1 /* UNDERLINE */;
                    case 'overline':
                        return 2 /* OVERLINE */;
                    case 'line-through':
                        return 3 /* LINE_THROUGH */;
                    case 'none':
                        return 4 /* BLINK */;
                }
                return 0 /* NONE */;
            })
                .filter(function (line) { return line !== 0 /* NONE */; });
        }
    };

    var fontFamily = {
        name: "font-family",
        initialValue: '',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            var accumulator = [];
            var results = [];
            tokens.forEach(function (token) {
                switch (token.type) {
                    case 20 /* IDENT_TOKEN */:
                    case 0 /* STRING_TOKEN */:
                        accumulator.push(token.value);
                        break;
                    case 17 /* NUMBER_TOKEN */:
                        accumulator.push(token.number.toString());
                        break;
                    case 4 /* COMMA_TOKEN */:
                        results.push(accumulator.join(' '));
                        accumulator.length = 0;
                        break;
                }
            });
            if (accumulator.length) {
                results.push(accumulator.join(' '));
            }
            return results.map(function (result) { return (result.indexOf(' ') === -1 ? result : "'" + result + "'"); });
        }
    };

    var fontSize = {
        name: "font-size",
        initialValue: '0',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'length'
    };

    var fontWeight = {
        name: 'font-weight',
        initialValue: 'normal',
        type: 0 /* VALUE */,
        prefix: false,
        parse: function (_context, token) {
            if (isNumberToken(token)) {
                return token.number;
            }
            if (isIdentToken(token)) {
                switch (token.value) {
                    case 'bold':
                        return 700;
                    case 'normal':
                    default:
                        return 400;
                }
            }
            return 400;
        }
    };

    var fontVariant = {
        name: 'font-variant',
        initialValue: 'none',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (_context, tokens) {
            return tokens.filter(isIdentToken).map(function (token) { return token.value; });
        }
    };

    var fontStyle = {
        name: 'font-style',
        initialValue: 'normal',
        prefix: false,
        type: 2 /* IDENT_VALUE */,
        parse: function (_context, overflow) {
            switch (overflow) {
                case 'oblique':
                    return "oblique" /* OBLIQUE */;
                case 'italic':
                    return "italic" /* ITALIC */;
                case 'normal':
                default:
                    return "normal" /* NORMAL */;
            }
        }
    };

    var contains = function (bit, value) { return (bit & value) !== 0; };

    var content = {
        name: 'content',
        initialValue: 'none',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (_context, tokens) {
            if (tokens.length === 0) {
                return [];
            }
            var first = tokens[0];
            if (first.type === 20 /* IDENT_TOKEN */ && first.value === 'none') {
                return [];
            }
            return tokens;
        }
    };

    var counterIncrement = {
        name: 'counter-increment',
        initialValue: 'none',
        prefix: true,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            if (tokens.length === 0) {
                return null;
            }
            var first = tokens[0];
            if (first.type === 20 /* IDENT_TOKEN */ && first.value === 'none') {
                return null;
            }
            var increments = [];
            var filtered = tokens.filter(nonWhiteSpace);
            for (var i = 0; i < filtered.length; i++) {
                var counter = filtered[i];
                var next = filtered[i + 1];
                if (counter.type === 20 /* IDENT_TOKEN */) {
                    var increment = next && isNumberToken(next) ? next.number : 1;
                    increments.push({ counter: counter.value, increment: increment });
                }
            }
            return increments;
        }
    };

    var counterReset = {
        name: 'counter-reset',
        initialValue: 'none',
        prefix: true,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            if (tokens.length === 0) {
                return [];
            }
            var resets = [];
            var filtered = tokens.filter(nonWhiteSpace);
            for (var i = 0; i < filtered.length; i++) {
                var counter = filtered[i];
                var next = filtered[i + 1];
                if (isIdentToken(counter) && counter.value !== 'none') {
                    var reset = next && isNumberToken(next) ? next.number : 0;
                    resets.push({ counter: counter.value, reset: reset });
                }
            }
            return resets;
        }
    };

    var duration = {
        name: 'duration',
        initialValue: '0s',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (context, tokens) {
            return tokens.filter(isDimensionToken).map(function (token) { return time.parse(context, token); });
        }
    };

    var quotes = {
        name: 'quotes',
        initialValue: 'none',
        prefix: true,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            if (tokens.length === 0) {
                return null;
            }
            var first = tokens[0];
            if (first.type === 20 /* IDENT_TOKEN */ && first.value === 'none') {
                return null;
            }
            var quotes = [];
            var filtered = tokens.filter(isStringToken);
            if (filtered.length % 2 !== 0) {
                return null;
            }
            for (var i = 0; i < filtered.length; i += 2) {
                var open_1 = filtered[i].value;
                var close_1 = filtered[i + 1].value;
                quotes.push({ open: open_1, close: close_1 });
            }
            return quotes;
        }
    };
    var getQuote = function (quotes, depth, open) {
        if (!quotes) {
            return '';
        }
        var quote = quotes[Math.min(depth, quotes.length - 1)];
        if (!quote) {
            return '';
        }
        return open ? quote.open : quote.close;
    };

    var boxShadow = {
        name: 'box-shadow',
        initialValue: 'none',
        type: 1 /* LIST */,
        prefix: false,
        parse: function (context, tokens) {
            if (tokens.length === 1 && isIdentWithValue(tokens[0], 'none')) {
                return [];
            }
            return parseFunctionArgs(tokens).map(function (values) {
                var shadow = {
                    color: 0x000000ff,
                    offsetX: ZERO_LENGTH,
                    offsetY: ZERO_LENGTH,
                    blur: ZERO_LENGTH,
                    spread: ZERO_LENGTH,
                    inset: false
                };
                var c = 0;
                for (var i = 0; i < values.length; i++) {
                    var token = values[i];
                    if (isIdentWithValue(token, 'inset')) {
                        shadow.inset = true;
                    }
                    else if (isLength(token)) {
                        if (c === 0) {
                            shadow.offsetX = token;
                        }
                        else if (c === 1) {
                            shadow.offsetY = token;
                        }
                        else if (c === 2) {
                            shadow.blur = token;
                        }
                        else {
                            shadow.spread = token;
                        }
                        c++;
                    }
                    else {
                        shadow.color = color$1.parse(context, token);
                    }
                }
                return shadow;
            });
        }
    };

    var paintOrder = {
        name: 'paint-order',
        initialValue: 'normal',
        prefix: false,
        type: 1 /* LIST */,
        parse: function (_context, tokens) {
            var DEFAULT_VALUE = [0 /* FILL */, 1 /* STROKE */, 2 /* MARKERS */];
            var layers = [];
            tokens.filter(isIdentToken).forEach(function (token) {
                switch (token.value) {
                    case 'stroke':
                        layers.push(1 /* STROKE */);
                        break;
                    case 'fill':
                        layers.push(0 /* FILL */);
                        break;
                    case 'markers':
                        layers.push(2 /* MARKERS */);
                        break;
                }
            });
            DEFAULT_VALUE.forEach(function (value) {
                if (layers.indexOf(value) === -1) {
                    layers.push(value);
                }
            });
            return layers;
        }
    };

    var webkitTextStrokeColor = {
        name: "-webkit-text-stroke-color",
        initialValue: 'currentcolor',
        prefix: false,
        type: 3 /* TYPE_VALUE */,
        format: 'color'
    };

    var webkitTextStrokeWidth = {
        name: "-webkit-text-stroke-width",
        initialValue: '0',
        type: 0 /* VALUE */,
        prefix: false,
        parse: function (_context, token) {
            if (isDimensionToken(token)) {
                return token.number;
            }
            return 0;
        }
    };

    var CSSParsedDeclaration = /** @class */ (function () {
        function CSSParsedDeclaration(context, declaration) {
            var _a, _b;
            this.animationDuration = parse(context, duration, declaration.animationDuration);
            this.backgroundClip = parse(context, backgroundClip, declaration.backgroundClip);
            this.backgroundColor = parse(context, backgroundColor, declaration.backgroundColor);
            this.backgroundImage = parse(context, backgroundImage, declaration.backgroundImage);
            this.backgroundOrigin = parse(context, backgroundOrigin, declaration.backgroundOrigin);
            this.backgroundPosition = parse(context, backgroundPosition, declaration.backgroundPosition);
            this.backgroundRepeat = parse(context, backgroundRepeat, declaration.backgroundRepeat);
            this.backgroundSize = parse(context, backgroundSize, declaration.backgroundSize);
            this.borderTopColor = parse(context, borderTopColor, declaration.borderTopColor);
            this.borderRightColor = parse(context, borderRightColor, declaration.borderRightColor);
            this.borderBottomColor = parse(context, borderBottomColor, declaration.borderBottomColor);
            this.borderLeftColor = parse(context, borderLeftColor, declaration.borderLeftColor);
            this.borderTopLeftRadius = parse(context, borderTopLeftRadius, declaration.borderTopLeftRadius);
            this.borderTopRightRadius = parse(context, borderTopRightRadius, declaration.borderTopRightRadius);
            this.borderBottomRightRadius = parse(context, borderBottomRightRadius, declaration.borderBottomRightRadius);
            this.borderBottomLeftRadius = parse(context, borderBottomLeftRadius, declaration.borderBottomLeftRadius);
            this.borderTopStyle = parse(context, borderTopStyle, declaration.borderTopStyle);
            this.borderRightStyle = parse(context, borderRightStyle, declaration.borderRightStyle);
            this.borderBottomStyle = parse(context, borderBottomStyle, declaration.borderBottomStyle);
            this.borderLeftStyle = parse(context, borderLeftStyle, declaration.borderLeftStyle);
            this.borderTopWidth = parse(context, borderTopWidth, declaration.borderTopWidth);
            this.borderRightWidth = parse(context, borderRightWidth, declaration.borderRightWidth);
            this.borderBottomWidth = parse(context, borderBottomWidth, declaration.borderBottomWidth);
            this.borderLeftWidth = parse(context, borderLeftWidth, declaration.borderLeftWidth);
            this.boxShadow = parse(context, boxShadow, declaration.boxShadow);
            this.color = parse(context, color, declaration.color);
            this.direction = parse(context, direction, declaration.direction);
            this.display = parse(context, display, declaration.display);
            this.float = parse(context, float, declaration.cssFloat);
            this.fontFamily = parse(context, fontFamily, declaration.fontFamily);
            this.fontSize = parse(context, fontSize, declaration.fontSize);
            this.fontStyle = parse(context, fontStyle, declaration.fontStyle);
            this.fontVariant = parse(context, fontVariant, declaration.fontVariant);
            this.fontWeight = parse(context, fontWeight, declaration.fontWeight);
            this.letterSpacing = parse(context, letterSpacing, declaration.letterSpacing);
            this.lineBreak = parse(context, lineBreak, declaration.lineBreak);
            this.lineHeight = parse(context, lineHeight, declaration.lineHeight);
            this.listStyleImage = parse(context, listStyleImage, declaration.listStyleImage);
            this.listStylePosition = parse(context, listStylePosition, declaration.listStylePosition);
            this.listStyleType = parse(context, listStyleType, declaration.listStyleType);
            this.marginTop = parse(context, marginTop, declaration.marginTop);
            this.marginRight = parse(context, marginRight, declaration.marginRight);
            this.marginBottom = parse(context, marginBottom, declaration.marginBottom);
            this.marginLeft = parse(context, marginLeft, declaration.marginLeft);
            this.opacity = parse(context, opacity, declaration.opacity);
            var overflowTuple = parse(context, overflow, declaration.overflow);
            this.overflowX = overflowTuple[0];
            this.overflowY = overflowTuple[overflowTuple.length > 1 ? 1 : 0];
            this.overflowWrap = parse(context, overflowWrap, declaration.overflowWrap);
            this.paddingTop = parse(context, paddingTop, declaration.paddingTop);
            this.paddingRight = parse(context, paddingRight, declaration.paddingRight);
            this.paddingBottom = parse(context, paddingBottom, declaration.paddingBottom);
            this.paddingLeft = parse(context, paddingLeft, declaration.paddingLeft);
            this.paintOrder = parse(context, paintOrder, declaration.paintOrder);
            this.position = parse(context, position, declaration.position);
            this.textAlign = parse(context, textAlign, declaration.textAlign);
            this.textDecorationColor = parse(context, textDecorationColor, (_a = declaration.textDecorationColor) !== null && _a !== void 0 ? _a : declaration.color);
            this.textDecorationLine = parse(context, textDecorationLine, (_b = declaration.textDecorationLine) !== null && _b !== void 0 ? _b : declaration.textDecoration);
            this.textShadow = parse(context, textShadow, declaration.textShadow);
            this.textTransform = parse(context, textTransform, declaration.textTransform);
            this.transform = parse(context, transform$1, declaration.transform);
            this.transformOrigin = parse(context, transformOrigin, declaration.transformOrigin);
            this.visibility = parse(context, visibility, declaration.visibility);
            this.webkitTextStrokeColor = parse(context, webkitTextStrokeColor, declaration.webkitTextStrokeColor);
            this.webkitTextStrokeWidth = parse(context, webkitTextStrokeWidth, declaration.webkitTextStrokeWidth);
            this.wordBreak = parse(context, wordBreak, declaration.wordBreak);
            this.zIndex = parse(context, zIndex, declaration.zIndex);
        }
        CSSParsedDeclaration.prototype.isVisible = function () {
            return this.display > 0 && this.opacity > 0 && this.visibility === 0 /* VISIBLE */;
        };
        CSSParsedDeclaration.prototype.isTransparent = function () {
            return isTransparent(this.backgroundColor);
        };
        CSSParsedDeclaration.prototype.isTransformed = function () {
            return this.transform !== null;
        };
        CSSParsedDeclaration.prototype.isPositioned = function () {
            return this.position !== 0 /* STATIC */;
        };
        CSSParsedDeclaration.prototype.isPositionedWithZIndex = function () {
            return this.isPositioned() && !this.zIndex.auto;
        };
        CSSParsedDeclaration.prototype.isFloating = function () {
            return this.float !== 0 /* NONE */;
        };
        CSSParsedDeclaration.prototype.isInlineLevel = function () {
            return (contains(this.display, 4 /* INLINE */) ||
                contains(this.display, 33554432 /* INLINE_BLOCK */) ||
                contains(this.display, 268435456 /* INLINE_FLEX */) ||
                contains(this.display, 536870912 /* INLINE_GRID */) ||
                contains(this.display, 67108864 /* INLINE_LIST_ITEM */) ||
                contains(this.display, 134217728 /* INLINE_TABLE */));
        };
        return CSSParsedDeclaration;
    }());
    var CSSParsedPseudoDeclaration = /** @class */ (function () {
        function CSSParsedPseudoDeclaration(context, declaration) {
            this.content = parse(context, content, declaration.content);
            this.quotes = parse(context, quotes, declaration.quotes);
        }
        return CSSParsedPseudoDeclaration;
    }());
    var CSSParsedCounterDeclaration = /** @class */ (function () {
        function CSSParsedCounterDeclaration(context, declaration) {
            this.counterIncrement = parse(context, counterIncrement, declaration.counterIncrement);
            this.counterReset = parse(context, counterReset, declaration.counterReset);
        }
        return CSSParsedCounterDeclaration;
    }());
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    var parse = function (context, descriptor, style) {
        var tokenizer = new Tokenizer();
        var value = style !== null && typeof style !== 'undefined' ? style.toString() : descriptor.initialValue;
        tokenizer.write(value);
        var parser = new Parser(tokenizer.read());
        switch (descriptor.type) {
            case 2 /* IDENT_VALUE */:
                var token = parser.parseComponentValue();
                return descriptor.parse(context, isIdentToken(token) ? token.value : descriptor.initialValue);
            case 0 /* VALUE */:
                return descriptor.parse(context, parser.parseComponentValue());
            case 1 /* LIST */:
                return descriptor.parse(context, parser.parseComponentValues());
            case 4 /* TOKEN_VALUE */:
                return parser.parseComponentValue();
            case 3 /* TYPE_VALUE */:
                switch (descriptor.format) {
                    case 'angle':
                        return angle.parse(context, parser.parseComponentValue());
                    case 'color':
                        return color$1.parse(context, parser.parseComponentValue());
                    case 'image':
                        return image.parse(context, parser.parseComponentValue());
                    case 'length':
                        var length_1 = parser.parseComponentValue();
                        return isLength(length_1) ? length_1 : ZERO_LENGTH;
                    case 'length-percentage':
                        var value_1 = parser.parseComponentValue();
                        return isLengthPercentage(value_1) ? value_1 : ZERO_LENGTH;
                    case 'time':
                        return time.parse(context, parser.parseComponentValue());
                }
                break;
        }
    };

    var elementDebuggerAttribute = 'data-html2canvas-debug';
    var getElementDebugType = function (element) {
        var attribute = element.getAttribute(elementDebuggerAttribute);
        switch (attribute) {
            case 'all':
                return 1 /* ALL */;
            case 'clone':
                return 2 /* CLONE */;
            case 'parse':
                return 3 /* PARSE */;
            case 'render':
                return 4 /* RENDER */;
            default:
                return 0 /* NONE */;
        }
    };
    var isDebugging = function (element, type) {
        var elementType = getElementDebugType(element);
        return elementType === 1 /* ALL */ || type === elementType;
    };

    var ElementContainer = /** @class */ (function () {
        function ElementContainer(context, element) {
            this.context = context;
            this.textNodes = [];
            this.elements = [];
            this.flags = 0;
            if (isDebugging(element, 3 /* PARSE */)) {
                debugger;
            }
            this.styles = new CSSParsedDeclaration(context, window.getComputedStyle(element, null));
            if (isHTMLElementNode(element)) {
                if (this.styles.animationDuration.some(function (duration) { return duration > 0; })) {
                    element.style.animationDuration = '0s';
                }
                if (this.styles.transform !== null) {
                    // getBoundingClientRect takes transforms into account
                    element.style.transform = 'none';
                }
            }
            this.bounds = parseBounds(this.context, element);
            if (isDebugging(element, 4 /* RENDER */)) {
                this.flags |= 16 /* DEBUG_RENDER */;
            }
        }
        return ElementContainer;
    }());

    /*
     * text-segmentation 1.0.3 <https://github.com/niklasvh/text-segmentation>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var base64 = ' ';

    /*
     * utrie 1.0.2 <https://github.com/niklasvh/utrie>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // Use a lookup table to find the index.
    var lookup$1 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
    for (var i$1 = 0; i$1 < chars$1.length; i$1++) {
        lookup$1[chars$1.charCodeAt(i$1)] = i$1;
    }
    var decode = function (base64) {
        var bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;
        if (base64[base64.length - 1] === '=') {
            bufferLength--;
            if (base64[base64.length - 2] === '=') {
                bufferLength--;
            }
        }
        var buffer = typeof ArrayBuffer !== 'undefined' &&
            typeof Uint8Array !== 'undefined' &&
            typeof Uint8Array.prototype.slice !== 'undefined'
            ? new ArrayBuffer(bufferLength)
            : new Array(bufferLength);
        var bytes = Array.isArray(buffer) ? buffer : new Uint8Array(buffer);
        for (i = 0; i < len; i += 4) {
            encoded1 = lookup$1[base64.charCodeAt(i)];
            encoded2 = lookup$1[base64.charCodeAt(i + 1)];
            encoded3 = lookup$1[base64.charCodeAt(i + 2)];
            encoded4 = lookup$1[base64.charCodeAt(i + 3)];
            bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
            bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
            bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
        }
        return buffer;
    };
    var polyUint16Array = function (buffer) {
        var length = buffer.length;
        var bytes = [];
        for (var i = 0; i < length; i += 2) {
            bytes.push((buffer[i + 1] << 8) | buffer[i]);
        }
        return bytes;
    };
    var polyUint32Array = function (buffer) {
        var length = buffer.length;
        var bytes = [];
        for (var i = 0; i < length; i += 4) {
            bytes.push((buffer[i + 3] << 24) | (buffer[i + 2] << 16) | (buffer[i + 1] << 8) | buffer[i]);
        }
        return bytes;
    };

    /** Shift size for getting the index-2 table offset. */
    var UTRIE2_SHIFT_2 = 5;
    /** Shift size for getting the index-1 table offset. */
    var UTRIE2_SHIFT_1 = 6 + 5;
    /**
     * Shift size for shifting left the index array values.
     * Increases possible data size with 16-bit index values at the cost
     * of compactability.
     * This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY.
     */
    var UTRIE2_INDEX_SHIFT = 2;
    /**
     * Difference between the two shift sizes,
     * for getting an index-1 offset from an index-2 offset. 6=11-5
     */
    var UTRIE2_SHIFT_1_2 = UTRIE2_SHIFT_1 - UTRIE2_SHIFT_2;
    /**
     * The part of the index-2 table for U+D800..U+DBFF stores values for
     * lead surrogate code _units_ not code _points_.
     * Values for lead surrogate code _points_ are indexed with this portion of the table.
     * Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.)
     */
    var UTRIE2_LSCP_INDEX_2_OFFSET = 0x10000 >> UTRIE2_SHIFT_2;
    /** Number of entries in a data block. 32=0x20 */
    var UTRIE2_DATA_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_2;
    /** Mask for getting the lower bits for the in-data-block offset. */
    var UTRIE2_DATA_MASK = UTRIE2_DATA_BLOCK_LENGTH - 1;
    var UTRIE2_LSCP_INDEX_2_LENGTH = 0x400 >> UTRIE2_SHIFT_2;
    /** Count the lengths of both BMP pieces. 2080=0x820 */
    var UTRIE2_INDEX_2_BMP_LENGTH = UTRIE2_LSCP_INDEX_2_OFFSET + UTRIE2_LSCP_INDEX_2_LENGTH;
    /**
     * The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.
     * Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2.
     */
    var UTRIE2_UTF8_2B_INDEX_2_OFFSET = UTRIE2_INDEX_2_BMP_LENGTH;
    var UTRIE2_UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; /* U+0800 is the first code point after 2-byte UTF-8 */
    /**
     * The index-1 table, only used for supplementary code points, at offset 2112=0x840.
     * Variable length, for code points up to highStart, where the last single-value range starts.
     * Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1.
     * (For 0x100000 supplementary code points U+10000..U+10ffff.)
     *
     * The part of the index-2 table for supplementary code points starts
     * after this index-1 table.
     *
     * Both the index-1 table and the following part of the index-2 table
     * are omitted completely if there is only BMP data.
     */
    var UTRIE2_INDEX_1_OFFSET = UTRIE2_UTF8_2B_INDEX_2_OFFSET + UTRIE2_UTF8_2B_INDEX_2_LENGTH;
    /**
     * Number of index-1 entries for the BMP. 32=0x20
     * This part of the index-1 table is omitted from the serialized form.
     */
    var UTRIE2_OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> UTRIE2_SHIFT_1;
    /** Number of entries in an index-2 block. 64=0x40 */
    var UTRIE2_INDEX_2_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_1_2;
    /** Mask for getting the lower bits for the in-index-2-block offset. */
    var UTRIE2_INDEX_2_MASK = UTRIE2_INDEX_2_BLOCK_LENGTH - 1;
    var slice16 = function (view, start, end) {
        if (view.slice) {
            return view.slice(start, end);
        }
        return new Uint16Array(Array.prototype.slice.call(view, start, end));
    };
    var slice32 = function (view, start, end) {
        if (view.slice) {
            return view.slice(start, end);
        }
        return new Uint32Array(Array.prototype.slice.call(view, start, end));
    };
    var createTrieFromBase64 = function (base64, _byteLength) {
        var buffer = decode(base64);
        var view32 = Array.isArray(buffer) ? polyUint32Array(buffer) : new Uint32Array(buffer);
        var view16 = Array.isArray(buffer) ? polyUint16Array(buffer) : new Uint16Array(buffer);
        var headerLength = 24;
        var index = slice16(view16, headerLength / 2, view32[4] / 2);
        var data = view32[5] === 2
            ? slice16(view16, (headerLength + view32[4]) / 2)
            : slice32(view32, Math.ceil((headerLength + view32[4]) / 4));
        return new Trie(view32[0], view32[1], view32[2], view32[3], index, data);
    };
    var Trie = /** @class */ (function () {
        function Trie(initialValue, errorValue, highStart, highValueIndex, index, data) {
            this.initialValue = initialValue;
            this.errorValue = errorValue;
            this.highStart = highStart;
            this.highValueIndex = highValueIndex;
            this.index = index;
            this.data = data;
        }
        /**
         * Get the value for a code point as stored in the Trie.
         *
         * @param codePoint the code point
         * @return the value
         */
        Trie.prototype.get = function (codePoint) {
            var ix;
            if (codePoint >= 0) {
                if (codePoint < 0x0d800 || (codePoint > 0x0dbff && codePoint <= 0x0ffff)) {
                    // Ordinary BMP code point, excluding leading surrogates.
                    // BMP uses a single level lookup.  BMP index starts at offset 0 in the Trie2 index.
                    // 16 bit data is stored in the index array itself.
                    ix = this.index[codePoint >> UTRIE2_SHIFT_2];
                    ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);
                    return this.data[ix];
                }
                if (codePoint <= 0xffff) {
                    // Lead Surrogate Code Point.  A Separate index section is stored for
                    // lead surrogate code units and code points.
                    //   The main index has the code unit data.
                    //   For this function, we need the code point data.
                    // Note: this expression could be refactored for slightly improved efficiency, but
                    //       surrogate code points will be so rare in practice that it's not worth it.
                    ix = this.index[UTRIE2_LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> UTRIE2_SHIFT_2)];
                    ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);
                    return this.data[ix];
                }
                if (codePoint < this.highStart) {
                    // Supplemental code point, use two-level lookup.
                    ix = UTRIE2_INDEX_1_OFFSET - UTRIE2_OMITTED_BMP_INDEX_1_LENGTH + (codePoint >> UTRIE2_SHIFT_1);
                    ix = this.index[ix];
                    ix += (codePoint >> UTRIE2_SHIFT_2) & UTRIE2_INDEX_2_MASK;
                    ix = this.index[ix];
                    ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);
                    return this.data[ix];
                }
                if (codePoint <= 0x10ffff) {
                    return this.data[this.highValueIndex];
                }
            }
            // Fall through.  The code point is outside of the legal range of 0..0x10ffff.
            return this.errorValue;
        };
        return Trie;
    }());

    /*
     * base64-arraybuffer 1.0.2 <https://github.com/niklasvh/base64-arraybuffer>
     * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
     * Released under MIT License
     */
    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // Use a lookup table to find the index.
    var lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
    for (var i = 0; i < chars.length; i++) {
        lookup[chars.charCodeAt(i)] = i;
    }

    var Prepend = 1;
    var CR = 2;
    var LF = 3;
    var Control = 4;
    var Extend = 5;
    var SpacingMark = 7;
    var L = 8;
    var V = 9;
    var T = 10;
    var LV = 11;
    var LVT = 12;
    var ZWJ = 13;
    var Extended_Pictographic = 14;
    var RI = 15;
    var toCodePoints = function (str) {
        var codePoints = [];
        var i = 0;
        var length = str.length;
        while (i < length) {
            var value = str.charCodeAt(i++);
            if (value >= 0xd800 && value <= 0xdbff && i < length) {
                var extra = str.charCodeAt(i++);
                if ((extra & 0xfc00) === 0xdc00) {
                    codePoints.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
                }
                else {
                    codePoints.push(value);
                    i--;
                }
            }
            else {
                codePoints.push(value);
            }
        }
        return codePoints;
    };
    var fromCodePoint = function () {
        var codePoints = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            codePoints[_i] = arguments[_i];
        }
        if (String.fromCodePoint) {
            return String.fromCodePoint.apply(String, codePoints);
        }
        var length = codePoints.length;
        if (!length) {
            return '';
        }
        var codeUnits = [];
        var index = -1;
        var result = '';
        while (++index < length) {
            var codePoint = codePoints[index];
            if (codePoint <= 0xffff) {
                codeUnits.push(codePoint);
            }
            else {
                codePoint -= 0x10000;
                codeUnits.push((codePoint >> 10) + 0xd800, (codePoint % 0x400) + 0xdc00);
            }
            if (index + 1 === length || codeUnits.length > 0x4000) {
                result += String.fromCharCode.apply(String, codeUnits);
                codeUnits.length = 0;
            }
        }
        return result;
    };
    var UnicodeTrie = createTrieFromBase64(base64);
    var BREAK_NOT_ALLOWED = '×';
    var BREAK_ALLOWED = '÷';
    var codePointToClass = function (codePoint) { return UnicodeTrie.get(codePoint); };
    var _graphemeBreakAtIndex = function (_codePoints, classTypes, index) {
        var prevIndex = index - 2;
        var prev = classTypes[prevIndex];
        var current = classTypes[index - 1];
        var next = classTypes[index];
        // GB3 Do not break between a CR and LF
        if (current === CR && next === LF) {
            return BREAK_NOT_ALLOWED;
        }
        // GB4 Otherwise, break before and after controls.
        if (current === CR || current === LF || current === Control) {
            return BREAK_ALLOWED;
        }
        // GB5
        if (next === CR || next === LF || next === Control) {
            return BREAK_ALLOWED;
        }
        // Do not break Hangul syllable sequences.
        // GB6
        if (current === L && [L, V, LV, LVT].indexOf(next) !== -1) {
            return BREAK_NOT_ALLOWED;
        }
        // GB7
        if ((current === LV || current === V) && (next === V || next === T)) {
            return BREAK_NOT_ALLOWED;
        }
        // GB8
        if ((current === LVT || current === T) && next === T) {
            return BREAK_NOT_ALLOWED;
        }
        // GB9 Do not break before extending characters or ZWJ.
        if (next === ZWJ || next === Extend) {
            return BREAK_NOT_ALLOWED;
        }
        // Do not break before SpacingMarks, or after Prepend characters.
        // GB9a
        if (next === SpacingMark) {
            return BREAK_NOT_ALLOWED;
        }
        // GB9a
        if (current === Prepend) {
            return BREAK_NOT_ALLOWED;
        }
        // GB11 Do not break within emoji modifier sequences or emoji zwj sequences.
        if (current === ZWJ && next === Extended_Pictographic) {
            while (prev === Extend) {
                prev = classTypes[--prevIndex];
            }
            if (prev === Extended_Pictographic) {
                return BREAK_NOT_ALLOWED;
            }
        }
        // GB12 Do not break within emoji flag sequences.
        // That is, do not break between regional indicator (RI) symbols
        // if there is an odd number of RI characters before the break point.
        if (current === RI && next === RI) {
            var countRI = 0;
            while (prev === RI) {
                countRI++;
                prev = classTypes[--prevIndex];
            }
            if (countRI % 2 === 0) {
                return BREAK_NOT_ALLOWED;
            }
        }
        return BREAK_ALLOWED;
    };
    var GraphemeBreaker = function (str) {
        var codePoints = toCodePoints(str);
        var length = codePoints.length;
        var index = 0;
        var lastEnd = 0;
        var classTypes = codePoints.map(codePointToClass);
        return {
            next: function () {
                if (index >= length) {
                    return { done: true, value: null };
                }
                var graphemeBreak = BREAK_NOT_ALLOWED;
                while (index < length &&
                    (graphemeBreak = _graphemeBreakAtIndex(codePoints, classTypes, ++index)) === BREAK_NOT_ALLOWED) { }
                if (graphemeBreak !== BREAK_NOT_ALLOWED || index === length) {
                    var value = fromCodePoint.apply(null, codePoints.slice(lastEnd, index));
                    lastEnd = index;
                    return { value: value, done: false };
                }
                return { done: true, value: null };
            },
        };
    };
    var splitGraphemes = function (str) {
        var breaker = GraphemeBreaker(str);
        var graphemes = [];
        var bk;
        while (!(bk = breaker.next()).done) {
            if (bk.value) {
                graphemes.push(bk.value.slice());
            }
        }
        return graphemes;
    };

    var testRangeBounds = function (document) {
        var TEST_HEIGHT = 123;
        if (document.createRange) {
            var range = document.createRange();
            if (range.getBoundingClientRect) {
                var testElement = document.createElement('boundtest');
                testElement.style.height = TEST_HEIGHT + "px";
                testElement.style.display = 'block';
                document.body.appendChild(testElement);
                range.selectNode(testElement);
                var rangeBounds = range.getBoundingClientRect();
                var rangeHeight = Math.round(rangeBounds.height);
                document.body.removeChild(testElement);
                if (rangeHeight === TEST_HEIGHT) {
                    return true;
                }
            }
        }
        return false;
    };
    var testIOSLineBreak = function (document) {
        var testElement = document.createElement('boundtest');
        testElement.style.width = '50px';
        testElement.style.display = 'block';
        testElement.style.fontSize = '12px';
        testElement.style.letterSpacing = '0px';
        testElement.style.wordSpacing = '0px';
        document.body.appendChild(testElement);
        var range = document.createRange();
        testElement.innerHTML = typeof ''.repeat === 'function' ? '&#128104;'.repeat(10) : '';
        var node = testElement.firstChild;
        var textList = toCodePoints$1(node.data).map(function (i) { return fromCodePoint$1(i); });
        var offset = 0;
        var prev = {};
        // ios 13 does not handle range getBoundingClientRect line changes correctly #2177
        var supports = textList.every(function (text, i) {
            range.setStart(node, offset);
            range.setEnd(node, offset + text.length);
            var rect = range.getBoundingClientRect();
            offset += text.length;
            var boundAhead = rect.x > prev.x || rect.y > prev.y;
            prev = rect;
            if (i === 0) {
                return true;
            }
            return boundAhead;
        });
        document.body.removeChild(testElement);
        return supports;
    };
    var testCORS = function () { return typeof new Image().crossOrigin !== 'undefined'; };
    var testResponseType = function () { return typeof new XMLHttpRequest().responseType === 'string'; };
    var testSVG = function (document) {
        var img = new Image();
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        if (!ctx) {
            return false;
        }
        img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";
        try {
            ctx.drawImage(img, 0, 0);
            canvas.toDataURL();
        }
        catch (e) {
            return false;
        }
        return true;
    };
    var isGreenPixel = function (data) {
        return data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;
    };
    var testForeignObject = function (document) {
        var canvas = document.createElement('canvas');
        var size = 100;
        canvas.width = size;
        canvas.height = size;
        var ctx = canvas.getContext('2d');
        if (!ctx) {
            return Promise.reject(false);
        }
        ctx.fillStyle = 'rgb(0, 255, 0)';
        ctx.fillRect(0, 0, size, size);
        var img = new Image();
        var greenImageSrc = canvas.toDataURL();
        img.src = greenImageSrc;
        var svg = createForeignObjectSVG(size, size, 0, 0, img);
        ctx.fillStyle = 'red';
        ctx.fillRect(0, 0, size, size);
        return loadSerializedSVG$1(svg)
            .then(function (img) {
            ctx.drawImage(img, 0, 0);
            var data = ctx.getImageData(0, 0, size, size).data;
            ctx.fillStyle = 'red';
            ctx.fillRect(0, 0, size, size);
            var node = document.createElement('div');
            node.style.backgroundImage = "url(" + greenImageSrc + ")";
            node.style.height = size + "px";
            // Firefox 55 does not render inline <img /> tags
            return isGreenPixel(data)
                ? loadSerializedSVG$1(createForeignObjectSVG(size, size, 0, 0, node))
                : Promise.reject(false);
        })
            .then(function (img) {
            ctx.drawImage(img, 0, 0);
            // Edge does not render background-images
            return isGreenPixel(ctx.getImageData(0, 0, size, size).data);
        })
            .catch(function () { return false; });
    };
    var createForeignObjectSVG = function (width, height, x, y, node) {
        var xmlns = 'http://www.w3.org/2000/svg';
        var svg = document.createElementNS(xmlns, 'svg');
        var foreignObject = document.createElementNS(xmlns, 'foreignObject');
        svg.setAttributeNS(null, 'width', width.toString());
        svg.setAttributeNS(null, 'height', height.toString());
        foreignObject.setAttributeNS(null, 'width', '100%');
        foreignObject.setAttributeNS(null, 'height', '100%');
        foreignObject.setAttributeNS(null, 'x', x.toString());
        foreignObject.setAttributeNS(null, 'y', y.toString());
        foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
        svg.appendChild(foreignObject);
        foreignObject.appendChild(node);
        return svg;
    };
    var loadSerializedSVG$1 = function (svg) {
        return new Promise(function (resolve, reject) {
            var img = new Image();
            img.onload = function () { return resolve(img); };
            img.onerror = reject;
            img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(new XMLSerializer().serializeToString(svg));
        });
    };
    var FEATURES = {
        get SUPPORT_RANGE_BOUNDS() {
            var value = testRangeBounds(document);
            Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', { value: value });
            return value;
        },
        get SUPPORT_WORD_BREAKING() {
            var value = FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);
            Object.defineProperty(FEATURES, 'SUPPORT_WORD_BREAKING', { value: value });
            return value;
        },
        get SUPPORT_SVG_DRAWING() {
            var value = testSVG(document);
            Object.defineProperty(FEATURES, 'SUPPORT_SVG_DRAWING', { value: value });
            return value;
        },
        get SUPPORT_FOREIGNOBJECT_DRAWING() {
            var value = typeof Array.from === 'function' && typeof window.fetch === 'function'
                ? testForeignObject(document)
                : Promise.resolve(false);
            Object.defineProperty(FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', { value: value });
            return value;
        },
        get SUPPORT_CORS_IMAGES() {
            var value = testCORS();
            Object.defineProperty(FEATURES, 'SUPPORT_CORS_IMAGES', { value: value });
            return value;
        },
        get SUPPORT_RESPONSE_TYPE() {
            var value = testResponseType();
            Object.defineProperty(FEATURES, 'SUPPORT_RESPONSE_TYPE', { value: value });
            return value;
        },
        get SUPPORT_CORS_XHR() {
            var value = 'withCredentials' in new XMLHttpRequest();
            Object.defineProperty(FEATURES, 'SUPPORT_CORS_XHR', { value: value });
            return value;
        },
        get SUPPORT_NATIVE_TEXT_SEGMENTATION() {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            var value = !!(typeof Intl !== 'undefined' && Intl.Segmenter);
            Object.defineProperty(FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', { value: value });
            return value;
        }
    };

    var TextBounds = /** @class */ (function () {
        function TextBounds(text, bounds) {
            this.text = text;
            this.bounds = bounds;
        }
        return TextBounds;
    }());
    var parseTextBounds = function (context, value, styles, node) {
        var textList = breakText(value, styles);
        var textBounds = [];
        var offset = 0;
        textList.forEach(function (text) {
            if (styles.textDecorationLine.length || text.trim().length > 0) {
                if (FEATURES.SUPPORT_RANGE_BOUNDS) {
                    var clientRects = createRange(node, offset, text.length).getClientRects();
                    if (clientRects.length > 1) {
                        var subSegments = segmentGraphemes(text);
                        var subOffset_1 = 0;
                        subSegments.forEach(function (subSegment) {
                            textBounds.push(new TextBounds(subSegment, Bounds.fromDOMRectList(context, createRange(node, subOffset_1 + offset, subSegment.length).getClientRects())));
                            subOffset_1 += subSegment.length;
                        });
                    }
                    else {
                        textBounds.push(new TextBounds(text, Bounds.fromDOMRectList(context, clientRects)));
                    }
                }
                else {
                    var replacementNode = node.splitText(text.length);
                    textBounds.push(new TextBounds(text, getWrapperBounds(context, node)));
                    node = replacementNode;
                }
            }
            else if (!FEATURES.SUPPORT_RANGE_BOUNDS) {
                node = node.splitText(text.length);
            }
            offset += text.length;
        });
        return textBounds;
    };
    var getWrapperBounds = function (context, node) {
        var ownerDocument = node.ownerDocument;
        if (ownerDocument) {
            var wrapper = ownerDocument.createElement('html2canvaswrapper');
            wrapper.appendChild(node.cloneNode(true));
            var parentNode = node.parentNode;
            if (parentNode) {
                parentNode.replaceChild(wrapper, node);
                var bounds = parseBounds(context, wrapper);
                if (wrapper.firstChild) {
                    parentNode.replaceChild(wrapper.firstChild, wrapper);
                }
                return bounds;
            }
        }
        return Bounds.EMPTY;
    };
    var createRange = function (node, offset, length) {
        var ownerDocument = node.ownerDocument;
        if (!ownerDocument) {
            throw new Error('Node has no owner document');
        }
        var range = ownerDocument.createRange();
        range.setStart(node, offset);
        range.setEnd(node, offset + length);
        return range;
    };
    var segmentGraphemes = function (value) {
        if (FEATURES.SUPPORT_NATIVE_TEXT_SEGMENTATION) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            var segmenter = new Intl.Segmenter(void 0, { granularity: 'grapheme' });
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            return Array.from(segmenter.segment(value)).map(function (segment) { return segment.segment; });
        }
        return splitGraphemes(value);
    };
    var segmentWords = function (value, styles) {
        if (FEATURES.SUPPORT_NATIVE_TEXT_SEGMENTATION) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            var segmenter = new Intl.Segmenter(void 0, {
                granularity: 'word'
            });
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            return Array.from(segmenter.segment(value)).map(function (segment) { return segment.segment; });
        }
        return breakWords(value, styles);
    };
    var breakText = function (value, styles) {
        return styles.letterSpacing !== 0 ? segmentGraphemes(value) : segmentWords(value, styles);
    };
    // https://drafts.csswg.org/css-text/#word-separator
    var wordSeparators = [0x0020, 0x00a0, 0x1361, 0x10100, 0x10101, 0x1039, 0x1091];
    var breakWords = function (str, styles) {
        var breaker = LineBreaker(str, {
            lineBreak: styles.lineBreak,
            wordBreak: styles.overflowWrap === "break-word" /* BREAK_WORD */ ? 'break-word' : styles.wordBreak
        });
        var words = [];
        var bk;
        var _loop_1 = function () {
            if (bk.value) {
                var value = bk.value.slice();
                var codePoints = toCodePoints$1(value);
                var word_1 = '';
                codePoints.forEach(function (codePoint) {
                    if (wordSeparators.indexOf(codePoint) === -1) {
                        word_1 += fromCodePoint$1(codePoint);
                    }
                    else {
                        if (word_1.length) {
                            words.push(word_1);
                        }
                        words.push(fromCodePoint$1(codePoint));
                        word_1 = '';
                    }
                });
                if (word_1.length) {
                    words.push(word_1);
                }
            }
        };
        while (!(bk = breaker.next()).done) {
            _loop_1();
        }
        return words;
    };

    var TextContainer = /** @class */ (function () {
        function TextContainer(context, node, styles) {
            this.text = transform(node.data, styles.textTransform);
            this.textBounds = parseTextBounds(context, this.text, styles, node);
        }
        return TextContainer;
    }());
    var transform = function (text, transform) {
        switch (transform) {
            case 1 /* LOWERCASE */:
                return text.toLowerCase();
            case 3 /* CAPITALIZE */:
                return text.replace(CAPITALIZE, capitalize);
            case 2 /* UPPERCASE */:
                return text.toUpperCase();
            default:
                return text;
        }
    };
    var CAPITALIZE = /(^|\s|:|-|\(|\))([a-z])/g;
    var capitalize = function (m, p1, p2) {
        if (m.length > 0) {
            return p1 + p2.toUpperCase();
        }
        return m;
    };

    var ImageElementContainer = /** @class */ (function (_super) {
        __extends(ImageElementContainer, _super);
        function ImageElementContainer(context, img) {
            var _this = _super.call(this, context, img) || this;
            _this.src = img.currentSrc || img.src;
            _this.intrinsicWidth = img.naturalWidth;
            _this.intrinsicHeight = img.naturalHeight;
            _this.context.cache.addImage(_this.src);
            return _this;
        }
        return ImageElementContainer;
    }(ElementContainer));

    var CanvasElementContainer = /** @class */ (function (_super) {
        __extends(CanvasElementContainer, _super);
        function CanvasElementContainer(context, canvas) {
            var _this = _super.call(this, context, canvas) || this;
            _this.canvas = canvas;
            _this.intrinsicWidth = canvas.width;
            _this.intrinsicHeight = canvas.height;
            return _this;
        }
        return CanvasElementContainer;
    }(ElementContainer));

    var SVGElementContainer = /** @class */ (function (_super) {
        __extends(SVGElementContainer, _super);
        function SVGElementContainer(context, img) {
            var _this = _super.call(this, context, img) || this;
            var s = new XMLSerializer();
            var bounds = parseBounds(context, img);
            img.setAttribute('width', bounds.width + "px");
            img.setAttribute('height', bounds.height + "px");
            _this.svg = "data:image/svg+xml," + encodeURIComponent(s.serializeToString(img));
            _this.intrinsicWidth = img.width.baseVal.value;
            _this.intrinsicHeight = img.height.baseVal.value;
            _this.context.cache.addImage(_this.svg);
            return _this;
        }
        return SVGElementContainer;
    }(ElementContainer));

    var LIElementContainer = /** @class */ (function (_super) {
        __extends(LIElementContainer, _super);
        function LIElementContainer(context, element) {
            var _this = _super.call(this, context, element) || this;
            _this.value = element.value;
            return _this;
        }
        return LIElementContainer;
    }(ElementContainer));

    var OLElementContainer = /** @class */ (function (_super) {
        __extends(OLElementContainer, _super);
        function OLElementContainer(context, element) {
            var _this = _super.call(this, context, element) || this;
            _this.start = element.start;
            _this.reversed = typeof element.reversed === 'boolean' && element.reversed === true;
            return _this;
        }
        return OLElementContainer;
    }(ElementContainer));

    var CHECKBOX_BORDER_RADIUS = [
        {
            type: 15 /* DIMENSION_TOKEN */,
            flags: 0,
            unit: 'px',
            number: 3
        }
    ];
    var RADIO_BORDER_RADIUS = [
        {
            type: 16 /* PERCENTAGE_TOKEN */,
            flags: 0,
            number: 50
        }
    ];
    var reformatInputBounds = function (bounds) {
        if (bounds.width > bounds.height) {
            return new Bounds(bounds.left + (bounds.width - bounds.height) / 2, bounds.top, bounds.height, bounds.height);
        }
        else if (bounds.width < bounds.height) {
            return new Bounds(bounds.left, bounds.top + (bounds.height - bounds.width) / 2, bounds.width, bounds.width);
        }
        return bounds;
    };
    var getInputValue = function (node) {
        var value = node.type === PASSWORD ? new Array(node.value.length + 1).join('\u2022') : node.value;
        return value.length === 0 ? node.placeholder || '' : value;
    };
    var CHECKBOX = 'checkbox';
    var RADIO = 'radio';
    var PASSWORD = 'password';
    var INPUT_COLOR = 0x2a2a2aff;
    var InputElementContainer = /** @class */ (function (_super) {
        __extends(InputElementContainer, _super);
        function InputElementContainer(context, input) {
            var _this = _super.call(this, context, input) || this;
            _this.type = input.type.toLowerCase();
            _this.checked = input.checked;
            _this.value = getInputValue(input);
            if (_this.type === CHECKBOX || _this.type === RADIO) {
                _this.styles.backgroundColor = 0xdededeff;
                _this.styles.borderTopColor =
                    _this.styles.borderRightColor =
                        _this.styles.borderBottomColor =
                            _this.styles.borderLeftColor =
                                0xa5a5a5ff;
                _this.styles.borderTopWidth =
                    _this.styles.borderRightWidth =
                        _this.styles.borderBottomWidth =
                            _this.styles.borderLeftWidth =
                                1;
                _this.styles.borderTopStyle =
                    _this.styles.borderRightStyle =
                        _this.styles.borderBottomStyle =
                            _this.styles.borderLeftStyle =
                                1 /* SOLID */;
                _this.styles.backgroundClip = [0 /* BORDER_BOX */];
                _this.styles.backgroundOrigin = [0 /* BORDER_BOX */];
                _this.bounds = reformatInputBounds(_this.bounds);
            }
            switch (_this.type) {
                case CHECKBOX:
                    _this.styles.borderTopRightRadius =
                        _this.styles.borderTopLeftRadius =
                            _this.styles.borderBottomRightRadius =
                                _this.styles.borderBottomLeftRadius =
                                    CHECKBOX_BORDER_RADIUS;
                    break;
                case RADIO:
                    _this.styles.borderTopRightRadius =
                        _this.styles.borderTopLeftRadius =
                            _this.styles.borderBottomRightRadius =
                                _this.styles.borderBottomLeftRadius =
                                    RADIO_BORDER_RADIUS;
                    break;
            }
            return _this;
        }
        return InputElementContainer;
    }(ElementContainer));

    var SelectElementContainer = /** @class */ (function (_super) {
        __extends(SelectElementContainer, _super);
        function SelectElementContainer(context, element) {
            var _this = _super.call(this, context, element) || this;
            var option = element.options[element.selectedIndex || 0];
            _this.value = option ? option.text || '' : '';
            return _this;
        }
        return SelectElementContainer;
    }(ElementContainer));

    var TextareaElementContainer = /** @class */ (function (_super) {
        __extends(TextareaElementContainer, _super);
        function TextareaElementContainer(context, element) {
            var _this = _super.call(this, context, element) || this;
            _this.value = element.value;
            return _this;
        }
        return TextareaElementContainer;
    }(ElementContainer));

    var IFrameElementContainer = /** @class */ (function (_super) {
        __extends(IFrameElementContainer, _super);
        function IFrameElementContainer(context, iframe) {
            var _this = _super.call(this, context, iframe) || this;
            _this.src = iframe.src;
            _this.width = parseInt(iframe.width, 10) || 0;
            _this.height = parseInt(iframe.height, 10) || 0;
            _this.backgroundColor = _this.styles.backgroundColor;
            try {
                if (iframe.contentWindow &&
                    iframe.contentWindow.document &&
                    iframe.contentWindow.document.documentElement) {
                    _this.tree = parseTree(context, iframe.contentWindow.document.documentElement);
                    // http://www.w3.org/TR/css3-background/#special-backgrounds
                    var documentBackgroundColor = iframe.contentWindow.document.documentElement
                        ? parseColor(context, getComputedStyle(iframe.contentWindow.document.documentElement).backgroundColor)
                        : COLORS.TRANSPARENT;
                    var bodyBackgroundColor = iframe.contentWindow.document.body
                        ? parseColor(context, getComputedStyle(iframe.contentWindow.document.body).backgroundColor)
                        : COLORS.TRANSPARENT;
                    _this.backgroundColor = isTransparent(documentBackgroundColor)
                        ? isTransparent(bodyBackgroundColor)
                            ? _this.styles.backgroundColor
                            : bodyBackgroundColor
                        : documentBackgroundColor;
                }
            }
            catch (e) { }
            return _this;
        }
        return IFrameElementContainer;
    }(ElementContainer));

    var LIST_OWNERS = ['OL', 'UL', 'MENU'];
    var parseNodeTree = function (context, node, parent, root) {
        for (var childNode = node.firstChild, nextNode = void 0; childNode; childNode = nextNode) {
            nextNode = childNode.nextSibling;
            if (isTextNode(childNode) && childNode.data.trim().length > 0) {
                parent.textNodes.push(new TextContainer(context, childNode, parent.styles));
            }
            else if (isElementNode(childNode)) {
                if (isSlotElement(childNode) && childNode.assignedNodes) {
                    childNode.assignedNodes().forEach(function (childNode) { return parseNodeTree(context, childNode, parent, root); });
                }
                else {
                    var container = createContainer(context, childNode);
                    if (container.styles.isVisible()) {
                        if (createsRealStackingContext(childNode, container, root)) {
                            container.flags |= 4 /* CREATES_REAL_STACKING_CONTEXT */;
                        }
                        else if (createsStackingContext(container.styles)) {
                            container.flags |= 2 /* CREATES_STACKING_CONTEXT */;
                        }
                        if (LIST_OWNERS.indexOf(childNode.tagName) !== -1) {
                            container.flags |= 8 /* IS_LIST_OWNER */;
                        }
                        parent.elements.push(container);
                        childNode.slot;
                        if (childNode.shadowRoot) {
                            parseNodeTree(context, childNode.shadowRoot, container, root);
                        }
                        else if (!isTextareaElement(childNode) &&
                            !isSVGElement(childNode) &&
                            !isSelectElement(childNode)) {
                            parseNodeTree(context, childNode, container, root);
                        }
                    }
                }
            }
        }
    };
    var createContainer = function (context, element) {
        if (isImageElement(element)) {
            return new ImageElementContainer(context, element);
        }
        if (isCanvasElement(element)) {
            return new CanvasElementContainer(context, element);
        }
        if (isSVGElement(element)) {
            return new SVGElementContainer(context, element);
        }
        if (isLIElement(element)) {
            return new LIElementContainer(context, element);
        }
        if (isOLElement(element)) {
            return new OLElementContainer(context, element);
        }
        if (isInputElement(element)) {
            return new InputElementContainer(context, element);
        }
        if (isSelectElement(element)) {
            return new SelectElementContainer(context, element);
        }
        if (isTextareaElement(element)) {
            return new TextareaElementContainer(context, element);
        }
        if (isIFrameElement(element)) {
            return new IFrameElementContainer(context, element);
        }
        return new ElementContainer(context, element);
    };
    var parseTree = function (context, element) {
        var container = createContainer(context, element);
        container.flags |= 4 /* CREATES_REAL_STACKING_CONTEXT */;
        parseNodeTree(context, element, container, container);
        return container;
    };
    var createsRealStackingContext = function (node, container, root) {
        return (container.styles.isPositionedWithZIndex() ||
            container.styles.opacity < 1 ||
            container.styles.isTransformed() ||
            (isBodyElement(node) && root.styles.isTransparent()));
    };
    var createsStackingContext = function (styles) { return styles.isPositioned() || styles.isFloating(); };
    var isTextNode = function (node) { return node.nodeType === Node.TEXT_NODE; };
    var isElementNode = function (node) { return node.nodeType === Node.ELEMENT_NODE; };
    var isHTMLElementNode = function (node) {
        return isElementNode(node) && typeof node.style !== 'undefined' && !isSVGElementNode(node);
    };
    var isSVGElementNode = function (element) {
        return typeof element.className === 'object';
    };
    var isLIElement = function (node) { return node.tagName === 'LI'; };
    var isOLElement = function (node) { return node.tagName === 'OL'; };
    var isInputElement = function (node) { return node.tagName === 'INPUT'; };
    var isHTMLElement = function (node) { return node.tagName === 'HTML'; };
    var isSVGElement = function (node) { return node.tagName === 'svg'; };
    var isBodyElement = function (node) { return node.tagName === 'BODY'; };
    var isCanvasElement = function (node) { return node.tagName === 'CANVAS'; };
    var isVideoElement = function (node) { return node.tagName === 'VIDEO'; };
    var isImageElement = function (node) { return node.tagName === 'IMG'; };
    var isIFrameElement = function (node) { return node.tagName === 'IFRAME'; };
    var isStyleElement = function (node) { return node.tagName === 'STYLE'; };
    var isScriptElement = function (node) { return node.tagName === 'SCRIPT'; };
    var isTextareaElement = function (node) { return node.tagName === 'TEXTAREA'; };
    var isSelectElement = function (node) { return node.tagName === 'SELECT'; };
    var isSlotElement = function (node) { return node.tagName === 'SLOT'; };
    // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
    var isCustomElement = function (node) { return node.tagName.indexOf('-') > 0; };

    var CounterState = /** @class */ (function () {
        function CounterState() {
            this.counters = {};
        }
        CounterState.prototype.getCounterValue = function (name) {
            var counter = this.counters[name];
            if (counter && counter.length) {
                return counter[counter.length - 1];
            }
            return 1;
        };
        CounterState.prototype.getCounterValues = function (name) {
            var counter = this.counters[name];
            return counter ? counter : [];
        };
        CounterState.prototype.pop = function (counters) {
            var _this = this;
            counters.forEach(function (counter) { return _this.counters[counter].pop(); });
        };
        CounterState.prototype.parse = function (style) {
            var _this = this;
            var counterIncrement = style.counterIncrement;
            var counterReset = style.counterReset;
            var canReset = true;
            if (counterIncrement !== null) {
                counterIncrement.forEach(function (entry) {
                    var counter = _this.counters[entry.counter];
                    if (counter && entry.increment !== 0) {
                        canReset = false;
                        if (!counter.length) {
                            counter.push(1);
                        }
                        counter[Math.max(0, counter.length - 1)] += entry.increment;
                    }
                });
            }
            var counterNames = [];
            if (canReset) {
                counterReset.forEach(function (entry) {
                    var counter = _this.counters[entry.counter];
                    counterNames.push(entry.counter);
                    if (!counter) {
                        counter = _this.counters[entry.counter] = [];
                    }
                    counter.push(entry.reset);
                });
            }
            return counterNames;
        };
        return CounterState;
    }());
    var ROMAN_UPPER = {
        integers: [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
        values: ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
    };
    var ARMENIAN = {
        integers: [
            9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 90, 80, 70,
            60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
        ],
        values: [
            'Ք',
            'Փ',
            'Ւ',
            'Ց',
            'Ր',
            'Տ',
            'Վ',
            'Ս',
            'Ռ',
            'Ջ',
            'Պ',
            'Չ',
            'Ո',
            'Շ',
            'Ն',
            'Յ',
            'Մ',
            'Ճ',
            'Ղ',
            'Ձ',
            'Հ',
            'Կ',
            'Ծ',
            'Խ',
            'Լ',
            'Ի',
            'Ժ',
            'Թ',
            'Ը',
            'Է',
            'Զ',
            'Ե',
            'Դ',
            'Գ',
            'Բ',
            'Ա'
        ]
    };
    var HEBREW = {
        integers: [
            10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 400, 300, 200, 100, 90, 80, 70, 60, 50, 40, 30, 20,
            19, 18, 17, 16, 15, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
        ],
        values: [
            'י׳',
            'ט׳',
            'ח׳',
            'ז׳',
            'ו׳',
            'ה׳',
            'ד׳',
            'ג׳',
            'ב׳',
            'א׳',
            'ת',
            'ש',
            'ר',
            'ק',
            'צ',
            'פ',
            'ע',
            'ס',
            'נ',
            'מ',
            'ל',
            'כ',
            'יט',
            'יח',
            'יז',
            'טז',
            'טו',
            'י',
            'ט',
            'ח',
            'ז',
            'ו',
            'ה',
            'ד',
            'ג',
            'ב',
            'א'
        ]
    };
    var GEORGIAN = {
        integers: [
            10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 90,
            80, 70, 60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
        ],
        values: [
            'ჵ',
            'ჰ',
            'ჯ',
            'ჴ',
            'ხ',
            'ჭ',
            'წ',
            'ძ',
            'ც',
            'ჩ',
            'შ',
            'ყ',
            'ღ',
            'ქ',
            'ფ',
            'ჳ',
            'ტ',
            'ს',
            'რ',
            'ჟ',
            'პ',
            'ო',
            'ჲ',
            'ნ',
            'მ',
            'ლ',
            'კ',
            'ი',
            'თ',
            'ჱ',
            'ზ',
            'ვ',
            'ე',
            'დ',
            'გ',
            'ბ',
            'ა'
        ]
    };
    var createAdditiveCounter = function (value, min, max, symbols, fallback, suffix) {
        if (value < min || value > max) {
            return createCounterText(value, fallback, suffix.length > 0);
        }
        return (symbols.integers.reduce(function (string, integer, index) {
            while (value >= integer) {
                value -= integer;
                string += symbols.values[index];
            }
            return string;
        }, '') + suffix);
    };
    var createCounterStyleWithSymbolResolver = function (value, codePointRangeLength, isNumeric, resolver) {
        var string = '';
        do {
            if (!isNumeric) {
                value--;
            }
            string = resolver(value) + string;
            value /= codePointRangeLength;
        } while (value * codePointRangeLength >= codePointRangeLength);
        return string;
    };
    var createCounterStyleFromRange = function (value, codePointRangeStart, codePointRangeEnd, isNumeric, suffix) {
        var codePointRangeLength = codePointRangeEnd - codePointRangeStart + 1;
        return ((value < 0 ? '-' : '') +
            (createCounterStyleWithSymbolResolver(Math.abs(value), codePointRangeLength, isNumeric, function (codePoint) {
                return fromCodePoint$1(Math.floor(codePoint % codePointRangeLength) + codePointRangeStart);
            }) +
                suffix));
    };
    var createCounterStyleFromSymbols = function (value, symbols, suffix) {
        if (suffix === void 0) { suffix = '. '; }
        var codePointRangeLength = symbols.length;
        return (createCounterStyleWithSymbolResolver(Math.abs(value), codePointRangeLength, false, function (codePoint) { return symbols[Math.floor(codePoint % codePointRangeLength)]; }) + suffix);
    };
    var CJK_ZEROS = 1 << 0;
    var CJK_TEN_COEFFICIENTS = 1 << 1;
    var CJK_TEN_HIGH_COEFFICIENTS = 1 << 2;
    var CJK_HUNDRED_COEFFICIENTS = 1 << 3;
    var createCJKCounter = function (value, numbers, multipliers, negativeSign, suffix, flags) {
        if (value < -9999 || value > 9999) {
            return createCounterText(value, 4 /* CJK_DECIMAL */, suffix.length > 0);
        }
        var tmp = Math.abs(value);
        var string = suffix;
        if (tmp === 0) {
            return numbers[0] + string;
        }
        for (var digit = 0; tmp > 0 && digit <= 4; digit++) {
            var coefficient = tmp % 10;
            if (coefficient === 0 && contains(flags, CJK_ZEROS) && string !== '') {
                string = numbers[coefficient] + string;
            }
            else if (coefficient > 1 ||
                (coefficient === 1 && digit === 0) ||
                (coefficient === 1 && digit === 1 && contains(flags, CJK_TEN_COEFFICIENTS)) ||
                (coefficient === 1 && digit === 1 && contains(flags, CJK_TEN_HIGH_COEFFICIENTS) && value > 100) ||
                (coefficient === 1 && digit > 1 && contains(flags, CJK_HUNDRED_COEFFICIENTS))) {
                string = numbers[coefficient] + (digit > 0 ? multipliers[digit - 1] : '') + string;
            }
            else if (coefficient === 1 && digit > 0) {
                string = multipliers[digit - 1] + string;
            }
            tmp = Math.floor(tmp / 10);
        }
        return (value < 0 ? negativeSign : '') + string;
    };
    var CHINESE_INFORMAL_MULTIPLIERS = '十百千萬';
    var CHINESE_FORMAL_MULTIPLIERS = '拾佰仟萬';
    var JAPANESE_NEGATIVE = 'マイナス';
    var KOREAN_NEGATIVE = '마이너스';
    var createCounterText = function (value, type, appendSuffix) {
        var defaultSuffix = appendSuffix ? '. ' : '';
        var cjkSuffix = appendSuffix ? '、' : '';
        var koreanSuffix = appendSuffix ? ', ' : '';
        var spaceSuffix = appendSuffix ? ' ' : '';
        switch (type) {
            case 0 /* DISC */:
                return '•' + spaceSuffix;
            case 1 /* CIRCLE */:
                return '◦' + spaceSuffix;
            case 2 /* SQUARE */:
                return '◾' + spaceSuffix;
            case 5 /* DECIMAL_LEADING_ZERO */:
                var string = createCounterStyleFromRange(value, 48, 57, true, defaultSuffix);
                return string.length < 4 ? "0" + string : string;
            case 4 /* CJK_DECIMAL */:
                return createCounterStyleFromSymbols(value, '〇一二三四五六七八九', cjkSuffix);
            case 6 /* LOWER_ROMAN */:
                return createAdditiveCounter(value, 1, 3999, ROMAN_UPPER, 3 /* DECIMAL */, defaultSuffix).toLowerCase();
            case 7 /* UPPER_ROMAN */:
                return createAdditiveCounter(value, 1, 3999, ROMAN_UPPER, 3 /* DECIMAL */, defaultSuffix);
            case 8 /* LOWER_GREEK */:
                return createCounterStyleFromRange(value, 945, 969, false, defaultSuffix);
            case 9 /* LOWER_ALPHA */:
                return createCounterStyleFromRange(value, 97, 122, false, defaultSuffix);
            case 10 /* UPPER_ALPHA */:
                return createCounterStyleFromRange(value, 65, 90, false, defaultSuffix);
            case 11 /* ARABIC_INDIC */:
                return createCounterStyleFromRange(value, 1632, 1641, true, defaultSuffix);
            case 12 /* ARMENIAN */:
            case 49 /* UPPER_ARMENIAN */:
                return createAdditiveCounter(value, 1, 9999, ARMENIAN, 3 /* DECIMAL */, defaultSuffix);
            case 35 /* LOWER_ARMENIAN */:
                return createAdditiveCounter(value, 1, 9999, ARMENIAN, 3 /* DECIMAL */, defaultSuffix).toLowerCase();
            case 13 /* BENGALI */:
                return createCounterStyleFromRange(value, 2534, 2543, true, defaultSuffix);
            case 14 /* CAMBODIAN */:
            case 30 /* KHMER */:
                return createCounterStyleFromRange(value, 6112, 6121, true, defaultSuffix);
            case 15 /* CJK_EARTHLY_BRANCH */:
                return createCounterStyleFromSymbols(value, '子丑寅卯辰巳午未申酉戌亥', cjkSuffix);
            case 16 /* CJK_HEAVENLY_STEM */:
                return createCounterStyleFromSymbols(value, '甲乙丙丁戊己庚辛壬癸', cjkSuffix);
            case 17 /* CJK_IDEOGRAPHIC */:
            case 48 /* TRAD_CHINESE_INFORMAL */:
                return createCJKCounter(value, '零一二三四五六七八九', CHINESE_INFORMAL_MULTIPLIERS, '負', cjkSuffix, CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS);
            case 47 /* TRAD_CHINESE_FORMAL */:
                return createCJKCounter(value, '零壹貳參肆伍陸柒捌玖', CHINESE_FORMAL_MULTIPLIERS, '負', cjkSuffix, CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS);
            case 42 /* SIMP_CHINESE_INFORMAL */:
                return createCJKCounter(value, '零一二三四五六七八九', CHINESE_INFORMAL_MULTIPLIERS, '负', cjkSuffix, CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS);
            case 41 /* SIMP_CHINESE_FORMAL */:
                return createCJKCounter(value, '零壹贰叁肆伍陆柒捌玖', CHINESE_FORMAL_MULTIPLIERS, '负', cjkSuffix, CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS);
            case 26 /* JAPANESE_INFORMAL */:
                return createCJKCounter(value, '〇一二三四五六七八九', '十百千万', JAPANESE_NEGATIVE, cjkSuffix, 0);
            case 25 /* JAPANESE_FORMAL */:
                return createCJKCounter(value, '零壱弐参四伍六七八九', '拾百千万', JAPANESE_NEGATIVE, cjkSuffix, CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS);
            case 31 /* KOREAN_HANGUL_FORMAL */:
                return createCJKCounter(value, '영일이삼사오육칠팔구', '십백천만', KOREAN_NEGATIVE, koreanSuffix, CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS);
            case 33 /* KOREAN_HANJA_INFORMAL */:
                return createCJKCounter(value, '零一二三四五六七八九', '十百千萬', KOREAN_NEGATIVE, koreanSuffix, 0);
            case 32 /* KOREAN_HANJA_FORMAL */:
                return createCJKCounter(value, '零壹貳參四五六七八九', '拾百千', KOREAN_NEGATIVE, koreanSuffix, CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS);
            case 18 /* DEVANAGARI */:
                return createCounterStyleFromRange(value, 0x966, 0x96f, true, defaultSuffix);
            case 20 /* GEORGIAN */:
                return createAdditiveCounter(value, 1, 19999, GEORGIAN, 3 /* DECIMAL */, defaultSuffix);
            case 21 /* GUJARATI */:
                return createCounterStyleFromRange(value, 0xae6, 0xaef, true, defaultSuffix);
            case 22 /* GURMUKHI */:
                return createCounterStyleFromRange(value, 0xa66, 0xa6f, true, defaultSuffix);
            case 22 /* HEBREW */:
                return createAdditiveCounter(value, 1, 10999, HEBREW, 3 /* DECIMAL */, defaultSuffix);
            case 23 /* HIRAGANA */:
                return createCounterStyleFromSymbols(value, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをん');
            case 24 /* HIRAGANA_IROHA */:
                return createCounterStyleFromSymbols(value, 'いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす');
            case 27 /* KANNADA */:
                return createCounterStyleFromRange(value, 0xce6, 0xcef, true, defaultSuffix);
            case 28 /* KATAKANA */:
                return createCounterStyleFromSymbols(value, 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヰヱヲン', cjkSuffix);
            case 29 /* KATAKANA_IROHA */:
                return createCounterStyleFromSymbols(value, 'イロハニホヘトチリヌルヲワカヨタレソツネナラムウヰノオクヤマケフコエテアサキユメミシヱヒモセス', cjkSuffix);
            case 34 /* LAO */:
                return createCounterStyleFromRange(value, 0xed0, 0xed9, true, defaultSuffix);
            case 37 /* MONGOLIAN */:
                return createCounterStyleFromRange(value, 0x1810, 0x1819, true, defaultSuffix);
            case 38 /* MYANMAR */:
                return createCounterStyleFromRange(value, 0x1040, 0x1049, true, defaultSuffix);
            case 39 /* ORIYA */:
                return createCounterStyleFromRange(value, 0xb66, 0xb6f, true, defaultSuffix);
            case 40 /* PERSIAN */:
                return createCounterStyleFromRange(value, 0x6f0, 0x6f9, true, defaultSuffix);
            case 43 /* TAMIL */:
                return createCounterStyleFromRange(value, 0xbe6, 0xbef, true, defaultSuffix);
            case 44 /* TELUGU */:
                return createCounterStyleFromRange(value, 0xc66, 0xc6f, true, defaultSuffix);
            case 45 /* THAI */:
                return createCounterStyleFromRange(value, 0xe50, 0xe59, true, defaultSuffix);
            case 46 /* TIBETAN */:
                return createCounterStyleFromRange(value, 0xf20, 0xf29, true, defaultSuffix);
            case 3 /* DECIMAL */:
            default:
                return createCounterStyleFromRange(value, 48, 57, true, defaultSuffix);
        }
    };

    var IGNORE_ATTRIBUTE = 'data-html2canvas-ignore';
    var DocumentCloner = /** @class */ (function () {
        function DocumentCloner(context, element, options) {
            this.context = context;
            this.options = options;
            this.scrolledElements = [];
            this.referenceElement = element;
            this.counters = new CounterState();
            this.quoteDepth = 0;
            if (!element.ownerDocument) {
                throw new Error('Cloned element does not have an owner document');
            }
            this.documentElement = this.cloneNode(element.ownerDocument.documentElement, false);
        }
        DocumentCloner.prototype.toIFrame = function (ownerDocument, windowSize) {
            var _this = this;
            var iframe = createIFrameContainer(ownerDocument, windowSize);
            if (!iframe.contentWindow) {
                return Promise.reject("Unable to find iframe window");
            }
            var scrollX = ownerDocument.defaultView.pageXOffset;
            var scrollY = ownerDocument.defaultView.pageYOffset;
            var cloneWindow = iframe.contentWindow;
            var documentClone = cloneWindow.document;
            /* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
             if window url is about:blank, we can assign the url to current by writing onto the document
             */
            var iframeLoad = iframeLoader(iframe).then(function () { return __awaiter(_this, void 0, void 0, function () {
                var onclone, referenceElement;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            this.scrolledElements.forEach(restoreNodeScroll);
                            if (cloneWindow) {
                                cloneWindow.scrollTo(windowSize.left, windowSize.top);
                                if (/(iPad|iPhone|iPod)/g.test(navigator.userAgent) &&
                                    (cloneWindow.scrollY !== windowSize.top || cloneWindow.scrollX !== windowSize.left)) {
                                    this.context.logger.warn('Unable to restore scroll position for cloned document');
                                    this.context.windowBounds = this.context.windowBounds.add(cloneWindow.scrollX - windowSize.left, cloneWindow.scrollY - windowSize.top, 0, 0);
                                }
                            }
                            onclone = this.options.onclone;
                            referenceElement = this.clonedReferenceElement;
                            if (typeof referenceElement === 'undefined') {
                                return [2 /*return*/, Promise.reject("Error finding the " + this.referenceElement.nodeName + " in the cloned document")];
                            }
                            if (!(documentClone.fonts && documentClone.fonts.ready)) return [3 /*break*/, 2];
                            return [4 /*yield*/, documentClone.fonts.ready];
                        case 1:
                            _a.sent();
                            _a.label = 2;
                        case 2:
                            if (!/(AppleWebKit)/g.test(navigator.userAgent)) return [3 /*break*/, 4];
                            return [4 /*yield*/, imagesReady(documentClone)];
                        case 3:
                            _a.sent();
                            _a.label = 4;
                        case 4:
                            if (typeof onclone === 'function') {
                                return [2 /*return*/, Promise.resolve()
                                        .then(function () { return onclone(documentClone, referenceElement); })
                                        .then(function () { return iframe; })];
                            }
                            return [2 /*return*/, iframe];
                    }
                });
            }); });
            documentClone.open();
            documentClone.write(serializeDoctype(document.doctype) + "<html></html>");
            // Chrome scrolls the parent document for some reason after the write to the cloned window???
            restoreOwnerScroll(this.referenceElement.ownerDocument, scrollX, scrollY);
            documentClone.replaceChild(documentClone.adoptNode(this.documentElement), documentClone.documentElement);
            documentClone.close();
            return iframeLoad;
        };
        DocumentCloner.prototype.createElementClone = function (node) {
            if (isDebugging(node, 2 /* CLONE */)) {
                debugger;
            }
            if (isCanvasElement(node)) {
                return this.createCanvasClone(node);
            }
            if (isVideoElement(node)) {
                return this.createVideoClone(node);
            }
            if (isStyleElement(node)) {
                return this.createStyleClone(node);
            }
            var clone = node.cloneNode(false);
            if (isImageElement(clone)) {
                if (isImageElement(node) && node.currentSrc && node.currentSrc !== node.src) {
                    clone.src = node.currentSrc;
                    clone.srcset = '';
                }
                if (clone.loading === 'lazy') {
                    clone.loading = 'eager';
                }
            }
            if (isCustomElement(clone)) {
                return this.createCustomElementClone(clone);
            }
            return clone;
        };
        DocumentCloner.prototype.createCustomElementClone = function (node) {
            var clone = document.createElement('html2canvascustomelement');
            copyCSSStyles(node.style, clone);
            return clone;
        };
        DocumentCloner.prototype.createStyleClone = function (node) {
            try {
                var sheet = node.sheet;
                if (sheet && sheet.cssRules) {
                    var css = [].slice.call(sheet.cssRules, 0).reduce(function (css, rule) {
                        if (rule && typeof rule.cssText === 'string') {
                            return css + rule.cssText;
                        }
                        return css;
                    }, '');
                    var style = node.cloneNode(false);
                    style.textContent = css;
                    return style;
                }
            }
            catch (e) {
                // accessing node.sheet.cssRules throws a DOMException
                this.context.logger.error('Unable to access cssRules property', e);
                if (e.name !== 'SecurityError') {
                    throw e;
                }
            }
            return node.cloneNode(false);
        };
        DocumentCloner.prototype.createCanvasClone = function (canvas) {
            var _a;
            if (this.options.inlineImages && canvas.ownerDocument) {
                var img = canvas.ownerDocument.createElement('img');
                try {
                    img.src = canvas.toDataURL();
                    return img;
                }
                catch (e) {
                    this.context.logger.info("Unable to inline canvas contents, canvas is tainted", canvas);
                }
            }
            var clonedCanvas = canvas.cloneNode(false);
            try {
                clonedCanvas.width = canvas.width;
                clonedCanvas.height = canvas.height;
                var ctx = canvas.getContext('2d');
                var clonedCtx = clonedCanvas.getContext('2d');
                if (clonedCtx) {
                    if (!this.options.allowTaint && ctx) {
                        clonedCtx.putImageData(ctx.getImageData(0, 0, canvas.width, canvas.height), 0, 0);
                    }
                    else {
                        var gl = (_a = canvas.getContext('webgl2')) !== null && _a !== void 0 ? _a : canvas.getContext('webgl');
                        if (gl) {
                            var attribs = gl.getContextAttributes();
                            if ((attribs === null || attribs === void 0 ? void 0 : attribs.preserveDrawingBuffer) === false) {
                                this.context.logger.warn('Unable to clone WebGL context as it has preserveDrawingBuffer=false', canvas);
                            }
                        }
                        clonedCtx.drawImage(canvas, 0, 0);
                    }
                }
                return clonedCanvas;
            }
            catch (e) {
                this.context.logger.info("Unable to clone canvas as it is tainted", canvas);
            }
            return clonedCanvas;
        };
        DocumentCloner.prototype.createVideoClone = function (video) {
            var canvas = video.ownerDocument.createElement('canvas');
            canvas.width = video.offsetWidth;
            canvas.height = video.offsetHeight;
            var ctx = canvas.getContext('2d');
            try {
                if (ctx) {
                    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
                    if (!this.options.allowTaint) {
                        ctx.getImageData(0, 0, canvas.width, canvas.height);
                    }
                }
                return canvas;
            }
            catch (e) {
                this.context.logger.info("Unable to clone video as it is tainted", video);
            }
            var blankCanvas = video.ownerDocument.createElement('canvas');
            blankCanvas.width = video.offsetWidth;
            blankCanvas.height = video.offsetHeight;
            return blankCanvas;
        };
        DocumentCloner.prototype.appendChildNode = function (clone, child, copyStyles) {
            if (!isElementNode(child) ||
                (!isScriptElement(child) &&
                    !child.hasAttribute(IGNORE_ATTRIBUTE) &&
                    (typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child)))) {
                if (!this.options.copyStyles || !isElementNode(child) || !isStyleElement(child)) {
                    clone.appendChild(this.cloneNode(child, copyStyles));
                }
            }
        };
        DocumentCloner.prototype.cloneChildNodes = function (node, clone, copyStyles) {
            var _this = this;
            for (var child = node.shadowRoot ? node.shadowRoot.firstChild : node.firstChild; child; child = child.nextSibling) {
                if (isElementNode(child) && isSlotElement(child) && typeof child.assignedNodes === 'function') {
                    var assignedNodes = child.assignedNodes();
                    if (assignedNodes.length) {
                        assignedNodes.forEach(function (assignedNode) { return _this.appendChildNode(clone, assignedNode, copyStyles); });
                    }
                }
                else {
                    this.appendChildNode(clone, child, copyStyles);
                }
            }
        };
        DocumentCloner.prototype.cloneNode = function (node, copyStyles) {
            if (isTextNode(node)) {
                return document.createTextNode(node.data);
            }
            if (!node.ownerDocument) {
                return node.cloneNode(false);
            }
            var window = node.ownerDocument.defaultView;
            if (window && isElementNode(node) && (isHTMLElementNode(node) || isSVGElementNode(node))) {
                var clone = this.createElementClone(node);
                clone.style.transitionProperty = 'none';
                var style = window.getComputedStyle(node);
                var styleBefore = window.getComputedStyle(node, ':before');
                var styleAfter = window.getComputedStyle(node, ':after');
                if (this.referenceElement === node && isHTMLElementNode(clone)) {
                    this.clonedReferenceElement = clone;
                }
                if (isBodyElement(clone)) {
                    createPseudoHideStyles(clone);
                }
                var counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
                var before = this.resolvePseudoContent(node, clone, styleBefore, PseudoElementType.BEFORE);
                if (isCustomElement(node)) {
                    copyStyles = true;
                }
                if (!isVideoElement(node)) {
                    this.cloneChildNodes(node, clone, copyStyles);
                }
                if (before) {
                    clone.insertBefore(before, clone.firstChild);
                }
                var after = this.resolvePseudoContent(node, clone, styleAfter, PseudoElementType.AFTER);
                if (after) {
                    clone.appendChild(after);
                }
                this.counters.pop(counters);
                if ((style && (this.options.copyStyles || isSVGElementNode(node)) && !isIFrameElement(node)) ||
                    copyStyles) {
                    copyCSSStyles(style, clone);
                }
                if (node.scrollTop !== 0 || node.scrollLeft !== 0) {
                    this.scrolledElements.push([clone, node.scrollLeft, node.scrollTop]);
                }
                if ((isTextareaElement(node) || isSelectElement(node)) &&
                    (isTextareaElement(clone) || isSelectElement(clone))) {
                    clone.value = node.value;
                }
                return clone;
            }
            return node.cloneNode(false);
        };
        DocumentCloner.prototype.resolvePseudoContent = function (node, clone, style, pseudoElt) {
            var _this = this;
            if (!style) {
                return;
            }
            var value = style.content;
            var document = clone.ownerDocument;
            if (!document || !value || value === 'none' || value === '-moz-alt-content' || style.display === 'none') {
                return;
            }
            this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
            var declaration = new CSSParsedPseudoDeclaration(this.context, style);
            var anonymousReplacedElement = document.createElement('html2canvaspseudoelement');
            copyCSSStyles(style, anonymousReplacedElement);
            declaration.content.forEach(function (token) {
                if (token.type === 0 /* STRING_TOKEN */) {
                    anonymousReplacedElement.appendChild(document.createTextNode(token.value));
                }
                else if (token.type === 22 /* URL_TOKEN */) {
                    var img = document.createElement('img');
                    img.src = token.value;
                    img.style.opacity = '1';
                    anonymousReplacedElement.appendChild(img);
                }
                else if (token.type === 18 /* FUNCTION */) {
                    if (token.name === 'attr') {
                        var attr = token.values.filter(isIdentToken);
                        if (attr.length) {
                            anonymousReplacedElement.appendChild(document.createTextNode(node.getAttribute(attr[0].value) || ''));
                        }
                    }
                    else if (token.name === 'counter') {
                        var _a = token.values.filter(nonFunctionArgSeparator), counter = _a[0], counterStyle = _a[1];
                        if (counter && isIdentToken(counter)) {
                            var counterState = _this.counters.getCounterValue(counter.value);
                            var counterType = counterStyle && isIdentToken(counterStyle)
                                ? listStyleType.parse(_this.context, counterStyle.value)
                                : 3 /* DECIMAL */;
                            anonymousReplacedElement.appendChild(document.createTextNode(createCounterText(counterState, counterType, false)));
                        }
                    }
                    else if (token.name === 'counters') {
                        var _b = token.values.filter(nonFunctionArgSeparator), counter = _b[0], delim = _b[1], counterStyle = _b[2];
                        if (counter && isIdentToken(counter)) {
                            var counterStates = _this.counters.getCounterValues(counter.value);
                            var counterType_1 = counterStyle && isIdentToken(counterStyle)
                                ? listStyleType.parse(_this.context, counterStyle.value)
                                : 3 /* DECIMAL */;
                            var separator = delim && delim.type === 0 /* STRING_TOKEN */ ? delim.value : '';
                            var text = counterStates
                                .map(function (value) { return createCounterText(value, counterType_1, false); })
                                .join(separator);
                            anonymousReplacedElement.appendChild(document.createTextNode(text));
                        }
                    }
                    else ;
                }
                else if (token.type === 20 /* IDENT_TOKEN */) {
                    switch (token.value) {
                        case 'open-quote':
                            anonymousReplacedElement.appendChild(document.createTextNode(getQuote(declaration.quotes, _this.quoteDepth++, true)));
                            break;
                        case 'close-quote':
                            anonymousReplacedElement.appendChild(document.createTextNode(getQuote(declaration.quotes, --_this.quoteDepth, false)));
                            break;
                        default:
                            // safari doesn't parse string tokens correctly because of lack of quotes
                            anonymousReplacedElement.appendChild(document.createTextNode(token.value));
                    }
                }
            });
            anonymousReplacedElement.className = PSEUDO_HIDE_ELEMENT_CLASS_BEFORE + " " + PSEUDO_HIDE_ELEMENT_CLASS_AFTER;
            var newClassName = pseudoElt === PseudoElementType.BEFORE
                ? " " + PSEUDO_HIDE_ELEMENT_CLASS_BEFORE
                : " " + PSEUDO_HIDE_ELEMENT_CLASS_AFTER;
            if (isSVGElementNode(clone)) {
                clone.className.baseValue += newClassName;
            }
            else {
                clone.className += newClassName;
            }
            return anonymousReplacedElement;
        };
        DocumentCloner.destroy = function (container) {
            if (container.parentNode) {
                container.parentNode.removeChild(container);
                return true;
            }
            return false;
        };
        return DocumentCloner;
    }());
    var PseudoElementType;
    (function (PseudoElementType) {
        PseudoElementType[PseudoElementType["BEFORE"] = 0] = "BEFORE";
        PseudoElementType[PseudoElementType["AFTER"] = 1] = "AFTER";
    })(PseudoElementType || (PseudoElementType = {}));
    var createIFrameContainer = function (ownerDocument, bounds) {
        var cloneIframeContainer = ownerDocument.createElement('iframe');
        cloneIframeContainer.className = 'html2canvas-container';
        cloneIframeContainer.style.visibility = 'hidden';
        cloneIframeContainer.style.position = 'fixed';
        cloneIframeContainer.style.left = '-10000px';
        cloneIframeContainer.style.top = '0px';
        cloneIframeContainer.style.border = '0';
        cloneIframeContainer.width = bounds.width.toString();
        cloneIframeContainer.height = bounds.height.toString();
        cloneIframeContainer.scrolling = 'no'; // ios won't scroll without it
        cloneIframeContainer.setAttribute(IGNORE_ATTRIBUTE, 'true');
        ownerDocument.body.appendChild(cloneIframeContainer);
        return cloneIframeContainer;
    };
    var imageReady = function (img) {
        return new Promise(function (resolve) {
            if (img.complete) {
                resolve();
                return;
            }
            if (!img.src) {
                resolve();
                return;
            }
            img.onload = resolve;
            img.onerror = resolve;
        });
    };
    var imagesReady = function (document) {
        return Promise.all([].slice.call(document.images, 0).map(imageReady));
    };
    var iframeLoader = function (iframe) {
        return new Promise(function (resolve, reject) {
            var cloneWindow = iframe.contentWindow;
            if (!cloneWindow) {
                return reject("No window assigned for iframe");
            }
            var documentClone = cloneWindow.document;
            cloneWindow.onload = iframe.onload = function () {
                cloneWindow.onload = iframe.onload = null;
                var interval = setInterval(function () {
                    if (documentClone.body.childNodes.length > 0 && documentClone.readyState === 'complete') {
                        clearInterval(interval);
                        resolve(iframe);
                    }
                }, 50);
            };
        });
    };
    var ignoredStyleProperties = [
        'all',
        'd',
        'content' // Safari shows pseudoelements if content is set
    ];
    var copyCSSStyles = function (style, target) {
        // Edge does not provide value for cssText
        for (var i = style.length - 1; i >= 0; i--) {
            var property = style.item(i);
            if (ignoredStyleProperties.indexOf(property) === -1) {
                target.style.setProperty(property, style.getPropertyValue(property));
            }
        }
        return target;
    };
    var serializeDoctype = function (doctype) {
        var str = '';
        if (doctype) {
            str += '<!DOCTYPE ';
            if (doctype.name) {
                str += doctype.name;
            }
            if (doctype.internalSubset) {
                str += doctype.internalSubset;
            }
            if (doctype.publicId) {
                str += "\"" + doctype.publicId + "\"";
            }
            if (doctype.systemId) {
                str += "\"" + doctype.systemId + "\"";
            }
            str += '>';
        }
        return str;
    };
    var restoreOwnerScroll = function (ownerDocument, x, y) {
        if (ownerDocument &&
            ownerDocument.defaultView &&
            (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
            ownerDocument.defaultView.scrollTo(x, y);
        }
    };
    var restoreNodeScroll = function (_a) {
        var element = _a[0], x = _a[1], y = _a[2];
        element.scrollLeft = x;
        element.scrollTop = y;
    };
    var PSEUDO_BEFORE = ':before';
    var PSEUDO_AFTER = ':after';
    var PSEUDO_HIDE_ELEMENT_CLASS_BEFORE = '___html2canvas___pseudoelement_before';
    var PSEUDO_HIDE_ELEMENT_CLASS_AFTER = '___html2canvas___pseudoelement_after';
    var PSEUDO_HIDE_ELEMENT_STYLE = "{\n    content: \"\" !important;\n    display: none !important;\n}";
    var createPseudoHideStyles = function (body) {
        createStyles(body, "." + PSEUDO_HIDE_ELEMENT_CLASS_BEFORE + PSEUDO_BEFORE + PSEUDO_HIDE_ELEMENT_STYLE + "\n         ." + PSEUDO_HIDE_ELEMENT_CLASS_AFTER + PSEUDO_AFTER + PSEUDO_HIDE_ELEMENT_STYLE);
    };
    var createStyles = function (body, styles) {
        var document = body.ownerDocument;
        if (document) {
            var style = document.createElement('style');
            style.textContent = styles;
            body.appendChild(style);
        }
    };

    var CacheStorage = /** @class */ (function () {
        function CacheStorage() {
        }
        CacheStorage.getOrigin = function (url) {
            var link = CacheStorage._link;
            if (!link) {
                return 'about:blank';
            }
            link.href = url;
            link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/
            return link.protocol + link.hostname + link.port;
        };
        CacheStorage.isSameOrigin = function (src) {
            return CacheStorage.getOrigin(src) === CacheStorage._origin;
        };
        CacheStorage.setContext = function (window) {
            CacheStorage._link = window.document.createElement('a');
            CacheStorage._origin = CacheStorage.getOrigin(window.location.href);
        };
        CacheStorage._origin = 'about:blank';
        return CacheStorage;
    }());
    var Cache = /** @class */ (function () {
        function Cache(context, _options) {
            this.context = context;
            this._options = _options;
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            this._cache = {};
        }
        Cache.prototype.addImage = function (src) {
            var result = Promise.resolve();
            if (this.has(src)) {
                return result;
            }
            if (isBlobImage(src) || isRenderable(src)) {
                (this._cache[src] = this.loadImage(src)).catch(function () {
                    // prevent unhandled rejection
                });
                return result;
            }
            return result;
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        Cache.prototype.match = function (src) {
            return this._cache[src];
        };
        Cache.prototype.loadImage = function (key) {
            return __awaiter(this, void 0, void 0, function () {
                var isSameOrigin, useCORS, useProxy, src;
                var _this = this;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            isSameOrigin = CacheStorage.isSameOrigin(key);
                            useCORS = !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
                            useProxy = !isInlineImage(key) &&
                                !isSameOrigin &&
                                !isBlobImage(key) &&
                                typeof this._options.proxy === 'string' &&
                                FEATURES.SUPPORT_CORS_XHR &&
                                !useCORS;
                            if (!isSameOrigin &&
                                this._options.allowTaint === false &&
                                !isInlineImage(key) &&
                                !isBlobImage(key) &&
                                !useProxy &&
                                !useCORS) {
                                return [2 /*return*/];
                            }
                            src = key;
                            if (!useProxy) return [3 /*break*/, 2];
                            return [4 /*yield*/, this.proxy(src)];
                        case 1:
                            src = _a.sent();
                            _a.label = 2;
                        case 2:
                            this.context.logger.debug("Added image " + key.substring(0, 256));
                            return [4 /*yield*/, new Promise(function (resolve, reject) {
                                    var img = new Image();
                                    img.onload = function () { return resolve(img); };
                                    img.onerror = reject;
                                    //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
                                    if (isInlineBase64Image(src) || useCORS) {
                                        img.crossOrigin = 'anonymous';
                                    }
                                    img.src = src;
                                    if (img.complete === true) {
                                        // Inline XML images may fail to parse, throwing an Error later on
                                        setTimeout(function () { return resolve(img); }, 500);
                                    }
                                    if (_this._options.imageTimeout > 0) {
                                        setTimeout(function () { return reject("Timed out (" + _this._options.imageTimeout + "ms) loading image"); }, _this._options.imageTimeout);
                                    }
                                })];
                        case 3: return [2 /*return*/, _a.sent()];
                    }
                });
            });
        };
        Cache.prototype.has = function (key) {
            return typeof this._cache[key] !== 'undefined';
        };
        Cache.prototype.keys = function () {
            return Promise.resolve(Object.keys(this._cache));
        };
        Cache.prototype.proxy = function (src) {
            var _this = this;
            var proxy = this._options.proxy;
            if (!proxy) {
                throw new Error('No proxy defined');
            }
            var key = src.substring(0, 256);
            return new Promise(function (resolve, reject) {
                var responseType = FEATURES.SUPPORT_RESPONSE_TYPE ? 'blob' : 'text';
                var xhr = new XMLHttpRequest();
                xhr.onload = function () {
                    if (xhr.status === 200) {
                        if (responseType === 'text') {
                            resolve(xhr.response);
                        }
                        else {
                            var reader_1 = new FileReader();
                            reader_1.addEventListener('load', function () { return resolve(reader_1.result); }, false);
                            reader_1.addEventListener('error', function (e) { return reject(e); }, false);
                            reader_1.readAsDataURL(xhr.response);
                        }
                    }
                    else {
                        reject("Failed to proxy resource " + key + " with status code " + xhr.status);
                    }
                };
                xhr.onerror = reject;
                var queryString = proxy.indexOf('?') > -1 ? '&' : '?';
                xhr.open('GET', "" + proxy + queryString + "url=" + encodeURIComponent(src) + "&responseType=" + responseType);
                if (responseType !== 'text' && xhr instanceof XMLHttpRequest) {
                    xhr.responseType = responseType;
                }
                if (_this._options.imageTimeout) {
                    var timeout_1 = _this._options.imageTimeout;
                    xhr.timeout = timeout_1;
                    xhr.ontimeout = function () { return reject("Timed out (" + timeout_1 + "ms) proxying " + key); };
                }
                xhr.send();
            });
        };
        return Cache;
    }());
    var INLINE_SVG = /^data:image\/svg\+xml/i;
    var INLINE_BASE64 = /^data:image\/.*;base64,/i;
    var INLINE_IMG = /^data:image\/.*/i;
    var isRenderable = function (src) { return FEATURES.SUPPORT_SVG_DRAWING || !isSVG(src); };
    var isInlineImage = function (src) { return INLINE_IMG.test(src); };
    var isInlineBase64Image = function (src) { return INLINE_BASE64.test(src); };
    var isBlobImage = function (src) { return src.substr(0, 4) === 'blob'; };
    var isSVG = function (src) { return src.substr(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src); };

    var Vector = /** @class */ (function () {
        function Vector(x, y) {
            this.type = 0 /* VECTOR */;
            this.x = x;
            this.y = y;
        }
        Vector.prototype.add = function (deltaX, deltaY) {
            return new Vector(this.x + deltaX, this.y + deltaY);
        };
        return Vector;
    }());

    var lerp = function (a, b, t) {
        return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
    };
    var BezierCurve = /** @class */ (function () {
        function BezierCurve(start, startControl, endControl, end) {
            this.type = 1 /* BEZIER_CURVE */;
            this.start = start;
            this.startControl = startControl;
            this.endControl = endControl;
            this.end = end;
        }
        BezierCurve.prototype.subdivide = function (t, firstHalf) {
            var ab = lerp(this.start, this.startControl, t);
            var bc = lerp(this.startControl, this.endControl, t);
            var cd = lerp(this.endControl, this.end, t);
            var abbc = lerp(ab, bc, t);
            var bccd = lerp(bc, cd, t);
            var dest = lerp(abbc, bccd, t);
            return firstHalf ? new BezierCurve(this.start, ab, abbc, dest) : new BezierCurve(dest, bccd, cd, this.end);
        };
        BezierCurve.prototype.add = function (deltaX, deltaY) {
            return new BezierCurve(this.start.add(deltaX, deltaY), this.startControl.add(deltaX, deltaY), this.endControl.add(deltaX, deltaY), this.end.add(deltaX, deltaY));
        };
        BezierCurve.prototype.reverse = function () {
            return new BezierCurve(this.end, this.endControl, this.startControl, this.start);
        };
        return BezierCurve;
    }());
    var isBezierCurve = function (path) { return path.type === 1 /* BEZIER_CURVE */; };

    var BoundCurves = /** @class */ (function () {
        function BoundCurves(element) {
            var styles = element.styles;
            var bounds = element.bounds;
            var _a = getAbsoluteValueForTuple(styles.borderTopLeftRadius, bounds.width, bounds.height), tlh = _a[0], tlv = _a[1];
            var _b = getAbsoluteValueForTuple(styles.borderTopRightRadius, bounds.width, bounds.height), trh = _b[0], trv = _b[1];
            var _c = getAbsoluteValueForTuple(styles.borderBottomRightRadius, bounds.width, bounds.height), brh = _c[0], brv = _c[1];
            var _d = getAbsoluteValueForTuple(styles.borderBottomLeftRadius, bounds.width, bounds.height), blh = _d[0], blv = _d[1];
            var factors = [];
            factors.push((tlh + trh) / bounds.width);
            factors.push((blh + brh) / bounds.width);
            factors.push((tlv + blv) / bounds.height);
            factors.push((trv + brv) / bounds.height);
            var maxFactor = Math.max.apply(Math, factors);
            if (maxFactor > 1) {
                tlh /= maxFactor;
                tlv /= maxFactor;
                trh /= maxFactor;
                trv /= maxFactor;
                brh /= maxFactor;
                brv /= maxFactor;
                blh /= maxFactor;
                blv /= maxFactor;
            }
            var topWidth = bounds.width - trh;
            var rightHeight = bounds.height - brv;
            var bottomWidth = bounds.width - brh;
            var leftHeight = bounds.height - blv;
            var borderTopWidth = styles.borderTopWidth;
            var borderRightWidth = styles.borderRightWidth;
            var borderBottomWidth = styles.borderBottomWidth;
            var borderLeftWidth = styles.borderLeftWidth;
            var paddingTop = getAbsoluteValue(styles.paddingTop, element.bounds.width);
            var paddingRight = getAbsoluteValue(styles.paddingRight, element.bounds.width);
            var paddingBottom = getAbsoluteValue(styles.paddingBottom, element.bounds.width);
            var paddingLeft = getAbsoluteValue(styles.paddingLeft, element.bounds.width);
            this.topLeftBorderDoubleOuterBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth / 3, bounds.top + borderTopWidth / 3, tlh - borderLeftWidth / 3, tlv - borderTopWidth / 3, CORNER.TOP_LEFT)
                    : new Vector(bounds.left + borderLeftWidth / 3, bounds.top + borderTopWidth / 3);
            this.topRightBorderDoubleOuterBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + topWidth, bounds.top + borderTopWidth / 3, trh - borderRightWidth / 3, trv - borderTopWidth / 3, CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth / 3, bounds.top + borderTopWidth / 3);
            this.bottomRightBorderDoubleOuterBox =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + bottomWidth, bounds.top + rightHeight, brh - borderRightWidth / 3, brv - borderBottomWidth / 3, CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth / 3, bounds.top + bounds.height - borderBottomWidth / 3);
            this.bottomLeftBorderDoubleOuterBox =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth / 3, bounds.top + leftHeight, blh - borderLeftWidth / 3, blv - borderBottomWidth / 3, CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left + borderLeftWidth / 3, bounds.top + bounds.height - borderBottomWidth / 3);
            this.topLeftBorderDoubleInnerBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + (borderLeftWidth * 2) / 3, bounds.top + (borderTopWidth * 2) / 3, tlh - (borderLeftWidth * 2) / 3, tlv - (borderTopWidth * 2) / 3, CORNER.TOP_LEFT)
                    : new Vector(bounds.left + (borderLeftWidth * 2) / 3, bounds.top + (borderTopWidth * 2) / 3);
            this.topRightBorderDoubleInnerBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + topWidth, bounds.top + (borderTopWidth * 2) / 3, trh - (borderRightWidth * 2) / 3, trv - (borderTopWidth * 2) / 3, CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width - (borderRightWidth * 2) / 3, bounds.top + (borderTopWidth * 2) / 3);
            this.bottomRightBorderDoubleInnerBox =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + bottomWidth, bounds.top + rightHeight, brh - (borderRightWidth * 2) / 3, brv - (borderBottomWidth * 2) / 3, CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width - (borderRightWidth * 2) / 3, bounds.top + bounds.height - (borderBottomWidth * 2) / 3);
            this.bottomLeftBorderDoubleInnerBox =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left + (borderLeftWidth * 2) / 3, bounds.top + leftHeight, blh - (borderLeftWidth * 2) / 3, blv - (borderBottomWidth * 2) / 3, CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left + (borderLeftWidth * 2) / 3, bounds.top + bounds.height - (borderBottomWidth * 2) / 3);
            this.topLeftBorderStroke =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth / 2, bounds.top + borderTopWidth / 2, tlh - borderLeftWidth / 2, tlv - borderTopWidth / 2, CORNER.TOP_LEFT)
                    : new Vector(bounds.left + borderLeftWidth / 2, bounds.top + borderTopWidth / 2);
            this.topRightBorderStroke =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + topWidth, bounds.top + borderTopWidth / 2, trh - borderRightWidth / 2, trv - borderTopWidth / 2, CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth / 2, bounds.top + borderTopWidth / 2);
            this.bottomRightBorderStroke =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + bottomWidth, bounds.top + rightHeight, brh - borderRightWidth / 2, brv - borderBottomWidth / 2, CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth / 2, bounds.top + bounds.height - borderBottomWidth / 2);
            this.bottomLeftBorderStroke =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth / 2, bounds.top + leftHeight, blh - borderLeftWidth / 2, blv - borderBottomWidth / 2, CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left + borderLeftWidth / 2, bounds.top + bounds.height - borderBottomWidth / 2);
            this.topLeftBorderBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left, bounds.top, tlh, tlv, CORNER.TOP_LEFT)
                    : new Vector(bounds.left, bounds.top);
            this.topRightBorderBox =
                trh > 0 || trv > 0
                    ? getCurvePoints(bounds.left + topWidth, bounds.top, trh, trv, CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width, bounds.top);
            this.bottomRightBorderBox =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + bottomWidth, bounds.top + rightHeight, brh, brv, CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width, bounds.top + bounds.height);
            this.bottomLeftBorderBox =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left, bounds.top + leftHeight, blh, blv, CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left, bounds.top + bounds.height);
            this.topLeftPaddingBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth, bounds.top + borderTopWidth, Math.max(0, tlh - borderLeftWidth), Math.max(0, tlv - borderTopWidth), CORNER.TOP_LEFT)
                    : new Vector(bounds.left + borderLeftWidth, bounds.top + borderTopWidth);
            this.topRightPaddingBox =
                trh > 0 || trv > 0
                    ? getCurvePoints(bounds.left + Math.min(topWidth, bounds.width - borderRightWidth), bounds.top + borderTopWidth, topWidth > bounds.width + borderRightWidth ? 0 : Math.max(0, trh - borderRightWidth), Math.max(0, trv - borderTopWidth), CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth, bounds.top + borderTopWidth);
            this.bottomRightPaddingBox =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + Math.min(bottomWidth, bounds.width - borderLeftWidth), bounds.top + Math.min(rightHeight, bounds.height - borderBottomWidth), Math.max(0, brh - borderRightWidth), Math.max(0, brv - borderBottomWidth), CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width - borderRightWidth, bounds.top + bounds.height - borderBottomWidth);
            this.bottomLeftPaddingBox =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth, bounds.top + Math.min(leftHeight, bounds.height - borderBottomWidth), Math.max(0, blh - borderLeftWidth), Math.max(0, blv - borderBottomWidth), CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left + borderLeftWidth, bounds.top + bounds.height - borderBottomWidth);
            this.topLeftContentBox =
                tlh > 0 || tlv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth + paddingLeft, bounds.top + borderTopWidth + paddingTop, Math.max(0, tlh - (borderLeftWidth + paddingLeft)), Math.max(0, tlv - (borderTopWidth + paddingTop)), CORNER.TOP_LEFT)
                    : new Vector(bounds.left + borderLeftWidth + paddingLeft, bounds.top + borderTopWidth + paddingTop);
            this.topRightContentBox =
                trh > 0 || trv > 0
                    ? getCurvePoints(bounds.left + Math.min(topWidth, bounds.width + borderLeftWidth + paddingLeft), bounds.top + borderTopWidth + paddingTop, topWidth > bounds.width + borderLeftWidth + paddingLeft ? 0 : trh - borderLeftWidth + paddingLeft, trv - (borderTopWidth + paddingTop), CORNER.TOP_RIGHT)
                    : new Vector(bounds.left + bounds.width - (borderRightWidth + paddingRight), bounds.top + borderTopWidth + paddingTop);
            this.bottomRightContentBox =
                brh > 0 || brv > 0
                    ? getCurvePoints(bounds.left + Math.min(bottomWidth, bounds.width - (borderLeftWidth + paddingLeft)), bounds.top + Math.min(rightHeight, bounds.height + borderTopWidth + paddingTop), Math.max(0, brh - (borderRightWidth + paddingRight)), brv - (borderBottomWidth + paddingBottom), CORNER.BOTTOM_RIGHT)
                    : new Vector(bounds.left + bounds.width - (borderRightWidth + paddingRight), bounds.top + bounds.height - (borderBottomWidth + paddingBottom));
            this.bottomLeftContentBox =
                blh > 0 || blv > 0
                    ? getCurvePoints(bounds.left + borderLeftWidth + paddingLeft, bounds.top + leftHeight, Math.max(0, blh - (borderLeftWidth + paddingLeft)), blv - (borderBottomWidth + paddingBottom), CORNER.BOTTOM_LEFT)
                    : new Vector(bounds.left + borderLeftWidth + paddingLeft, bounds.top + bounds.height - (borderBottomWidth + paddingBottom));
        }
        return BoundCurves;
    }());
    var CORNER;
    (function (CORNER) {
        CORNER[CORNER["TOP_LEFT"] = 0] = "TOP_LEFT";
        CORNER[CORNER["TOP_RIGHT"] = 1] = "TOP_RIGHT";
        CORNER[CORNER["BOTTOM_RIGHT"] = 2] = "BOTTOM_RIGHT";
        CORNER[CORNER["BOTTOM_LEFT"] = 3] = "BOTTOM_LEFT";
    })(CORNER || (CORNER = {}));
    var getCurvePoints = function (x, y, r1, r2, position) {
        var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
        var ox = r1 * kappa; // control point offset horizontal
        var oy = r2 * kappa; // control point offset vertical
        var xm = x + r1; // x-middle
        var ym = y + r2; // y-middle
        switch (position) {
            case CORNER.TOP_LEFT:
                return new BezierCurve(new Vector(x, ym), new Vector(x, ym - oy), new Vector(xm - ox, y), new Vector(xm, y));
            case CORNER.TOP_RIGHT:
                return new BezierCurve(new Vector(x, y), new Vector(x + ox, y), new Vector(xm, ym - oy), new Vector(xm, ym));
            case CORNER.BOTTOM_RIGHT:
                return new BezierCurve(new Vector(xm, y), new Vector(xm, y + oy), new Vector(x + ox, ym), new Vector(x, ym));
            case CORNER.BOTTOM_LEFT:
            default:
                return new BezierCurve(new Vector(xm, ym), new Vector(xm - ox, ym), new Vector(x, y + oy), new Vector(x, y));
        }
    };
    var calculateBorderBoxPath = function (curves) {
        return [curves.topLeftBorderBox, curves.topRightBorderBox, curves.bottomRightBorderBox, curves.bottomLeftBorderBox];
    };
    var calculateContentBoxPath = function (curves) {
        return [
            curves.topLeftContentBox,
            curves.topRightContentBox,
            curves.bottomRightContentBox,
            curves.bottomLeftContentBox
        ];
    };
    var calculatePaddingBoxPath = function (curves) {
        return [
            curves.topLeftPaddingBox,
            curves.topRightPaddingBox,
            curves.bottomRightPaddingBox,
            curves.bottomLeftPaddingBox
        ];
    };

    var TransformEffect = /** @class */ (function () {
        function TransformEffect(offsetX, offsetY, matrix) {
            this.offsetX = offsetX;
            this.offsetY = offsetY;
            this.matrix = matrix;
            this.type = 0 /* TRANSFORM */;
            this.target = 2 /* BACKGROUND_BORDERS */ | 4 /* CONTENT */;
        }
        return TransformEffect;
    }());
    var ClipEffect = /** @class */ (function () {
        function ClipEffect(path, target) {
            this.path = path;
            this.target = target;
            this.type = 1 /* CLIP */;
        }
        return ClipEffect;
    }());
    var OpacityEffect = /** @class */ (function () {
        function OpacityEffect(opacity) {
            this.opacity = opacity;
            this.type = 2 /* OPACITY */;
            this.target = 2 /* BACKGROUND_BORDERS */ | 4 /* CONTENT */;
        }
        return OpacityEffect;
    }());
    var isTransformEffect = function (effect) {
        return effect.type === 0 /* TRANSFORM */;
    };
    var isClipEffect = function (effect) { return effect.type === 1 /* CLIP */; };
    var isOpacityEffect = function (effect) { return effect.type === 2 /* OPACITY */; };

    var equalPath = function (a, b) {
        if (a.length === b.length) {
            return a.some(function (v, i) { return v === b[i]; });
        }
        return false;
    };
    var transformPath = function (path, deltaX, deltaY, deltaW, deltaH) {
        return path.map(function (point, index) {
            switch (index) {
                case 0:
                    return point.add(deltaX, deltaY);
                case 1:
                    return point.add(deltaX + deltaW, deltaY);
                case 2:
                    return point.add(deltaX + deltaW, deltaY + deltaH);
                case 3:
                    return point.add(deltaX, deltaY + deltaH);
            }
            return point;
        });
    };

    var StackingContext = /** @class */ (function () {
        function StackingContext(container) {
            this.element = container;
            this.inlineLevel = [];
            this.nonInlineLevel = [];
            this.negativeZIndex = [];
            this.zeroOrAutoZIndexOrTransformedOrOpacity = [];
            this.positiveZIndex = [];
            this.nonPositionedFloats = [];
            this.nonPositionedInlineLevel = [];
        }
        return StackingContext;
    }());
    var ElementPaint = /** @class */ (function () {
        function ElementPaint(container, parent) {
            this.container = container;
            this.parent = parent;
            this.effects = [];
            this.curves = new BoundCurves(this.container);
            if (this.container.styles.opacity < 1) {
                this.effects.push(new OpacityEffect(this.container.styles.opacity));
            }
            if (this.container.styles.transform !== null) {
                var offsetX = this.container.bounds.left + this.container.styles.transformOrigin[0].number;
                var offsetY = this.container.bounds.top + this.container.styles.transformOrigin[1].number;
                var matrix = this.container.styles.transform;
                this.effects.push(new TransformEffect(offsetX, offsetY, matrix));
            }
            if (this.container.styles.overflowX !== 0 /* VISIBLE */) {
                var borderBox = calculateBorderBoxPath(this.curves);
                var paddingBox = calculatePaddingBoxPath(this.curves);
                if (equalPath(borderBox, paddingBox)) {
                    this.effects.push(new ClipEffect(borderBox, 2 /* BACKGROUND_BORDERS */ | 4 /* CONTENT */));
                }
                else {
                    this.effects.push(new ClipEffect(borderBox, 2 /* BACKGROUND_BORDERS */));
                    this.effects.push(new ClipEffect(paddingBox, 4 /* CONTENT */));
                }
            }
        }
        ElementPaint.prototype.getEffects = function (target) {
            var inFlow = [2 /* ABSOLUTE */, 3 /* FIXED */].indexOf(this.container.styles.position) === -1;
            var parent = this.parent;
            var effects = this.effects.slice(0);
            while (parent) {
                var croplessEffects = parent.effects.filter(function (effect) { return !isClipEffect(effect); });
                if (inFlow || parent.container.styles.position !== 0 /* STATIC */ || !parent.parent) {
                    effects.unshift.apply(effects, croplessEffects);
                    inFlow = [2 /* ABSOLUTE */, 3 /* FIXED */].indexOf(parent.container.styles.position) === -1;
                    if (parent.container.styles.overflowX !== 0 /* VISIBLE */) {
                        var borderBox = calculateBorderBoxPath(parent.curves);
                        var paddingBox = calculatePaddingBoxPath(parent.curves);
                        if (!equalPath(borderBox, paddingBox)) {
                            effects.unshift(new ClipEffect(paddingBox, 2 /* BACKGROUND_BORDERS */ | 4 /* CONTENT */));
                        }
                    }
                }
                else {
                    effects.unshift.apply(effects, croplessEffects);
                }
                parent = parent.parent;
            }
            return effects.filter(function (effect) { return contains(effect.target, target); });
        };
        return ElementPaint;
    }());
    var parseStackTree = function (parent, stackingContext, realStackingContext, listItems) {
        parent.container.elements.forEach(function (child) {
            var treatAsRealStackingContext = contains(child.flags, 4 /* CREATES_REAL_STACKING_CONTEXT */);
            var createsStackingContext = contains(child.flags, 2 /* CREATES_STACKING_CONTEXT */);
            var paintContainer = new ElementPaint(child, parent);
            if (contains(child.styles.display, 2048 /* LIST_ITEM */)) {
                listItems.push(paintContainer);
            }
            var listOwnerItems = contains(child.flags, 8 /* IS_LIST_OWNER */) ? [] : listItems;
            if (treatAsRealStackingContext || createsStackingContext) {
                var parentStack = treatAsRealStackingContext || child.styles.isPositioned() ? realStackingContext : stackingContext;
                var stack = new StackingContext(paintContainer);
                if (child.styles.isPositioned() || child.styles.opacity < 1 || child.styles.isTransformed()) {
                    var order_1 = child.styles.zIndex.order;
                    if (order_1 < 0) {
                        var index_1 = 0;
                        parentStack.negativeZIndex.some(function (current, i) {
                            if (order_1 > current.element.container.styles.zIndex.order) {
                                index_1 = i;
                                return false;
                            }
                            else if (index_1 > 0) {
                                return true;
                            }
                            return false;
                        });
                        parentStack.negativeZIndex.splice(index_1, 0, stack);
                    }
                    else if (order_1 > 0) {
                        var index_2 = 0;
                        parentStack.positiveZIndex.some(function (current, i) {
                            if (order_1 >= current.element.container.styles.zIndex.order) {
                                index_2 = i + 1;
                                return false;
                            }
                            else if (index_2 > 0) {
                                return true;
                            }
                            return false;
                        });
                        parentStack.positiveZIndex.splice(index_2, 0, stack);
                    }
                    else {
                        parentStack.zeroOrAutoZIndexOrTransformedOrOpacity.push(stack);
                    }
                }
                else {
                    if (child.styles.isFloating()) {
                        parentStack.nonPositionedFloats.push(stack);
                    }
                    else {
                        parentStack.nonPositionedInlineLevel.push(stack);
                    }
                }
                parseStackTree(paintContainer, stack, treatAsRealStackingContext ? stack : realStackingContext, listOwnerItems);
            }
            else {
                if (child.styles.isInlineLevel()) {
                    stackingContext.inlineLevel.push(paintContainer);
                }
                else {
                    stackingContext.nonInlineLevel.push(paintContainer);
                }
                parseStackTree(paintContainer, stackingContext, realStackingContext, listOwnerItems);
            }
            if (contains(child.flags, 8 /* IS_LIST_OWNER */)) {
                processListItems(child, listOwnerItems);
            }
        });
    };
    var processListItems = function (owner, elements) {
        var numbering = owner instanceof OLElementContainer ? owner.start : 1;
        var reversed = owner instanceof OLElementContainer ? owner.reversed : false;
        for (var i = 0; i < elements.length; i++) {
            var item = elements[i];
            if (item.container instanceof LIElementContainer &&
                typeof item.container.value === 'number' &&
                item.container.value !== 0) {
                numbering = item.container.value;
            }
            item.listValue = createCounterText(numbering, item.container.styles.listStyleType, true);
            numbering += reversed ? -1 : 1;
        }
    };
    var parseStackingContexts = function (container) {
        var paintContainer = new ElementPaint(container, null);
        var root = new StackingContext(paintContainer);
        var listItems = [];
        parseStackTree(paintContainer, root, root, listItems);
        processListItems(paintContainer.container, listItems);
        return root;
    };

    var parsePathForBorder = function (curves, borderSide) {
        switch (borderSide) {
            case 0:
                return createPathFromCurves(curves.topLeftBorderBox, curves.topLeftPaddingBox, curves.topRightBorderBox, curves.topRightPaddingBox);
            case 1:
                return createPathFromCurves(curves.topRightBorderBox, curves.topRightPaddingBox, curves.bottomRightBorderBox, curves.bottomRightPaddingBox);
            case 2:
                return createPathFromCurves(curves.bottomRightBorderBox, curves.bottomRightPaddingBox, curves.bottomLeftBorderBox, curves.bottomLeftPaddingBox);
            case 3:
            default:
                return createPathFromCurves(curves.bottomLeftBorderBox, curves.bottomLeftPaddingBox, curves.topLeftBorderBox, curves.topLeftPaddingBox);
        }
    };
    var parsePathForBorderDoubleOuter = function (curves, borderSide) {
        switch (borderSide) {
            case 0:
                return createPathFromCurves(curves.topLeftBorderBox, curves.topLeftBorderDoubleOuterBox, curves.topRightBorderBox, curves.topRightBorderDoubleOuterBox);
            case 1:
                return createPathFromCurves(curves.topRightBorderBox, curves.topRightBorderDoubleOuterBox, curves.bottomRightBorderBox, curves.bottomRightBorderDoubleOuterBox);
            case 2:
                return createPathFromCurves(curves.bottomRightBorderBox, curves.bottomRightBorderDoubleOuterBox, curves.bottomLeftBorderBox, curves.bottomLeftBorderDoubleOuterBox);
            case 3:
            default:
                return createPathFromCurves(curves.bottomLeftBorderBox, curves.bottomLeftBorderDoubleOuterBox, curves.topLeftBorderBox, curves.topLeftBorderDoubleOuterBox);
        }
    };
    var parsePathForBorderDoubleInner = function (curves, borderSide) {
        switch (borderSide) {
            case 0:
                return createPathFromCurves(curves.topLeftBorderDoubleInnerBox, curves.topLeftPaddingBox, curves.topRightBorderDoubleInnerBox, curves.topRightPaddingBox);
            case 1:
                return createPathFromCurves(curves.topRightBorderDoubleInnerBox, curves.topRightPaddingBox, curves.bottomRightBorderDoubleInnerBox, curves.bottomRightPaddingBox);
            case 2:
                return createPathFromCurves(curves.bottomRightBorderDoubleInnerBox, curves.bottomRightPaddingBox, curves.bottomLeftBorderDoubleInnerBox, curves.bottomLeftPaddingBox);
            case 3:
            default:
                return createPathFromCurves(curves.bottomLeftBorderDoubleInnerBox, curves.bottomLeftPaddingBox, curves.topLeftBorderDoubleInnerBox, curves.topLeftPaddingBox);
        }
    };
    var parsePathForBorderStroke = function (curves, borderSide) {
        switch (borderSide) {
            case 0:
                return createStrokePathFromCurves(curves.topLeftBorderStroke, curves.topRightBorderStroke);
            case 1:
                return createStrokePathFromCurves(curves.topRightBorderStroke, curves.bottomRightBorderStroke);
            case 2:
                return createStrokePathFromCurves(curves.bottomRightBorderStroke, curves.bottomLeftBorderStroke);
            case 3:
            default:
                return createStrokePathFromCurves(curves.bottomLeftBorderStroke, curves.topLeftBorderStroke);
        }
    };
    var createStrokePathFromCurves = function (outer1, outer2) {
        var path = [];
        if (isBezierCurve(outer1)) {
            path.push(outer1.subdivide(0.5, false));
        }
        else {
            path.push(outer1);
        }
        if (isBezierCurve(outer2)) {
            path.push(outer2.subdivide(0.5, true));
        }
        else {
            path.push(outer2);
        }
        return path;
    };
    var createPathFromCurves = function (outer1, inner1, outer2, inner2) {
        var path = [];
        if (isBezierCurve(outer1)) {
            path.push(outer1.subdivide(0.5, false));
        }
        else {
            path.push(outer1);
        }
        if (isBezierCurve(outer2)) {
            path.push(outer2.subdivide(0.5, true));
        }
        else {
            path.push(outer2);
        }
        if (isBezierCurve(inner2)) {
            path.push(inner2.subdivide(0.5, true).reverse());
        }
        else {
            path.push(inner2);
        }
        if (isBezierCurve(inner1)) {
            path.push(inner1.subdivide(0.5, false).reverse());
        }
        else {
            path.push(inner1);
        }
        return path;
    };

    var paddingBox = function (element) {
        var bounds = element.bounds;
        var styles = element.styles;
        return bounds.add(styles.borderLeftWidth, styles.borderTopWidth, -(styles.borderRightWidth + styles.borderLeftWidth), -(styles.borderTopWidth + styles.borderBottomWidth));
    };
    var contentBox = function (element) {
        var styles = element.styles;
        var bounds = element.bounds;
        var paddingLeft = getAbsoluteValue(styles.paddingLeft, bounds.width);
        var paddingRight = getAbsoluteValue(styles.paddingRight, bounds.width);
        var paddingTop = getAbsoluteValue(styles.paddingTop, bounds.width);
        var paddingBottom = getAbsoluteValue(styles.paddingBottom, bounds.width);
        return bounds.add(paddingLeft + styles.borderLeftWidth, paddingTop + styles.borderTopWidth, -(styles.borderRightWidth + styles.borderLeftWidth + paddingLeft + paddingRight), -(styles.borderTopWidth + styles.borderBottomWidth + paddingTop + paddingBottom));
    };

    var calculateBackgroundPositioningArea = function (backgroundOrigin, element) {
        if (backgroundOrigin === 0 /* BORDER_BOX */) {
            return element.bounds;
        }
        if (backgroundOrigin === 2 /* CONTENT_BOX */) {
            return contentBox(element);
        }
        return paddingBox(element);
    };
    var calculateBackgroundPaintingArea = function (backgroundClip, element) {
        if (backgroundClip === 0 /* BORDER_BOX */) {
            return element.bounds;
        }
        if (backgroundClip === 2 /* CONTENT_BOX */) {
            return contentBox(element);
        }
        return paddingBox(element);
    };
    var calculateBackgroundRendering = function (container, index, intrinsicSize) {
        var backgroundPositioningArea = calculateBackgroundPositioningArea(getBackgroundValueForIndex(container.styles.backgroundOrigin, index), container);
        var backgroundPaintingArea = calculateBackgroundPaintingArea(getBackgroundValueForIndex(container.styles.backgroundClip, index), container);
        var backgroundImageSize = calculateBackgroundSize(getBackgroundValueForIndex(container.styles.backgroundSize, index), intrinsicSize, backgroundPositioningArea);
        var sizeWidth = backgroundImageSize[0], sizeHeight = backgroundImageSize[1];
        var position = getAbsoluteValueForTuple(getBackgroundValueForIndex(container.styles.backgroundPosition, index), backgroundPositioningArea.width - sizeWidth, backgroundPositioningArea.height - sizeHeight);
        var path = calculateBackgroundRepeatPath(getBackgroundValueForIndex(container.styles.backgroundRepeat, index), position, backgroundImageSize, backgroundPositioningArea, backgroundPaintingArea);
        var offsetX = Math.round(backgroundPositioningArea.left + position[0]);
        var offsetY = Math.round(backgroundPositioningArea.top + position[1]);
        return [path, offsetX, offsetY, sizeWidth, sizeHeight];
    };
    var isAuto = function (token) { return isIdentToken(token) && token.value === BACKGROUND_SIZE.AUTO; };
    var hasIntrinsicValue = function (value) { return typeof value === 'number'; };
    var calculateBackgroundSize = function (size, _a, bounds) {
        var intrinsicWidth = _a[0], intrinsicHeight = _a[1], intrinsicProportion = _a[2];
        var first = size[0], second = size[1];
        if (!first) {
            return [0, 0];
        }
        if (isLengthPercentage(first) && second && isLengthPercentage(second)) {
            return [getAbsoluteValue(first, bounds.width), getAbsoluteValue(second, bounds.height)];
        }
        var hasIntrinsicProportion = hasIntrinsicValue(intrinsicProportion);
        if (isIdentToken(first) && (first.value === BACKGROUND_SIZE.CONTAIN || first.value === BACKGROUND_SIZE.COVER)) {
            if (hasIntrinsicValue(intrinsicProportion)) {
                var targetRatio = bounds.width / bounds.height;
                return targetRatio < intrinsicProportion !== (first.value === BACKGROUND_SIZE.COVER)
                    ? [bounds.width, bounds.width / intrinsicProportion]
                    : [bounds.height * intrinsicProportion, bounds.height];
            }
            return [bounds.width, bounds.height];
        }
        var hasIntrinsicWidth = hasIntrinsicValue(intrinsicWidth);
        var hasIntrinsicHeight = hasIntrinsicValue(intrinsicHeight);
        var hasIntrinsicDimensions = hasIntrinsicWidth || hasIntrinsicHeight;
        // If the background-size is auto or auto auto:
        if (isAuto(first) && (!second || isAuto(second))) {
            // If the image has both horizontal and vertical intrinsic dimensions, it's rendered at that size.
            if (hasIntrinsicWidth && hasIntrinsicHeight) {
                return [intrinsicWidth, intrinsicHeight];
            }
            // If the image has no intrinsic dimensions and has no intrinsic proportions,
            // it's rendered at the size of the background positioning area.
            if (!hasIntrinsicProportion && !hasIntrinsicDimensions) {
                return [bounds.width, bounds.height];
            }
            // TODO If the image has no intrinsic dimensions but has intrinsic proportions, it's rendered as if contain had been specified instead.
            // If the image has only one intrinsic dimension and has intrinsic proportions, it's rendered at the size corresponding to that one dimension.
            // The other dimension is computed using the specified dimension and the intrinsic proportions.
            if (hasIntrinsicDimensions && hasIntrinsicProportion) {
                var width_1 = hasIntrinsicWidth
                    ? intrinsicWidth
                    : intrinsicHeight * intrinsicProportion;
                var height_1 = hasIntrinsicHeight
                    ? intrinsicHeight
                    : intrinsicWidth / intrinsicProportion;
                return [width_1, height_1];
            }
            // If the image has only one intrinsic dimension but has no intrinsic proportions,
            // it's rendered using the specified dimension and the other dimension of the background positioning area.
            var width_2 = hasIntrinsicWidth ? intrinsicWidth : bounds.width;
            var height_2 = hasIntrinsicHeight ? intrinsicHeight : bounds.height;
            return [width_2, height_2];
        }
        // If the image has intrinsic proportions, it's stretched to the specified dimension.
        // The unspecified dimension is computed using the specified dimension and the intrinsic proportions.
        if (hasIntrinsicProportion) {
            var width_3 = 0;
            var height_3 = 0;
            if (isLengthPercentage(first)) {
                width_3 = getAbsoluteValue(first, bounds.width);
            }
            else if (isLengthPercentage(second)) {
                height_3 = getAbsoluteValue(second, bounds.height);
            }
            if (isAuto(first)) {
                width_3 = height_3 * intrinsicProportion;
            }
            else if (!second || isAuto(second)) {
                height_3 = width_3 / intrinsicProportion;
            }
            return [width_3, height_3];
        }
        // If the image has no intrinsic proportions, it's stretched to the specified dimension.
        // The unspecified dimension is computed using the image's corresponding intrinsic dimension,
        // if there is one. If there is no such intrinsic dimension,
        // it becomes the corresponding dimension of the background positioning area.
        var width = null;
        var height = null;
        if (isLengthPercentage(first)) {
            width = getAbsoluteValue(first, bounds.width);
        }
        else if (second && isLengthPercentage(second)) {
            height = getAbsoluteValue(second, bounds.height);
        }
        if (width !== null && (!second || isAuto(second))) {
            height =
                hasIntrinsicWidth && hasIntrinsicHeight
                    ? (width / intrinsicWidth) * intrinsicHeight
                    : bounds.height;
        }
        if (height !== null && isAuto(first)) {
            width =
                hasIntrinsicWidth && hasIntrinsicHeight
                    ? (height / intrinsicHeight) * intrinsicWidth
                    : bounds.width;
        }
        if (width !== null && height !== null) {
            return [width, height];
        }
        throw new Error("Unable to calculate background-size for element");
    };
    var getBackgroundValueForIndex = function (values, index) {
        var value = values[index];
        if (typeof value === 'undefined') {
            return values[0];
        }
        return value;
    };
    var calculateBackgroundRepeatPath = function (repeat, _a, _b, backgroundPositioningArea, backgroundPaintingArea) {
        var x = _a[0], y = _a[1];
        var width = _b[0], height = _b[1];
        switch (repeat) {
            case 2 /* REPEAT_X */:
                return [
                    new Vector(Math.round(backgroundPositioningArea.left), Math.round(backgroundPositioningArea.top + y)),
                    new Vector(Math.round(backgroundPositioningArea.left + backgroundPositioningArea.width), Math.round(backgroundPositioningArea.top + y)),
                    new Vector(Math.round(backgroundPositioningArea.left + backgroundPositioningArea.width), Math.round(height + backgroundPositioningArea.top + y)),
                    new Vector(Math.round(backgroundPositioningArea.left), Math.round(height + backgroundPositioningArea.top + y))
                ];
            case 3 /* REPEAT_Y */:
                return [
                    new Vector(Math.round(backgroundPositioningArea.left + x), Math.round(backgroundPositioningArea.top)),
                    new Vector(Math.round(backgroundPositioningArea.left + x + width), Math.round(backgroundPositioningArea.top)),
                    new Vector(Math.round(backgroundPositioningArea.left + x + width), Math.round(backgroundPositioningArea.height + backgroundPositioningArea.top)),
                    new Vector(Math.round(backgroundPositioningArea.left + x), Math.round(backgroundPositioningArea.height + backgroundPositioningArea.top))
                ];
            case 1 /* NO_REPEAT */:
                return [
                    new Vector(Math.round(backgroundPositioningArea.left + x), Math.round(backgroundPositioningArea.top + y)),
                    new Vector(Math.round(backgroundPositioningArea.left + x + width), Math.round(backgroundPositioningArea.top + y)),
                    new Vector(Math.round(backgroundPositioningArea.left + x + width), Math.round(backgroundPositioningArea.top + y + height)),
                    new Vector(Math.round(backgroundPositioningArea.left + x), Math.round(backgroundPositioningArea.top + y + height))
                ];
            default:
                return [
                    new Vector(Math.round(backgroundPaintingArea.left), Math.round(backgroundPaintingArea.top)),
                    new Vector(Math.round(backgroundPaintingArea.left + backgroundPaintingArea.width), Math.round(backgroundPaintingArea.top)),
                    new Vector(Math.round(backgroundPaintingArea.left + backgroundPaintingArea.width), Math.round(backgroundPaintingArea.height + backgroundPaintingArea.top)),
                    new Vector(Math.round(backgroundPaintingArea.left), Math.round(backgroundPaintingArea.height + backgroundPaintingArea.top))
                ];
        }
    };

    var SMALL_IMAGE = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';

    var SAMPLE_TEXT = 'Hidden Text';
    var FontMetrics = /** @class */ (function () {
        function FontMetrics(document) {
            this._data = {};
            this._document = document;
        }
        FontMetrics.prototype.parseMetrics = function (fontFamily, fontSize) {
            var container = this._document.createElement('div');
            var img = this._document.createElement('img');
            var span = this._document.createElement('span');
            var body = this._document.body;
            container.style.visibility = 'hidden';
            container.style.fontFamily = fontFamily;
            container.style.fontSize = fontSize;
            container.style.margin = '0';
            container.style.padding = '0';
            container.style.whiteSpace = 'nowrap';
            body.appendChild(container);
            img.src = SMALL_IMAGE;
            img.width = 1;
            img.height = 1;
            img.style.margin = '0';
            img.style.padding = '0';
            img.style.verticalAlign = 'baseline';
            span.style.fontFamily = fontFamily;
            span.style.fontSize = fontSize;
            span.style.margin = '0';
            span.style.padding = '0';
            span.appendChild(this._document.createTextNode(SAMPLE_TEXT));
            container.appendChild(span);
            container.appendChild(img);
            var baseline = img.offsetTop - span.offsetTop + 2;
            container.removeChild(span);
            container.appendChild(this._document.createTextNode(SAMPLE_TEXT));
            container.style.lineHeight = 'normal';
            img.style.verticalAlign = 'super';
            var middle = img.offsetTop - container.offsetTop + 2;
            body.removeChild(container);
            return { baseline: baseline, middle: middle };
        };
        FontMetrics.prototype.getMetrics = function (fontFamily, fontSize) {
            var key = fontFamily + " " + fontSize;
            if (typeof this._data[key] === 'undefined') {
                this._data[key] = this.parseMetrics(fontFamily, fontSize);
            }
            return this._data[key];
        };
        return FontMetrics;
    }());

    var Renderer = /** @class */ (function () {
        function Renderer(context, options) {
            this.context = context;
            this.options = options;
        }
        return Renderer;
    }());

    var MASK_OFFSET = 10000;
    var CanvasRenderer = /** @class */ (function (_super) {
        __extends(CanvasRenderer, _super);
        function CanvasRenderer(context, options) {
            var _this = _super.call(this, context, options) || this;
            _this._activeEffects = [];
            _this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
            _this.ctx = _this.canvas.getContext('2d');
            if (!options.canvas) {
                _this.canvas.width = Math.floor(options.width * options.scale);
                _this.canvas.height = Math.floor(options.height * options.scale);
                _this.canvas.style.width = options.width + "px";
                _this.canvas.style.height = options.height + "px";
            }
            _this.fontMetrics = new FontMetrics(document);
            _this.ctx.scale(_this.options.scale, _this.options.scale);
            _this.ctx.translate(-options.x, -options.y);
            _this.ctx.textBaseline = 'bottom';
            _this._activeEffects = [];
            _this.context.logger.debug("Canvas renderer initialized (" + options.width + "x" + options.height + ") with scale " + options.scale);
            return _this;
        }
        CanvasRenderer.prototype.applyEffects = function (effects) {
            var _this = this;
            while (this._activeEffects.length) {
                this.popEffect();
            }
            effects.forEach(function (effect) { return _this.applyEffect(effect); });
        };
        CanvasRenderer.prototype.applyEffect = function (effect) {
            this.ctx.save();
            if (isOpacityEffect(effect)) {
                this.ctx.globalAlpha = effect.opacity;
            }
            if (isTransformEffect(effect)) {
                this.ctx.translate(effect.offsetX, effect.offsetY);
                this.ctx.transform(effect.matrix[0], effect.matrix[1], effect.matrix[2], effect.matrix[3], effect.matrix[4], effect.matrix[5]);
                this.ctx.translate(-effect.offsetX, -effect.offsetY);
            }
            if (isClipEffect(effect)) {
                this.path(effect.path);
                this.ctx.clip();
            }
            this._activeEffects.push(effect);
        };
        CanvasRenderer.prototype.popEffect = function () {
            this._activeEffects.pop();
            this.ctx.restore();
        };
        CanvasRenderer.prototype.renderStack = function (stack) {
            return __awaiter(this, void 0, void 0, function () {
                var styles;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            styles = stack.element.container.styles;
                            if (!styles.isVisible()) return [3 /*break*/, 2];
                            return [4 /*yield*/, this.renderStackContent(stack)];
                        case 1:
                            _a.sent();
                            _a.label = 2;
                        case 2: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderNode = function (paint) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            if (contains(paint.container.flags, 16 /* DEBUG_RENDER */)) {
                                debugger;
                            }
                            if (!paint.container.styles.isVisible()) return [3 /*break*/, 3];
                            return [4 /*yield*/, this.renderNodeBackgroundAndBorders(paint)];
                        case 1:
                            _a.sent();
                            return [4 /*yield*/, this.renderNodeContent(paint)];
                        case 2:
                            _a.sent();
                            _a.label = 3;
                        case 3: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderTextWithLetterSpacing = function (text, letterSpacing, baseline) {
            var _this = this;
            if (letterSpacing === 0) {
                this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + baseline);
            }
            else {
                var letters = segmentGraphemes(text.text);
                letters.reduce(function (left, letter) {
                    _this.ctx.fillText(letter, left, text.bounds.top + baseline);
                    return left + _this.ctx.measureText(letter).width;
                }, text.bounds.left);
            }
        };
        CanvasRenderer.prototype.createFontStyle = function (styles) {
            var fontVariant = styles.fontVariant
                .filter(function (variant) { return variant === 'normal' || variant === 'small-caps'; })
                .join('');
            var fontFamily = fixIOSSystemFonts(styles.fontFamily).join(', ');
            var fontSize = isDimensionToken(styles.fontSize)
                ? "" + styles.fontSize.number + styles.fontSize.unit
                : styles.fontSize.number + "px";
            return [
                [styles.fontStyle, fontVariant, styles.fontWeight, fontSize, fontFamily].join(' '),
                fontFamily,
                fontSize
            ];
        };
        CanvasRenderer.prototype.renderTextNode = function (text, styles) {
            return __awaiter(this, void 0, void 0, function () {
                var _a, font, fontFamily, fontSize, _b, baseline, middle, paintOrder;
                var _this = this;
                return __generator(this, function (_c) {
                    _a = this.createFontStyle(styles), font = _a[0], fontFamily = _a[1], fontSize = _a[2];
                    this.ctx.font = font;
                    this.ctx.direction = styles.direction === 1 /* RTL */ ? 'rtl' : 'ltr';
                    this.ctx.textAlign = 'left';
                    this.ctx.textBaseline = 'alphabetic';
                    _b = this.fontMetrics.getMetrics(fontFamily, fontSize), baseline = _b.baseline, middle = _b.middle;
                    paintOrder = styles.paintOrder;
                    text.textBounds.forEach(function (text) {
                        paintOrder.forEach(function (paintOrderLayer) {
                            switch (paintOrderLayer) {
                                case 0 /* FILL */:
                                    _this.ctx.fillStyle = asString(styles.color);
                                    _this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline);
                                    var textShadows = styles.textShadow;
                                    if (textShadows.length && text.text.trim().length) {
                                        textShadows
                                            .slice(0)
                                            .reverse()
                                            .forEach(function (textShadow) {
                                            _this.ctx.shadowColor = asString(textShadow.color);
                                            _this.ctx.shadowOffsetX = textShadow.offsetX.number * _this.options.scale;
                                            _this.ctx.shadowOffsetY = textShadow.offsetY.number * _this.options.scale;
                                            _this.ctx.shadowBlur = textShadow.blur.number;
                                            _this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline);
                                        });
                                        _this.ctx.shadowColor = '';
                                        _this.ctx.shadowOffsetX = 0;
                                        _this.ctx.shadowOffsetY = 0;
                                        _this.ctx.shadowBlur = 0;
                                    }
                                    if (styles.textDecorationLine.length) {
                                        _this.ctx.fillStyle = asString(styles.textDecorationColor || styles.color);
                                        styles.textDecorationLine.forEach(function (textDecorationLine) {
                                            switch (textDecorationLine) {
                                                case 1 /* UNDERLINE */:
                                                    // Draws a line at the baseline of the font
                                                    // TODO As some browsers display the line as more than 1px if the font-size is big,
                                                    // need to take that into account both in position and size
                                                    _this.ctx.fillRect(text.bounds.left, Math.round(text.bounds.top + baseline), text.bounds.width, 1);
                                                    break;
                                                case 2 /* OVERLINE */:
                                                    _this.ctx.fillRect(text.bounds.left, Math.round(text.bounds.top), text.bounds.width, 1);
                                                    break;
                                                case 3 /* LINE_THROUGH */:
                                                    // TODO try and find exact position for line-through
                                                    _this.ctx.fillRect(text.bounds.left, Math.ceil(text.bounds.top + middle), text.bounds.width, 1);
                                                    break;
                                            }
                                        });
                                    }
                                    break;
                                case 1 /* STROKE */:
                                    if (styles.webkitTextStrokeWidth && text.text.trim().length) {
                                        _this.ctx.strokeStyle = asString(styles.webkitTextStrokeColor);
                                        _this.ctx.lineWidth = styles.webkitTextStrokeWidth;
                                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                                        _this.ctx.lineJoin = !!window.chrome ? 'miter' : 'round';
                                        _this.ctx.strokeText(text.text, text.bounds.left, text.bounds.top + baseline);
                                    }
                                    _this.ctx.strokeStyle = '';
                                    _this.ctx.lineWidth = 0;
                                    _this.ctx.lineJoin = 'miter';
                                    break;
                            }
                        });
                    });
                    return [2 /*return*/];
                });
            });
        };
        CanvasRenderer.prototype.renderReplacedElement = function (container, curves, image) {
            if (image && container.intrinsicWidth > 0 && container.intrinsicHeight > 0) {
                var box = contentBox(container);
                var path = calculatePaddingBoxPath(curves);
                this.path(path);
                this.ctx.save();
                this.ctx.clip();
                this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, box.left, box.top, box.width, box.height);
                this.ctx.restore();
            }
        };
        CanvasRenderer.prototype.renderNodeContent = function (paint) {
            return __awaiter(this, void 0, void 0, function () {
                var container, curves, styles, _i, _a, child, image, image, iframeRenderer, canvas, size, _b, fontFamily, fontSize, baseline, bounds, x, textBounds, img, image, url, fontFamily, bounds;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            this.applyEffects(paint.getEffects(4 /* CONTENT */));
                            container = paint.container;
                            curves = paint.curves;
                            styles = container.styles;
                            _i = 0, _a = container.textNodes;
                            _c.label = 1;
                        case 1:
                            if (!(_i < _a.length)) return [3 /*break*/, 4];
                            child = _a[_i];
                            return [4 /*yield*/, this.renderTextNode(child, styles)];
                        case 2:
                            _c.sent();
                            _c.label = 3;
                        case 3:
                            _i++;
                            return [3 /*break*/, 1];
                        case 4:
                            if (!(container instanceof ImageElementContainer)) return [3 /*break*/, 8];
                            _c.label = 5;
                        case 5:
                            _c.trys.push([5, 7, , 8]);
                            return [4 /*yield*/, this.context.cache.match(container.src)];
                        case 6:
                            image = _c.sent();
                            this.renderReplacedElement(container, curves, image);
                            return [3 /*break*/, 8];
                        case 7:
                            _c.sent();
                            this.context.logger.error("Error loading image " + container.src);
                            return [3 /*break*/, 8];
                        case 8:
                            if (container instanceof CanvasElementContainer) {
                                this.renderReplacedElement(container, curves, container.canvas);
                            }
                            if (!(container instanceof SVGElementContainer)) return [3 /*break*/, 12];
                            _c.label = 9;
                        case 9:
                            _c.trys.push([9, 11, , 12]);
                            return [4 /*yield*/, this.context.cache.match(container.svg)];
                        case 10:
                            image = _c.sent();
                            this.renderReplacedElement(container, curves, image);
                            return [3 /*break*/, 12];
                        case 11:
                            _c.sent();
                            this.context.logger.error("Error loading svg " + container.svg.substring(0, 255));
                            return [3 /*break*/, 12];
                        case 12:
                            if (!(container instanceof IFrameElementContainer && container.tree)) return [3 /*break*/, 14];
                            iframeRenderer = new CanvasRenderer(this.context, {
                                scale: this.options.scale,
                                backgroundColor: container.backgroundColor,
                                x: 0,
                                y: 0,
                                width: container.width,
                                height: container.height
                            });
                            return [4 /*yield*/, iframeRenderer.render(container.tree)];
                        case 13:
                            canvas = _c.sent();
                            if (container.width && container.height) {
                                this.ctx.drawImage(canvas, 0, 0, container.width, container.height, container.bounds.left, container.bounds.top, container.bounds.width, container.bounds.height);
                            }
                            _c.label = 14;
                        case 14:
                            if (container instanceof InputElementContainer) {
                                size = Math.min(container.bounds.width, container.bounds.height);
                                if (container.type === CHECKBOX) {
                                    if (container.checked) {
                                        this.ctx.save();
                                        this.path([
                                            new Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79),
                                            new Vector(container.bounds.left + size * 0.16, container.bounds.top + size * 0.5549),
                                            new Vector(container.bounds.left + size * 0.27347, container.bounds.top + size * 0.44071),
                                            new Vector(container.bounds.left + size * 0.39694, container.bounds.top + size * 0.5649),
                                            new Vector(container.bounds.left + size * 0.72983, container.bounds.top + size * 0.23),
                                            new Vector(container.bounds.left + size * 0.84, container.bounds.top + size * 0.34085),
                                            new Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79)
                                        ]);
                                        this.ctx.fillStyle = asString(INPUT_COLOR);
                                        this.ctx.fill();
                                        this.ctx.restore();
                                    }
                                }
                                else if (container.type === RADIO) {
                                    if (container.checked) {
                                        this.ctx.save();
                                        this.ctx.beginPath();
                                        this.ctx.arc(container.bounds.left + size / 2, container.bounds.top + size / 2, size / 4, 0, Math.PI * 2, true);
                                        this.ctx.fillStyle = asString(INPUT_COLOR);
                                        this.ctx.fill();
                                        this.ctx.restore();
                                    }
                                }
                            }
                            if (isTextInputElement(container) && container.value.length) {
                                _b = this.createFontStyle(styles), fontFamily = _b[0], fontSize = _b[1];
                                baseline = this.fontMetrics.getMetrics(fontFamily, fontSize).baseline;
                                this.ctx.font = fontFamily;
                                this.ctx.fillStyle = asString(styles.color);
                                this.ctx.textBaseline = 'alphabetic';
                                this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
                                bounds = contentBox(container);
                                x = 0;
                                switch (container.styles.textAlign) {
                                    case 1 /* CENTER */:
                                        x += bounds.width / 2;
                                        break;
                                    case 2 /* RIGHT */:
                                        x += bounds.width;
                                        break;
                                }
                                textBounds = bounds.add(x, 0, 0, -bounds.height / 2 + 1);
                                this.ctx.save();
                                this.path([
                                    new Vector(bounds.left, bounds.top),
                                    new Vector(bounds.left + bounds.width, bounds.top),
                                    new Vector(bounds.left + bounds.width, bounds.top + bounds.height),
                                    new Vector(bounds.left, bounds.top + bounds.height)
                                ]);
                                this.ctx.clip();
                                this.renderTextWithLetterSpacing(new TextBounds(container.value, textBounds), styles.letterSpacing, baseline);
                                this.ctx.restore();
                                this.ctx.textBaseline = 'alphabetic';
                                this.ctx.textAlign = 'left';
                            }
                            if (!contains(container.styles.display, 2048 /* LIST_ITEM */)) return [3 /*break*/, 20];
                            if (!(container.styles.listStyleImage !== null)) return [3 /*break*/, 19];
                            img = container.styles.listStyleImage;
                            if (!(img.type === 0 /* URL */)) return [3 /*break*/, 18];
                            image = void 0;
                            url = img.url;
                            _c.label = 15;
                        case 15:
                            _c.trys.push([15, 17, , 18]);
                            return [4 /*yield*/, this.context.cache.match(url)];
                        case 16:
                            image = _c.sent();
                            this.ctx.drawImage(image, container.bounds.left - (image.width + 10), container.bounds.top);
                            return [3 /*break*/, 18];
                        case 17:
                            _c.sent();
                            this.context.logger.error("Error loading list-style-image " + url);
                            return [3 /*break*/, 18];
                        case 18: return [3 /*break*/, 20];
                        case 19:
                            if (paint.listValue && container.styles.listStyleType !== -1 /* NONE */) {
                                fontFamily = this.createFontStyle(styles)[0];
                                this.ctx.font = fontFamily;
                                this.ctx.fillStyle = asString(styles.color);
                                this.ctx.textBaseline = 'middle';
                                this.ctx.textAlign = 'right';
                                bounds = new Bounds(container.bounds.left, container.bounds.top + getAbsoluteValue(container.styles.paddingTop, container.bounds.width), container.bounds.width, computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 1);
                                this.renderTextWithLetterSpacing(new TextBounds(paint.listValue, bounds), styles.letterSpacing, computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 2);
                                this.ctx.textBaseline = 'bottom';
                                this.ctx.textAlign = 'left';
                            }
                            _c.label = 20;
                        case 20: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderStackContent = function (stack) {
            return __awaiter(this, void 0, void 0, function () {
                var _i, _a, child, _b, _c, child, _d, _e, child, _f, _g, child, _h, _j, child, _k, _l, child, _m, _o, child;
                return __generator(this, function (_p) {
                    switch (_p.label) {
                        case 0:
                            if (contains(stack.element.container.flags, 16 /* DEBUG_RENDER */)) {
                                debugger;
                            }
                            // https://www.w3.org/TR/css-position-3/#painting-order
                            // 1. the background and borders of the element forming the stacking context.
                            return [4 /*yield*/, this.renderNodeBackgroundAndBorders(stack.element)];
                        case 1:
                            // https://www.w3.org/TR/css-position-3/#painting-order
                            // 1. the background and borders of the element forming the stacking context.
                            _p.sent();
                            _i = 0, _a = stack.negativeZIndex;
                            _p.label = 2;
                        case 2:
                            if (!(_i < _a.length)) return [3 /*break*/, 5];
                            child = _a[_i];
                            return [4 /*yield*/, this.renderStack(child)];
                        case 3:
                            _p.sent();
                            _p.label = 4;
                        case 4:
                            _i++;
                            return [3 /*break*/, 2];
                        case 5: 
                        // 3. For all its in-flow, non-positioned, block-level descendants in tree order:
                        return [4 /*yield*/, this.renderNodeContent(stack.element)];
                        case 6:
                            // 3. For all its in-flow, non-positioned, block-level descendants in tree order:
                            _p.sent();
                            _b = 0, _c = stack.nonInlineLevel;
                            _p.label = 7;
                        case 7:
                            if (!(_b < _c.length)) return [3 /*break*/, 10];
                            child = _c[_b];
                            return [4 /*yield*/, this.renderNode(child)];
                        case 8:
                            _p.sent();
                            _p.label = 9;
                        case 9:
                            _b++;
                            return [3 /*break*/, 7];
                        case 10:
                            _d = 0, _e = stack.nonPositionedFloats;
                            _p.label = 11;
                        case 11:
                            if (!(_d < _e.length)) return [3 /*break*/, 14];
                            child = _e[_d];
                            return [4 /*yield*/, this.renderStack(child)];
                        case 12:
                            _p.sent();
                            _p.label = 13;
                        case 13:
                            _d++;
                            return [3 /*break*/, 11];
                        case 14:
                            _f = 0, _g = stack.nonPositionedInlineLevel;
                            _p.label = 15;
                        case 15:
                            if (!(_f < _g.length)) return [3 /*break*/, 18];
                            child = _g[_f];
                            return [4 /*yield*/, this.renderStack(child)];
                        case 16:
                            _p.sent();
                            _p.label = 17;
                        case 17:
                            _f++;
                            return [3 /*break*/, 15];
                        case 18:
                            _h = 0, _j = stack.inlineLevel;
                            _p.label = 19;
                        case 19:
                            if (!(_h < _j.length)) return [3 /*break*/, 22];
                            child = _j[_h];
                            return [4 /*yield*/, this.renderNode(child)];
                        case 20:
                            _p.sent();
                            _p.label = 21;
                        case 21:
                            _h++;
                            return [3 /*break*/, 19];
                        case 22:
                            _k = 0, _l = stack.zeroOrAutoZIndexOrTransformedOrOpacity;
                            _p.label = 23;
                        case 23:
                            if (!(_k < _l.length)) return [3 /*break*/, 26];
                            child = _l[_k];
                            return [4 /*yield*/, this.renderStack(child)];
                        case 24:
                            _p.sent();
                            _p.label = 25;
                        case 25:
                            _k++;
                            return [3 /*break*/, 23];
                        case 26:
                            _m = 0, _o = stack.positiveZIndex;
                            _p.label = 27;
                        case 27:
                            if (!(_m < _o.length)) return [3 /*break*/, 30];
                            child = _o[_m];
                            return [4 /*yield*/, this.renderStack(child)];
                        case 28:
                            _p.sent();
                            _p.label = 29;
                        case 29:
                            _m++;
                            return [3 /*break*/, 27];
                        case 30: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.mask = function (paths) {
            this.ctx.beginPath();
            this.ctx.moveTo(0, 0);
            this.ctx.lineTo(this.canvas.width, 0);
            this.ctx.lineTo(this.canvas.width, this.canvas.height);
            this.ctx.lineTo(0, this.canvas.height);
            this.ctx.lineTo(0, 0);
            this.formatPath(paths.slice(0).reverse());
            this.ctx.closePath();
        };
        CanvasRenderer.prototype.path = function (paths) {
            this.ctx.beginPath();
            this.formatPath(paths);
            this.ctx.closePath();
        };
        CanvasRenderer.prototype.formatPath = function (paths) {
            var _this = this;
            paths.forEach(function (point, index) {
                var start = isBezierCurve(point) ? point.start : point;
                if (index === 0) {
                    _this.ctx.moveTo(start.x, start.y);
                }
                else {
                    _this.ctx.lineTo(start.x, start.y);
                }
                if (isBezierCurve(point)) {
                    _this.ctx.bezierCurveTo(point.startControl.x, point.startControl.y, point.endControl.x, point.endControl.y, point.end.x, point.end.y);
                }
            });
        };
        CanvasRenderer.prototype.renderRepeat = function (path, pattern, offsetX, offsetY) {
            this.path(path);
            this.ctx.fillStyle = pattern;
            this.ctx.translate(offsetX, offsetY);
            this.ctx.fill();
            this.ctx.translate(-offsetX, -offsetY);
        };
        CanvasRenderer.prototype.resizeImage = function (image, width, height) {
            var _a;
            if (image.width === width && image.height === height) {
                return image;
            }
            var ownerDocument = (_a = this.canvas.ownerDocument) !== null && _a !== void 0 ? _a : document;
            var canvas = ownerDocument.createElement('canvas');
            canvas.width = Math.max(1, width);
            canvas.height = Math.max(1, height);
            var ctx = canvas.getContext('2d');
            ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);
            return canvas;
        };
        CanvasRenderer.prototype.renderBackgroundImage = function (container) {
            return __awaiter(this, void 0, void 0, function () {
                var index, _loop_1, this_1, _i, _a, backgroundImage;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            index = container.styles.backgroundImage.length - 1;
                            _loop_1 = function (backgroundImage) {
                                var image, url, _c, path, x, y, width, height, pattern, _d, path, x, y, width, height, _e, lineLength, x0, x1, y0, y1, canvas, ctx, gradient_1, pattern, _f, path, left, top_1, width, height, position, x, y, _g, rx, ry, radialGradient_1, midX, midY, f, invF;
                                return __generator(this, function (_h) {
                                    switch (_h.label) {
                                        case 0:
                                            if (!(backgroundImage.type === 0 /* URL */)) return [3 /*break*/, 5];
                                            image = void 0;
                                            url = backgroundImage.url;
                                            _h.label = 1;
                                        case 1:
                                            _h.trys.push([1, 3, , 4]);
                                            return [4 /*yield*/, this_1.context.cache.match(url)];
                                        case 2:
                                            image = _h.sent();
                                            return [3 /*break*/, 4];
                                        case 3:
                                            _h.sent();
                                            this_1.context.logger.error("Error loading background-image " + url);
                                            return [3 /*break*/, 4];
                                        case 4:
                                            if (image) {
                                                _c = calculateBackgroundRendering(container, index, [
                                                    image.width,
                                                    image.height,
                                                    image.width / image.height
                                                ]), path = _c[0], x = _c[1], y = _c[2], width = _c[3], height = _c[4];
                                                pattern = this_1.ctx.createPattern(this_1.resizeImage(image, width, height), 'repeat');
                                                this_1.renderRepeat(path, pattern, x, y);
                                            }
                                            return [3 /*break*/, 6];
                                        case 5:
                                            if (isLinearGradient(backgroundImage)) {
                                                _d = calculateBackgroundRendering(container, index, [null, null, null]), path = _d[0], x = _d[1], y = _d[2], width = _d[3], height = _d[4];
                                                _e = calculateGradientDirection(backgroundImage.angle, width, height), lineLength = _e[0], x0 = _e[1], x1 = _e[2], y0 = _e[3], y1 = _e[4];
                                                canvas = document.createElement('canvas');
                                                canvas.width = width;
                                                canvas.height = height;
                                                ctx = canvas.getContext('2d');
                                                gradient_1 = ctx.createLinearGradient(x0, y0, x1, y1);
                                                processColorStops(backgroundImage.stops, lineLength).forEach(function (colorStop) {
                                                    return gradient_1.addColorStop(colorStop.stop, asString(colorStop.color));
                                                });
                                                ctx.fillStyle = gradient_1;
                                                ctx.fillRect(0, 0, width, height);
                                                if (width > 0 && height > 0) {
                                                    pattern = this_1.ctx.createPattern(canvas, 'repeat');
                                                    this_1.renderRepeat(path, pattern, x, y);
                                                }
                                            }
                                            else if (isRadialGradient(backgroundImage)) {
                                                _f = calculateBackgroundRendering(container, index, [
                                                    null,
                                                    null,
                                                    null
                                                ]), path = _f[0], left = _f[1], top_1 = _f[2], width = _f[3], height = _f[4];
                                                position = backgroundImage.position.length === 0 ? [FIFTY_PERCENT] : backgroundImage.position;
                                                x = getAbsoluteValue(position[0], width);
                                                y = getAbsoluteValue(position[position.length - 1], height);
                                                _g = calculateRadius(backgroundImage, x, y, width, height), rx = _g[0], ry = _g[1];
                                                if (rx > 0 && ry > 0) {
                                                    radialGradient_1 = this_1.ctx.createRadialGradient(left + x, top_1 + y, 0, left + x, top_1 + y, rx);
                                                    processColorStops(backgroundImage.stops, rx * 2).forEach(function (colorStop) {
                                                        return radialGradient_1.addColorStop(colorStop.stop, asString(colorStop.color));
                                                    });
                                                    this_1.path(path);
                                                    this_1.ctx.fillStyle = radialGradient_1;
                                                    if (rx !== ry) {
                                                        midX = container.bounds.left + 0.5 * container.bounds.width;
                                                        midY = container.bounds.top + 0.5 * container.bounds.height;
                                                        f = ry / rx;
                                                        invF = 1 / f;
                                                        this_1.ctx.save();
                                                        this_1.ctx.translate(midX, midY);
                                                        this_1.ctx.transform(1, 0, 0, f, 0, 0);
                                                        this_1.ctx.translate(-midX, -midY);
                                                        this_1.ctx.fillRect(left, invF * (top_1 - midY) + midY, width, height * invF);
                                                        this_1.ctx.restore();
                                                    }
                                                    else {
                                                        this_1.ctx.fill();
                                                    }
                                                }
                                            }
                                            _h.label = 6;
                                        case 6:
                                            index--;
                                            return [2 /*return*/];
                                    }
                                });
                            };
                            this_1 = this;
                            _i = 0, _a = container.styles.backgroundImage.slice(0).reverse();
                            _b.label = 1;
                        case 1:
                            if (!(_i < _a.length)) return [3 /*break*/, 4];
                            backgroundImage = _a[_i];
                            return [5 /*yield**/, _loop_1(backgroundImage)];
                        case 2:
                            _b.sent();
                            _b.label = 3;
                        case 3:
                            _i++;
                            return [3 /*break*/, 1];
                        case 4: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderSolidBorder = function (color, side, curvePoints) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    this.path(parsePathForBorder(curvePoints, side));
                    this.ctx.fillStyle = asString(color);
                    this.ctx.fill();
                    return [2 /*return*/];
                });
            });
        };
        CanvasRenderer.prototype.renderDoubleBorder = function (color, width, side, curvePoints) {
            return __awaiter(this, void 0, void 0, function () {
                var outerPaths, innerPaths;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            if (!(width < 3)) return [3 /*break*/, 2];
                            return [4 /*yield*/, this.renderSolidBorder(color, side, curvePoints)];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                        case 2:
                            outerPaths = parsePathForBorderDoubleOuter(curvePoints, side);
                            this.path(outerPaths);
                            this.ctx.fillStyle = asString(color);
                            this.ctx.fill();
                            innerPaths = parsePathForBorderDoubleInner(curvePoints, side);
                            this.path(innerPaths);
                            this.ctx.fill();
                            return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderNodeBackgroundAndBorders = function (paint) {
            return __awaiter(this, void 0, void 0, function () {
                var styles, hasBackground, borders, backgroundPaintingArea, side, _i, borders_1, border;
                var _this = this;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            this.applyEffects(paint.getEffects(2 /* BACKGROUND_BORDERS */));
                            styles = paint.container.styles;
                            hasBackground = !isTransparent(styles.backgroundColor) || styles.backgroundImage.length;
                            borders = [
                                { style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth },
                                { style: styles.borderRightStyle, color: styles.borderRightColor, width: styles.borderRightWidth },
                                { style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth },
                                { style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth }
                            ];
                            backgroundPaintingArea = calculateBackgroundCurvedPaintingArea(getBackgroundValueForIndex(styles.backgroundClip, 0), paint.curves);
                            if (!(hasBackground || styles.boxShadow.length)) return [3 /*break*/, 2];
                            this.ctx.save();
                            this.path(backgroundPaintingArea);
                            this.ctx.clip();
                            if (!isTransparent(styles.backgroundColor)) {
                                this.ctx.fillStyle = asString(styles.backgroundColor);
                                this.ctx.fill();
                            }
                            return [4 /*yield*/, this.renderBackgroundImage(paint.container)];
                        case 1:
                            _a.sent();
                            this.ctx.restore();
                            styles.boxShadow
                                .slice(0)
                                .reverse()
                                .forEach(function (shadow) {
                                _this.ctx.save();
                                var borderBoxArea = calculateBorderBoxPath(paint.curves);
                                var maskOffset = shadow.inset ? 0 : MASK_OFFSET;
                                var shadowPaintingArea = transformPath(borderBoxArea, -maskOffset + (shadow.inset ? 1 : -1) * shadow.spread.number, (shadow.inset ? 1 : -1) * shadow.spread.number, shadow.spread.number * (shadow.inset ? -2 : 2), shadow.spread.number * (shadow.inset ? -2 : 2));
                                if (shadow.inset) {
                                    _this.path(borderBoxArea);
                                    _this.ctx.clip();
                                    _this.mask(shadowPaintingArea);
                                }
                                else {
                                    _this.mask(borderBoxArea);
                                    _this.ctx.clip();
                                    _this.path(shadowPaintingArea);
                                }
                                _this.ctx.shadowOffsetX = shadow.offsetX.number + maskOffset;
                                _this.ctx.shadowOffsetY = shadow.offsetY.number;
                                _this.ctx.shadowColor = asString(shadow.color);
                                _this.ctx.shadowBlur = shadow.blur.number;
                                _this.ctx.fillStyle = shadow.inset ? asString(shadow.color) : 'rgba(0,0,0,1)';
                                _this.ctx.fill();
                                _this.ctx.restore();
                            });
                            _a.label = 2;
                        case 2:
                            side = 0;
                            _i = 0, borders_1 = borders;
                            _a.label = 3;
                        case 3:
                            if (!(_i < borders_1.length)) return [3 /*break*/, 13];
                            border = borders_1[_i];
                            if (!(border.style !== 0 /* NONE */ && !isTransparent(border.color) && border.width > 0)) return [3 /*break*/, 11];
                            if (!(border.style === 2 /* DASHED */)) return [3 /*break*/, 5];
                            return [4 /*yield*/, this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 2 /* DASHED */)];
                        case 4:
                            _a.sent();
                            return [3 /*break*/, 11];
                        case 5:
                            if (!(border.style === 3 /* DOTTED */)) return [3 /*break*/, 7];
                            return [4 /*yield*/, this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 3 /* DOTTED */)];
                        case 6:
                            _a.sent();
                            return [3 /*break*/, 11];
                        case 7:
                            if (!(border.style === 4 /* DOUBLE */)) return [3 /*break*/, 9];
                            return [4 /*yield*/, this.renderDoubleBorder(border.color, border.width, side, paint.curves)];
                        case 8:
                            _a.sent();
                            return [3 /*break*/, 11];
                        case 9: return [4 /*yield*/, this.renderSolidBorder(border.color, side, paint.curves)];
                        case 10:
                            _a.sent();
                            _a.label = 11;
                        case 11:
                            side++;
                            _a.label = 12;
                        case 12:
                            _i++;
                            return [3 /*break*/, 3];
                        case 13: return [2 /*return*/];
                    }
                });
            });
        };
        CanvasRenderer.prototype.renderDashedDottedBorder = function (color, width, side, curvePoints, style) {
            return __awaiter(this, void 0, void 0, function () {
                var strokePaths, boxPaths, startX, startY, endX, endY, length, dashLength, spaceLength, useLineDash, multiplier, numberOfDashes, minSpace, maxSpace, path1, path2, path1, path2;
                return __generator(this, function (_a) {
                    this.ctx.save();
                    strokePaths = parsePathForBorderStroke(curvePoints, side);
                    boxPaths = parsePathForBorder(curvePoints, side);
                    if (style === 2 /* DASHED */) {
                        this.path(boxPaths);
                        this.ctx.clip();
                    }
                    if (isBezierCurve(boxPaths[0])) {
                        startX = boxPaths[0].start.x;
                        startY = boxPaths[0].start.y;
                    }
                    else {
                        startX = boxPaths[0].x;
                        startY = boxPaths[0].y;
                    }
                    if (isBezierCurve(boxPaths[1])) {
                        endX = boxPaths[1].end.x;
                        endY = boxPaths[1].end.y;
                    }
                    else {
                        endX = boxPaths[1].x;
                        endY = boxPaths[1].y;
                    }
                    if (side === 0 || side === 2) {
                        length = Math.abs(startX - endX);
                    }
                    else {
                        length = Math.abs(startY - endY);
                    }
                    this.ctx.beginPath();
                    if (style === 3 /* DOTTED */) {
                        this.formatPath(strokePaths);
                    }
                    else {
                        this.formatPath(boxPaths.slice(0, 2));
                    }
                    dashLength = width < 3 ? width * 3 : width * 2;
                    spaceLength = width < 3 ? width * 2 : width;
                    if (style === 3 /* DOTTED */) {
                        dashLength = width;
                        spaceLength = width;
                    }
                    useLineDash = true;
                    if (length <= dashLength * 2) {
                        useLineDash = false;
                    }
                    else if (length <= dashLength * 2 + spaceLength) {
                        multiplier = length / (2 * dashLength + spaceLength);
                        dashLength *= multiplier;
                        spaceLength *= multiplier;
                    }
                    else {
                        numberOfDashes = Math.floor((length + spaceLength) / (dashLength + spaceLength));
                        minSpace = (length - numberOfDashes * dashLength) / (numberOfDashes - 1);
                        maxSpace = (length - (numberOfDashes + 1) * dashLength) / numberOfDashes;
                        spaceLength =
                            maxSpace <= 0 || Math.abs(spaceLength - minSpace) < Math.abs(spaceLength - maxSpace)
                                ? minSpace
                                : maxSpace;
                    }
                    if (useLineDash) {
                        if (style === 3 /* DOTTED */) {
                            this.ctx.setLineDash([0, dashLength + spaceLength]);
                        }
                        else {
                            this.ctx.setLineDash([dashLength, spaceLength]);
                        }
                    }
                    if (style === 3 /* DOTTED */) {
                        this.ctx.lineCap = 'round';
                        this.ctx.lineWidth = width;
                    }
                    else {
                        this.ctx.lineWidth = width * 2 + 1.1;
                    }
                    this.ctx.strokeStyle = asString(color);
                    this.ctx.stroke();
                    this.ctx.setLineDash([]);
                    // dashed round edge gap
                    if (style === 2 /* DASHED */) {
                        if (isBezierCurve(boxPaths[0])) {
                            path1 = boxPaths[3];
                            path2 = boxPaths[0];
                            this.ctx.beginPath();
                            this.formatPath([new Vector(path1.end.x, path1.end.y), new Vector(path2.start.x, path2.start.y)]);
                            this.ctx.stroke();
                        }
                        if (isBezierCurve(boxPaths[1])) {
                            path1 = boxPaths[1];
                            path2 = boxPaths[2];
                            this.ctx.beginPath();
                            this.formatPath([new Vector(path1.end.x, path1.end.y), new Vector(path2.start.x, path2.start.y)]);
                            this.ctx.stroke();
                        }
                    }
                    this.ctx.restore();
                    return [2 /*return*/];
                });
            });
        };
        CanvasRenderer.prototype.render = function (element) {
            return __awaiter(this, void 0, void 0, function () {
                var stack;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            if (this.options.backgroundColor) {
                                this.ctx.fillStyle = asString(this.options.backgroundColor);
                                this.ctx.fillRect(this.options.x, this.options.y, this.options.width, this.options.height);
                            }
                            stack = parseStackingContexts(element);
                            return [4 /*yield*/, this.renderStack(stack)];
                        case 1:
                            _a.sent();
                            this.applyEffects([]);
                            return [2 /*return*/, this.canvas];
                    }
                });
            });
        };
        return CanvasRenderer;
    }(Renderer));
    var isTextInputElement = function (container) {
        if (container instanceof TextareaElementContainer) {
            return true;
        }
        else if (container instanceof SelectElementContainer) {
            return true;
        }
        else if (container instanceof InputElementContainer && container.type !== RADIO && container.type !== CHECKBOX) {
            return true;
        }
        return false;
    };
    var calculateBackgroundCurvedPaintingArea = function (clip, curves) {
        switch (clip) {
            case 0 /* BORDER_BOX */:
                return calculateBorderBoxPath(curves);
            case 2 /* CONTENT_BOX */:
                return calculateContentBoxPath(curves);
            case 1 /* PADDING_BOX */:
            default:
                return calculatePaddingBoxPath(curves);
        }
    };
    var canvasTextAlign = function (textAlign) {
        switch (textAlign) {
            case 1 /* CENTER */:
                return 'center';
            case 2 /* RIGHT */:
                return 'right';
            case 0 /* LEFT */:
            default:
                return 'left';
        }
    };
    // see https://github.com/niklasvh/html2canvas/pull/2645
    var iOSBrokenFonts = ['-apple-system', 'system-ui'];
    var fixIOSSystemFonts = function (fontFamilies) {
        return /iPhone OS 15_(0|1)/.test(window.navigator.userAgent)
            ? fontFamilies.filter(function (fontFamily) { return iOSBrokenFonts.indexOf(fontFamily) === -1; })
            : fontFamilies;
    };

    var ForeignObjectRenderer = /** @class */ (function (_super) {
        __extends(ForeignObjectRenderer, _super);
        function ForeignObjectRenderer(context, options) {
            var _this = _super.call(this, context, options) || this;
            _this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
            _this.ctx = _this.canvas.getContext('2d');
            _this.options = options;
            _this.canvas.width = Math.floor(options.width * options.scale);
            _this.canvas.height = Math.floor(options.height * options.scale);
            _this.canvas.style.width = options.width + "px";
            _this.canvas.style.height = options.height + "px";
            _this.ctx.scale(_this.options.scale, _this.options.scale);
            _this.ctx.translate(-options.x, -options.y);
            _this.context.logger.debug("EXPERIMENTAL ForeignObject renderer initialized (" + options.width + "x" + options.height + " at " + options.x + "," + options.y + ") with scale " + options.scale);
            return _this;
        }
        ForeignObjectRenderer.prototype.render = function (element) {
            return __awaiter(this, void 0, void 0, function () {
                var svg, img;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            svg = createForeignObjectSVG(this.options.width * this.options.scale, this.options.height * this.options.scale, this.options.scale, this.options.scale, element);
                            return [4 /*yield*/, loadSerializedSVG(svg)];
                        case 1:
                            img = _a.sent();
                            if (this.options.backgroundColor) {
                                this.ctx.fillStyle = asString(this.options.backgroundColor);
                                this.ctx.fillRect(0, 0, this.options.width * this.options.scale, this.options.height * this.options.scale);
                            }
                            this.ctx.drawImage(img, -this.options.x * this.options.scale, -this.options.y * this.options.scale);
                            return [2 /*return*/, this.canvas];
                    }
                });
            });
        };
        return ForeignObjectRenderer;
    }(Renderer));
    var loadSerializedSVG = function (svg) {
        return new Promise(function (resolve, reject) {
            var img = new Image();
            img.onload = function () {
                resolve(img);
            };
            img.onerror = reject;
            img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(new XMLSerializer().serializeToString(svg));
        });
    };

    var Logger = /** @class */ (function () {
        function Logger(_a) {
            var id = _a.id, enabled = _a.enabled;
            this.id = id;
            this.enabled = enabled;
            this.start = Date.now();
        }
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        Logger.prototype.debug = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            if (this.enabled) {
                // eslint-disable-next-line no-console
                if (typeof window !== 'undefined' && window.console && typeof console.debug === 'function') {
                    // eslint-disable-next-line no-console
                    console.debug.apply(console, __spreadArray([this.id, this.getTime() + "ms"], args));
                }
                else {
                    this.info.apply(this, args);
                }
            }
        };
        Logger.prototype.getTime = function () {
            return Date.now() - this.start;
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        Logger.prototype.info = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            if (this.enabled) {
                // eslint-disable-next-line no-console
                if (typeof window !== 'undefined' && window.console && typeof console.info === 'function') {
                    // eslint-disable-next-line no-console
                    console.info.apply(console, __spreadArray([this.id, this.getTime() + "ms"], args));
                }
            }
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        Logger.prototype.warn = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            if (this.enabled) {
                // eslint-disable-next-line no-console
                if (typeof window !== 'undefined' && window.console && typeof console.warn === 'function') {
                    // eslint-disable-next-line no-console
                    console.warn.apply(console, __spreadArray([this.id, this.getTime() + "ms"], args));
                }
                else {
                    this.info.apply(this, args);
                }
            }
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        Logger.prototype.error = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            if (this.enabled) {
                // eslint-disable-next-line no-console
                if (typeof window !== 'undefined' && window.console && typeof console.error === 'function') {
                    // eslint-disable-next-line no-console
                    console.error.apply(console, __spreadArray([this.id, this.getTime() + "ms"], args));
                }
                else {
                    this.info.apply(this, args);
                }
            }
        };
        Logger.instances = {};
        return Logger;
    }());

    var Context = /** @class */ (function () {
        function Context(options, windowBounds) {
            var _a;
            this.windowBounds = windowBounds;
            this.instanceName = "#" + Context.instanceCount++;
            this.logger = new Logger({ id: this.instanceName, enabled: options.logging });
            this.cache = (_a = options.cache) !== null && _a !== void 0 ? _a : new Cache(this, options);
        }
        Context.instanceCount = 1;
        return Context;
    }());

    var html2canvas = function (element, options) {
        if (options === void 0) { options = {}; }
        return renderElement(element, options);
    };
    if (typeof window !== 'undefined') {
        CacheStorage.setContext(window);
    }
    var renderElement = function (element, opts) { return __awaiter(void 0, void 0, void 0, function () {
        var ownerDocument, defaultView, resourceOptions, contextOptions, windowOptions, windowBounds, context, foreignObjectRendering, cloneOptions, documentCloner, clonedElement, container, _a, width, height, left, top, backgroundColor, renderOptions, canvas, renderer, root, renderer;
        var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
        return __generator(this, function (_u) {
            switch (_u.label) {
                case 0:
                    if (!element || typeof element !== 'object') {
                        return [2 /*return*/, Promise.reject('Invalid element provided as first argument')];
                    }
                    ownerDocument = element.ownerDocument;
                    if (!ownerDocument) {
                        throw new Error("Element is not attached to a Document");
                    }
                    defaultView = ownerDocument.defaultView;
                    if (!defaultView) {
                        throw new Error("Document is not attached to a Window");
                    }
                    resourceOptions = {
                        allowTaint: (_b = opts.allowTaint) !== null && _b !== void 0 ? _b : false,
                        imageTimeout: (_c = opts.imageTimeout) !== null && _c !== void 0 ? _c : 15000,
                        proxy: opts.proxy,
                        useCORS: (_d = opts.useCORS) !== null && _d !== void 0 ? _d : false
                    };
                    contextOptions = __assign({ logging: (_e = opts.logging) !== null && _e !== void 0 ? _e : true, cache: opts.cache }, resourceOptions);
                    windowOptions = {
                        windowWidth: (_f = opts.windowWidth) !== null && _f !== void 0 ? _f : defaultView.innerWidth,
                        windowHeight: (_g = opts.windowHeight) !== null && _g !== void 0 ? _g : defaultView.innerHeight,
                        scrollX: (_h = opts.scrollX) !== null && _h !== void 0 ? _h : defaultView.pageXOffset,
                        scrollY: (_j = opts.scrollY) !== null && _j !== void 0 ? _j : defaultView.pageYOffset
                    };
                    windowBounds = new Bounds(windowOptions.scrollX, windowOptions.scrollY, windowOptions.windowWidth, windowOptions.windowHeight);
                    context = new Context(contextOptions, windowBounds);
                    foreignObjectRendering = (_k = opts.foreignObjectRendering) !== null && _k !== void 0 ? _k : false;
                    cloneOptions = {
                        allowTaint: (_l = opts.allowTaint) !== null && _l !== void 0 ? _l : false,
                        onclone: opts.onclone,
                        ignoreElements: opts.ignoreElements,
                        inlineImages: foreignObjectRendering,
                        copyStyles: foreignObjectRendering
                    };
                    context.logger.debug("Starting document clone with size " + windowBounds.width + "x" + windowBounds.height + " scrolled to " + -windowBounds.left + "," + -windowBounds.top);
                    documentCloner = new DocumentCloner(context, element, cloneOptions);
                    clonedElement = documentCloner.clonedReferenceElement;
                    if (!clonedElement) {
                        return [2 /*return*/, Promise.reject("Unable to find element in cloned iframe")];
                    }
                    return [4 /*yield*/, documentCloner.toIFrame(ownerDocument, windowBounds)];
                case 1:
                    container = _u.sent();
                    _a = isBodyElement(clonedElement) || isHTMLElement(clonedElement)
                        ? parseDocumentSize(clonedElement.ownerDocument)
                        : parseBounds(context, clonedElement), width = _a.width, height = _a.height, left = _a.left, top = _a.top;
                    backgroundColor = parseBackgroundColor(context, clonedElement, opts.backgroundColor);
                    renderOptions = {
                        canvas: opts.canvas,
                        backgroundColor: backgroundColor,
                        scale: (_o = (_m = opts.scale) !== null && _m !== void 0 ? _m : defaultView.devicePixelRatio) !== null && _o !== void 0 ? _o : 1,
                        x: ((_p = opts.x) !== null && _p !== void 0 ? _p : 0) + left,
                        y: ((_q = opts.y) !== null && _q !== void 0 ? _q : 0) + top,
                        width: (_r = opts.width) !== null && _r !== void 0 ? _r : Math.ceil(width),
                        height: (_s = opts.height) !== null && _s !== void 0 ? _s : Math.ceil(height)
                    };
                    if (!foreignObjectRendering) return [3 /*break*/, 3];
                    context.logger.debug("Document cloned, using foreign object rendering");
                    renderer = new ForeignObjectRenderer(context, renderOptions);
                    return [4 /*yield*/, renderer.render(clonedElement)];
                case 2:
                    canvas = _u.sent();
                    return [3 /*break*/, 5];
                case 3:
                    context.logger.debug("Document cloned, element located at " + left + "," + top + " with size " + width + "x" + height + " using computed rendering");
                    context.logger.debug("Starting DOM parsing");
                    root = parseTree(context, clonedElement);
                    if (backgroundColor === root.styles.backgroundColor) {
                        root.styles.backgroundColor = COLORS.TRANSPARENT;
                    }
                    context.logger.debug("Starting renderer for element at " + renderOptions.x + "," + renderOptions.y + " with size " + renderOptions.width + "x" + renderOptions.height);
                    renderer = new CanvasRenderer(context, renderOptions);
                    return [4 /*yield*/, renderer.render(root)];
                case 4:
                    canvas = _u.sent();
                    _u.label = 5;
                case 5:
                    if ((_t = opts.removeContainer) !== null && _t !== void 0 ? _t : true) {
                        if (!DocumentCloner.destroy(container)) {
                            context.logger.error("Cannot detach cloned iframe as it is not in the DOM anymore");
                        }
                    }
                    context.logger.debug("Finished rendering");
                    return [2 /*return*/, canvas];
            }
        });
    }); };
    var parseBackgroundColor = function (context, element, backgroundColorOverride) {
        var ownerDocument = element.ownerDocument;
        // http://www.w3.org/TR/css3-background/#special-backgrounds
        var documentBackgroundColor = ownerDocument.documentElement
            ? parseColor(context, getComputedStyle(ownerDocument.documentElement).backgroundColor)
            : COLORS.TRANSPARENT;
        var bodyBackgroundColor = ownerDocument.body
            ? parseColor(context, getComputedStyle(ownerDocument.body).backgroundColor)
            : COLORS.TRANSPARENT;
        var defaultBackgroundColor = typeof backgroundColorOverride === 'string'
            ? parseColor(context, backgroundColorOverride)
            : backgroundColorOverride === null
                ? COLORS.TRANSPARENT
                : 0xffffffff;
        return element === ownerDocument.documentElement
            ? isTransparent(documentBackgroundColor)
                ? isTransparent(bodyBackgroundColor)
                    ? defaultBackgroundColor
                    : bodyBackgroundColor
                : documentBackgroundColor
            : defaultBackgroundColor;
    };

    return html2canvas;

})));
//# sourceMappingURL=html2canvas.js.map


/***/ }),

/***/ 8330:
/***/ ((module) => {

"use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"canvas-summary","version":"3.9.5","description":"Providing a data overview with vega charts.","private":true,"keywords":["jupyter","jupyterlab","jupyterlab-extension","widgets"],"files":["lib/**/*.js","dist/*.js","standalone/*"],"main":"lib/index.js","types":"./lib/index.d.ts","homepage":"https://github.com/satishlokkoju/deepview","bugs":{"url":"https://github.com/satishlokkoju/deepview/issues"},"author":"Satish Lokkoju","repository":{"type":"git","url":"https://github.com/satishlokkoju/deepview"},"scripts":{"build":"webpack --mode=development --progress && jupyter labextension build --development=True .","build:prod":"webpack --mode=production --progress && jupyter labextension build .","clean":"yarn run clean:lib && yarn run clean:nbextension && yarn run clean:labextension && yarn run clean:standalone","clean:lib":"rimraf lib","clean:labextension":"rimraf canvas_summary/labextension","clean:nbextension":"rimraf canvas_summary/nbextension/static/index.js","clean:standalone":"rimraf canvas_summary/standalone","lint":"eslint . --ext .ts,.tsx,.svelte --fix","lint:check":"eslint . --ext .ts,.tsx,.svelte","prepack":"yarn run build:prod","watch":"yarn run watch:nbextension","watch:nbextension":"webpack --watch --mode=development --progress","watch:labextension":"jupyter labextension watch .","dev":"yarn run watch & python -m http.server --directory ./canvas_summary/standalone 8082"},"dependencies":{"@betterwithdata/canvas_viz":"^1.1.0","@jupyter-widgets/base":"^1.1.10 || ^2.0.0 || ^3.0.0 || ^4.0.0","arquero":"^8.0.0"},"devDependencies":{"@fullhuman/postcss-purgecss":"^4.0.3","@jupyterlab/builder":"^3.6.8 || ^4.0.0","@phosphor/application":"^1.6.0","@phosphor/widgets":"^1.6.0","@tailwindcss/forms":"^0.3.2","@tsconfig/svelte":"^2.0.1","@types/webpack-env":"^1.13.6","@typescript-eslint/eslint-plugin":"^4.31.1","@typescript-eslint/parser":"^4.31.1","@webpack-cli/serve":"^1.2.2","autoprefixer":"^10.3.4","commitizen":"^4.2.4","css-loader":"^6.2.0","css-minimizer-webpack-plugin":"^3.0.1","cz-conventional-changelog":"^3.3.0","eslint":"^7.4.0","eslint-config-prettier":"^8.1.0","eslint-plugin-prettier":"^4.0.0","mini-css-extract-plugin":"^2.3.0","mkdirp":"^1.0.4","postcss":"^8.2.10","postcss-extend":"^1.0.5","postcss-import":"^14.0.1","postcss-load-config":"^3.0.1","postcss-loader":"^6.1.0","prettier":"^2.4.0","purgecss-from-svelte":"^2.0.2","rimraf":"^3.0.2","source-map-loader":"^3.0.0","style-loader":"^3.2.1","svelte":"^4.0.0","svelte-loader":"^3.1.7","svelte-preprocess":"^5.1.3","tailwindcss":"^2.2.15","ts-loader":"^9.1.0","typescript":"^4.9.0","webpack":"^5.52.1","webpack-cli":"^4.6.0","webpack-dev-server":"^4.2.1","yarn-run-all":"^3.1.1"},"jupyterlab":{"extension":"lib/index","outputDir":"canvas_summary/labextension/","sharedPackages":{"@jupyter-widgets/base":{"bundled":false,"singleton":true}}},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}');

/***/ }),

/***/ 8683:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.NbConvertManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const serverconnection_1 = __webpack_require__(2920);
const coreutils_2 = __webpack_require__(5764);
/**
 * The url for the lab nbconvert service.
 */
const NBCONVERT_SETTINGS_URL = 'api/nbconvert';
/**
 * The nbconvert API service manager.
 */
class NbConvertManager {
    /**
     * Create a new nbconvert manager.
     */
    constructor(options = {}) {
        var _a;
        this._exportFormats = null;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
    }
    /**
     * Fetch and cache the export formats from the expensive nbconvert handler.
     */
    async fetchExportFormats() {
        this._requestingFormats = new coreutils_2.PromiseDelegate();
        this._exportFormats = null;
        const base = this.serverSettings.baseUrl;
        const url = coreutils_1.URLExt.join(base, NBCONVERT_SETTINGS_URL);
        const { serverSettings } = this;
        const response = await serverconnection_1.ServerConnection.makeRequest(url, {}, serverSettings);
        if (response.status !== 200) {
            const err = await serverconnection_1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        const exportList = {};
        const keys = Object.keys(data);
        keys.forEach(function (key) {
            const mimeType = data[key].output_mimetype;
            exportList[key] = { output_mimetype: mimeType };
        });
        this._exportFormats = exportList;
        this._requestingFormats.resolve(exportList);
        return exportList;
    }
    /**
     * Get the list of export formats, preferring pre-cached ones.
     */
    async getExportFormats(force = true) {
        if (this._requestingFormats) {
            return this._requestingFormats.promise;
        }
        if (force || !this._exportFormats) {
            return await this.fetchExportFormats();
        }
        return this._exportFormats;
    }
}
exports.NbConvertManager = NbConvertManager;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 8790:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.RestContentProvider = exports.Drive = exports.ContentsManager = exports.Contents = void 0;
const coreutils_1 = __webpack_require__(8925);
const disposable_1 = __webpack_require__(7556);
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const validate = __importStar(__webpack_require__(2706));
/**
 * The url for the default drive service.
 */
const SERVICE_DRIVE_URL = 'api/contents';
/**
 * The url for the file access.
 */
const FILES_URL = 'files';
/**
 * A namespace for contents interfaces.
 */
var Contents;
(function (Contents) {
    /**
     * Validates an IModel, throwing an error if it does not pass.
     */
    function validateContentsModel(contents) {
        validate.validateContentsModel(contents);
    }
    Contents.validateContentsModel = validateContentsModel;
    /**
     * Validates an ICheckpointModel, throwing an error if it does not pass.
     */
    function validateCheckpointModel(checkpoint) {
        validate.validateCheckpointModel(checkpoint);
    }
    Contents.validateCheckpointModel = validateCheckpointModel;
})(Contents || (exports.Contents = Contents = {}));
/**
 * A contents manager that passes file operations to the server.
 * Multiple servers implementing the `IDrive` interface can be
 * attached to the contents manager, so that the same session can
 * perform file operations on multiple backends.
 *
 * This includes checkpointing with the normal file operations.
 */
class ContentsManager {
    /**
     * Construct a new contents manager object.
     *
     * @param options - The options used to initialize the object.
     */
    constructor(options = {}) {
        var _a, _b;
        this._isDisposed = false;
        this._additionalDrives = new Map();
        this._fileChanged = new signaling_1.Signal(this);
        const serverSettings = (this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : __1.ServerConnection.makeSettings());
        this._defaultDrive = (_b = options.defaultDrive) !== null && _b !== void 0 ? _b : new Drive({ serverSettings });
        this._defaultDrive.fileChanged.connect(this._onFileChanged, this);
    }
    /**
     * The default drive associated with the manager.
     */
    get defaultDrive() {
        return this._defaultDrive;
    }
    /**
     * A signal emitted when a file operation takes place.
     */
    get fileChanged() {
        return this._fileChanged;
    }
    /**
     * Test whether the manager has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the resources held by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._isDisposed = true;
        signaling_1.Signal.clearData(this);
    }
    /**
     * Add an `IDrive` to the manager.
     */
    addDrive(drive) {
        this._additionalDrives.set(drive.name, drive);
        drive.fileChanged.connect(this._onFileChanged, this);
    }
    /**
     * Given a path, get a shared model factory from the relevant backend.
     * The factory defined on content provider best matching the given path
     * takes precedence over the factory defined on the drive as a whole.
     * Returns `null` if the backend does not provide one.
     */
    getSharedModelFactory(path, options) {
        var _a, _b;
        const [drive] = this._driveForPath(path);
        const provider = (_a = drive.contentProviderRegistry) === null || _a === void 0 ? void 0 : _a.getProvider(options === null || options === void 0 ? void 0 : options.contentProviderId);
        if (provider === null || provider === void 0 ? void 0 : provider.sharedModelFactory) {
            return provider.sharedModelFactory;
        }
        return (_b = drive.sharedModelFactory) !== null && _b !== void 0 ? _b : null;
    }
    /**
     * Given a path of the form `drive:local/portion/of/it.txt`
     * get the local part of it.
     *
     * @param path the path.
     *
     * @returns The local part of the path.
     */
    localPath(path) {
        const parts = path.split('/');
        const firstParts = parts[0].split(':');
        if (firstParts.length === 1 || !this._additionalDrives.has(firstParts[0])) {
            return coreutils_1.PathExt.removeSlash(path);
        }
        return coreutils_1.PathExt.join(firstParts.slice(1).join(':'), ...parts.slice(1));
    }
    /**
     * Normalize a global path. Reduces '..' and '.' parts, and removes
     * leading slashes from the local part of the path, while retaining
     * the drive name if it exists.
     *
     * @param path the path.
     *
     * @returns The normalized path.
     */
    normalize(path) {
        const parts = path.split(':');
        if (parts.length === 1) {
            return coreutils_1.PathExt.normalize(path);
        }
        return `${parts[0]}:${coreutils_1.PathExt.normalize(parts.slice(1).join(':'))}`;
    }
    /**
     * Resolve a global path, starting from the root path. Behaves like
     * posix-path.resolve, with 3 differences:
     *  - will never prepend cwd
     *  - if root has a drive name, the result is prefixed with "<drive>:"
     *  - before adding drive name, leading slashes are removed
     *
     * @param path the path.
     *
     * @returns The normalized path.
     */
    resolvePath(root, path) {
        const driveName = this.driveName(root);
        const localPath = this.localPath(root);
        const resolved = coreutils_1.PathExt.resolve('/', localPath, path);
        return driveName ? `${driveName}:${resolved}` : resolved;
    }
    /**
     * Given a path of the form `drive:local/portion/of/it.txt`
     * get the name of the drive. If the path is missing
     * a drive portion, returns an empty string.
     *
     * @param path the path.
     *
     * @returns The drive name for the path, or the empty string.
     */
    driveName(path) {
        const parts = path.split('/');
        const firstParts = parts[0].split(':');
        if (firstParts.length === 1) {
            return '';
        }
        if (this._additionalDrives.has(firstParts[0])) {
            return firstParts[0];
        }
        return '';
    }
    /**
     * Get a file or directory.
     *
     * @param path The path to the file.
     *
     * @param options The options used to fetch the file.
     *
     * @returns A promise which resolves with the file content.
     */
    get(path, options) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.get(localPath, options).then(contentsModel => {
            const listing = [];
            if (contentsModel.type === 'directory' && contentsModel.content) {
                for (const item of contentsModel.content) {
                    listing.push({ ...item, path: this._toGlobalPath(drive, item.path) });
                }
                return {
                    ...contentsModel,
                    path: this._toGlobalPath(drive, localPath),
                    content: listing,
                    serverPath: contentsModel.path
                };
            }
            else {
                return {
                    ...contentsModel,
                    path: this._toGlobalPath(drive, localPath),
                    serverPath: contentsModel.path
                };
            }
        });
    }
    /**
     * Get an encoded download url given a file path.
     *
     * @param path - An absolute POSIX file path on the server.
     *
     * #### Notes
     * It is expected that the path contains no relative paths.
     *
     * The returned URL may include a query parameter.
     */
    getDownloadUrl(path) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.getDownloadUrl(localPath);
    }
    /**
     * Create a new untitled file or directory in the specified directory path.
     *
     * @param options The options used to create the file.
     *
     * @returns A promise which resolves with the created file content when the
     *    file is created.
     */
    newUntitled(options = {}) {
        if (options.path) {
            const globalPath = this.normalize(options.path);
            const [drive, localPath] = this._driveForPath(globalPath);
            return drive
                .newUntitled({ ...options, path: localPath })
                .then(contentsModel => {
                return {
                    ...contentsModel,
                    path: coreutils_1.PathExt.join(globalPath, contentsModel.name),
                    serverPath: contentsModel.path
                };
            });
        }
        else {
            return this._defaultDrive.newUntitled(options);
        }
    }
    /**
     * Delete a file.
     *
     * @param path - The path to the file.
     *
     * @returns A promise which resolves when the file is deleted.
     */
    delete(path) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.delete(localPath);
    }
    /**
     * Rename a file or directory.
     *
     * @param path - The original file path.
     *
     * @param newPath - The new file path.
     *
     * @returns A promise which resolves with the new file contents model when
     *   the file is renamed.
     */
    rename(path, newPath) {
        const [drive1, path1] = this._driveForPath(path);
        const [drive2, path2] = this._driveForPath(newPath);
        if (drive1 !== drive2) {
            throw Error('ContentsManager: renaming files must occur within a Drive');
        }
        return drive1.rename(path1, path2).then(contentsModel => {
            return {
                ...contentsModel,
                path: this._toGlobalPath(drive1, path2),
                serverPath: contentsModel.path
            };
        });
    }
    /**
     * Save a file.
     *
     * @param path - The desired file path.
     *
     * @param options - Optional overrides to the model.
     *
     * @returns A promise which resolves with the file content model when the
     *   file is saved.
     *
     * #### Notes
     * Ensure that `model.content` is populated for the file.
     */
    save(path, options = {}) {
        const globalPath = this.normalize(path);
        const [drive, localPath] = this._driveForPath(path);
        return drive
            .save(localPath, { ...options, path: localPath })
            .then(contentsModel => {
            return {
                ...contentsModel,
                path: globalPath,
                serverPath: contentsModel.path
            };
        });
    }
    /**
     * Copy a file into a given directory.
     *
     * @param path - The original file path.
     *
     * @param toDir - The destination directory path.
     *
     * @returns A promise which resolves with the new contents model when the
     *  file is copied.
     *
     * #### Notes
     * The server will select the name of the copied file.
     */
    copy(fromFile, toDir) {
        const [drive1, path1] = this._driveForPath(fromFile);
        const [drive2, path2] = this._driveForPath(toDir);
        if (drive1 === drive2) {
            return drive1.copy(path1, path2).then(contentsModel => {
                return {
                    ...contentsModel,
                    path: this._toGlobalPath(drive1, contentsModel.path),
                    serverPath: contentsModel.path
                };
            });
        }
        else {
            throw Error('Copying files between drives is not currently implemented');
        }
    }
    /**
     * Create a checkpoint for a file.
     *
     * @param path - The path of the file.
     *
     * @returns A promise which resolves with the new checkpoint model when the
     *   checkpoint is created.
     */
    createCheckpoint(path) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.createCheckpoint(localPath);
    }
    /**
     * List available checkpoints for a file.
     *
     * @param path - The path of the file.
     *
     * @returns A promise which resolves with a list of checkpoint models for
     *    the file.
     */
    listCheckpoints(path) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.listCheckpoints(localPath);
    }
    /**
     * Restore a file to a known checkpoint state.
     *
     * @param path - The path of the file.
     *
     * @param checkpointID - The id of the checkpoint to restore.
     *
     * @returns A promise which resolves when the checkpoint is restored.
     */
    restoreCheckpoint(path, checkpointID) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.restoreCheckpoint(localPath, checkpointID);
    }
    /**
     * Delete a checkpoint for a file.
     *
     * @param path - The path of the file.
     *
     * @param checkpointID - The id of the checkpoint to delete.
     *
     * @returns A promise which resolves when the checkpoint is deleted.
     */
    deleteCheckpoint(path, checkpointID) {
        const [drive, localPath] = this._driveForPath(path);
        return drive.deleteCheckpoint(localPath, checkpointID);
    }
    /**
     * Given a drive and a local path, construct a fully qualified
     * path. The inverse of `_driveForPath`.
     *
     * @param drive an `IDrive`.
     *
     * @param localPath the local path on the drive.
     *
     * @returns the fully qualified path.
     */
    _toGlobalPath(drive, localPath) {
        if (drive === this._defaultDrive) {
            return coreutils_1.PathExt.removeSlash(localPath);
        }
        else {
            return `${drive.name}:${coreutils_1.PathExt.removeSlash(localPath)}`;
        }
    }
    /**
     * Given a path, get the `IDrive to which it refers,
     * where the path satisfies the pattern
     * `'driveName:path/to/file'`. If there is no `driveName`
     * prepended to the path, it returns the default drive.
     *
     * @param path a path to a file.
     *
     * @returns A tuple containing an `IDrive` object for the path,
     * and a local path for that drive.
     */
    _driveForPath(path) {
        const driveName = this.driveName(path);
        const localPath = this.localPath(path);
        if (driveName) {
            return [this._additionalDrives.get(driveName), localPath];
        }
        else {
            return [this._defaultDrive, localPath];
        }
    }
    /**
     * Respond to fileChanged signals from the drives attached to
     * the manager. This prepends the drive name to the path if necessary,
     * and then forwards the signal.
     */
    _onFileChanged(sender, args) {
        var _a, _b;
        if (sender === this._defaultDrive) {
            this._fileChanged.emit(args);
        }
        else {
            let newValue = null;
            let oldValue = null;
            if ((_a = args.newValue) === null || _a === void 0 ? void 0 : _a.path) {
                newValue = {
                    ...args.newValue,
                    path: this._toGlobalPath(sender, args.newValue.path)
                };
            }
            if ((_b = args.oldValue) === null || _b === void 0 ? void 0 : _b.path) {
                oldValue = {
                    ...args.oldValue,
                    path: this._toGlobalPath(sender, args.oldValue.path)
                };
            }
            this._fileChanged.emit({
                type: args.type,
                newValue,
                oldValue
            });
        }
    }
}
exports.ContentsManager = ContentsManager;
/**
 * A default implementation for an `IDrive`, talking to the
 * server using the Jupyter REST API.
 */
class Drive {
    /**
     * Construct a new contents manager object.
     *
     * @param options - The options used to initialize the object.
     */
    constructor(options = {}) {
        var _a, _b, _c;
        this._isDisposed = false;
        this._fileChanged = new signaling_1.Signal(this);
        this.name = (_a = options.name) !== null && _a !== void 0 ? _a : 'Default';
        this._apiEndpoint = (_b = options.apiEndpoint) !== null && _b !== void 0 ? _b : SERVICE_DRIVE_URL;
        this.serverSettings =
            (_c = options.serverSettings) !== null && _c !== void 0 ? _c : __1.ServerConnection.makeSettings();
        const restContentProvider = new RestContentProvider({
            apiEndpoint: this._apiEndpoint,
            serverSettings: this.serverSettings
        });
        this.contentProviderRegistry = new ContentProviderRegistry({
            defaultProvider: restContentProvider
        });
        this.contentProviderRegistry.fileChanged.connect((registry, change) => {
            this._fileChanged.emit(change);
        });
    }
    /**
     * A signal emitted when a file operation takes place.
     */
    get fileChanged() {
        return this._fileChanged;
    }
    /**
     * Test whether the manager has been disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the resources held by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._isDisposed = true;
        signaling_1.Signal.clearData(this);
    }
    /**
     * Get a file or directory.
     *
     * @param localPath The path to the file.
     *
     * @param options The options used to fetch the file.
     *
     * @returns A promise which resolves with the file content.
     *
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async get(localPath, options) {
        const contentProvider = this.contentProviderRegistry.getProvider(options === null || options === void 0 ? void 0 : options.contentProviderId);
        return contentProvider.get(localPath, options);
    }
    /**
     * Get an encoded download url given a file path.
     *
     * @param localPath - An absolute POSIX file path on the server.
     *
     * #### Notes
     * It is expected that the path contains no relative paths.
     *
     * The returned URL may include a query parameter.
     */
    getDownloadUrl(localPath) {
        const baseUrl = this.serverSettings.baseUrl;
        let url = coreutils_1.URLExt.join(baseUrl, FILES_URL, coreutils_1.URLExt.encodeParts(localPath));
        let cookie = '';
        try {
            cookie = document.cookie;
        }
        catch (e) {
            // e.g. SecurityError in case of CSP Sandbox
        }
        const xsrfTokenMatch = cookie.match('\\b_xsrf=([^;]*)\\b');
        if (xsrfTokenMatch) {
            const fullUrl = new URL(url);
            fullUrl.searchParams.append('_xsrf', xsrfTokenMatch[1]);
            url = fullUrl.toString();
        }
        return Promise.resolve(url);
    }
    /**
     * Create a new untitled file or directory in the specified directory path.
     *
     * @param options The options used to create the file.
     *
     * @returns A promise which resolves with the created file content when the
     *    file is created.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async newUntitled(options = {}) {
        var _a;
        let body = '{}';
        if (options) {
            if (options.ext) {
                options.ext = Private.normalizeExtension(options.ext);
            }
            body = JSON.stringify(options);
        }
        const settings = this.serverSettings;
        const url = this._getUrl((_a = options.path) !== null && _a !== void 0 ? _a : '');
        const init = {
            method: 'POST',
            body
        };
        const response = await __1.ServerConnection.makeRequest(url, init, settings);
        if (response.status !== 201) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateContentsModel(data);
        this._fileChanged.emit({
            type: 'new',
            oldValue: null,
            newValue: data
        });
        return data;
    }
    /**
     * Delete a file.
     *
     * @param localPath - The path to the file.
     *
     * @returns A promise which resolves when the file is deleted.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents).
     */
    async delete(localPath) {
        const url = this._getUrl(localPath);
        const settings = this.serverSettings;
        const init = { method: 'DELETE' };
        const response = await __1.ServerConnection.makeRequest(url, init, settings);
        // TODO: update IPEP27 to specify errors more precisely, so
        // that error types can be detected here with certainty.
        if (response.status !== 204) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        this._fileChanged.emit({
            type: 'delete',
            oldValue: { path: localPath },
            newValue: null
        });
    }
    /**
     * Rename a file or directory.
     *
     * @param oldLocalPath - The original file path.
     *
     * @param newLocalPath - The new file path.
     *
     * @returns A promise which resolves with the new file contents model when
     *   the file is renamed.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async rename(oldLocalPath, newLocalPath) {
        const settings = this.serverSettings;
        const url = this._getUrl(oldLocalPath);
        const init = {
            method: 'PATCH',
            body: JSON.stringify({ path: newLocalPath })
        };
        const response = await __1.ServerConnection.makeRequest(url, init, settings);
        if (response.status !== 200) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateContentsModel(data);
        this._fileChanged.emit({
            type: 'rename',
            oldValue: { path: oldLocalPath },
            newValue: data
        });
        return data;
    }
    /**
     * Save a file.
     *
     * @param localPath - The desired file path.
     *
     * @param options - Optional overrides to the model.
     *
     * @returns A promise which resolves with the file content model when the
     *   file is saved.
     *
     * #### Notes
     * Ensure that `model.content` is populated for the file.
     *
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async save(localPath, options = {}) {
        const contentProvider = this.contentProviderRegistry.getProvider(options === null || options === void 0 ? void 0 : options.contentProviderId);
        const data = await contentProvider.save(localPath, options);
        this._fileChanged.emit({
            type: 'save',
            oldValue: null,
            newValue: data
        });
        return data;
    }
    /**
     * Copy a file into a given directory.
     *
     * @param localPath - The original file path.
     *
     * @param toDir - The destination directory path.
     *
     * @returns A promise which resolves with the new contents model when the
     *  file is copied.
     *
     * #### Notes
     * The server will select the name of the copied file.
     *
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async copy(fromFile, toDir) {
        const settings = this.serverSettings;
        const url = this._getUrl(toDir);
        const init = {
            method: 'POST',
            body: JSON.stringify({ copy_from: fromFile })
        };
        const response = await __1.ServerConnection.makeRequest(url, init, settings);
        if (response.status !== 201) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateContentsModel(data);
        this._fileChanged.emit({
            type: 'new',
            oldValue: null,
            newValue: data
        });
        return data;
    }
    /**
     * Create a checkpoint for a file.
     *
     * @param localPath - The path of the file.
     *
     * @returns A promise which resolves with the new checkpoint model when the
     *   checkpoint is created.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async createCheckpoint(localPath) {
        const url = this._getUrl(localPath, 'checkpoints');
        const init = { method: 'POST' };
        const response = await __1.ServerConnection.makeRequest(url, init, this.serverSettings);
        if (response.status !== 201) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateCheckpointModel(data);
        return data;
    }
    /**
     * List available checkpoints for a file.
     *
     * @param localPath - The path of the file.
     *
     * @returns A promise which resolves with a list of checkpoint models for
     *    the file.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async listCheckpoints(localPath) {
        const url = this._getUrl(localPath, 'checkpoints');
        const response = await __1.ServerConnection.makeRequest(url, {}, this.serverSettings);
        if (response.status !== 200) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        if (!Array.isArray(data)) {
            throw new Error('Invalid Checkpoint list');
        }
        for (let i = 0; i < data.length; i++) {
            validate.validateCheckpointModel(data[i]);
        }
        return data;
    }
    /**
     * Restore a file to a known checkpoint state.
     *
     * @param localPath - The path of the file.
     *
     * @param checkpointID - The id of the checkpoint to restore.
     *
     * @returns A promise which resolves when the checkpoint is restored.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents).
     */
    async restoreCheckpoint(localPath, checkpointID) {
        const url = this._getUrl(localPath, 'checkpoints', checkpointID);
        const init = { method: 'POST' };
        const response = await __1.ServerConnection.makeRequest(url, init, this.serverSettings);
        if (response.status !== 204) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
    }
    /**
     * Delete a checkpoint for a file.
     *
     * @param localPath - The path of the file.
     *
     * @param checkpointID - The id of the checkpoint to delete.
     *
     * @returns A promise which resolves when the checkpoint is deleted.
     *
     * #### Notes
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents).
     */
    async deleteCheckpoint(localPath, checkpointID) {
        const url = this._getUrl(localPath, 'checkpoints', checkpointID);
        const init = { method: 'DELETE' };
        const response = await __1.ServerConnection.makeRequest(url, init, this.serverSettings);
        if (response.status !== 204) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
    }
    /**
     * Get a REST url for a file given a path.
     */
    _getUrl(...args) {
        const parts = args.map(path => coreutils_1.URLExt.encodeParts(path));
        const baseUrl = this.serverSettings.baseUrl;
        return coreutils_1.URLExt.join(baseUrl, this._apiEndpoint, ...parts);
    }
}
exports.Drive = Drive;
/**
 * A namespace for module private data.
 */
var Private;
(function (Private) {
    /**
     * Normalize a file extension to be of the type `'.foo'`.
     *
     * Adds a leading dot if not present and converts to lower case.
     */
    function normalizeExtension(extension) {
        if (extension.length > 0 && extension.indexOf('.') !== 0) {
            extension = `.${extension}`;
        }
        return extension;
    }
    Private.normalizeExtension = normalizeExtension;
})(Private || (Private = {}));
/**
 * The default registry of content providers.
 */
class ContentProviderRegistry {
    /**
     * Construct a new content provider registry.
     *
     * @param options - The options used to initialize the registry.
     */
    constructor(options) {
        this._providers = new Map();
        this._fileChanged = new signaling_1.Signal(this);
        this.register('default', options.defaultProvider);
        this._defaultProvider = options.defaultProvider;
    }
    /**
     * Add a content provider to the registry.
     *
     * @param identifier - The identifier of the provider; it can be reused between drives.
     * @param provider - The content provider to register.
     */
    register(identifier, provider) {
        if (this._providers.has(identifier)) {
            throw Error(`Provider with ${identifier} identifier was already registered on this drive`);
        }
        this._providers.set(identifier, provider);
        const fileChangedProxy = (_provider, change) => {
            this._fileChanged.emit(change);
        };
        if (provider.fileChanged) {
            provider.fileChanged.connect(fileChangedProxy);
        }
        return new disposable_1.DisposableDelegate(() => {
            if (provider.fileChanged) {
                provider.fileChanged.disconnect(fileChangedProxy);
            }
            if (this._providers.has(identifier)) {
                this._providers.delete(identifier);
            }
        });
    }
    /**
     * Get a content provider matching provided identifier.
     *
     * If no identifier is provided, return the default provider.
     * Throws an error if a provider with given identifier is not found.
     *
     * @param identifier - identifier of the content provider.
     */
    getProvider(identifier) {
        if (!identifier) {
            return this._defaultProvider;
        }
        const provider = this._providers.get(identifier);
        if (!provider) {
            throw Error(`Provider ${identifier} is not registered`);
        }
        return provider;
    }
    /**
     * A proxy of the file changed signal for all the providers.
     */
    get fileChanged() {
        return this._fileChanged;
    }
}
/**
 * A content provider using the Jupyter REST API.
 */
class RestContentProvider {
    constructor(options) {
        this._options = options;
    }
    /**
     * Get a file or directory.
     *
     * @param localPath The path to the file.
     *
     * @param options The options used to fetch the file.
     *
     * @returns A promise which resolves with the file content.
     *
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async get(localPath, options) {
        let url = this._getUrl(localPath);
        if (options) {
            // The notebook type cannot take a format option.
            if (options.type === 'notebook') {
                delete options['format'];
            }
            const content = options.content ? '1' : '0';
            const hash = options.hash ? '1' : '0';
            const params = { ...options, content, hash };
            url += coreutils_1.URLExt.objectToQueryString(params);
        }
        const settings = this._options.serverSettings;
        const response = await __1.ServerConnection.makeRequest(url, {}, settings);
        if (response.status !== 200) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateContentsModel(data);
        return data;
    }
    /**
     * Save a file.
     *
     * @param localPath - The desired file path.
     *
     * @param options - Optional overrides to the model.
     *
     * @returns A promise which resolves with the file content model when the
     *   file is saved.
     *
     * #### Notes
     * Ensure that `model.content` is populated for the file.
     *
     * Uses the [Jupyter Server API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter-server/jupyter_server/main/jupyter_server/services/api/api.yaml#!/contents) and validates the response model.
     */
    async save(localPath, options = {}) {
        const settings = this._options.serverSettings;
        const url = this._getUrl(localPath);
        const init = {
            method: 'PUT',
            body: JSON.stringify(options)
        };
        const response = await __1.ServerConnection.makeRequest(url, init, settings);
        // will return 200 for an existing file and 201 for a new file
        if (response.status !== 200 && response.status !== 201) {
            const err = await __1.ServerConnection.ResponseError.create(response);
            throw err;
        }
        const data = await response.json();
        validate.validateContentsModel(data);
        return data;
    }
    /**
     * Get a REST url for a file given a path.
     */
    _getUrl(...args) {
        const parts = args.map(path => coreutils_1.URLExt.encodeParts(path));
        const baseUrl = this._options.serverSettings.baseUrl;
        return coreutils_1.URLExt.join(baseUrl, this._options.apiEndpoint, ...parts);
    }
}
exports.RestContentProvider = RestContentProvider;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 8792:
/***/ ((module) => {

"use strict";


// do not edit .js files directly - edit src/index.jst



module.exports = function equal(a, b) {
  if (a === b) return true;

  if (a && b && typeof a == 'object' && typeof b == 'object') {
    if (a.constructor !== b.constructor) return false;

    var length, i, keys;
    if (Array.isArray(a)) {
      length = a.length;
      if (length != b.length) return false;
      for (i = length; i-- !== 0;)
        if (!equal(a[i], b[i])) return false;
      return true;
    }



    if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
    if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
    if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

    keys = Object.keys(a);
    length = keys.length;
    if (length !== Object.keys(b).length) return false;

    for (i = length; i-- !== 0;)
      if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;

    for (i = length; i-- !== 0;) {
      var key = keys[i];

      if (!equal(a[key], b[key])) return false;
    }

    return true;
  }

  // true if both NaN, false otherwise
  return a!==a && b!==b;
};


/***/ }),

/***/ 8925:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/**
 * @packageDocumentation
 * @module coreutils
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
__exportStar(__webpack_require__(9704), exports);
__exportStar(__webpack_require__(9269), exports);
__exportStar(__webpack_require__(1232), exports);
__exportStar(__webpack_require__(9547), exports);
__exportStar(__webpack_require__(5964), exports);
__exportStar(__webpack_require__(9830), exports);
__exportStar(__webpack_require__(7361), exports);
__exportStar(__webpack_require__(8126), exports);
__exportStar(__webpack_require__(1796), exports);
__exportStar(__webpack_require__(1692), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 8958:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'sort-down';
var width = 320;
var height = 512;
var ligatures = [];
var unicode = 'f0dd';
var svgPathData = 'M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.Yn = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 9040:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TerminalAPI = exports.Terminal = void 0;
const Terminal = __importStar(__webpack_require__(6994));
exports.Terminal = Terminal;
const TerminalAPI = __importStar(__webpack_require__(6134));
exports.TerminalAPI = TerminalAPI;
__exportStar(__webpack_require__(9883), exports);
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 9191:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.UserManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const coreutils_2 = __webpack_require__(5764);
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const serverconnection_1 = __webpack_require__(2920);
const basemanager_1 = __webpack_require__(3867);
/**
 * The url for the lab workspaces service.
 */
const SERVICE_USER_URL = 'api/me';
/**
 * The service's ID.
 * Used to uniquely identify the poll, and
 * the item in local storage.
 */
const SERVICE_ID = '@jupyterlab/services:UserManager#user';
/**
 * The user API service manager.
 */
class UserManager extends basemanager_1.BaseManager {
    /**
     * Create a new user manager.
     */
    constructor(options = {}) {
        var _a;
        super(options);
        this._isReady = false;
        this._userChanged = new signaling_1.Signal(this);
        this._connectionFailure = new signaling_1.Signal(this);
        // Initialize internal data.
        this._ready = this.requestUser()
            .then(() => {
            if (this.isDisposed) {
                return;
            }
            this._isReady = true;
        })
            .catch(_ => 
        // Return a promise that will never resolve, so user service is never ready
        // This typically occurs when the backend has no user service
        new Promise(() => {
            // no-op
        }));
        this._pollSpecs = new polling_1.Poll({
            auto: false,
            factory: () => this.requestUser(),
            frequency: {
                interval: 61 * 1000,
                backoff: true,
                max: 300 * 1000
            },
            name: SERVICE_ID,
            standby: (_a = options.standby) !== null && _a !== void 0 ? _a : 'when-hidden'
        });
        void this.ready.then(() => {
            void this._pollSpecs.start();
        });
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._ready;
    }
    /**
     * Get the most recently fetched identity.
     */
    get identity() {
        return this._identity;
    }
    /**
     * Get the most recently fetched permissions.
     */
    get permissions() {
        return this._permissions;
    }
    /**
     * A signal emitted when the user changes.
     */
    get userChanged() {
        return this._userChanged;
    }
    /**
     * A signal emitted when there is a connection failure.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        this._pollSpecs.dispose();
        super.dispose();
    }
    /**
     * Force a refresh of the specs from the server.
     *
     * @returns A promise that resolves when the specs are fetched.
     *
     * #### Notes
     * This is intended to be called only in response to a user action,
     * since the manager maintains its internal state.
     */
    async refreshUser() {
        await this._pollSpecs.refresh();
        await this._pollSpecs.tick;
    }
    /**
     * Execute a request to the server to poll the user and update state.
     */
    async requestUser() {
        if (this.isDisposed) {
            return;
        }
        const { baseUrl } = this.serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const url = coreutils_1.URLExt.join(baseUrl, SERVICE_USER_URL);
        const response = await makeRequest(url, {}, this.serverSettings);
        if (response.status !== 200) {
            const err = await ResponseError.create(response);
            throw err;
        }
        const oldUser = {
            identity: this._identity,
            permissions: this._permissions
        };
        const newUser = await response.json();
        const identity = newUser.identity;
        // store the color and initials for the user
        // this info is not provided by the server
        const { localStorage } = window;
        const data = localStorage.getItem(SERVICE_ID);
        if (data && (!identity.initials || !identity.color)) {
            const localUser = JSON.parse(data);
            identity.initials =
                identity.initials ||
                    localUser.initials ||
                    identity.name.substring(0, 1);
            identity.color =
                identity.color || localUser.color || Private.getRandomColor();
        }
        if (!coreutils_2.JSONExt.deepEqual(newUser, oldUser)) {
            this._identity = identity;
            this._permissions = newUser.permissions;
            localStorage.setItem(SERVICE_ID, JSON.stringify(identity));
            this._userChanged.emit(newUser);
        }
    }
}
exports.UserManager = UserManager;
/**
 * A namespace for module-private functionality.
 *
 * Note: We do not want to export this function
 * to move it to css variables in the Theme.
 */
var Private;
(function (Private) {
    /**
     * Predefined colors for users
     */
    const userColors = [
        'var(--jp-collaborator-color1)',
        'var(--jp-collaborator-color2)',
        'var(--jp-collaborator-color3)',
        'var(--jp-collaborator-color4)',
        'var(--jp-collaborator-color5)',
        'var(--jp-collaborator-color6)',
        'var(--jp-collaborator-color7)'
    ];
    /**
     * Get a random color from the list of colors.
     */
    Private.getRandomColor = () => userColors[Math.floor(Math.random() * userColors.length)];
})(Private || (Private = {}));
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 9269:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
//# sourceMappingURL=interfaces.js.map

/***/ }),

/***/ 9480:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.EventManager = void 0;
const coreutils_1 = __webpack_require__(8925);
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const serverconnection_1 = __webpack_require__(2920);
/**
 * The url for the jupyter-server events service.
 */
const SERVICE_EVENTS_URL = 'api/events';
/**
 * The events API service manager.
 */
class EventManager {
    /**
     * Create a new event manager.
     */
    constructor(options = {}) {
        var _a;
        this._socket = null;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
        // If subscription fails, the poll attempts to reconnect and backs off.
        this._poll = new polling_1.Poll({ factory: () => this._subscribe() });
        this._stream = new signaling_1.Stream(this);
        // Subscribe to the events socket.
        void this._poll.start();
    }
    /**
     * Whether the event manager is disposed.
     */
    get isDisposed() {
        return this._poll.isDisposed;
    }
    /**
     * An event stream that emits and yields each new event.
     */
    get stream() {
        return this._stream;
    }
    /**
     * Dispose the event manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        // Clean up poll.
        this._poll.dispose();
        // Clean up socket.
        const socket = this._socket;
        if (socket) {
            this._socket = null;
            socket.onopen = () => undefined;
            socket.onerror = () => undefined;
            socket.onmessage = () => undefined;
            socket.onclose = () => undefined;
            socket.close();
        }
        // Clean up stream.
        signaling_1.Signal.clearData(this);
        this._stream.stop();
    }
    /**
     * Post an event request to be emitted by the event bus.
     */
    async emit(event) {
        const { serverSettings } = this;
        const { baseUrl } = serverSettings;
        const { makeRequest, ResponseError } = serverconnection_1.ServerConnection;
        const url = coreutils_1.URLExt.join(baseUrl, SERVICE_EVENTS_URL);
        const init = { body: JSON.stringify(event), method: 'POST' };
        const response = await makeRequest(url, init, serverSettings);
        if (response.status !== 204) {
            throw new ResponseError(response);
        }
    }
    /**
     * Subscribe to event bus emissions.
     */
    _subscribe() {
        return new Promise((_, reject) => {
            if (this.isDisposed) {
                return;
            }
            const { appendToken, token, WebSocket, wsUrl } = this.serverSettings;
            let url = coreutils_1.URLExt.join(wsUrl, SERVICE_EVENTS_URL, 'subscribe');
            if (appendToken && token !== '') {
                url += `?token=${encodeURIComponent(token)}`;
            }
            const socket = (this._socket = new WebSocket(url));
            const stream = this._stream;
            socket.onclose = () => reject(new Error('EventManager socket closed'));
            socket.onmessage = msg => msg.data && stream.emit(JSON.parse(msg.data));
        });
    }
}
exports.EventManager = EventManager;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 9547:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.MarkdownCodeBlocks = void 0;
/**
 * The namespace for code block functions which help
 * in extract code from markdown text
 */
var MarkdownCodeBlocks;
(function (MarkdownCodeBlocks) {
    MarkdownCodeBlocks.CODE_BLOCK_MARKER = '```';
    const markdownExtensions = [
        '.markdown',
        '.mdown',
        '.mkdn',
        '.md',
        '.mkd',
        '.mdwn',
        '.mdtxt',
        '.mdtext',
        '.text',
        '.txt',
        '.Rmd'
    ];
    class MarkdownCodeBlock {
        constructor(startLine) {
            this.startLine = startLine;
            this.code = '';
            this.endLine = -1;
        }
    }
    MarkdownCodeBlocks.MarkdownCodeBlock = MarkdownCodeBlock;
    /**
     * Check whether the given file extension is a markdown extension
     * @param extension - A file extension
     *
     * @returns true/false depending on whether this is a supported markdown extension
     */
    function isMarkdown(extension) {
        return markdownExtensions.indexOf(extension) > -1;
    }
    MarkdownCodeBlocks.isMarkdown = isMarkdown;
    /**
     * Construct all code snippets from current text
     * (this could be potentially optimized if we can cache and detect differences)
     * @param text - A string to parse codeblocks from
     *
     * @returns An array of MarkdownCodeBlocks.
     */
    function findMarkdownCodeBlocks(text) {
        if (!text || text === '') {
            return [];
        }
        const lines = text.split('\n');
        const codeBlocks = [];
        let currentBlock = null;
        for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
            const line = lines[lineIndex];
            const lineContainsMarker = line.indexOf(MarkdownCodeBlocks.CODE_BLOCK_MARKER) === 0;
            const constructingBlock = currentBlock != null;
            // Skip this line if it is not part of any code block and doesn't contain a marker.
            if (!lineContainsMarker && !constructingBlock) {
                continue;
            }
            // Check if we are already constructing a code block.
            if (!constructingBlock) {
                // Start constructing a new code block.
                currentBlock = new MarkdownCodeBlock(lineIndex);
                // Check whether this is a single line code block of the form ```a = 10```.
                const firstIndex = line.indexOf(MarkdownCodeBlocks.CODE_BLOCK_MARKER);
                const lastIndex = line.lastIndexOf(MarkdownCodeBlocks.CODE_BLOCK_MARKER);
                const isSingleLine = firstIndex !== lastIndex;
                if (isSingleLine) {
                    currentBlock.code = line.substring(firstIndex + MarkdownCodeBlocks.CODE_BLOCK_MARKER.length, lastIndex);
                    currentBlock.endLine = lineIndex;
                    codeBlocks.push(currentBlock);
                    currentBlock = null;
                }
            }
            else if (currentBlock) {
                if (lineContainsMarker) {
                    // End of block, finish it up.
                    currentBlock.endLine = lineIndex - 1;
                    codeBlocks.push(currentBlock);
                    currentBlock = null;
                }
                else {
                    // Append the current line.
                    currentBlock.code += line + '\n';
                }
            }
        }
        return codeBlocks;
    }
    MarkdownCodeBlocks.findMarkdownCodeBlocks = findMarkdownCodeBlocks;
})(MarkdownCodeBlocks || (exports.MarkdownCodeBlocks = MarkdownCodeBlocks = {}));
//# sourceMappingURL=markdowncodeblocks.js.map

/***/ }),

/***/ 9600:
/***/ ((module) => {

"use strict";


function hasKey(obj, keys) {
	var o = obj;
	keys.slice(0, -1).forEach(function (key) {
		o = o[key] || {};
	});

	var key = keys[keys.length - 1];
	return key in o;
}

function isNumber(x) {
	if (typeof x === 'number') { return true; }
	if ((/^0x[0-9a-f]+$/i).test(x)) { return true; }
	return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x);
}

function isConstructorOrProto(obj, key) {
	return (key === 'constructor' && typeof obj[key] === 'function') || key === '__proto__';
}

module.exports = function (args, opts) {
	if (!opts) { opts = {}; }

	var flags = {
		bools: {},
		strings: {},
		unknownFn: null,
	};

	if (typeof opts.unknown === 'function') {
		flags.unknownFn = opts.unknown;
	}

	if (typeof opts.boolean === 'boolean' && opts.boolean) {
		flags.allBools = true;
	} else {
		[].concat(opts.boolean).filter(Boolean).forEach(function (key) {
			flags.bools[key] = true;
		});
	}

	var aliases = {};

	function aliasIsBoolean(key) {
		return aliases[key].some(function (x) {
			return flags.bools[x];
		});
	}

	Object.keys(opts.alias || {}).forEach(function (key) {
		aliases[key] = [].concat(opts.alias[key]);
		aliases[key].forEach(function (x) {
			aliases[x] = [key].concat(aliases[key].filter(function (y) {
				return x !== y;
			}));
		});
	});

	[].concat(opts.string).filter(Boolean).forEach(function (key) {
		flags.strings[key] = true;
		if (aliases[key]) {
			[].concat(aliases[key]).forEach(function (k) {
				flags.strings[k] = true;
			});
		}
	});

	var defaults = opts.default || {};

	var argv = { _: [] };

	function argDefined(key, arg) {
		return (flags.allBools && (/^--[^=]+$/).test(arg))
			|| flags.strings[key]
			|| flags.bools[key]
			|| aliases[key];
	}

	function setKey(obj, keys, value) {
		var o = obj;
		for (var i = 0; i < keys.length - 1; i++) {
			var key = keys[i];
			if (isConstructorOrProto(o, key)) { return; }
			if (o[key] === undefined) { o[key] = {}; }
			if (
				o[key] === Object.prototype
				|| o[key] === Number.prototype
				|| o[key] === String.prototype
			) {
				o[key] = {};
			}
			if (o[key] === Array.prototype) { o[key] = []; }
			o = o[key];
		}

		var lastKey = keys[keys.length - 1];
		if (isConstructorOrProto(o, lastKey)) { return; }
		if (
			o === Object.prototype
			|| o === Number.prototype
			|| o === String.prototype
		) {
			o = {};
		}
		if (o === Array.prototype) { o = []; }
		if (o[lastKey] === undefined || flags.bools[lastKey] || typeof o[lastKey] === 'boolean') {
			o[lastKey] = value;
		} else if (Array.isArray(o[lastKey])) {
			o[lastKey].push(value);
		} else {
			o[lastKey] = [o[lastKey], value];
		}
	}

	function setArg(key, val, arg) {
		if (arg && flags.unknownFn && !argDefined(key, arg)) {
			if (flags.unknownFn(arg) === false) { return; }
		}

		var value = !flags.strings[key] && isNumber(val)
			? Number(val)
			: val;
		setKey(argv, key.split('.'), value);

		(aliases[key] || []).forEach(function (x) {
			setKey(argv, x.split('.'), value);
		});
	}

	Object.keys(flags.bools).forEach(function (key) {
		setArg(key, defaults[key] === undefined ? false : defaults[key]);
	});

	var notFlags = [];

	if (args.indexOf('--') !== -1) {
		notFlags = args.slice(args.indexOf('--') + 1);
		args = args.slice(0, args.indexOf('--'));
	}

	for (var i = 0; i < args.length; i++) {
		var arg = args[i];
		var key;
		var next;

		if ((/^--.+=/).test(arg)) {
			// Using [\s\S] instead of . because js doesn't support the
			// 'dotall' regex modifier. See:
			// http://stackoverflow.com/a/1068308/13216
			var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
			key = m[1];
			var value = m[2];
			if (flags.bools[key]) {
				value = value !== 'false';
			}
			setArg(key, value, arg);
		} else if ((/^--no-.+/).test(arg)) {
			key = arg.match(/^--no-(.+)/)[1];
			setArg(key, false, arg);
		} else if ((/^--.+/).test(arg)) {
			key = arg.match(/^--(.+)/)[1];
			next = args[i + 1];
			if (
				next !== undefined
				&& !(/^(-|--)[^-]/).test(next)
				&& !flags.bools[key]
				&& !flags.allBools
				&& (aliases[key] ? !aliasIsBoolean(key) : true)
			) {
				setArg(key, next, arg);
				i += 1;
			} else if ((/^(true|false)$/).test(next)) {
				setArg(key, next === 'true', arg);
				i += 1;
			} else {
				setArg(key, flags.strings[key] ? '' : true, arg);
			}
		} else if ((/^-[^-]+/).test(arg)) {
			var letters = arg.slice(1, -1).split('');

			var broken = false;
			for (var j = 0; j < letters.length; j++) {
				next = arg.slice(j + 2);

				if (next === '-') {
					setArg(letters[j], next, arg);
					continue;
				}

				if ((/[A-Za-z]/).test(letters[j]) && next[0] === '=') {
					setArg(letters[j], next.slice(1), arg);
					broken = true;
					break;
				}

				if (
					(/[A-Za-z]/).test(letters[j])
					&& (/-?\d+(\.\d*)?(e-?\d+)?$/).test(next)
				) {
					setArg(letters[j], next, arg);
					broken = true;
					break;
				}

				if (letters[j + 1] && letters[j + 1].match(/\W/)) {
					setArg(letters[j], arg.slice(j + 2), arg);
					broken = true;
					break;
				} else {
					setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
				}
			}

			key = arg.slice(-1)[0];
			if (!broken && key !== '-') {
				if (
					args[i + 1]
					&& !(/^(-|--)[^-]/).test(args[i + 1])
					&& !flags.bools[key]
					&& (aliases[key] ? !aliasIsBoolean(key) : true)
				) {
					setArg(key, args[i + 1], arg);
					i += 1;
				} else if (args[i + 1] && (/^(true|false)$/).test(args[i + 1])) {
					setArg(key, args[i + 1] === 'true', arg);
					i += 1;
				} else {
					setArg(key, flags.strings[key] ? '' : true, arg);
				}
			}
		} else {
			if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
				argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg));
			}
			if (opts.stopEarly) {
				argv._.push.apply(argv._, args.slice(i + 1));
				break;
			}
		}
	}

	Object.keys(defaults).forEach(function (k) {
		if (!hasKey(argv, k.split('.'))) {
			setKey(argv, k.split('.'), defaults[k]);

			(aliases[k] || []).forEach(function (x) {
				setKey(argv, x.split('.'), defaults[k]);
			});
		}
	});

	if (opts['--']) {
		argv['--'] = notFlags.slice();
	} else {
		notFlags.forEach(function (k) {
			argv._.push(k);
		});
	}

	return argv;
};


/***/ }),

/***/ 9704:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ActivityMonitor = void 0;
const signaling_1 = __webpack_require__(3992);
/**
 * A class that monitors activity on a signal.
 */
class ActivityMonitor {
    /**
     * Construct a new activity monitor.
     */
    constructor(options) {
        this._timer = -1;
        this._timeout = -1;
        this._isDisposed = false;
        this._activityStopped = new signaling_1.Signal(this);
        options.signal.connect(this._onSignalFired, this);
        this._timeout = options.timeout || 1000;
    }
    /**
     * A signal emitted when activity has ceased.
     */
    get activityStopped() {
        return this._activityStopped;
    }
    /**
     * The timeout associated with the monitor, in milliseconds.
     */
    get timeout() {
        return this._timeout;
    }
    set timeout(value) {
        this._timeout = value;
    }
    /**
     * Test whether the monitor has been disposed.
     *
     * #### Notes
     * This is a read-only property.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the resources used by the activity monitor.
     */
    dispose() {
        if (this._isDisposed) {
            return;
        }
        this._isDisposed = true;
        signaling_1.Signal.clearData(this);
    }
    /**
     * A signal handler for the monitored signal.
     */
    _onSignalFired(sender, args) {
        clearTimeout(this._timer);
        this._sender = sender;
        this._args = args;
        this._timer = setTimeout(() => {
            this._activityStopped.emit({
                sender: this._sender,
                args: this._args
            });
        }, this._timeout);
    }
}
exports.ActivityMonitor = ActivityMonitor;
//# sourceMappingURL=activitymonitor.js.map

/***/ }),

/***/ 9708:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
//# sourceMappingURL=interfaces.js.map

/***/ }),

/***/ 9718:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;

__webpack_unused_export__ = ({ value: true });
var prefix = 'fas';
var iconName = 'layer-group';
var width = 512;
var height = 512;
var ligatures = [];
var unicode = 'f5fd';
var svgPathData = 'M12.41 148.02l232.94 105.67c6.8 3.09 14.49 3.09 21.29 0l232.94-105.67c16.55-7.51 16.55-32.52 0-40.03L266.65 2.31a25.607 25.607 0 0 0-21.29 0L12.41 107.98c-16.55 7.51-16.55 32.53 0 40.04zm487.18 88.28l-58.09-26.33-161.64 73.27c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.51 209.97l-58.1 26.33c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 276.3c16.55-7.5 16.55-32.5 0-40zm0 127.8l-57.87-26.23-161.86 73.37c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.29 337.87 12.41 364.1c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 404.1c16.55-7.5 16.55-32.5 0-40z';

exports.mw = {
  prefix: prefix,
  iconName: iconName,
  icon: [
    width,
    height,
    ligatures,
    unicode,
    svgPathData
  ]};

exports.qI = exports.mw;
__webpack_unused_export__ = prefix;
__webpack_unused_export__ = iconName;
__webpack_unused_export__ = width;
__webpack_unused_export__ = height;
__webpack_unused_export__ = ligatures;
__webpack_unused_export__ = unicode;
__webpack_unused_export__ = svgPathData;

/***/ }),

/***/ 9740:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ServiceManager = void 0;
const signaling_1 = __webpack_require__(3992);
const builder_1 = __webpack_require__(4219);
const contents_1 = __webpack_require__(8790);
const event_1 = __webpack_require__(9480);
const kernel_1 = __webpack_require__(973);
const kernelspec_1 = __webpack_require__(2946);
const nbconvert_1 = __webpack_require__(8683);
const serverconnection_1 = __webpack_require__(2920);
const session_1 = __webpack_require__(7668);
const setting_1 = __webpack_require__(7780);
const terminal_1 = __webpack_require__(9040);
const user_1 = __webpack_require__(9191);
const workspace_1 = __webpack_require__(8053);
/**
 * A Jupyter services manager.
 */
class ServiceManager {
    /**
     * Construct a new services provider.
     */
    constructor(options = {}) {
        var _a, _b;
        this._isDisposed = false;
        this._connectionFailure = new signaling_1.Signal(this);
        this._isReady = false;
        const defaultDrive = options.defaultDrive;
        const serverSettings = (_a = options.serverSettings) !== null && _a !== void 0 ? _a : serverconnection_1.ServerConnection.makeSettings();
        const standby = (_b = options.standby) !== null && _b !== void 0 ? _b : 'when-hidden';
        const normalized = { defaultDrive, serverSettings, standby };
        this.serverSettings = serverSettings;
        this.contents = options.contents || new contents_1.ContentsManager(normalized);
        this.events = options.events || new event_1.EventManager(normalized);
        this.kernels = options.kernels || new kernel_1.KernelManager(normalized);
        this.sessions =
            options.sessions ||
                new session_1.SessionManager({
                    ...normalized,
                    kernelManager: this.kernels
                });
        this.settings = options.settings || new setting_1.SettingManager(normalized);
        this.terminals = options.terminals || new terminal_1.TerminalManager(normalized);
        this.builder = options.builder || new builder_1.BuildManager(normalized);
        this.workspaces = options.workspaces || new workspace_1.WorkspaceManager(normalized);
        this.nbconvert = options.nbconvert || new nbconvert_1.NbConvertManager(normalized);
        this.kernelspecs = options.kernelspecs || new kernelspec_1.KernelSpecManager(normalized);
        this.user = options.user || new user_1.UserManager(normalized);
        // Proxy all connection failures from the individual service managers.
        this.kernelspecs.connectionFailure.connect(this._onConnectionFailure, this);
        this.sessions.connectionFailure.connect(this._onConnectionFailure, this);
        this.terminals.connectionFailure.connect(this._onConnectionFailure, this);
        // Define promises that need to be resolved before service manager is ready.
        const readyList = [this.sessions.ready, this.kernelspecs.ready];
        if (this.terminals.isAvailable()) {
            readyList.push(this.terminals.ready);
        }
        this._readyPromise = Promise.all(readyList).then(() => {
            this._isReady = true;
        });
    }
    /**
     * A signal emitted when there is a connection failure with the kernel.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Test whether the service manager is disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._isDisposed = true;
        signaling_1.Signal.clearData(this);
        this.contents.dispose();
        this.events.dispose();
        this.sessions.dispose();
        this.terminals.dispose();
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._readyPromise;
    }
    _onConnectionFailure(sender, err) {
        this._connectionFailure.emit(err);
    }
}
exports.ServiceManager = ServiceManager;
//# sourceMappingURL=manager.js.map

/***/ }),

/***/ 9822:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TerminalConnection = void 0;
const coreutils_1 = __webpack_require__(8925);
const coreutils_2 = __webpack_require__(5764);
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const restapi_1 = __webpack_require__(6134);
/**
 * An implementation of a terminal interface.
 */
class TerminalConnection {
    /**
     * Construct a new terminal session.
     */
    constructor(options) {
        var _a, _b;
        /**
         * Create the terminal websocket connection and add socket status handlers.
         *
         * #### Notes
         * You are responsible for updating the connection status as appropriate.
         */
        this._createSocket = () => {
            this._errorIfDisposed();
            // Make sure the socket is clear
            this._clearSocket();
            // Update the connection status to reflect opening a new connection.
            this._updateConnectionStatus('connecting');
            const name = this._name;
            const settings = this.serverSettings;
            let url = coreutils_1.URLExt.join(settings.wsUrl, 'terminals', 'websocket', encodeURIComponent(name));
            // If token authentication is in use.
            const token = settings.token;
            if (settings.appendToken && token !== '') {
                url = url + `?token=${encodeURIComponent(token)}`;
            }
            this._ws = new settings.WebSocket(url);
            this._ws.onmessage = this._onWSMessage;
            this._ws.onclose = this._onWSClose;
            this._ws.onerror = this._onWSClose;
        };
        // Websocket messages events are defined as variables to bind `this`
        this._onWSMessage = (event) => {
            if (this._isDisposed) {
                return;
            }
            const data = JSON.parse(event.data);
            // Handle a disconnect message.
            if (data[0] === 'disconnect') {
                this.dispose();
            }
            if (this._connectionStatus === 'connecting') {
                // After reconnection, ignore all messages until a 'setup' message
                // before we are truly connected. Setting the connection status to
                // connected only then means that if we do not get a setup message
                // before our retry timeout, we will delete the websocket and try again.
                if (data[0] === 'setup') {
                    this._updateConnectionStatus('connected');
                }
                return;
            }
            this._messageReceived.emit({
                type: data[0],
                content: data.slice(1)
            });
        };
        this._onWSClose = (event) => {
            console.warn(`Terminal websocket closed: ${event.code}`);
            if (!this.isDisposed) {
                this._reconnect();
            }
        };
        this._connectionStatus = 'connecting';
        this._connectionStatusChanged = new signaling_1.Signal(this);
        this._isDisposed = false;
        this._disposed = new signaling_1.Signal(this);
        this._messageReceived = new signaling_1.Signal(this);
        this._reconnectTimeout = null;
        this._ws = null;
        this._noOp = () => {
            /* no-op */
        };
        this._reconnectLimit = 7;
        this._reconnectAttempt = 0;
        this._pendingMessages = [];
        this._name = options.model.name;
        this.serverSettings =
            (_a = options.serverSettings) !== null && _a !== void 0 ? _a : __1.ServerConnection.makeSettings();
        this._terminalAPIClient =
            (_b = options.terminalAPIClient) !== null && _b !== void 0 ? _b : new restapi_1.TerminalAPIClient({ serverSettings: this.serverSettings });
        this._createSocket();
    }
    /**
     * A signal emitted when the session is disposed.
     */
    get disposed() {
        return this._disposed;
    }
    /**
     * A signal emitted when a message is received from the server.
     */
    get messageReceived() {
        return this._messageReceived;
    }
    /**
     * Get the name of the terminal session.
     */
    get name() {
        return this._name;
    }
    /**
     * Get the model for the terminal session.
     */
    get model() {
        return { name: this._name };
    }
    /**
     * Test whether the session is disposed.
     */
    get isDisposed() {
        return this._isDisposed;
    }
    /**
     * Dispose of the resources held by the session.
     */
    dispose() {
        if (this._isDisposed) {
            return;
        }
        this._isDisposed = true;
        this._disposed.emit();
        this._updateConnectionStatus('disconnected');
        this._clearSocket();
        signaling_1.Signal.clearData(this);
    }
    /**
     * Send a message to the terminal session.
     *
     * #### Notes
     * If the connection is down, the message will be queued for sending when
     * the connection comes back up.
     */
    send(message) {
        this._sendMessage(message);
    }
    /**
     * Send a message on the websocket, or possibly queue for later sending.
     *
     * @param queue - whether to queue the message if it cannot be sent
     */
    _sendMessage(message, queue = true) {
        if (this._isDisposed || !message.content) {
            return;
        }
        if (this.connectionStatus === 'connected' && this._ws) {
            const msg = [message.type, ...message.content];
            this._ws.send(JSON.stringify(msg));
        }
        else if (queue) {
            this._pendingMessages.push(message);
        }
        else {
            throw new Error(`Could not send message: ${JSON.stringify(message)}`);
        }
    }
    /**
     * Send pending messages to the kernel.
     */
    _sendPending() {
        // We check to make sure we are still connected each time. For
        // example, if a websocket buffer overflows, it may close, so we should
        // stop sending messages.
        while (this.connectionStatus === 'connected' &&
            this._pendingMessages.length > 0) {
            this._sendMessage(this._pendingMessages[0], false);
            // We shift the message off the queue after the message is sent so that
            // if there is an exception, the message is still pending.
            this._pendingMessages.shift();
        }
    }
    /**
     * Reconnect to a terminal.
     *
     * #### Notes
     * This may try multiple times to reconnect to a terminal, and will sever
     * any existing connection.
     */
    reconnect() {
        this._errorIfDisposed();
        const result = new coreutils_2.PromiseDelegate();
        // Set up a listener for the connection status changing, which accepts or
        // rejects after the retries are done.
        const fulfill = (sender, status) => {
            if (status === 'connected') {
                result.resolve();
                this.connectionStatusChanged.disconnect(fulfill, this);
            }
            else if (status === 'disconnected') {
                result.reject(new Error('Terminal connection disconnected'));
                this.connectionStatusChanged.disconnect(fulfill, this);
            }
        };
        this.connectionStatusChanged.connect(fulfill, this);
        // Reset the reconnect limit so we start the connection attempts fresh
        this._reconnectAttempt = 0;
        // Start the reconnection process, which will also clear any existing
        // connection.
        this._reconnect();
        // Return the promise that should resolve on connection or reject if the
        // retries don't work.
        return result.promise;
    }
    /**
     * Attempt a connection if we have not exhausted connection attempts.
     */
    _reconnect() {
        this._errorIfDisposed();
        // Clear any existing reconnection attempt
        clearTimeout(this._reconnectTimeout);
        // Update the connection status and schedule a possible reconnection.
        if (this._reconnectAttempt < this._reconnectLimit) {
            this._updateConnectionStatus('connecting');
            // The first reconnect attempt should happen immediately, and subsequent
            // attempts should pick a random number in a growing range so that we
            // don't overload the server with synchronized reconnection attempts
            // across multiple kernels.
            const timeout = Private.getRandomIntInclusive(0, 1e3 * (Math.pow(2, this._reconnectAttempt) - 1));
            console.error(`Connection lost, reconnecting in ${Math.floor(timeout / 1000)} seconds.`);
            this._reconnectTimeout = setTimeout(this._createSocket, timeout);
            this._reconnectAttempt += 1;
        }
        else {
            this._updateConnectionStatus('disconnected');
        }
        // Clear the websocket event handlers and the socket itself.
        this._clearSocket();
    }
    /**
     * Forcefully clear the socket state.
     *
     * #### Notes
     * This will clear all socket state without calling any handlers and will
     * not update the connection status. If you call this method, you are
     * responsible for updating the connection status as needed and recreating
     * the socket if you plan to reconnect.
     */
    _clearSocket() {
        if (this._ws !== null) {
            // Clear the websocket event handlers and the socket itself.
            this._ws.onopen = this._noOp;
            this._ws.onclose = this._noOp;
            this._ws.onerror = this._noOp;
            this._ws.onmessage = this._noOp;
            this._ws.close();
            this._ws = null;
        }
    }
    /**
     * Shut down the terminal session.
     */
    async shutdown() {
        await this._terminalAPIClient.shutdown(this.name);
        this.dispose();
    }
    /**
     * Clone the current terminal connection.
     */
    clone() {
        return new TerminalConnection({
            model: this.model,
            serverSettings: this.serverSettings,
            terminalAPIClient: this._terminalAPIClient
        });
    }
    /**
     * Handle connection status changes.
     */
    _updateConnectionStatus(connectionStatus) {
        if (this._connectionStatus === connectionStatus) {
            return;
        }
        this._connectionStatus = connectionStatus;
        // If we are not 'connecting', stop any reconnection attempts.
        if (connectionStatus !== 'connecting') {
            this._reconnectAttempt = 0;
            clearTimeout(this._reconnectTimeout);
        }
        // Send the pending messages if we just connected.
        if (connectionStatus === 'connected') {
            this._sendPending();
        }
        // Notify others that the connection status changed.
        this._connectionStatusChanged.emit(connectionStatus);
    }
    /**
     * Utility function to throw an error if this instance is disposed.
     */
    _errorIfDisposed() {
        if (this.isDisposed) {
            throw new Error('Terminal connection is disposed');
        }
    }
    /**
     * A signal emitted when the terminal connection status changes.
     */
    get connectionStatusChanged() {
        return this._connectionStatusChanged;
    }
    /**
     * The current connection status of the terminal connection.
     */
    get connectionStatus() {
        return this._connectionStatus;
    }
}
exports.TerminalConnection = TerminalConnection;
var Private;
(function (Private) {
    /**
     * Get a random integer between min and max, inclusive of both.
     *
     * #### Notes
     * From
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
     *
     * From the MDN page: It might be tempting to use Math.round() to accomplish
     * that, but doing so would cause your random numbers to follow a non-uniform
     * distribution, which may not be acceptable for your needs.
     */
    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    Private.getRandomIntInclusive = getRandomIntInclusive;
})(Private || (Private = {}));
//# sourceMappingURL=default.js.map

/***/ }),

/***/ 9830:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PathExt = void 0;
const path_1 = __webpack_require__(9942);
/**
 * The namespace for path-related functions.
 *
 * Note that Jupyter server paths do not start with a leading slash.
 */
var PathExt;
(function (PathExt) {
    /**
     * Join all arguments together and normalize the resulting path.
     * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
     *
     * @param paths - The string paths to join.
     */
    function join(...paths) {
        const path = path_1.posix.join(...paths);
        return path === '.' ? '' : removeSlash(path);
    }
    PathExt.join = join;
    /**
     * Join all arguments together and normalize the resulting path and preserve the leading slash.
     *
     * @param paths - The string paths to join.
     */
    function joinWithLeadingSlash(...paths) {
        const path = path_1.posix.join(...paths);
        return path === '.' ? '' : path;
    }
    PathExt.joinWithLeadingSlash = joinWithLeadingSlash;
    /**
     * Return the last portion of a path. Similar to the Unix basename command.
     * Often used to extract the file name from a fully qualified path.
     *
     * @param path - The path to evaluate.
     *
     * @param ext - An extension to remove from the result.
     */
    function basename(path, ext) {
        return path_1.posix.basename(path, ext);
    }
    PathExt.basename = basename;
    /**
     * Get the directory name of a path, similar to the Unix dirname command.
     * When an empty path is given, returns the root path.
     *
     * @param path - The file path.
     */
    function dirname(path) {
        const dir = removeSlash(path_1.posix.dirname(path));
        return dir === '.' ? '' : dir;
    }
    PathExt.dirname = dirname;
    /**
     * Get the extension of the path.
     *
     * @param path - The file path.
     *
     * @returns the extension of the file.
     *
     * #### Notes
     * The extension is the string from the last occurrence of the `.`
     * character to end of string in the last portion of the path, inclusive.
     * If there is no `.` in the last portion of the path, or if the first
     * character of the basename of path [[basename]] is `.`, then an
     * empty string is returned.
     */
    function extname(path) {
        return path_1.posix.extname(path);
    }
    PathExt.extname = extname;
    /**
     * Normalize a string path, reducing '..' and '.' parts.
     * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
     * When an empty path is given, returns the root path.
     *
     * @param path - The string path to normalize.
     */
    function normalize(path) {
        if (path === '') {
            return '';
        }
        return removeSlash(path_1.posix.normalize(path));
    }
    PathExt.normalize = normalize;
    /**
     * Resolve a sequence of paths or path segments into an absolute path.
     * The root path in the application has no leading slash, so it is removed.
     *
     * @param parts - The paths to join.
     *
     * #### Notes
     * The right-most parameter is considered \{to\}.  Other parameters are considered an array of \{from\}.
     *
     * Starting from leftmost \{from\} parameter, resolves \{to\} to an absolute path.
     *
     * If \{to\} isn't already absolute, \{from\} arguments are prepended in right to left order, until an absolute path is found. If after using all \{from\} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory.
     */
    function resolve(...parts) {
        return removeSlash(path_1.posix.resolve(...parts));
    }
    PathExt.resolve = resolve;
    /**
     * Solve the relative path from \{from\} to \{to\}.
     *
     * @param from - The source path.
     *
     * @param to - The target path.
     *
     * #### Notes
     * If from and to each resolve to the same path (after calling
     * path.resolve() on each), a zero-length string is returned.
     * If a zero-length string is passed as from or to, `/`
     * will be used instead of the zero-length strings.
     */
    function relative(from, to) {
        return removeSlash(path_1.posix.relative(from, to));
    }
    PathExt.relative = relative;
    /**
     * Normalize a file extension to be of the type `'.foo'`.
     *
     * @param extension - the file extension.
     *
     * #### Notes
     * Adds a leading dot if not present and converts to lower case.
     */
    function normalizeExtension(extension) {
        if (extension.length > 0 && extension.indexOf('.') !== 0) {
            extension = `.${extension}`;
        }
        return extension;
    }
    PathExt.normalizeExtension = normalizeExtension;
    /**
     * Remove the leading slash from a path.
     *
     * @param path the path from which to remove a leading slash.
     */
    function removeSlash(path) {
        if (path.indexOf('/') === 0) {
            path = path.slice(1);
        }
        return path;
    }
    PathExt.removeSlash = removeSlash;
})(PathExt || (exports.PathExt = PathExt = {}));
//# sourceMappingURL=path.js.map

/***/ }),

/***/ 9883:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TerminalManager = void 0;
const polling_1 = __webpack_require__(6049);
const signaling_1 = __webpack_require__(3992);
const __1 = __webpack_require__(7883);
const basemanager_1 = __webpack_require__(3867);
const restapi_1 = __webpack_require__(6134);
const default_1 = __webpack_require__(9822);
/**
 * A terminal session manager.
 */
class TerminalManager extends basemanager_1.BaseManager {
    /**
     * Construct a new terminal manager.
     */
    constructor(options = {}) {
        var _a, _b;
        super(options);
        this._isReady = false;
        // As an optimization, we unwrap the models to just store the names.
        this._names = [];
        this._terminalConnections = new Set();
        this._runningChanged = new signaling_1.Signal(this);
        this._connectionFailure = new signaling_1.Signal(this);
        this._terminalAPIClient =
            (_a = options.terminalAPIClient) !== null && _a !== void 0 ? _a : new restapi_1.TerminalAPIClient({ serverSettings: this.serverSettings });
        // Check if terminals are available
        if (!this.isAvailable()) {
            this._ready = Promise.reject('Terminals unavailable');
            this._ready.catch(_ => undefined);
            return;
        }
        // Start polling with exponential backoff.
        this._pollModels = new polling_1.Poll({
            auto: false,
            factory: () => this.requestRunning(),
            frequency: {
                interval: 10 * 1000,
                backoff: true,
                max: 300 * 1000
            },
            name: `@jupyterlab/services:TerminalManager#models`,
            standby: (_b = options.standby) !== null && _b !== void 0 ? _b : 'when-hidden'
        });
        // Initialize internal data.
        this._ready = (async () => {
            await this._pollModels.start();
            await this._pollModels.tick;
            this._isReady = true;
        })();
    }
    /**
     * Test whether the manager is ready.
     */
    get isReady() {
        return this._isReady;
    }
    /**
     * A promise that fulfills when the manager is ready.
     */
    get ready() {
        return this._ready;
    }
    /**
     * A signal emitted when the running terminals change.
     */
    get runningChanged() {
        return this._runningChanged;
    }
    /**
     * A signal emitted when there is a connection failure.
     */
    get connectionFailure() {
        return this._connectionFailure;
    }
    /**
     * Dispose of the resources used by the manager.
     */
    dispose() {
        if (this.isDisposed) {
            return;
        }
        this._names.length = 0;
        this._terminalConnections.forEach(x => x.dispose());
        this._pollModels.dispose();
        super.dispose();
    }
    /**
     * Whether the terminal service is available.
     */
    isAvailable() {
        return this._terminalAPIClient.isAvailable;
    }
    /*
     * Connect to a running terminal.
     *
     * @param options - The options used to connect to the terminal.
     *
     * @returns The new terminal connection instance.
     *
     * #### Notes
     * The manager `serverSettings` will be used.
     */
    connectTo(options) {
        const terminalConnection = new default_1.TerminalConnection({
            ...options,
            serverSettings: this.serverSettings,
            terminalAPIClient: this._terminalAPIClient
        });
        this._onStarted(terminalConnection);
        if (!this._names.includes(options.model.name)) {
            // We trust the user to connect to an existing session, but we verify
            // asynchronously.
            void this.refreshRunning().catch(() => {
                /* no-op */
            });
        }
        return terminalConnection;
    }
    /**
     * Create an iterator over the most recent running terminals.
     *
     * @returns A new iterator over the running terminals.
     */
    running() {
        return this._models[Symbol.iterator]();
    }
    /**
     * Force a refresh of the running terminals.
     *
     * @returns A promise that with the list of running terminals.
     *
     * #### Notes
     * This is intended to be called only in response to a user action,
     * since the manager maintains its internal state.
     */
    async refreshRunning() {
        await this._pollModels.refresh();
        await this._pollModels.tick;
    }
    /**
     * Create a new terminal session.
     *
     * @param options - The options used to create the terminal.
     *
     * @returns A promise that resolves with the terminal connection instance.
     *
     * #### Notes
     * The manager `serverSettings` will be used unless overridden in the
     * options.
     */
    async startNew(options = {}) {
        const { name, cwd } = options;
        const model = await this._terminalAPIClient.startNew({
            name,
            cwd
        });
        await this.refreshRunning();
        return this.connectTo({ model });
    }
    /**
     * Shut down a terminal session by name.
     */
    async shutdown(name) {
        await this._terminalAPIClient.shutdown(name);
        await this.refreshRunning();
    }
    /**
     * Shut down all terminal sessions.
     *
     * @returns A promise that resolves when all of the sessions are shut down.
     */
    async shutdownAll() {
        // Update the list of models to make sure our list is current.
        await this.refreshRunning();
        // Shut down all models.
        await Promise.all(this._names.map(name => this._terminalAPIClient.shutdown(name)));
        // Update the list of models to clear out our state.
        await this.refreshRunning();
    }
    /**
     * Execute a request to the server to poll running terminals and update state.
     */
    async requestRunning() {
        var _a, _b;
        let models;
        try {
            models = await this._terminalAPIClient.listRunning();
        }
        catch (err) {
            // Handle network errors, as well as cases where we are on a
            // JupyterHub and the server is not running. JupyterHub returns a
            // 503 (<2.0) or 424 (>2.0) in that case.
            if (err instanceof __1.ServerConnection.NetworkError ||
                ((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 503 ||
                ((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 424) {
                this._connectionFailure.emit(err);
            }
            throw err;
        }
        if (this.isDisposed) {
            return;
        }
        const names = models.map(({ name }) => name).sort();
        if (names === this._names) {
            // Identical models list, so just return
            return;
        }
        this._names = names;
        this._terminalConnections.forEach(tc => {
            if (!names.includes(tc.name)) {
                tc.dispose();
            }
        });
        this._runningChanged.emit(this._models);
    }
    /**
     * Handle a session starting.
     */
    _onStarted(terminalConnection) {
        this._terminalConnections.add(terminalConnection);
        terminalConnection.disposed.connect(this._onDisposed, this);
    }
    /**
     * Handle a session terminating.
     */
    _onDisposed(terminalConnection) {
        this._terminalConnections.delete(terminalConnection);
        // Update the running models to make sure we reflect the server state
        void this.refreshRunning().catch(() => {
            /* no-op */
        });
    }
    get _models() {
        return this._names.map(name => {
            return { name };
        });
    }
}
exports.TerminalManager = TerminalManager;
/**
 * The namespace for TerminalManager statics.
 */
(function (TerminalManager) {
    /**
     * A no-op terminal manager to be used when starting terminals is not supported.
     */
    class NoopManager extends TerminalManager {
        constructor() {
            super(...arguments);
            this._readyPromise = new Promise(() => {
                /* no-op */
            });
        }
        /**
         * Whether the manager is active.
         */
        get isActive() {
            return false;
        }
        /**
         * Used for testing.
         */
        get parentReady() {
            return super.ready;
        }
        /**
         * A promise that fulfills when the manager is ready (never).
         */
        get ready() {
            return this.parentReady.then(() => this._readyPromise);
        }
        /**
         * Create a new terminal session - throw an error since it is not supported.
         *
         */
        async startNew(options) {
            return Promise.reject(new Error('Not implemented in no-op Terminal Manager'));
        }
        /*
         * Connect to a running terminal - throw an error since it is not supported.
         */
        connectTo(options) {
            throw Error('Not implemented in no-op Terminal Manager');
        }
        /**
         * Shut down a session by id - throw an error since it is not supported.
         */
        async shutdown(id) {
            return Promise.reject(new Error('Not implemented in no-op Terminal Manager'));
        }
        /**
         * Execute a request to the server to poll running sessions and update state.
         */
        async requestRunning() {
            return Promise.resolve();
        }
    }
    TerminalManager.NoopManager = NoopManager;
})(TerminalManager || (exports.TerminalManager = TerminalManager = {}));
//# sourceMappingURL=manager.js.map

/***/ }),

/***/ 9909:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.supportedKernelWebSocketProtocols = void 0;
exports.createMessage = createMessage;
exports.isStreamMsg = isStreamMsg;
exports.isDisplayDataMsg = isDisplayDataMsg;
exports.isUpdateDisplayDataMsg = isUpdateDisplayDataMsg;
exports.isExecuteInputMsg = isExecuteInputMsg;
exports.isExecuteResultMsg = isExecuteResultMsg;
exports.isErrorMsg = isErrorMsg;
exports.isStatusMsg = isStatusMsg;
exports.isClearOutputMsg = isClearOutputMsg;
exports.isDebugEventMsg = isDebugEventMsg;
exports.isCommOpenMsg = isCommOpenMsg;
exports.isCommCloseMsg = isCommCloseMsg;
exports.isCommMsgMsg = isCommMsgMsg;
exports.isInfoRequestMsg = isInfoRequestMsg;
exports.isExecuteReplyMsg = isExecuteReplyMsg;
exports.isDebugRequestMsg = isDebugRequestMsg;
exports.isDebugReplyMsg = isDebugReplyMsg;
exports.isInputRequestMsg = isInputRequestMsg;
exports.isInputReplyMsg = isInputReplyMsg;
const coreutils_1 = __webpack_require__(5764);
function createMessage(options) {
    var _a, _b, _c, _d, _e, _f;
    return {
        buffers: (_a = options.buffers) !== null && _a !== void 0 ? _a : [],
        channel: options.channel,
        content: options.content,
        header: {
            date: new Date().toISOString(),
            msg_id: (_b = options.msgId) !== null && _b !== void 0 ? _b : coreutils_1.UUID.uuid4(),
            msg_type: options.msgType,
            session: options.session,
            username: (_c = options.username) !== null && _c !== void 0 ? _c : '',
            subshell_id: (_d = options.subshellId) !== null && _d !== void 0 ? _d : null,
            version: '5.2'
        },
        metadata: (_e = options.metadata) !== null && _e !== void 0 ? _e : {},
        parent_header: (_f = options.parentHeader) !== null && _f !== void 0 ? _f : {}
    };
}
/**
 * Test whether a kernel message is a `'stream'` message.
 */
function isStreamMsg(msg) {
    return msg.header.msg_type === 'stream';
}
/**
 * Test whether a kernel message is an `'display_data'` message.
 */
function isDisplayDataMsg(msg) {
    return msg.header.msg_type === 'display_data';
}
/**
 * Test whether a kernel message is an `'update_display_data'` message.
 */
function isUpdateDisplayDataMsg(msg) {
    return msg.header.msg_type === 'update_display_data';
}
/**
 * Test whether a kernel message is an `'execute_input'` message.
 */
function isExecuteInputMsg(msg) {
    return msg.header.msg_type === 'execute_input';
}
/**
 * Test whether a kernel message is an `'execute_result'` message.
 */
function isExecuteResultMsg(msg) {
    return msg.header.msg_type === 'execute_result';
}
/**
 * Test whether a kernel message is an `'error'` message.
 */
function isErrorMsg(msg) {
    return msg.header.msg_type === 'error';
}
/**
 * Test whether a kernel message is a `'status'` message.
 */
function isStatusMsg(msg) {
    return msg.header.msg_type === 'status';
}
/**
 * Test whether a kernel message is a `'clear_output'` message.
 */
function isClearOutputMsg(msg) {
    return msg.header.msg_type === 'clear_output';
}
/**
 * Test whether a kernel message is an experimental `'debug_event'` message.
 *
 * @hidden
 *
 * #### Notes
 * Debug messages are experimental messages that are not in the official
 * kernel message specification. As such, this is *NOT* considered
 * part of the public API, and may change without notice.
 */
function isDebugEventMsg(msg) {
    return msg.header.msg_type === 'debug_event';
}
/**
 * Test whether a kernel message is a `'comm_open'` message.
 */
function isCommOpenMsg(msg) {
    return msg.header.msg_type === 'comm_open';
}
/**
 * Test whether a kernel message is a `'comm_close'` message.
 */
function isCommCloseMsg(msg) {
    return msg.header.msg_type === 'comm_close';
}
/**
 * Test whether a kernel message is a `'comm_msg'` message.
 */
function isCommMsgMsg(msg) {
    return msg.header.msg_type === 'comm_msg';
}
/**
 * Test whether a kernel message is a `'kernel_info_request'` message.
 */
function isInfoRequestMsg(msg) {
    return msg.header.msg_type === 'kernel_info_request';
}
/**
 * Test whether a kernel message is an `'execute_reply'` message.
 */
function isExecuteReplyMsg(msg) {
    return msg.header.msg_type === 'execute_reply';
}
/**
 * Test whether a kernel message is an experimental `'debug_request'` message.
 *
 * @hidden
 *
 * #### Notes
 * Debug messages are experimental messages that are not in the official
 * kernel message specification. As such, this is *NOT* considered
 * part of the public API, and may change without notice.
 */
function isDebugRequestMsg(msg) {
    return msg.header.msg_type === 'debug_request';
}
/**
 * Test whether a kernel message is an experimental `'debug_reply'` message.
 *
 * @hidden
 *
 * #### Notes
 * Debug messages are experimental messages that are not in the official
 * kernel message specification. As such, this is *NOT* considered
 * part of the public API, and may change without notice.
 */
function isDebugReplyMsg(msg) {
    return msg.header.msg_type === 'debug_reply';
}
/**
 * Test whether a kernel message is an `'input_request'` message.
 */
function isInputRequestMsg(msg) {
    return msg.header.msg_type === 'input_request';
}
/**
 * Test whether a kernel message is an `'input_reply'` message.
 */
function isInputReplyMsg(msg) {
    return msg.header.msg_type === 'input_reply';
}
// ///////////////////////////////////////////////
// Message (de)serialization
// ///////////////////////////////////////////////
/**
 * The list of supported kernel wire protocols over websocket.
 */
var supportedKernelWebSocketProtocols;
(function (supportedKernelWebSocketProtocols) {
    supportedKernelWebSocketProtocols["v1KernelWebsocketJupyterOrg"] = "v1.kernel.websocket.jupyter.org";
})(supportedKernelWebSocketProtocols || (exports.supportedKernelWebSocketProtocols = supportedKernelWebSocketProtocols = {}));
//# sourceMappingURL=messages.js.map

/***/ }),

/***/ 9942:
/***/ ((module) => {

"use strict";
// 'path' module extracted from Node.js v8.11.1 (only the posix part)
// transplited with Babel

// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.



function assertPath(path) {
  if (typeof path !== 'string') {
    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
  }
}

// Resolves . and .. elements in a path with directory names
function normalizeStringPosix(path, allowAboveRoot) {
  var res = '';
  var lastSegmentLength = 0;
  var lastSlash = -1;
  var dots = 0;
  var code;
  for (var i = 0; i <= path.length; ++i) {
    if (i < path.length)
      code = path.charCodeAt(i);
    else if (code === 47 /*/*/)
      break;
    else
      code = 47 /*/*/;
    if (code === 47 /*/*/) {
      if (lastSlash === i - 1 || dots === 1) {
        // NOOP
      } else if (lastSlash !== i - 1 && dots === 2) {
        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
          if (res.length > 2) {
            var lastSlashIndex = res.lastIndexOf('/');
            if (lastSlashIndex !== res.length - 1) {
              if (lastSlashIndex === -1) {
                res = '';
                lastSegmentLength = 0;
              } else {
                res = res.slice(0, lastSlashIndex);
                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
              }
              lastSlash = i;
              dots = 0;
              continue;
            }
          } else if (res.length === 2 || res.length === 1) {
            res = '';
            lastSegmentLength = 0;
            lastSlash = i;
            dots = 0;
            continue;
          }
        }
        if (allowAboveRoot) {
          if (res.length > 0)
            res += '/..';
          else
            res = '..';
          lastSegmentLength = 2;
        }
      } else {
        if (res.length > 0)
          res += '/' + path.slice(lastSlash + 1, i);
        else
          res = path.slice(lastSlash + 1, i);
        lastSegmentLength = i - lastSlash - 1;
      }
      lastSlash = i;
      dots = 0;
    } else if (code === 46 /*.*/ && dots !== -1) {
      ++dots;
    } else {
      dots = -1;
    }
  }
  return res;
}

function _format(sep, pathObject) {
  var dir = pathObject.dir || pathObject.root;
  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
  if (!dir) {
    return base;
  }
  if (dir === pathObject.root) {
    return dir + base;
  }
  return dir + sep + base;
}

var posix = {
  // path.resolve([from ...], to)
  resolve: function resolve() {
    var resolvedPath = '';
    var resolvedAbsolute = false;
    var cwd;

    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path;
      if (i >= 0)
        path = arguments[i];
      else {
        if (cwd === undefined)
          cwd = process.cwd();
        path = cwd;
      }

      assertPath(path);

      // Skip empty entries
      if (path.length === 0) {
        continue;
      }

      resolvedPath = path + '/' + resolvedPath;
      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
    }

    // At this point the path should be resolved to a full absolute path, but
    // handle relative paths to be safe (might happen when process.cwd() fails)

    // Normalize the path
    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);

    if (resolvedAbsolute) {
      if (resolvedPath.length > 0)
        return '/' + resolvedPath;
      else
        return '/';
    } else if (resolvedPath.length > 0) {
      return resolvedPath;
    } else {
      return '.';
    }
  },

  normalize: function normalize(path) {
    assertPath(path);

    if (path.length === 0) return '.';

    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;

    // Normalize the path
    path = normalizeStringPosix(path, !isAbsolute);

    if (path.length === 0 && !isAbsolute) path = '.';
    if (path.length > 0 && trailingSeparator) path += '/';

    if (isAbsolute) return '/' + path;
    return path;
  },

  isAbsolute: function isAbsolute(path) {
    assertPath(path);
    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
  },

  join: function join() {
    if (arguments.length === 0)
      return '.';
    var joined;
    for (var i = 0; i < arguments.length; ++i) {
      var arg = arguments[i];
      assertPath(arg);
      if (arg.length > 0) {
        if (joined === undefined)
          joined = arg;
        else
          joined += '/' + arg;
      }
    }
    if (joined === undefined)
      return '.';
    return posix.normalize(joined);
  },

  relative: function relative(from, to) {
    assertPath(from);
    assertPath(to);

    if (from === to) return '';

    from = posix.resolve(from);
    to = posix.resolve(to);

    if (from === to) return '';

    // Trim any leading backslashes
    var fromStart = 1;
    for (; fromStart < from.length; ++fromStart) {
      if (from.charCodeAt(fromStart) !== 47 /*/*/)
        break;
    }
    var fromEnd = from.length;
    var fromLen = fromEnd - fromStart;

    // Trim any leading backslashes
    var toStart = 1;
    for (; toStart < to.length; ++toStart) {
      if (to.charCodeAt(toStart) !== 47 /*/*/)
        break;
    }
    var toEnd = to.length;
    var toLen = toEnd - toStart;

    // Compare paths to find the longest common path from root
    var length = fromLen < toLen ? fromLen : toLen;
    var lastCommonSep = -1;
    var i = 0;
    for (; i <= length; ++i) {
      if (i === length) {
        if (toLen > length) {
          if (to.charCodeAt(toStart + i) === 47 /*/*/) {
            // We get here if `from` is the exact base path for `to`.
            // For example: from='/foo/bar'; to='/foo/bar/baz'
            return to.slice(toStart + i + 1);
          } else if (i === 0) {
            // We get here if `from` is the root
            // For example: from='/'; to='/foo'
            return to.slice(toStart + i);
          }
        } else if (fromLen > length) {
          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
            // We get here if `to` is the exact base path for `from`.
            // For example: from='/foo/bar/baz'; to='/foo/bar'
            lastCommonSep = i;
          } else if (i === 0) {
            // We get here if `to` is the root.
            // For example: from='/foo'; to='/'
            lastCommonSep = 0;
          }
        }
        break;
      }
      var fromCode = from.charCodeAt(fromStart + i);
      var toCode = to.charCodeAt(toStart + i);
      if (fromCode !== toCode)
        break;
      else if (fromCode === 47 /*/*/)
        lastCommonSep = i;
    }

    var out = '';
    // Generate the relative path based on the path difference between `to`
    // and `from`
    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
        if (out.length === 0)
          out += '..';
        else
          out += '/..';
      }
    }

    // Lastly, append the rest of the destination (`to`) path that comes after
    // the common path parts
    if (out.length > 0)
      return out + to.slice(toStart + lastCommonSep);
    else {
      toStart += lastCommonSep;
      if (to.charCodeAt(toStart) === 47 /*/*/)
        ++toStart;
      return to.slice(toStart);
    }
  },

  _makeLong: function _makeLong(path) {
    return path;
  },

  dirname: function dirname(path) {
    assertPath(path);
    if (path.length === 0) return '.';
    var code = path.charCodeAt(0);
    var hasRoot = code === 47 /*/*/;
    var end = -1;
    var matchedSlash = true;
    for (var i = path.length - 1; i >= 1; --i) {
      code = path.charCodeAt(i);
      if (code === 47 /*/*/) {
          if (!matchedSlash) {
            end = i;
            break;
          }
        } else {
        // We saw the first non-path separator
        matchedSlash = false;
      }
    }

    if (end === -1) return hasRoot ? '/' : '.';
    if (hasRoot && end === 1) return '//';
    return path.slice(0, end);
  },

  basename: function basename(path, ext) {
    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
    assertPath(path);

    var start = 0;
    var end = -1;
    var matchedSlash = true;
    var i;

    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
      if (ext.length === path.length && ext === path) return '';
      var extIdx = ext.length - 1;
      var firstNonSlashEnd = -1;
      for (i = path.length - 1; i >= 0; --i) {
        var code = path.charCodeAt(i);
        if (code === 47 /*/*/) {
            // If we reached a path separator that was not part of a set of path
            // separators at the end of the string, stop now
            if (!matchedSlash) {
              start = i + 1;
              break;
            }
          } else {
          if (firstNonSlashEnd === -1) {
            // We saw the first non-path separator, remember this index in case
            // we need it if the extension ends up not matching
            matchedSlash = false;
            firstNonSlashEnd = i + 1;
          }
          if (extIdx >= 0) {
            // Try to match the explicit extension
            if (code === ext.charCodeAt(extIdx)) {
              if (--extIdx === -1) {
                // We matched the extension, so mark this as the end of our path
                // component
                end = i;
              }
            } else {
              // Extension does not match, so our result is the entire path
              // component
              extIdx = -1;
              end = firstNonSlashEnd;
            }
          }
        }
      }

      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
      return path.slice(start, end);
    } else {
      for (i = path.length - 1; i >= 0; --i) {
        if (path.charCodeAt(i) === 47 /*/*/) {
            // If we reached a path separator that was not part of a set of path
            // separators at the end of the string, stop now
            if (!matchedSlash) {
              start = i + 1;
              break;
            }
          } else if (end === -1) {
          // We saw the first non-path separator, mark this as the end of our
          // path component
          matchedSlash = false;
          end = i + 1;
        }
      }

      if (end === -1) return '';
      return path.slice(start, end);
    }
  },

  extname: function extname(path) {
    assertPath(path);
    var startDot = -1;
    var startPart = 0;
    var end = -1;
    var matchedSlash = true;
    // Track the state of characters (if any) we see before our first dot and
    // after any path separator we find
    var preDotState = 0;
    for (var i = path.length - 1; i >= 0; --i) {
      var code = path.charCodeAt(i);
      if (code === 47 /*/*/) {
          // If we reached a path separator that was not part of a set of path
          // separators at the end of the string, stop now
          if (!matchedSlash) {
            startPart = i + 1;
            break;
          }
          continue;
        }
      if (end === -1) {
        // We saw the first non-path separator, mark this as the end of our
        // extension
        matchedSlash = false;
        end = i + 1;
      }
      if (code === 46 /*.*/) {
          // If this is our first dot, mark it as the start of our extension
          if (startDot === -1)
            startDot = i;
          else if (preDotState !== 1)
            preDotState = 1;
      } else if (startDot !== -1) {
        // We saw a non-dot and non-path separator before our dot, so we should
        // have a good chance at having a non-empty extension
        preDotState = -1;
      }
    }

    if (startDot === -1 || end === -1 ||
        // We saw a non-dot character immediately before the dot
        preDotState === 0 ||
        // The (right-most) trimmed path component is exactly '..'
        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
      return '';
    }
    return path.slice(startDot, end);
  },

  format: function format(pathObject) {
    if (pathObject === null || typeof pathObject !== 'object') {
      throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
    }
    return _format('/', pathObject);
  },

  parse: function parse(path) {
    assertPath(path);

    var ret = { root: '', dir: '', base: '', ext: '', name: '' };
    if (path.length === 0) return ret;
    var code = path.charCodeAt(0);
    var isAbsolute = code === 47 /*/*/;
    var start;
    if (isAbsolute) {
      ret.root = '/';
      start = 1;
    } else {
      start = 0;
    }
    var startDot = -1;
    var startPart = 0;
    var end = -1;
    var matchedSlash = true;
    var i = path.length - 1;

    // Track the state of characters (if any) we see before our first dot and
    // after any path separator we find
    var preDotState = 0;

    // Get non-dir info
    for (; i >= start; --i) {
      code = path.charCodeAt(i);
      if (code === 47 /*/*/) {
          // If we reached a path separator that was not part of a set of path
          // separators at the end of the string, stop now
          if (!matchedSlash) {
            startPart = i + 1;
            break;
          }
          continue;
        }
      if (end === -1) {
        // We saw the first non-path separator, mark this as the end of our
        // extension
        matchedSlash = false;
        end = i + 1;
      }
      if (code === 46 /*.*/) {
          // If this is our first dot, mark it as the start of our extension
          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
        } else if (startDot !== -1) {
        // We saw a non-dot and non-path separator before our dot, so we should
        // have a good chance at having a non-empty extension
        preDotState = -1;
      }
    }

    if (startDot === -1 || end === -1 ||
    // We saw a non-dot character immediately before the dot
    preDotState === 0 ||
    // The (right-most) trimmed path component is exactly '..'
    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
      if (end !== -1) {
        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
      }
    } else {
      if (startPart === 0 && isAbsolute) {
        ret.name = path.slice(1, startDot);
        ret.base = path.slice(1, end);
      } else {
        ret.name = path.slice(startPart, startDot);
        ret.base = path.slice(startPart, end);
      }
      ret.ext = path.slice(startDot, end);
    }

    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';

    return ret;
  },

  sep: '/',
  delimiter: ':',
  win32: null,
  posix: null
};

posix.posix = posix;

module.exports = posix;


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/global */
/******/ 	(() => {
/******/ 		__webpack_require__.g = (function() {
/******/ 			if (typeof globalThis === 'object') return globalThis;
/******/ 			try {
/******/ 				return this || new Function('return this')();
/******/ 			} catch (e) {
/******/ 				if (typeof window === 'object') return window;
/******/ 			}
/******/ 		})();
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  CanvasSummaryModel: () => (/* reexport */ CanvasSummaryModel),
  CanvasSummaryView: () => (/* reexport */ CanvasSummaryView),
  MODULE_NAME: () => (/* reexport */ MODULE_NAME),
  MODULE_VERSION: () => (/* reexport */ MODULE_VERSION)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/array.js
var array_namespaceObject = {};
__webpack_require__.r(array_namespaceObject);
__webpack_require__.d(array_namespaceObject, {
  compact: () => (compact),
  concat: () => (concat),
  includes: () => (includes),
  indexof: () => (indexof),
  join: () => (join),
  lastindexof: () => (lastindexof),
  length: () => (array_length),
  pluck: () => (pluck),
  reverse: () => (reverse),
  slice: () => (slice)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/date.js
var date_namespaceObject = {};
__webpack_require__.r(date_namespaceObject);
__webpack_require__.d(date_namespaceObject, {
  date: () => (date),
  datetime: () => (datetime),
  dayofweek: () => (dayofweek),
  dayofyear: () => (dayofyear),
  format_date: () => (format_date),
  format_utcdate: () => (format_utcdate),
  hours: () => (hours),
  milliseconds: () => (milliseconds),
  minutes: () => (minutes),
  month: () => (month),
  now: () => (date_now),
  quarter: () => (quarter),
  seconds: () => (seconds),
  timestamp: () => (timestamp),
  utcdate: () => (utcdate),
  utcdatetime: () => (utcdatetime),
  utcdayofweek: () => (utcdayofweek),
  utcdayofyear: () => (utcdayofyear),
  utchours: () => (utchours),
  utcmilliseconds: () => (utcmilliseconds),
  utcminutes: () => (utcminutes),
  utcmonth: () => (utcmonth),
  utcquarter: () => (utcquarter),
  utcseconds: () => (utcseconds),
  utcweek: () => (utcweek),
  utcyear: () => (utcyear),
  week: () => (week),
  year: () => (year)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/json.js
var json_namespaceObject = {};
__webpack_require__.r(json_namespaceObject);
__webpack_require__.d(json_namespaceObject, {
  parse_json: () => (parse_json),
  to_json: () => (to_json)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/math.js
var math_namespaceObject = {};
__webpack_require__.r(math_namespaceObject);
__webpack_require__.d(math_namespaceObject, {
  abs: () => (abs),
  acos: () => (acos),
  acosh: () => (acosh),
  asin: () => (asin),
  asinh: () => (asinh),
  atan: () => (atan),
  atan2: () => (atan2),
  atanh: () => (atanh),
  cbrt: () => (cbrt),
  ceil: () => (ceil),
  clz32: () => (clz32),
  cos: () => (cos),
  cosh: () => (cosh),
  degrees: () => (math_degrees),
  exp: () => (exp),
  expm1: () => (expm1),
  floor: () => (floor),
  fround: () => (fround),
  greatest: () => (math_greatest),
  is_finite: () => (is_finite),
  is_nan: () => (is_nan),
  least: () => (least),
  log: () => (log),
  log10: () => (log10),
  log1p: () => (log1p),
  log2: () => (log2),
  pow: () => (pow),
  radians: () => (math_radians),
  random: () => (math_random),
  round: () => (round),
  sign: () => (sign),
  sin: () => (sin),
  sinh: () => (sinh),
  sqrt: () => (sqrt),
  tan: () => (tan),
  tanh: () => (tanh),
  trunc: () => (trunc)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/object.js
var object_namespaceObject = {};
__webpack_require__.r(object_namespaceObject);
__webpack_require__.d(object_namespaceObject, {
  entries: () => (object_entries),
  has: () => (has),
  keys: () => (keys),
  object: () => (object),
  values: () => (values)
});

// NAMESPACE OBJECT: ../../node_modules/arquero/src/op/functions/string.js
var string_namespaceObject = {};
__webpack_require__.r(string_namespaceObject);
__webpack_require__.d(string_namespaceObject, {
  endswith: () => (endswith),
  lower: () => (lower),
  match: () => (match),
  normalize: () => (normalize),
  padend: () => (padend),
  padstart: () => (padstart),
  parse_date: () => (parse_date),
  parse_float: () => (parse_float),
  parse_int: () => (parse_int),
  repeat: () => (string_repeat),
  replace: () => (replace),
  split: () => (split),
  startswith: () => (startswith),
  substring: () => (substring),
  trim: () => (trim),
  upper: () => (upper)
});

// NAMESPACE OBJECT: ../../node_modules/vega-transforms/build/vega-transforms.module.js
var vega_transforms_module_namespaceObject = {};
__webpack_require__.r(vega_transforms_module_namespaceObject);
__webpack_require__.d(vega_transforms_module_namespaceObject, {
  aggregate: () => (Aggregate),
  bin: () => (Bin),
  collect: () => (Collect),
  compare: () => (Compare),
  countpattern: () => (CountPattern),
  cross: () => (Cross),
  density: () => (Density),
  dotbin: () => (DotBin),
  expression: () => (Expression),
  extent: () => (Extent),
  facet: () => (Facet),
  field: () => (Field),
  filter: () => (Filter),
  flatten: () => (Flatten),
  fold: () => (Fold),
  formula: () => (Formula),
  generate: () => (Generate),
  impute: () => (Impute),
  joinaggregate: () => (JoinAggregate),
  kde: () => (KDE),
  key: () => (Key),
  load: () => (Load),
  lookup: () => (Lookup),
  multiextent: () => (MultiExtent),
  multivalues: () => (MultiValues),
  params: () => (Params),
  pivot: () => (Pivot),
  prefacet: () => (PreFacet),
  project: () => (Project),
  proxy: () => (extension_Proxy),
  quantile: () => (Quantile),
  relay: () => (Relay),
  sample: () => (Sample),
  sequence: () => (Sequence),
  sieve: () => (Sieve),
  subflow: () => (Subflow),
  timeunit: () => (vega_transforms_module_TimeUnit),
  tupleindex: () => (TupleIndex),
  values: () => (Values),
  window: () => (Window)
});

// NAMESPACE OBJECT: ../../node_modules/d3-interpolate/src/index.js
var d3_interpolate_src_namespaceObject = {};
__webpack_require__.r(d3_interpolate_src_namespaceObject);
__webpack_require__.d(d3_interpolate_src_namespaceObject, {
  interpolate: () => (value),
  interpolateArray: () => (d3_interpolate_src_array),
  interpolateBasis: () => (src_basis),
  interpolateBasisClosed: () => (src_basisClosed),
  interpolateCubehelix: () => (src_cubehelix),
  interpolateCubehelixLong: () => (cubehelixLong),
  interpolateDate: () => (src_date),
  interpolateDiscrete: () => (discrete),
  interpolateHcl: () => (src_hcl),
  interpolateHclLong: () => (hclLong),
  interpolateHsl: () => (src_hsl),
  interpolateHslLong: () => (hslLong),
  interpolateHue: () => (src_hue),
  interpolateLab: () => (lab_lab),
  interpolateNumber: () => (src_number),
  interpolateNumberArray: () => (numberArray),
  interpolateObject: () => (src_object),
  interpolateRgb: () => (rgb),
  interpolateRgbBasis: () => (rgbBasis),
  interpolateRgbBasisClosed: () => (rgbBasisClosed),
  interpolateRound: () => (src_round),
  interpolateString: () => (string),
  interpolateTransformCss: () => (interpolateTransformCss),
  interpolateTransformSvg: () => (interpolateTransformSvg),
  interpolateZoom: () => (src_zoom),
  piecewise: () => (piecewise),
  quantize: () => (src_quantize)
});

// NAMESPACE OBJECT: ../../node_modules/vega-view-transforms/build/vega-view-transforms.module.js
var vega_view_transforms_module_namespaceObject = {};
__webpack_require__.r(vega_view_transforms_module_namespaceObject);
__webpack_require__.d(vega_view_transforms_module_namespaceObject, {
  bound: () => (Bound),
  identifier: () => (vega_view_transforms_module_Identifier),
  mark: () => (Mark),
  overlap: () => (Overlap),
  render: () => (Render),
  viewlayout: () => (ViewLayout)
});

// NAMESPACE OBJECT: ../../node_modules/vega-encode/build/vega-encode.module.js
var vega_encode_module_namespaceObject = {};
__webpack_require__.r(vega_encode_module_namespaceObject);
__webpack_require__.d(vega_encode_module_namespaceObject, {
  axisticks: () => (AxisTicks),
  datajoin: () => (DataJoin),
  encode: () => (Encode),
  legendentries: () => (LegendEntries),
  linkpath: () => (LinkPath),
  pie: () => (Pie),
  scale: () => (Scale),
  sortitems: () => (SortItems),
  stack: () => (Stack)
});

// NAMESPACE OBJECT: ../../node_modules/vega-geo/build/vega-geo.module.js
var vega_geo_module_namespaceObject = {};
__webpack_require__.r(vega_geo_module_namespaceObject);
__webpack_require__.d(vega_geo_module_namespaceObject, {
  contour: () => (Contour),
  geojson: () => (GeoJSON),
  geopath: () => (GeoPath),
  geopoint: () => (GeoPoint),
  geoshape: () => (GeoShape),
  graticule: () => (Graticule),
  heatmap: () => (Heatmap),
  isocontour: () => (Isocontour),
  kde2d: () => (KDE2D),
  projection: () => (Projection)
});

// NAMESPACE OBJECT: ../../node_modules/vega-force/build/vega-force.module.js
var vega_force_module_namespaceObject = {};
__webpack_require__.r(vega_force_module_namespaceObject);
__webpack_require__.d(vega_force_module_namespaceObject, {
  force: () => (Force)
});

// NAMESPACE OBJECT: ../../node_modules/vega-hierarchy/build/vega-hierarchy.module.js
var vega_hierarchy_module_namespaceObject = {};
__webpack_require__.r(vega_hierarchy_module_namespaceObject);
__webpack_require__.d(vega_hierarchy_module_namespaceObject, {
  nest: () => (Nest),
  pack: () => (Pack),
  partition: () => (Partition),
  stratify: () => (Stratify),
  tree: () => (Tree),
  treelinks: () => (TreeLinks),
  treemap: () => (Treemap)
});

// NAMESPACE OBJECT: ../../node_modules/vega-label/build/vega-label.module.js
var vega_label_module_namespaceObject = {};
__webpack_require__.r(vega_label_module_namespaceObject);
__webpack_require__.d(vega_label_module_namespaceObject, {
  label: () => (Label)
});

// NAMESPACE OBJECT: ../../node_modules/vega-regression/build/vega-regression.module.js
var vega_regression_module_namespaceObject = {};
__webpack_require__.r(vega_regression_module_namespaceObject);
__webpack_require__.d(vega_regression_module_namespaceObject, {
  loess: () => (Loess),
  regression: () => (Regression)
});

// NAMESPACE OBJECT: ../../node_modules/vega-voronoi/build/vega-voronoi.module.js
var vega_voronoi_module_namespaceObject = {};
__webpack_require__.r(vega_voronoi_module_namespaceObject);
__webpack_require__.d(vega_voronoi_module_namespaceObject, {
  voronoi: () => (vega_voronoi_module_Voronoi)
});

// NAMESPACE OBJECT: ../../node_modules/vega-wordcloud/build/vega-wordcloud.module.js
var vega_wordcloud_module_namespaceObject = {};
__webpack_require__.r(vega_wordcloud_module_namespaceObject);
__webpack_require__.d(vega_wordcloud_module_namespaceObject, {
  wordcloud: () => (Wordcloud)
});

// NAMESPACE OBJECT: ../../node_modules/vega-crossfilter/build/vega-crossfilter.module.js
var vega_crossfilter_module_namespaceObject = {};
__webpack_require__.r(vega_crossfilter_module_namespaceObject);
__webpack_require__.d(vega_crossfilter_module_namespaceObject, {
  crossfilter: () => (CrossFilter),
  resolvefilter: () => (ResolveFilter)
});

// NAMESPACE OBJECT: ../../node_modules/vega/build/vega.module.js
var vega_module_namespaceObject = {};
__webpack_require__.r(vega_module_namespaceObject);
__webpack_require__.d(vega_module_namespaceObject, {
  Bounds: () => (Bounds),
  CanvasHandler: () => (CanvasHandler),
  CanvasRenderer: () => (CanvasRenderer),
  DATE: () => (DATE),
  DAY: () => (DAY),
  DAYOFYEAR: () => (DAYOFYEAR),
  Dataflow: () => (Dataflow),
  Debug: () => (vega_util_module_Debug),
  Error: () => (Error$1),
  EventStream: () => (EventStream),
  Gradient: () => (Gradient),
  GroupItem: () => (GroupItem),
  HOURS: () => (HOURS),
  Handler: () => (Handler),
  HybridHandler: () => (HybridHandler),
  HybridRenderer: () => (HybridRenderer),
  Info: () => (vega_util_module_Info),
  Item: () => (Item),
  MILLISECONDS: () => (MILLISECONDS),
  MINUTES: () => (MINUTES),
  MONTH: () => (MONTH),
  Marks: () => (Marks),
  MultiPulse: () => (MultiPulse),
  None: () => (None),
  Operator: () => (Operator),
  Parameters: () => (Parameters),
  Pulse: () => (Pulse),
  QUARTER: () => (QUARTER),
  RenderType: () => (RenderType),
  Renderer: () => (Renderer),
  ResourceLoader: () => (ResourceLoader),
  SECONDS: () => (SECONDS),
  SVGHandler: () => (SVGHandler),
  SVGRenderer: () => (SVGRenderer),
  SVGStringRenderer: () => (SVGStringRenderer),
  Scenegraph: () => (Scenegraph),
  TIME_UNITS: () => (TIME_UNITS),
  Transform: () => (Transform),
  View: () => (View),
  WEEK: () => (WEEK),
  Warn: () => (vega_util_module_Warn),
  YEAR: () => (YEAR),
  accessor: () => (accessor),
  accessorFields: () => (accessorFields),
  accessorName: () => (accessorName),
  array: () => (vega_util_module_array),
  ascending: () => (vega_util_module_ascending),
  bandwidthNRD: () => (estimateBandwidth),
  bin: () => (vega_statistics_module_bin),
  bootstrapCI: () => (bootstrapCI),
  boundClip: () => (boundClip),
  boundContext: () => (boundContext),
  boundItem: () => (boundItem),
  boundMark: () => (boundMark),
  boundStroke: () => (boundStroke),
  changeset: () => (changeset),
  clampRange: () => (clampRange),
  codegenExpression: () => (vega_expression_module_codegen),
  compare: () => (vega_util_module_compare),
  constant: () => (vega_util_module_constant),
  cumulativeLogNormal: () => (cumulativeLogNormal),
  cumulativeNormal: () => (cumulativeNormal),
  cumulativeUniform: () => (cumulativeUniform),
  dayofyear: () => (vega_time_module_dayofyear),
  debounce: () => (debounce),
  defaultLocale: () => (vega_format_module_defaultLocale),
  definition: () => (definition),
  densityLogNormal: () => (densityLogNormal),
  densityNormal: () => (densityNormal),
  densityUniform: () => (densityUniform),
  domChild: () => (domChild),
  domClear: () => (domClear),
  domCreate: () => (domCreate),
  domFind: () => (domFind),
  dotbin: () => (dotbin),
  error: () => (vega_util_module_error),
  expressionFunction: () => (expressionFunction),
  extend: () => (extend),
  extent: () => (extent),
  extentIndex: () => (extentIndex),
  falsy: () => (falsy),
  fastmap: () => (fastmap),
  field: () => (vega_util_module_field),
  flush: () => (vega_util_module_flush),
  font: () => (font),
  fontFamily: () => (fontFamily),
  fontSize: () => (fontSize),
  format: () => (vega_loader_browser_module_format),
  formatLocale: () => (numberFormatDefaultLocale),
  formats: () => (vega_loader_browser_module_formats),
  hasOwnProperty: () => (vega_util_module_has),
  id: () => (id),
  identity: () => (vega_util_module_identity),
  inferType: () => (vega_loader_browser_module_inferType),
  inferTypes: () => (inferTypes),
  ingest: () => (ingest$1),
  inherits: () => (inherits),
  inrange: () => (inrange),
  interpolate: () => (interpolate),
  interpolateColors: () => (interpolateColors),
  interpolateRange: () => (interpolateRange),
  intersect: () => (vega_scenegraph_module_intersect),
  intersectBoxLine: () => (intersectBoxLine),
  intersectPath: () => (intersectPath),
  intersectPoint: () => (intersectPoint),
  intersectRule: () => (intersectRule),
  isArray: () => (vega_util_module_isArray),
  isBoolean: () => (isBoolean),
  isDate: () => (vega_util_module_isDate),
  isFunction: () => (vega_util_module_isFunction),
  isIterable: () => (vega_util_module_isIterable),
  isNumber: () => (vega_util_module_isNumber),
  isObject: () => (vega_util_module_isObject),
  isRegExp: () => (vega_util_module_isRegExp),
  isString: () => (vega_util_module_isString),
  isTuple: () => (isTuple),
  key: () => (vega_util_module_key),
  lerp: () => (lerp),
  lineHeight: () => (lineHeight),
  loader: () => (loader),
  locale: () => (vega_format_module_locale),
  logger: () => (logger),
  lruCache: () => (lruCache),
  markup: () => (markup),
  merge: () => (merge),
  mergeConfig: () => (mergeConfig),
  multiLineOffset: () => (multiLineOffset),
  one: () => (one),
  pad: () => (vega_util_module_pad),
  panLinear: () => (panLinear),
  panLog: () => (panLog),
  panPow: () => (panPow),
  panSymlog: () => (panSymlog),
  parse: () => (vega_parser_module_parse),
  parseExpression: () => (parser),
  parseSelector: () => (eventSelector),
  path: () => (path),
  pathCurves: () => (curves),
  pathEqual: () => (pathEqual),
  pathParse: () => (vega_scenegraph_module_parse),
  pathRectangle: () => (vg_rect),
  pathRender: () => (pathRender),
  pathSymbols: () => (vega_scenegraph_module_symbols),
  pathTrail: () => (vg_trail),
  peek: () => (peek),
  point: () => (vega_scenegraph_module_point),
  projection: () => (vega_projection_module_projection),
  quantileLogNormal: () => (quantileLogNormal),
  quantileNormal: () => (quantileNormal),
  quantileUniform: () => (quantileUniform),
  quantiles: () => (quantiles),
  quantizeInterpolator: () => (quantizeInterpolator),
  quarter: () => (vega_util_module_quarter),
  quartiles: () => (quartiles),
  random: () => (vega_statistics_module_random),
  randomInteger: () => (integer),
  randomKDE: () => (kde),
  randomLCG: () => (vega_statistics_module_lcg),
  randomLogNormal: () => (lognormal),
  randomMixture: () => (mixture),
  randomNormal: () => (gaussian),
  randomUniform: () => (uniform),
  read: () => (read),
  regressionConstant: () => (vega_statistics_module_constant),
  regressionExp: () => (vega_statistics_module_exp),
  regressionLinear: () => (vega_statistics_module_linear),
  regressionLoess: () => (loess),
  regressionLog: () => (vega_statistics_module_log),
  regressionPoly: () => (poly),
  regressionPow: () => (vega_statistics_module_pow),
  regressionQuad: () => (quad),
  renderModule: () => (renderModule),
  repeat: () => (vega_util_module_repeat),
  resetDefaultLocale: () => (resetDefaultLocale),
  resetSVGClipId: () => (resetSVGClipId),
  resetSVGDefIds: () => (resetSVGDefIds),
  responseType: () => (responseType),
  runtimeContext: () => (vega_runtime_module_context),
  sampleCurve: () => (sampleCurve),
  sampleLogNormal: () => (sampleLogNormal),
  sampleNormal: () => (sampleNormal),
  sampleUniform: () => (sampleUniform),
  scale: () => (vega_scale_module_scale),
  sceneEqual: () => (sceneEqual),
  sceneFromJSON: () => (sceneFromJSON),
  scenePickVisit: () => (pickVisit),
  sceneToJSON: () => (sceneToJSON),
  sceneVisit: () => (vega_scenegraph_module_visit),
  sceneZOrder: () => (zorder),
  scheme: () => (scheme),
  serializeXML: () => (serializeXML),
  setHybridRendererOptions: () => (setHybridRendererOptions),
  setRandom: () => (setRandom),
  span: () => (span),
  splitAccessPath: () => (splitAccessPath),
  stringValue: () => ($),
  textMetrics: () => (textMetrics),
  timeBin: () => (vega_time_module_bin),
  timeFloor: () => (timeFloor),
  timeFormatLocale: () => (timeFormatDefaultLocale),
  timeInterval: () => (vega_time_module_timeInterval),
  timeOffset: () => (timeOffset),
  timeSequence: () => (timeSequence),
  timeUnitSpecifier: () => (timeUnitSpecifier),
  timeUnits: () => (timeUnits),
  toBoolean: () => (toBoolean),
  toDate: () => (toDate),
  toNumber: () => (vega_util_module_toNumber),
  toSet: () => (vega_util_module_toSet),
  toString: () => (vega_util_module_toString),
  transform: () => (vega_dataflow_module_transform),
  transforms: () => (vega_dataflow_module_transforms),
  truncate: () => (truncate),
  truthy: () => (truthy),
  tupleid: () => (tupleid),
  typeParsers: () => (typeParsers),
  utcFloor: () => (utcFloor),
  utcInterval: () => (utcInterval),
  utcOffset: () => (utcOffset),
  utcSequence: () => (utcSequence),
  utcdayofyear: () => (vega_time_module_utcdayofyear),
  utcquarter: () => (vega_util_module_utcquarter),
  utcweek: () => (vega_time_module_utcweek),
  version: () => (vega_module_version),
  visitArray: () => (visitArray),
  week: () => (vega_time_module_week),
  writeConfig: () => (writeConfig),
  zero: () => (zero),
  zoomLinear: () => (zoomLinear),
  zoomLog: () => (zoomLog),
  zoomPow: () => (zoomPow),
  zoomSymlog: () => (zoomSymlog)
});

// NAMESPACE OBJECT: ../../node_modules/vega-lite/build/src/index.js
var build_src_namespaceObject = {};
__webpack_require__.r(build_src_namespaceObject);
__webpack_require__.d(build_src_namespaceObject, {
  accessPathDepth: () => (accessPathDepth),
  accessPathWithDatum: () => (accessPathWithDatum),
  accessWithDatumToUnescapedPath: () => (accessWithDatumToUnescapedPath),
  compile: () => (compile_compile),
  contains: () => (util_contains),
  deepEqual: () => (util_deepEqual),
  deleteNestedProperty: () => (deleteNestedProperty),
  duplicate: () => (duplicate),
  entries: () => (util_entries),
  every: () => (every),
  fieldIntersection: () => (fieldIntersection),
  flatAccessWithDatum: () => (flatAccessWithDatum),
  getFirstDefined: () => (getFirstDefined),
  hasIntersection: () => (hasIntersection),
  hasProperty: () => (util_hasProperty),
  hash: () => (util_hash),
  internalField: () => (internalField),
  isBoolean: () => (util_isBoolean),
  isEmpty: () => (isEmpty),
  isEqual: () => (isEqual),
  isInternalField: () => (isInternalField),
  isNullOrFalse: () => (isNullOrFalse),
  isNumeric: () => (isNumeric),
  keys: () => (util_keys),
  logicalExpr: () => (logicalExpr),
  mergeDeep: () => (mergeDeep),
  never: () => (never),
  normalize: () => (normalize_normalize),
  normalizeAngle: () => (normalizeAngle),
  omit: () => (omit),
  pick: () => (util_pick),
  prefixGenerator: () => (prefixGenerator),
  removePathFromField: () => (removePathFromField),
  replaceAll: () => (replaceAll),
  replacePathInField: () => (replacePathInField),
  resetIdCounter: () => (resetIdCounter),
  setEqual: () => (setEqual),
  some: () => (some),
  stringify: () => (util_stringify),
  titleCase: () => (titleCase),
  unique: () => (unique),
  uniqueId: () => (uniqueId),
  vals: () => (vals),
  varName: () => (varName),
  version: () => (src_version)
});

// NAMESPACE OBJECT: ../../node_modules/vega-themes/build/vega-themes.module.js
var vega_themes_module_namespaceObject = {};
__webpack_require__.r(vega_themes_module_namespaceObject);
__webpack_require__.d(vega_themes_module_namespaceObject, {
  carbong10: () => (carbong10),
  carbong100: () => (carbong100),
  carbong90: () => (carbong90),
  carbonwhite: () => (carbonwhite),
  dark: () => (darkTheme),
  excel: () => (excelTheme),
  fivethirtyeight: () => (fiveThirtyEightTheme),
  ggplot2: () => (ggplot2Theme),
  googlecharts: () => (googlechartsTheme),
  latimes: () => (latimesTheme),
  powerbi: () => (powerbiTheme),
  quartz: () => (quartzTheme),
  urbaninstitute: () => (urbanInstituteTheme),
  version: () => (vega_themes_module_version),
  vox: () => (voxTheme)
});

;// ./src/version.ts
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// eslint-disable-next-line @typescript-eslint/no-var-requires
const data = __webpack_require__(8330);
/**
 * The _model_module_version/_view_module_version this package implements.
 *
 * The html widget manager assumes that this is the same as the npm package
 * version number.
 */
const MODULE_VERSION = data.version;
/*
 * The current package name.
 */
const MODULE_NAME = data.name;

// EXTERNAL MODULE: external "@jupyter-widgets/base"
var base_ = __webpack_require__(2055);
;// ../../canvas_viz/dist/index.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */







const serializers = Object.assign(Object.assign({}, base_.DOMWidgetModel.serializers), { table: {
        serialize: (value) => {
            return new DataView(value.buffer.slice(0));
        },
    } });

;// ../../node_modules/svelte/src/runtime/internal/utils.js
/** @returns {void} */
function utils_noop() {}

const utils_identity = (x) => x;

/**
 * @template T
 * @template S
 * @param {T} tar
 * @param {S} src
 * @returns {T & S}
 */
function utils_assign(tar, src) {
	// @ts-ignore
	for (const k in src) tar[k] = src[k];
	return /** @type {T & S} */ (tar);
}

// Adapted from https://github.com/then/is-promise/blob/master/index.js
// Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE
/**
 * @param {any} value
 * @returns {value is PromiseLike<any>}
 */
function is_promise(value) {
	return (
		!!value &&
		(typeof value === 'object' || typeof value === 'function') &&
		typeof (/** @type {any} */ (value).then) === 'function'
	);
}

/** @returns {void} */
function add_location(element, file, line, column, char) {
	element.__svelte_meta = {
		loc: { file, line, column, char }
	};
}

function run(fn) {
	return fn();
}

function utils_blank_object() {
	return Object.create(null);
}

/**
 * @param {Function[]} fns
 * @returns {void}
 */
function utils_run_all(fns) {
	fns.forEach(run);
}

/**
 * @param {any} thing
 * @returns {thing is Function}
 */
function utils_is_function(thing) {
	return typeof thing === 'function';
}

/** @returns {boolean} */
function safe_not_equal(a, b) {
	return a != a ? b == b : a !== b || (a && typeof a === 'object') || typeof a === 'function';
}

let src_url_equal_anchor;

/**
 * @param {string} element_src
 * @param {string} url
 * @returns {boolean}
 */
function src_url_equal(element_src, url) {
	if (element_src === url) return true;
	if (!src_url_equal_anchor) {
		src_url_equal_anchor = document.createElement('a');
	}
	// This is actually faster than doing URL(..).href
	src_url_equal_anchor.href = url;
	return element_src === src_url_equal_anchor.href;
}

/** @param {string} srcset */
function split_srcset(srcset) {
	return srcset.split(',').map((src) => src.trim().split(' ').filter(Boolean));
}

/**
 * @param {HTMLSourceElement | HTMLImageElement} element_srcset
 * @param {string | undefined | null} srcset
 * @returns {boolean}
 */
function srcset_url_equal(element_srcset, srcset) {
	const element_urls = split_srcset(element_srcset.srcset);
	const urls = split_srcset(srcset || '');

	return (
		urls.length === element_urls.length &&
		urls.every(
			([url, width], i) =>
				width === element_urls[i][1] &&
				// We need to test both ways because Vite will create an a full URL with
				// `new URL(asset, import.meta.url).href` for the client when `base: './'`, and the
				// relative URLs inside srcset are not automatically resolved to absolute URLs by
				// browsers (in contrast to img.src). This means both SSR and DOM code could
				// contain relative or absolute URLs.
				(src_url_equal(element_urls[i][0], url) || src_url_equal(url, element_urls[i][0]))
		)
	);
}

/** @returns {boolean} */
function not_equal(a, b) {
	return a != a ? b == b : a !== b;
}

/** @returns {boolean} */
function is_empty(obj) {
	return Object.keys(obj).length === 0;
}

/** @returns {void} */
function validate_store(store, name) {
	if (store != null && typeof store.subscribe !== 'function') {
		throw new Error(`'${name}' is not a store with a 'subscribe' method`);
	}
}

function subscribe(store, ...callbacks) {
	if (store == null) {
		for (const callback of callbacks) {
			callback(undefined);
		}
		return utils_noop;
	}
	const unsub = store.subscribe(...callbacks);
	return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
}

/**
 * Get the current value from a store by subscribing and immediately unsubscribing.
 *
 * https://svelte.dev/docs/svelte-store#get
 * @template T
 * @param {import('../store/public.js').Readable<T>} store
 * @returns {T}
 */
function get_store_value(store) {
	let value;
	subscribe(store, (_) => (value = _))();
	return value;
}

/** @returns {void} */
function component_subscribe(component, store, callback) {
	component.$$.on_destroy.push(subscribe(store, callback));
}

function create_slot(definition, ctx, $$scope, fn) {
	if (definition) {
		const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
		return definition[0](slot_ctx);
	}
}

function get_slot_context(definition, ctx, $$scope, fn) {
	return definition[1] && fn ? utils_assign($$scope.ctx.slice(), definition[1](fn(ctx))) : $$scope.ctx;
}

function get_slot_changes(definition, $$scope, dirty, fn) {
	if (definition[2] && fn) {
		const lets = definition[2](fn(dirty));
		if ($$scope.dirty === undefined) {
			return lets;
		}
		if (typeof lets === 'object') {
			const merged = [];
			const len = Math.max($$scope.dirty.length, lets.length);
			for (let i = 0; i < len; i += 1) {
				merged[i] = $$scope.dirty[i] | lets[i];
			}
			return merged;
		}
		return $$scope.dirty | lets;
	}
	return $$scope.dirty;
}

/** @returns {void} */
function update_slot_base(
	slot,
	slot_definition,
	ctx,
	$$scope,
	slot_changes,
	get_slot_context_fn
) {
	if (slot_changes) {
		const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
		slot.p(slot_context, slot_changes);
	}
}

/** @returns {void} */
function update_slot(
	slot,
	slot_definition,
	ctx,
	$$scope,
	dirty,
	get_slot_changes_fn,
	get_slot_context_fn
) {
	const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
	update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);
}

/** @returns {any[] | -1} */
function get_all_dirty_from_scope($$scope) {
	if ($$scope.ctx.length > 32) {
		const dirty = [];
		const length = $$scope.ctx.length / 32;
		for (let i = 0; i < length; i++) {
			dirty[i] = -1;
		}
		return dirty;
	}
	return -1;
}

/** @returns {{}} */
function exclude_internal_props(props) {
	const result = {};
	for (const k in props) if (k[0] !== '$') result[k] = props[k];
	return result;
}

/** @returns {{}} */
function compute_rest_props(props, keys) {
	const rest = {};
	keys = new Set(keys);
	for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k];
	return rest;
}

/** @returns {{}} */
function compute_slots(slots) {
	const result = {};
	for (const key in slots) {
		result[key] = true;
	}
	return result;
}

/** @returns {(this: any, ...args: any[]) => void} */
function once(fn) {
	let ran = false;
	return function (...args) {
		if (ran) return;
		ran = true;
		fn.call(this, ...args);
	};
}

function null_to_empty(value) {
	return value == null ? '' : value;
}

function set_store_value(store, ret, value) {
	store.set(value);
	return ret;
}

const utils_has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);

function action_destroyer(action_result) {
	return action_result && utils_is_function(action_result.destroy) ? action_result.destroy : utils_noop;
}

/** @param {number | string} value
 * @returns {[number, string]}
 */
function utils_split_css_unit(value) {
	const split = typeof value === 'string' && value.match(/^\s*(-?[\d.]+)([^\s]*)\s*$/);
	return split ? [parseFloat(split[1]), split[2] || 'px'] : [/** @type {number} */ (value), 'px'];
}

const utils_contenteditable_truthy_values = (/* unused pure expression or super */ null && (['', true, 1, 'true', 'contenteditable']));

;// ../../node_modules/svelte/src/runtime/internal/environment.js


const is_client = typeof window !== 'undefined';

/** @type {() => number} */
let environment_now = is_client ? () => window.performance.now() : () => Date.now();

let raf = is_client ? (cb) => requestAnimationFrame(cb) : utils_noop;

// used internally for testing
/** @returns {void} */
function set_now(fn) {
	environment_now = fn;
}

/** @returns {void} */
function set_raf(fn) {
	raf = fn;
}

;// ../../node_modules/svelte/src/runtime/internal/loop.js


const tasks = new Set();

/**
 * @param {number} now
 * @returns {void}
 */
function run_tasks(now) {
	tasks.forEach((task) => {
		if (!task.c(now)) {
			tasks.delete(task);
			task.f();
		}
	});
	if (tasks.size !== 0) raf(run_tasks);
}

/**
 * For testing purposes only!
 * @returns {void}
 */
function clear_loops() {
	tasks.clear();
}

/**
 * Creates a new task that runs on each raf frame
 * until it returns a falsy value or is aborted
 * @param {import('./private.js').TaskCallback} callback
 * @returns {import('./private.js').Task}
 */
function loop_loop(callback) {
	/** @type {import('./private.js').TaskEntry} */
	let task;
	if (tasks.size === 0) raf(run_tasks);
	return {
		promise: new Promise((fulfill) => {
			tasks.add((task = { c: callback, f: fulfill }));
		}),
		abort() {
			tasks.delete(task);
		}
	};
}

;// ../../node_modules/svelte/src/runtime/internal/globals.js
/** @type {typeof globalThis} */
const globals =
	typeof window !== 'undefined'
		? window
		: typeof globalThis !== 'undefined'
		? globalThis
		: // @ts-ignore Node typings have this
		  global;

;// ../../node_modules/svelte/src/runtime/internal/ResizeObserverSingleton.js


/**
 * Resize observer singleton.
 * One listener per element only!
 * https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ
 */
class ResizeObserverSingleton {
	/**
	 * @private
	 * @readonly
	 * @type {WeakMap<Element, import('./private.js').Listener>}
	 */
	_listeners = "WeakMap" in globals ? new WeakMap() : undefined;

	/**
	 * @private
	 * @type {ResizeObserver}
	 */
	_observer = undefined;

	/** @type {ResizeObserverOptions} */
	options;

	/** @param {ResizeObserverOptions} options */
	constructor(options) {
		this.options = options;
	}

	/**
	 * @param {Element} element
	 * @param {import('./private.js').Listener} listener
	 * @returns {() => void}
	 */
	observe(element, listener) {
		this._listeners.set(element, listener);
		this._getObserver().observe(element, this.options);
		return () => {
			this._listeners.delete(element);
			this._observer.unobserve(element); // this line can probably be removed
		};
	}

	/**
	 * @private
	 */
	_getObserver() {
		return (
			this._observer ??
			(this._observer = new ResizeObserver((entries) => {
				for (const entry of entries) {
					ResizeObserverSingleton.entries.set(entry.target, entry);
					this._listeners.get(entry.target)?.(entry);
				}
			}))
		);
	}
}

// Needs to be written like this to pass the tree-shake-test
ResizeObserverSingleton.entries = "WeakMap" in globals ? new WeakMap() : undefined;

;// ../../node_modules/svelte/src/runtime/internal/dom.js




// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM
// at the end of hydration without touching the remaining nodes.
let is_hydrating = false;

/**
 * @returns {void}
 */
function start_hydrating() {
	is_hydrating = true;
}

/**
 * @returns {void}
 */
function end_hydrating() {
	is_hydrating = false;
}

/**
 * @param {number} low
 * @param {number} high
 * @param {(index: number) => number} key
 * @param {number} value
 * @returns {number}
 */
function upper_bound(low, high, key, value) {
	// Return first index of value larger than input value in the range [low, high)
	while (low < high) {
		const mid = low + ((high - low) >> 1);
		if (key(mid) <= value) {
			low = mid + 1;
		} else {
			high = mid;
		}
	}
	return low;
}

/**
 * @param {NodeEx} target
 * @returns {void}
 */
function init_hydrate(target) {
	if (target.hydrate_init) return;
	target.hydrate_init = true;
	// We know that all children have claim_order values since the unclaimed have been detached if target is not <head>

	let children = /** @type {ArrayLike<NodeEx2>} */ (target.childNodes);
	// If target is <head>, there may be children without claim_order
	if (target.nodeName === 'HEAD') {
		const my_children = [];
		for (let i = 0; i < children.length; i++) {
			const node = children[i];
			if (node.claim_order !== undefined) {
				my_children.push(node);
			}
		}
		children = my_children;
	}
	/*
	 * Reorder claimed children optimally.
	 * We can reorder claimed children optimally by finding the longest subsequence of
	 * nodes that are already claimed in order and only moving the rest. The longest
	 * subsequence of nodes that are claimed in order can be found by
	 * computing the longest increasing subsequence of .claim_order values.
	 *
	 * This algorithm is optimal in generating the least amount of reorder operations
	 * possible.
	 *
	 * Proof:
	 * We know that, given a set of reordering operations, the nodes that do not move
	 * always form an increasing subsequence, since they do not move among each other
	 * meaning that they must be already ordered among each other. Thus, the maximal
	 * set of nodes that do not move form a longest increasing subsequence.
	 */
	// Compute longest increasing subsequence
	// m: subsequence length j => index k of smallest value that ends an increasing subsequence of length j
	const m = new Int32Array(children.length + 1);
	// Predecessor indices + 1
	const p = new Int32Array(children.length);
	m[0] = -1;
	let longest = 0;
	for (let i = 0; i < children.length; i++) {
		const current = children[i].claim_order;
		// Find the largest subsequence length such that it ends in a value less than our current value
		// upper_bound returns first greater value, so we subtract one
		// with fast path for when we are on the current longest subsequence
		const seq_len =
			(longest > 0 && children[m[longest]].claim_order <= current
				? longest + 1
				: upper_bound(1, longest, (idx) => children[m[idx]].claim_order, current)) - 1;
		p[i] = m[seq_len] + 1;
		const new_len = seq_len + 1;
		// We can guarantee that current is the smallest value. Otherwise, we would have generated a longer sequence.
		m[new_len] = i;
		longest = Math.max(new_len, longest);
	}
	// The longest increasing subsequence of nodes (initially reversed)

	/**
	 * @type {NodeEx2[]}
	 */
	const lis = [];
	// The rest of the nodes, nodes that will be moved

	/**
	 * @type {NodeEx2[]}
	 */
	const to_move = [];
	let last = children.length - 1;
	for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {
		lis.push(children[cur - 1]);
		for (; last >= cur; last--) {
			to_move.push(children[last]);
		}
		last--;
	}
	for (; last >= 0; last--) {
		to_move.push(children[last]);
	}
	lis.reverse();
	// We sort the nodes being moved to guarantee that their insertion order matches the claim order
	to_move.sort((a, b) => a.claim_order - b.claim_order);
	// Finally, we move the nodes
	for (let i = 0, j = 0; i < to_move.length; i++) {
		while (j < lis.length && to_move[i].claim_order >= lis[j].claim_order) {
			j++;
		}
		const anchor = j < lis.length ? lis[j] : null;
		target.insertBefore(to_move[i], anchor);
	}
}

/**
 * @param {Node} target
 * @param {Node} node
 * @returns {void}
 */
function dom_append(target, node) {
	target.appendChild(node);
}

/**
 * @param {Node} target
 * @param {string} style_sheet_id
 * @param {string} styles
 * @returns {void}
 */
function append_styles(target, style_sheet_id, styles) {
	const append_styles_to = get_root_for_style(target);
	if (!append_styles_to.getElementById(style_sheet_id)) {
		const style = dom_element('style');
		style.id = style_sheet_id;
		style.textContent = styles;
		append_stylesheet(append_styles_to, style);
	}
}

/**
 * @param {Node} node
 * @returns {ShadowRoot | Document}
 */
function get_root_for_style(node) {
	if (!node) return document;
	const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
	if (root && /** @type {ShadowRoot} */ (root).host) {
		return /** @type {ShadowRoot} */ (root);
	}
	return node.ownerDocument;
}

/**
 * @param {Node} node
 * @returns {CSSStyleSheet}
 */
function append_empty_stylesheet(node) {
	const style_element = dom_element('style');
	// For transitions to work without 'style-src: unsafe-inline' Content Security Policy,
	// these empty tags need to be allowed with a hash as a workaround until we move to the Web Animations API.
	// Using the hash for the empty string (for an empty tag) works in all browsers except Safari.
	// So as a workaround for the workaround, when we append empty style tags we set their content to /* empty */.
	// The hash 'sha256-9OlNO0DNEeaVzHL4RZwCLsBHA8WBQ8toBp/4F5XV2nc=' will then work even in Safari.
	style_element.textContent = '/* empty */';
	append_stylesheet(get_root_for_style(node), style_element);
	return style_element.sheet;
}

/**
 * @param {ShadowRoot | Document} node
 * @param {HTMLStyleElement} style
 * @returns {CSSStyleSheet}
 */
function append_stylesheet(node, style) {
	dom_append(/** @type {Document} */ (node).head || node, style);
	return style.sheet;
}

/**
 * @param {NodeEx} target
 * @param {NodeEx} node
 * @returns {void}
 */
function dom_append_hydration(target, node) {
	if (is_hydrating) {
		init_hydrate(target);
		if (
			target.actual_end_child === undefined ||
			(target.actual_end_child !== null && target.actual_end_child.parentNode !== target)
		) {
			target.actual_end_child = target.firstChild;
		}
		// Skip nodes of undefined ordering
		while (target.actual_end_child !== null && target.actual_end_child.claim_order === undefined) {
			target.actual_end_child = target.actual_end_child.nextSibling;
		}
		if (node !== target.actual_end_child) {
			// We only insert if the ordering of this node should be modified or the parent node is not target
			if (node.claim_order !== undefined || node.parentNode !== target) {
				target.insertBefore(node, target.actual_end_child);
			}
		} else {
			target.actual_end_child = node.nextSibling;
		}
	} else if (node.parentNode !== target || node.nextSibling !== null) {
		target.appendChild(node);
	}
}

/**
 * @param {Node} target
 * @param {Node} node
 * @param {Node} [anchor]
 * @returns {void}
 */
function dom_insert(target, node, anchor) {
	target.insertBefore(node, anchor || null);
}

/**
 * @param {NodeEx} target
 * @param {NodeEx} node
 * @param {NodeEx} [anchor]
 * @returns {void}
 */
function dom_insert_hydration(target, node, anchor) {
	if (is_hydrating && !anchor) {
		dom_append_hydration(target, node);
	} else if (node.parentNode !== target || node.nextSibling != anchor) {
		target.insertBefore(node, anchor || null);
	}
}

/**
 * @param {Node} node
 * @returns {void}
 */
function dom_detach(node) {
	if (node.parentNode) {
		node.parentNode.removeChild(node);
	}
}

/**
 * @returns {void} */
function destroy_each(iterations, detaching) {
	for (let i = 0; i < iterations.length; i += 1) {
		if (iterations[i]) iterations[i].d(detaching);
	}
}

/**
 * @template {keyof HTMLElementTagNameMap} K
 * @param {K} name
 * @returns {HTMLElementTagNameMap[K]}
 */
function dom_element(name) {
	return document.createElement(name);
}

/**
 * @template {keyof HTMLElementTagNameMap} K
 * @param {K} name
 * @param {string} is
 * @returns {HTMLElementTagNameMap[K]}
 */
function element_is(name, is) {
	return document.createElement(name, { is });
}

/**
 * @template T
 * @template {keyof T} K
 * @param {T} obj
 * @param {K[]} exclude
 * @returns {Pick<T, Exclude<keyof T, K>>}
 */
function object_without_properties(obj, exclude) {
	const target = /** @type {Pick<T, Exclude<keyof T, K>>} */ ({});
	for (const k in obj) {
		if (
			has_prop(obj, k) &&
			// @ts-ignore
			exclude.indexOf(k) === -1
		) {
			// @ts-ignore
			target[k] = obj[k];
		}
	}
	return target;
}

/**
 * @template {keyof SVGElementTagNameMap} K
 * @param {K} name
 * @returns {SVGElement}
 */
function svg_element(name) {
	return document.createElementNS('http://www.w3.org/2000/svg', name);
}

/**
 * @param {string} data
 * @returns {Text}
 */
function dom_text(data) {
	return document.createTextNode(data);
}

/**
 * @returns {Text} */
function space() {
	return dom_text(' ');
}

/**
 * @returns {Text} */
function empty() {
	return dom_text('');
}

/**
 * @param {string} content
 * @returns {Comment}
 */
function comment(content) {
	return document.createComment(content);
}

/**
 * @param {EventTarget} node
 * @param {string} event
 * @param {EventListenerOrEventListenerObject} handler
 * @param {boolean | AddEventListenerOptions | EventListenerOptions} [options]
 * @returns {() => void}
 */
function dom_listen(node, event, handler, options) {
	node.addEventListener(event, handler, options);
	return () => node.removeEventListener(event, handler, options);
}

/**
 * @returns {(event: any) => any} */
function prevent_default(fn) {
	return function (event) {
		event.preventDefault();
		// @ts-ignore
		return fn.call(this, event);
	};
}

/**
 * @returns {(event: any) => any} */
function stop_propagation(fn) {
	return function (event) {
		event.stopPropagation();
		// @ts-ignore
		return fn.call(this, event);
	};
}

/**
 * @returns {(event: any) => any} */
function stop_immediate_propagation(fn) {
	return function (event) {
		event.stopImmediatePropagation();
		// @ts-ignore
		return fn.call(this, event);
	};
}

/**
 * @returns {(event: any) => void} */
function dom_self(fn) {
	return function (event) {
		// @ts-ignore
		if (event.target === this) fn.call(this, event);
	};
}

/**
 * @returns {(event: any) => void} */
function trusted(fn) {
	return function (event) {
		// @ts-ignore
		if (event.isTrusted) fn.call(this, event);
	};
}

/**
 * @param {Element} node
 * @param {string} attribute
 * @param {string} [value]
 * @returns {void}
 */
function dom_attr(node, attribute, value) {
	if (value == null) node.removeAttribute(attribute);
	else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);
}
/**
 * List of attributes that should always be set through the attr method,
 * because updating them through the property setter doesn't work reliably.
 * In the example of `width`/`height`, the problem is that the setter only
 * accepts numeric values, but the attribute can also be set to a string like `50%`.
 * If this list becomes too big, rethink this approach.
 */
const always_set_through_set_attribute = (/* unused pure expression or super */ null && (['width', 'height']));

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {{ [x: string]: string }} attributes
 * @returns {void}
 */
function set_attributes(node, attributes) {
	// @ts-ignore
	const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
	for (const key in attributes) {
		if (attributes[key] == null) {
			node.removeAttribute(key);
		} else if (key === 'style') {
			node.style.cssText = attributes[key];
		} else if (key === '__value') {
			/** @type {any} */ (node).value = node[key] = attributes[key];
		} else if (
			descriptors[key] &&
			descriptors[key].set &&
			always_set_through_set_attribute.indexOf(key) === -1
		) {
			node[key] = attributes[key];
		} else {
			dom_attr(node, key, attributes[key]);
		}
	}
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {{ [x: string]: string }} attributes
 * @returns {void}
 */
function set_svg_attributes(node, attributes) {
	for (const key in attributes) {
		dom_attr(node, key, attributes[key]);
	}
}

/**
 * @param {Record<string, unknown>} data_map
 * @returns {void}
 */
function set_custom_element_data_map(node, data_map) {
	Object.keys(data_map).forEach((key) => {
		set_custom_element_data(node, key, data_map[key]);
	});
}

/**
 * @returns {void} */
function set_custom_element_data(node, prop, value) {
	const lower = prop.toLowerCase(); // for backwards compatibility with existing behavior we do lowercase first
	if (lower in node) {
		node[lower] = typeof node[lower] === 'boolean' && value === '' ? true : value;
	} else if (prop in node) {
		node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
	} else {
		dom_attr(node, prop, value);
	}
}

/**
 * @param {string} tag
 */
function set_dynamic_element_data(tag) {
	return /-/.test(tag) ? set_custom_element_data_map : set_attributes;
}

/**
 * @returns {void}
 */
function xlink_attr(node, attribute, value) {
	node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
}

/**
 * @param {HTMLElement} node
 * @returns {string}
 */
function get_svelte_dataset(node) {
	return node.dataset.svelteH;
}

/**
 * @returns {unknown[]} */
function get_binding_group_value(group, __value, checked) {
	const value = new Set();
	for (let i = 0; i < group.length; i += 1) {
		if (group[i].checked) value.add(group[i].__value);
	}
	if (!checked) {
		value.delete(__value);
	}
	return Array.from(value);
}

/**
 * @param {HTMLInputElement[]} group
 * @returns {{ p(...inputs: HTMLInputElement[]): void; r(): void; }}
 */
function init_binding_group(group) {
	/**
	 * @type {HTMLInputElement[]} */
	let _inputs;
	return {
		/* push */ p(...inputs) {
			_inputs = inputs;
			_inputs.forEach((input) => group.push(input));
		},
		/* remove */ r() {
			_inputs.forEach((input) => group.splice(group.indexOf(input), 1));
		}
	};
}

/**
 * @param {number[]} indexes
 * @returns {{ u(new_indexes: number[]): void; p(...inputs: HTMLInputElement[]): void; r: () => void; }}
 */
function init_binding_group_dynamic(group, indexes) {
	/**
	 * @type {HTMLInputElement[]} */
	let _group = get_binding_group(group);

	/**
	 * @type {HTMLInputElement[]} */
	let _inputs;

	function get_binding_group(group) {
		for (let i = 0; i < indexes.length; i++) {
			group = group[indexes[i]] = group[indexes[i]] || [];
		}
		return group;
	}

	/**
	 * @returns {void} */
	function push() {
		_inputs.forEach((input) => _group.push(input));
	}

	/**
	 * @returns {void} */
	function remove() {
		_inputs.forEach((input) => _group.splice(_group.indexOf(input), 1));
	}
	return {
		/* update */ u(new_indexes) {
			indexes = new_indexes;
			const new_group = get_binding_group(group);
			if (new_group !== _group) {
				remove();
				_group = new_group;
				push();
			}
		},
		/* push */ p(...inputs) {
			_inputs = inputs;
			push();
		},
		/* remove */ r: remove
	};
}

/** @returns {number} */
function to_number(value) {
	return value === '' ? null : +value;
}

/** @returns {any[]} */
function time_ranges_to_array(ranges) {
	const array = [];
	for (let i = 0; i < ranges.length; i += 1) {
		array.push({ start: ranges.start(i), end: ranges.end(i) });
	}
	return array;
}

/**
 * @param {Element} element
 * @returns {ChildNode[]}
 */
function children(element) {
	return Array.from(element.childNodes);
}

/**
 * @param {ChildNodeArray} nodes
 * @returns {void}
 */
function init_claim_info(nodes) {
	if (nodes.claim_info === undefined) {
		nodes.claim_info = { last_index: 0, total_claimed: 0 };
	}
}

/**
 * @template {ChildNodeEx} R
 * @param {ChildNodeArray} nodes
 * @param {(node: ChildNodeEx) => node is R} predicate
 * @param {(node: ChildNodeEx) => ChildNodeEx | undefined} process_node
 * @param {() => R} create_node
 * @param {boolean} dont_update_last_index
 * @returns {R}
 */
function claim_node(nodes, predicate, process_node, create_node, dont_update_last_index = false) {
	// Try to find nodes in an order such that we lengthen the longest increasing subsequence
	init_claim_info(nodes);
	const result_node = (() => {
		// We first try to find an element after the previous one
		for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {
			const node = nodes[i];
			if (predicate(node)) {
				const replacement = process_node(node);
				if (replacement === undefined) {
					nodes.splice(i, 1);
				} else {
					nodes[i] = replacement;
				}
				if (!dont_update_last_index) {
					nodes.claim_info.last_index = i;
				}
				return node;
			}
		}
		// Otherwise, we try to find one before
		// We iterate in reverse so that we don't go too far back
		for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {
			const node = nodes[i];
			if (predicate(node)) {
				const replacement = process_node(node);
				if (replacement === undefined) {
					nodes.splice(i, 1);
				} else {
					nodes[i] = replacement;
				}
				if (!dont_update_last_index) {
					nodes.claim_info.last_index = i;
				} else if (replacement === undefined) {
					// Since we spliced before the last_index, we decrease it
					nodes.claim_info.last_index--;
				}
				return node;
			}
		}
		// If we can't find any matching node, we create a new one
		return create_node();
	})();
	result_node.claim_order = nodes.claim_info.total_claimed;
	nodes.claim_info.total_claimed += 1;
	return result_node;
}

/**
 * @param {ChildNodeArray} nodes
 * @param {string} name
 * @param {{ [key: string]: boolean }} attributes
 * @param {(name: string) => Element | SVGElement} create_element
 * @returns {Element | SVGElement}
 */
function claim_element_base(nodes, name, attributes, create_element) {
	return claim_node(
		nodes,
		/** @returns {node is Element | SVGElement} */
		(node) => node.nodeName === name,
		/** @param {Element} node */
		(node) => {
			const remove = [];
			for (let j = 0; j < node.attributes.length; j++) {
				const attribute = node.attributes[j];
				if (!attributes[attribute.name]) {
					remove.push(attribute.name);
				}
			}
			remove.forEach((v) => node.removeAttribute(v));
			return undefined;
		},
		() => create_element(name)
	);
}

/**
 * @param {ChildNodeArray} nodes
 * @param {string} name
 * @param {{ [key: string]: boolean }} attributes
 * @returns {Element | SVGElement}
 */
function claim_element(nodes, name, attributes) {
	return claim_element_base(nodes, name, attributes, dom_element);
}

/**
 * @param {ChildNodeArray} nodes
 * @param {string} name
 * @param {{ [key: string]: boolean }} attributes
 * @returns {Element | SVGElement}
 */
function claim_svg_element(nodes, name, attributes) {
	return claim_element_base(nodes, name, attributes, svg_element);
}

/**
 * @param {ChildNodeArray} nodes
 * @returns {Text}
 */
function claim_text(nodes, data) {
	return claim_node(
		nodes,
		/** @returns {node is Text} */
		(node) => node.nodeType === 3,
		/** @param {Text} node */
		(node) => {
			const data_str = '' + data;
			if (node.data.startsWith(data_str)) {
				if (node.data.length !== data_str.length) {
					return node.splitText(data_str.length);
				}
			} else {
				node.data = data_str;
			}
		},
		() => dom_text(data),
		true // Text nodes should not update last index since it is likely not worth it to eliminate an increasing subsequence of actual elements
	);
}

/**
 * @returns {Text} */
function claim_space(nodes) {
	return claim_text(nodes, ' ');
}

/**
 * @param {ChildNodeArray} nodes
 * @returns {Comment}
 */
function claim_comment(nodes, data) {
	return claim_node(
		nodes,
		/** @returns {node is Comment} */
		(node) => node.nodeType === 8,
		/** @param {Comment} node */
		(node) => {
			node.data = '' + data;
			return undefined;
		},
		() => comment(data),
		true
	);
}

function get_comment_idx(nodes, text, start) {
	for (let i = start; i < nodes.length; i += 1) {
		const node = nodes[i];
		if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) {
			return i;
		}
	}
	return -1;
}

/**
 * @param {boolean} is_svg
 * @returns {HtmlTagHydration}
 */
function claim_html_tag(nodes, is_svg) {
	// find html opening tag
	const start_index = get_comment_idx(nodes, 'HTML_TAG_START', 0);
	const end_index = get_comment_idx(nodes, 'HTML_TAG_END', start_index + 1);
	if (start_index === -1 || end_index === -1) {
		return new HtmlTagHydration(is_svg);
	}

	init_claim_info(nodes);
	const html_tag_nodes = nodes.splice(start_index, end_index - start_index + 1);
	dom_detach(html_tag_nodes[0]);
	dom_detach(html_tag_nodes[html_tag_nodes.length - 1]);
	const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);
	if (claimed_nodes.length === 0) {
		return new HtmlTagHydration(is_svg);
	}
	for (const n of claimed_nodes) {
		n.claim_order = nodes.claim_info.total_claimed;
		nodes.claim_info.total_claimed += 1;
	}
	return new HtmlTagHydration(is_svg, claimed_nodes);
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @returns {void}
 */
function set_data(text, data) {
	data = '' + data;
	if (text.data === data) return;
	text.data = /** @type {string} */ (data);
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @returns {void}
 */
function set_data_contenteditable(text, data) {
	data = '' + data;
	if (text.wholeText === data) return;
	text.data = /** @type {string} */ (data);
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @param {string} attr_value
 * @returns {void}
 */
function set_data_maybe_contenteditable(text, data, attr_value) {
	if (~contenteditable_truthy_values.indexOf(attr_value)) {
		set_data_contenteditable(text, data);
	} else {
		set_data(text, data);
	}
}

/**
 * @returns {void} */
function set_input_value(input, value) {
	input.value = value == null ? '' : value;
}

/**
 * @returns {void} */
function set_input_type(input, type) {
	try {
		input.type = type;
	} catch (e) {
		// do nothing
	}
}

/**
 * @returns {void} */
function set_style(node, key, value, important) {
	if (value == null) {
		node.style.removeProperty(key);
	} else {
		node.style.setProperty(key, value, important ? 'important' : '');
	}
}

/**
 * @returns {void} */
function select_option(select, value, mounting) {
	for (let i = 0; i < select.options.length; i += 1) {
		const option = select.options[i];
		if (option.__value === value) {
			option.selected = true;
			return;
		}
	}
	if (!mounting || value !== undefined) {
		select.selectedIndex = -1; // no option should be selected
	}
}

/**
 * @returns {void} */
function select_options(select, value) {
	for (let i = 0; i < select.options.length; i += 1) {
		const option = select.options[i];
		option.selected = ~value.indexOf(option.__value);
	}
}

function select_value(select) {
	const selected_option = select.querySelector(':checked');
	return selected_option && selected_option.__value;
}

function select_multiple_value(select) {
	return [].map.call(select.querySelectorAll(':checked'), (option) => option.__value);
}
// unfortunately this can't be a constant as that wouldn't be tree-shakeable
// so we cache the result instead

/**
 * @type {boolean} */
let crossorigin;

/**
 * @returns {boolean} */
function is_crossorigin() {
	if (crossorigin === undefined) {
		crossorigin = false;
		try {
			if (typeof window !== 'undefined' && window.parent) {
				void window.parent.document;
			}
		} catch (error) {
			crossorigin = true;
		}
	}
	return crossorigin;
}

/**
 * @param {HTMLElement} node
 * @param {() => void} fn
 * @returns {() => void}
 */
function add_iframe_resize_listener(node, fn) {
	const computed_style = getComputedStyle(node);
	if (computed_style.position === 'static') {
		node.style.position = 'relative';
	}
	const iframe = dom_element('iframe');
	iframe.setAttribute(
		'style',
		'display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ' +
			'overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: -1;'
	);
	iframe.setAttribute('aria-hidden', 'true');
	iframe.tabIndex = -1;
	const crossorigin = is_crossorigin();

	/**
	 * @type {() => void}
	 */
	let unsubscribe;
	if (crossorigin) {
		iframe.src = "data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>";
		unsubscribe = dom_listen(
			window,
			'message',
			/** @param {MessageEvent} event */ (event) => {
				if (event.source === iframe.contentWindow) fn();
			}
		);
	} else {
		iframe.src = 'about:blank';
		iframe.onload = () => {
			unsubscribe = dom_listen(iframe.contentWindow, 'resize', fn);
			// make sure an initial resize event is fired _after_ the iframe is loaded (which is asynchronous)
			// see https://github.com/sveltejs/svelte/issues/4233
			fn();
		};
	}
	dom_append(node, iframe);
	return () => {
		if (crossorigin) {
			unsubscribe();
		} else if (unsubscribe && iframe.contentWindow) {
			unsubscribe();
		}
		dom_detach(iframe);
	};
}
const resize_observer_content_box = /* @__PURE__ */ new ResizeObserverSingleton({
	box: 'content-box'
});
const resize_observer_border_box = /* @__PURE__ */ new ResizeObserverSingleton({
	box: 'border-box'
});
const resize_observer_device_pixel_content_box = /* @__PURE__ */ new ResizeObserverSingleton(
	{ box: 'device-pixel-content-box' }
);


/**
 * @returns {void} */
function toggle_class(element, name, toggle) {
	// The `!!` is required because an `undefined` flag means flipping the current state.
	element.classList.toggle(name, !!toggle);
}

/**
 * @template T
 * @param {string} type
 * @param {T} [detail]
 * @param {{ bubbles?: boolean, cancelable?: boolean }} [options]
 * @returns {CustomEvent<T>}
 */
function dom_custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
	return new CustomEvent(type, { detail, bubbles, cancelable });
}

/**
 * @param {string} selector
 * @param {HTMLElement} parent
 * @returns {ChildNodeArray}
 */
function query_selector_all(selector, parent = document.body) {
	return Array.from(parent.querySelectorAll(selector));
}

/**
 * @param {string} nodeId
 * @param {HTMLElement} head
 * @returns {any[]}
 */
function head_selector(nodeId, head) {
	const result = [];
	let started = 0;
	for (const node of head.childNodes) {
		if (node.nodeType === 8 /* comment node */) {
			const comment = node.textContent.trim();
			if (comment === `HEAD_${nodeId}_END`) {
				started -= 1;
				result.push(node);
			} else if (comment === `HEAD_${nodeId}_START`) {
				started += 1;
				result.push(node);
			}
		} else if (started > 0) {
			result.push(node);
		}
	}
	return result;
}
/** */
class HtmlTag {
	/**
	 * @private
	 * @default false
	 */
	is_svg = false;
	/** parent for creating node */
	e = undefined;
	/** html tag nodes */
	n = undefined;
	/** target */
	t = undefined;
	/** anchor */
	a = undefined;
	constructor(is_svg = false) {
		this.is_svg = is_svg;
		this.e = this.n = null;
	}

	/**
	 * @param {string} html
	 * @returns {void}
	 */
	c(html) {
		this.h(html);
	}

	/**
	 * @param {string} html
	 * @param {HTMLElement | SVGElement} target
	 * @param {HTMLElement | SVGElement} anchor
	 * @returns {void}
	 */
	m(html, target, anchor = null) {
		if (!this.e) {
			if (this.is_svg)
				this.e = svg_element(/** @type {keyof SVGElementTagNameMap} */ (target.nodeName));
			/** #7364  target for <template> may be provided as #document-fragment(11) */ else
				this.e = dom_element(
					/** @type {keyof HTMLElementTagNameMap} */ (
						target.nodeType === 11 ? 'TEMPLATE' : target.nodeName
					)
				);
			this.t =
				target.tagName !== 'TEMPLATE'
					? target
					: /** @type {HTMLTemplateElement} */ (target).content;
			this.c(html);
		}
		this.i(anchor);
	}

	/**
	 * @param {string} html
	 * @returns {void}
	 */
	h(html) {
		this.e.innerHTML = html;
		this.n = Array.from(
			this.e.nodeName === 'TEMPLATE' ? this.e.content.childNodes : this.e.childNodes
		);
	}

	/**
	 * @returns {void} */
	i(anchor) {
		for (let i = 0; i < this.n.length; i += 1) {
			dom_insert(this.t, this.n[i], anchor);
		}
	}

	/**
	 * @param {string} html
	 * @returns {void}
	 */
	p(html) {
		this.d();
		this.h(html);
		this.i(this.a);
	}

	/**
	 * @returns {void} */
	d() {
		this.n.forEach(dom_detach);
	}
}

class HtmlTagHydration extends HtmlTag {
	/** @type {Element[]} hydration claimed nodes */
	l = undefined;

	constructor(is_svg = false, claimed_nodes) {
		super(is_svg);
		this.e = this.n = null;
		this.l = claimed_nodes;
	}

	/**
	 * @param {string} html
	 * @returns {void}
	 */
	c(html) {
		if (this.l) {
			this.n = this.l;
		} else {
			super.c(html);
		}
	}

	/**
	 * @returns {void} */
	i(anchor) {
		for (let i = 0; i < this.n.length; i += 1) {
			dom_insert_hydration(this.t, this.n[i], anchor);
		}
	}
}

/**
 * @param {NamedNodeMap} attributes
 * @returns {{}}
 */
function attribute_to_object(attributes) {
	const result = {};
	for (const attribute of attributes) {
		result[attribute.name] = attribute.value;
	}
	return result;
}

const escaped = {
	'"': '&quot;',
	'&': '&amp;',
	'<': '&lt;'
};

const regex_attribute_characters_to_escape = /["&<]/g;

/**
 * Note that the attribute itself should be surrounded in double quotes
 * @param {any} attribute
 */
function escape_attribute(attribute) {
	return String(attribute).replace(regex_attribute_characters_to_escape, (match) => escaped[match]);
}

/**
 * @param {Record<string, string>} attributes
 */
function stringify_spread(attributes) {
	let str = ' ';
	for (const key in attributes) {
		if (attributes[key] != null) {
			str += `${key}="${escape_attribute(attributes[key])}" `;
		}
	}

	return str;
}

/**
 * @param {HTMLElement} element
 * @returns {{}}
 */
function get_custom_elements_slots(element) {
	const result = {};
	element.childNodes.forEach(
		/** @param {Element} node */ (node) => {
			result[node.slot || 'default'] = true;
		}
	);
	return result;
}

function construct_svelte_component(component, props) {
	return new component(props);
}

/**
 * @typedef {Node & {
 * 	claim_order?: number;
 * 	hydrate_init?: true;
 * 	actual_end_child?: NodeEx;
 * 	childNodes: NodeListOf<NodeEx>;
 * }} NodeEx
 */

/** @typedef {ChildNode & NodeEx} ChildNodeEx */

/** @typedef {NodeEx & { claim_order: number }} NodeEx2 */

/**
 * @typedef {ChildNodeEx[] & {
 * 	claim_info?: {
 * 		last_index: number;
 * 		total_claimed: number;
 * 	};
 * }} ChildNodeArray
 */

;// ../../node_modules/svelte/src/runtime/internal/style_manager.js



// we need to store the information for multiple documents because a Svelte application could also contain iframes
// https://github.com/sveltejs/svelte/issues/3624
/** @type {Map<Document | ShadowRoot, import('./private.d.ts').StyleInformation>} */
const managed_styles = new Map();

let active = 0;

// https://github.com/darkskyapp/string-hash/blob/master/index.js
/**
 * @param {string} str
 * @returns {number}
 */
function hash(str) {
	let hash = 5381;
	let i = str.length;
	while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
	return hash >>> 0;
}

/**
 * @param {Document | ShadowRoot} doc
 * @param {Element & ElementCSSInlineStyle} node
 * @returns {{ stylesheet: any; rules: {}; }}
 */
function create_style_information(doc, node) {
	const info = { stylesheet: append_empty_stylesheet(node), rules: {} };
	managed_styles.set(doc, info);
	return info;
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {number} a
 * @param {number} b
 * @param {number} duration
 * @param {number} delay
 * @param {(t: number) => number} ease
 * @param {(t: number, u: number) => string} fn
 * @param {number} uid
 * @returns {string}
 */
function style_manager_create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
	const step = 16.666 / duration;
	let keyframes = '{\n';
	for (let p = 0; p <= 1; p += step) {
		const t = a + (b - a) * ease(p);
		keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`;
	}
	const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
	const name = `__svelte_${hash(rule)}_${uid}`;
	const doc = get_root_for_style(node);
	const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);
	if (!rules[name]) {
		rules[name] = true;
		stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
	}
	const animation = node.style.animation || '';
	node.style.animation = `${
		animation ? `${animation}, ` : ''
	}${name} ${duration}ms linear ${delay}ms 1 both`;
	active += 1;
	return name;
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {string} [name]
 * @returns {void}
 */
function style_manager_delete_rule(node, name) {
	const previous = (node.style.animation || '').split(', ');
	const next = previous.filter(
		name
			? (anim) => anim.indexOf(name) < 0 // remove specific animation
			: (anim) => anim.indexOf('__svelte') === -1 // remove all Svelte animations
	);
	const deleted = previous.length - next.length;
	if (deleted) {
		node.style.animation = next.join(', ');
		active -= deleted;
		if (!active) clear_rules();
	}
}

/** @returns {void} */
function clear_rules() {
	raf(() => {
		if (active) return;
		managed_styles.forEach((info) => {
			const { ownerNode } = info.stylesheet;
			// there is no ownerNode if it runs on jsdom.
			if (ownerNode) dom_detach(ownerNode);
		});
		managed_styles.clear();
	});
}

;// ../../node_modules/svelte/src/runtime/internal/animations.js





/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {import('./private.js').PositionRect} from
 * @param {import('./private.js').AnimationFn} fn
 */
function create_animation(node, from, fn, params) {
	if (!from) return noop;
	const to = node.getBoundingClientRect();
	if (
		from.left === to.left &&
		from.right === to.right &&
		from.top === to.top &&
		from.bottom === to.bottom
	)
		return noop;
	const {
		delay = 0,
		duration = 300,
		easing = linear,
		// @ts-ignore todo: should this be separated from destructuring? Or start/end added to public api and documentation?
		start: start_time = now() + delay,
		// @ts-ignore todo:
		end = start_time + duration,
		tick = noop,
		css
	} = fn(node, { from, to }, params);
	let running = true;
	let started = false;
	let name;
	/** @returns {void} */
	function start() {
		if (css) {
			name = create_rule(node, 0, 1, duration, delay, easing, css);
		}
		if (!delay) {
			started = true;
		}
	}
	/** @returns {void} */
	function stop() {
		if (css) delete_rule(node, name);
		running = false;
	}
	loop((now) => {
		if (!started && now >= start_time) {
			started = true;
		}
		if (started && now >= end) {
			tick(1, 0);
			stop();
		}
		if (!running) {
			return false;
		}
		if (started) {
			const p = now - start_time;
			const t = 0 + 1 * easing(p / duration);
			tick(t, 1 - t);
		}
		return true;
	});
	start();
	tick(0, 1);
	return stop;
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @returns {void}
 */
function fix_position(node) {
	const style = getComputedStyle(node);
	if (style.position !== 'absolute' && style.position !== 'fixed') {
		const { width, height } = style;
		const a = node.getBoundingClientRect();
		node.style.position = 'absolute';
		node.style.width = width;
		node.style.height = height;
		add_transform(node, a);
	}
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {import('./private.js').PositionRect} a
 * @returns {void}
 */
function add_transform(node, a) {
	const b = node.getBoundingClientRect();
	if (a.left !== b.left || a.top !== b.top) {
		const style = getComputedStyle(node);
		const transform = style.transform === 'none' ? '' : style.transform;
		node.style.transform = `${transform} translate(${a.left - b.left}px, ${a.top - b.top}px)`;
	}
}

;// ../../node_modules/svelte/src/runtime/internal/lifecycle.js


let lifecycle_current_component;

/** @returns {void} */
function lifecycle_set_current_component(component) {
	lifecycle_current_component = component;
}

function get_current_component() {
	if (!lifecycle_current_component) throw new Error('Function called outside component initialization');
	return lifecycle_current_component;
}

/**
 * Schedules a callback to run immediately before the component is updated after any state change.
 *
 * The first time the callback runs will be before the initial `onMount`
 *
 * https://svelte.dev/docs/svelte#beforeupdate
 * @param {() => any} fn
 * @returns {void}
 */
function beforeUpdate(fn) {
	get_current_component().$$.before_update.push(fn);
}

/**
 * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
 * It must be called during the component's initialisation (but doesn't need to live *inside* the component;
 * it can be called from an external module).
 *
 * If a function is returned _synchronously_ from `onMount`, it will be called when the component is unmounted.
 *
 * `onMount` does not run inside a [server-side component](https://svelte.dev/docs#run-time-server-side-component-api).
 *
 * https://svelte.dev/docs/svelte#onmount
 * @template T
 * @param {() => import('./private.js').NotFunction<T> | Promise<import('./private.js').NotFunction<T>> | (() => any)} fn
 * @returns {void}
 */
function onMount(fn) {
	get_current_component().$$.on_mount.push(fn);
}

/**
 * Schedules a callback to run immediately after the component has been updated.
 *
 * The first time the callback runs will be after the initial `onMount`
 *
 * https://svelte.dev/docs/svelte#afterupdate
 * @param {() => any} fn
 * @returns {void}
 */
function afterUpdate(fn) {
	get_current_component().$$.after_update.push(fn);
}

/**
 * Schedules a callback to run immediately before the component is unmounted.
 *
 * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
 * only one that runs inside a server-side component.
 *
 * https://svelte.dev/docs/svelte#ondestroy
 * @param {() => any} fn
 * @returns {void}
 */
function onDestroy(fn) {
	get_current_component().$$.on_destroy.push(fn);
}

/**
 * Creates an event dispatcher that can be used to dispatch [component events](https://svelte.dev/docs#template-syntax-component-directives-on-eventname).
 * Event dispatchers are functions that can take two arguments: `name` and `detail`.
 *
 * Component events created with `createEventDispatcher` create a
 * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent).
 * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture).
 * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)
 * property and can contain any type of data.
 *
 * The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument:
 * ```ts
 * const dispatch = createEventDispatcher<{
 *  loaded: never; // does not take a detail argument
 *  change: string; // takes a detail argument of type string, which is required
 *  optional: number | null; // takes an optional detail argument of type number
 * }>();
 * ```
 *
 * https://svelte.dev/docs/svelte#createeventdispatcher
 * @template {Record<string, any>} [EventMap=any]
 * @returns {import('./public.js').EventDispatcher<EventMap>}
 */
function createEventDispatcher() {
	const component = get_current_component();
	return (type, detail, { cancelable = false } = {}) => {
		const callbacks = component.$$.callbacks[type];
		if (callbacks) {
			// TODO are there situations where events could be dispatched
			// in a server (non-DOM) environment?
			const event = dom_custom_event(/** @type {string} */ (type), detail, { cancelable });
			callbacks.slice().forEach((fn) => {
				fn.call(component, event);
			});
			return !event.defaultPrevented;
		}
		return true;
	};
}

/**
 * Associates an arbitrary `context` object with the current component and the specified `key`
 * and returns that object. The context is then available to children of the component
 * (including slotted content) with `getContext`.
 *
 * Like lifecycle functions, this must be called during component initialisation.
 *
 * https://svelte.dev/docs/svelte#setcontext
 * @template T
 * @param {any} key
 * @param {T} context
 * @returns {T}
 */
function setContext(key, context) {
	get_current_component().$$.context.set(key, context);
	return context;
}

/**
 * Retrieves the context that belongs to the closest parent component with the specified `key`.
 * Must be called during component initialisation.
 *
 * https://svelte.dev/docs/svelte#getcontext
 * @template T
 * @param {any} key
 * @returns {T}
 */
function getContext(key) {
	return get_current_component().$$.context.get(key);
}

/**
 * Retrieves the whole context map that belongs to the closest parent component.
 * Must be called during component initialisation. Useful, for example, if you
 * programmatically create a component and want to pass the existing context to it.
 *
 * https://svelte.dev/docs/svelte#getallcontexts
 * @template {Map<any, any>} [T=Map<any, any>]
 * @returns {T}
 */
function getAllContexts() {
	return get_current_component().$$.context;
}

/**
 * Checks whether a given `key` has been set in the context of a parent component.
 * Must be called during component initialisation.
 *
 * https://svelte.dev/docs/svelte#hascontext
 * @param {any} key
 * @returns {boolean}
 */
function hasContext(key) {
	return get_current_component().$$.context.has(key);
}

// TODO figure out if we still want to support
// shorthand events, or if we want to implement
// a real bubbling mechanism
/**
 * @param component
 * @param event
 * @returns {void}
 */
function bubble(component, event) {
	const callbacks = component.$$.callbacks[event.type];
	if (callbacks) {
		// @ts-ignore
		callbacks.slice().forEach((fn) => fn.call(this, event));
	}
}

;// ../../node_modules/svelte/src/runtime/internal/scheduler.js



const dirty_components = [];
const intros = { enabled: false };
const binding_callbacks = [];

let render_callbacks = [];

const flush_callbacks = [];

const resolved_promise = /* @__PURE__ */ Promise.resolve();

let update_scheduled = false;

/** @returns {void} */
function schedule_update() {
	if (!update_scheduled) {
		update_scheduled = true;
		resolved_promise.then(flush);
	}
}

/** @returns {Promise<void>} */
function tick() {
	schedule_update();
	return resolved_promise;
}

/** @returns {void} */
function scheduler_add_render_callback(fn) {
	render_callbacks.push(fn);
}

/** @returns {void} */
function add_flush_callback(fn) {
	flush_callbacks.push(fn);
}

// flush() calls callbacks in this order:
// 1. All beforeUpdate callbacks, in order: parents before children
// 2. All bind:this callbacks, in reverse order: children before parents.
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
//    for afterUpdates called during the initial onMount, which are called in
//    reverse order: children before parents.
// Since callbacks might update component values, which could trigger another
// call to flush(), the following steps guard against this:
// 1. During beforeUpdate, any updated components will be added to the
//    dirty_components array and will cause a reentrant call to flush(). Because
//    the flush index is kept outside the function, the reentrant call will pick
//    up where the earlier call left off and go through all dirty components. The
//    current_component value is saved and restored so that the reentrant call will
//    not interfere with the "parent" flush() call.
// 2. bind:this callbacks cannot trigger new flush() calls.
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
//    callback called a second time; the seen_callbacks set, outside the flush()
//    function, guarantees this behavior.
const seen_callbacks = new Set();

let flushidx = 0; // Do *not* move this inside the flush() function

/** @returns {void} */
function flush() {
	// Do not reenter flush while dirty components are updated, as this can
	// result in an infinite loop. Instead, let the inner flush handle it.
	// Reentrancy is ok afterwards for bindings etc.
	if (flushidx !== 0) {
		return;
	}
	const saved_component = lifecycle_current_component;
	do {
		// first, call beforeUpdate functions
		// and update components
		try {
			while (flushidx < dirty_components.length) {
				const component = dirty_components[flushidx];
				flushidx++;
				lifecycle_set_current_component(component);
				update(component.$$);
			}
		} catch (e) {
			// reset dirty state to not end up in a deadlocked state and then rethrow
			dirty_components.length = 0;
			flushidx = 0;
			throw e;
		}
		lifecycle_set_current_component(null);
		dirty_components.length = 0;
		flushidx = 0;
		while (binding_callbacks.length) binding_callbacks.pop()();
		// then, once components are updated, call
		// afterUpdate functions. This may cause
		// subsequent updates...
		for (let i = 0; i < render_callbacks.length; i += 1) {
			const callback = render_callbacks[i];
			if (!seen_callbacks.has(callback)) {
				// ...so guard against infinite loops
				seen_callbacks.add(callback);
				callback();
			}
		}
		render_callbacks.length = 0;
	} while (dirty_components.length);
	while (flush_callbacks.length) {
		flush_callbacks.pop()();
	}
	update_scheduled = false;
	seen_callbacks.clear();
	lifecycle_set_current_component(saved_component);
}

/** @returns {void} */
function update($$) {
	if ($$.fragment !== null) {
		$$.update();
		utils_run_all($$.before_update);
		const dirty = $$.dirty;
		$$.dirty = [-1];
		$$.fragment && $$.fragment.p($$.ctx, dirty);
		$$.after_update.forEach(scheduler_add_render_callback);
	}
}

/**
 * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.
 * @param {Function[]} fns
 * @returns {void}
 */
function flush_render_callbacks(fns) {
	const filtered = [];
	const targets = [];
	render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c)));
	targets.forEach((c) => c());
	render_callbacks = filtered;
}

;// ../../node_modules/svelte/src/runtime/internal/transitions.js







/**
 * @type {Promise<void> | null}
 */
let promise;

/**
 * @returns {Promise<void>}
 */
function wait() {
	if (!promise) {
		promise = Promise.resolve();
		promise.then(() => {
			promise = null;
		});
	}
	return promise;
}

/**
 * @param {Element} node
 * @param {INTRO | OUTRO | boolean} direction
 * @param {'start' | 'end'} kind
 * @returns {void}
 */
function dispatch(node, direction, kind) {
	node.dispatchEvent(dom_custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
}

const outroing = new Set();

/**
 * @type {Outro}
 */
let outros;

/**
 * @returns {void} */
function group_outros() {
	outros = {
		r: 0,
		c: [],
		p: outros // parent group
	};
}

/**
 * @returns {void} */
function check_outros() {
	if (!outros.r) {
		utils_run_all(outros.c);
	}
	outros = outros.p;
}

/**
 * @param {import('./private.js').Fragment} block
 * @param {0 | 1} [local]
 * @returns {void}
 */
function transitions_transition_in(block, local) {
	if (block && block.i) {
		outroing.delete(block);
		block.i(local);
	}
}

/**
 * @param {import('./private.js').Fragment} block
 * @param {0 | 1} local
 * @param {0 | 1} [detach]
 * @param {() => void} [callback]
 * @returns {void}
 */
function transitions_transition_out(block, local, detach, callback) {
	if (block && block.o) {
		if (outroing.has(block)) return;
		outroing.add(block);
		outros.c.push(() => {
			outroing.delete(block);
			if (callback) {
				if (detach) block.d(1);
				callback();
			}
		});
		block.o(local);
	} else if (callback) {
		callback();
	}
}

/**
 * @type {import('../transition/public.js').TransitionConfig}
 */
const null_transition = { duration: 0 };

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {TransitionFn} fn
 * @param {any} params
 * @returns {{ start(): void; invalidate(): void; end(): void; }}
 */
function create_in_transition(node, fn, params) {
	/**
	 * @type {TransitionOptions} */
	const options = { direction: 'in' };
	let config = fn(node, params, options);
	let running = false;
	let animation_name;
	let task;
	let uid = 0;

	/**
	 * @returns {void} */
	function cleanup() {
		if (animation_name) delete_rule(node, animation_name);
	}

	/**
	 * @returns {void} */
	function go() {
		const {
			delay = 0,
			duration = 300,
			easing = linear,
			tick = noop,
			css
		} = config || null_transition;
		if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
		tick(0, 1);
		const start_time = now() + delay;
		const end_time = start_time + duration;
		if (task) task.abort();
		running = true;
		add_render_callback(() => dispatch(node, true, 'start'));
		task = loop((now) => {
			if (running) {
				if (now >= end_time) {
					tick(1, 0);
					dispatch(node, true, 'end');
					cleanup();
					return (running = false);
				}
				if (now >= start_time) {
					const t = easing((now - start_time) / duration);
					tick(t, 1 - t);
				}
			}
			return running;
		});
	}
	let started = false;
	return {
		start() {
			if (started) return;
			started = true;
			delete_rule(node);
			if (is_function(config)) {
				config = config(options);
				wait().then(go);
			} else {
				go();
			}
		},
		invalidate() {
			started = false;
		},
		end() {
			if (running) {
				cleanup();
				running = false;
			}
		}
	};
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {TransitionFn} fn
 * @param {any} params
 * @returns {{ end(reset: any): void; }}
 */
function create_out_transition(node, fn, params) {
	/** @type {TransitionOptions} */
	const options = { direction: 'out' };
	let config = fn(node, params, options);
	let running = true;
	let animation_name;
	const group = outros;
	group.r += 1;
	/** @type {boolean} */
	let original_inert_value;

	/**
	 * @returns {void} */
	function go() {
		const {
			delay = 0,
			duration = 300,
			easing = linear,
			tick = noop,
			css
		} = config || null_transition;

		if (css) animation_name = create_rule(node, 1, 0, duration, delay, easing, css);

		const start_time = now() + delay;
		const end_time = start_time + duration;
		add_render_callback(() => dispatch(node, false, 'start'));

		if ('inert' in node) {
			original_inert_value = /** @type {HTMLElement} */ (node).inert;
			node.inert = true;
		}

		loop((now) => {
			if (running) {
				if (now >= end_time) {
					tick(0, 1);
					dispatch(node, false, 'end');
					if (!--group.r) {
						// this will result in `end()` being called,
						// so we don't need to clean up here
						run_all(group.c);
					}
					return false;
				}
				if (now >= start_time) {
					const t = easing((now - start_time) / duration);
					tick(1 - t, t);
				}
			}
			return running;
		});
	}

	if (is_function(config)) {
		wait().then(() => {
			// @ts-ignore
			config = config(options);
			go();
		});
	} else {
		go();
	}

	return {
		end(reset) {
			if (reset && 'inert' in node) {
				node.inert = original_inert_value;
			}
			if (reset && config.tick) {
				config.tick(1, 0);
			}
			if (running) {
				if (animation_name) delete_rule(node, animation_name);
				running = false;
			}
		}
	};
}

/**
 * @param {Element & ElementCSSInlineStyle} node
 * @param {TransitionFn} fn
 * @param {any} params
 * @param {boolean} intro
 * @returns {{ run(b: 0 | 1): void; end(): void; }}
 */
function create_bidirectional_transition(node, fn, params, intro) {
	/**
	 * @type {TransitionOptions} */
	const options = { direction: 'both' };
	let config = fn(node, params, options);
	let t = intro ? 0 : 1;

	/**
	 * @type {Program | null} */
	let running_program = null;

	/**
	 * @type {PendingProgram | null} */
	let pending_program = null;
	let animation_name = null;

	/** @type {boolean} */
	let original_inert_value;

	/**
	 * @returns {void} */
	function clear_animation() {
		if (animation_name) style_manager_delete_rule(node, animation_name);
	}

	/**
	 * @param {PendingProgram} program
	 * @param {number} duration
	 * @returns {Program}
	 */
	function init(program, duration) {
		const d = /** @type {Program['d']} */ (program.b - t);
		duration *= Math.abs(d);
		return {
			a: t,
			b: program.b,
			d,
			duration,
			start: program.start,
			end: program.start + duration,
			group: program.group
		};
	}

	/**
	 * @param {INTRO | OUTRO} b
	 * @returns {void}
	 */
	function go(b) {
		const {
			delay = 0,
			duration = 300,
			easing = utils_identity,
			tick = utils_noop,
			css
		} = config || null_transition;

		/**
		 * @type {PendingProgram} */
		const program = {
			start: environment_now() + delay,
			b
		};

		if (!b) {
			// @ts-ignore todo: improve typings
			program.group = outros;
			outros.r += 1;
		}

		if ('inert' in node) {
			if (b) {
				if (original_inert_value !== undefined) {
					// aborted/reversed outro — restore previous inert value
					node.inert = original_inert_value;
				}
			} else {
				original_inert_value = /** @type {HTMLElement} */ (node).inert;
				node.inert = true;
			}
		}

		if (running_program || pending_program) {
			pending_program = program;
		} else {
			// if this is an intro, and there's a delay, we need to do
			// an initial tick and/or apply CSS animation immediately
			if (css) {
				clear_animation();
				animation_name = style_manager_create_rule(node, t, b, duration, delay, easing, css);
			}
			if (b) tick(0, 1);
			running_program = init(program, duration);
			scheduler_add_render_callback(() => dispatch(node, b, 'start'));
			loop_loop((now) => {
				if (pending_program && now > pending_program.start) {
					running_program = init(pending_program, duration);
					pending_program = null;
					dispatch(node, running_program.b, 'start');
					if (css) {
						clear_animation();
						animation_name = style_manager_create_rule(
							node,
							t,
							running_program.b,
							running_program.duration,
							0,
							easing,
							config.css
						);
					}
				}
				if (running_program) {
					if (now >= running_program.end) {
						tick((t = running_program.b), 1 - t);
						dispatch(node, running_program.b, 'end');
						if (!pending_program) {
							// we're done
							if (running_program.b) {
								// intro — we can tidy up immediately
								clear_animation();
							} else {
								// outro — needs to be coordinated
								if (!--running_program.group.r) utils_run_all(running_program.group.c);
							}
						}
						running_program = null;
					} else if (now >= running_program.start) {
						const p = now - running_program.start;
						t = running_program.a + running_program.d * easing(p / running_program.duration);
						tick(t, 1 - t);
					}
				}
				return !!(running_program || pending_program);
			});
		}
	}
	return {
		run(b) {
			if (utils_is_function(config)) {
				wait().then(() => {
					const opts = { direction: b ? 'in' : 'out' };
					// @ts-ignore
					config = config(opts);
					go(b);
				});
			} else {
				go(b);
			}
		},
		end() {
			clear_animation();
			running_program = pending_program = null;
		}
	};
}

/** @typedef {1} INTRO */
/** @typedef {0} OUTRO */
/** @typedef {{ direction: 'in' | 'out' | 'both' }} TransitionOptions */
/** @typedef {(node: Element, params: any, options: TransitionOptions) => import('../transition/public.js').TransitionConfig} TransitionFn */

/**
 * @typedef {Object} Outro
 * @property {number} r
 * @property {Function[]} c
 * @property {Object} p
 */

/**
 * @typedef {Object} PendingProgram
 * @property {number} start
 * @property {INTRO|OUTRO} b
 * @property {Outro} [group]
 */

/**
 * @typedef {Object} Program
 * @property {number} a
 * @property {INTRO|OUTRO} b
 * @property {1|-1} d
 * @property {number} duration
 * @property {number} start
 * @property {number} end
 * @property {Outro} [group]
 */

;// ../../node_modules/svelte/src/runtime/internal/await_block.js





/**
 * @template T
 * @param {Promise<T>} promise
 * @param {import('./private.js').PromiseInfo<T>} info
 * @returns {boolean}
 */
function handle_promise(promise, info) {
	const token = (info.token = {});
	/**
	 * @param {import('./private.js').FragmentFactory} type
	 * @param {0 | 1 | 2} index
	 * @param {number} [key]
	 * @param {any} [value]
	 * @returns {void}
	 */
	function update(type, index, key, value) {
		if (info.token !== token) return;
		info.resolved = value;
		let child_ctx = info.ctx;
		if (key !== undefined) {
			child_ctx = child_ctx.slice();
			child_ctx[key] = value;
		}
		const block = type && (info.current = type)(child_ctx);
		let needs_flush = false;
		if (info.block) {
			if (info.blocks) {
				info.blocks.forEach((block, i) => {
					if (i !== index && block) {
						group_outros();
						transitions_transition_out(block, 1, 1, () => {
							if (info.blocks[i] === block) {
								info.blocks[i] = null;
							}
						});
						check_outros();
					}
				});
			} else {
				info.block.d(1);
			}
			block.c();
			transitions_transition_in(block, 1);
			block.m(info.mount(), info.anchor);
			needs_flush = true;
		}
		info.block = block;
		if (info.blocks) info.blocks[index] = block;
		if (needs_flush) {
			flush();
		}
	}
	if (is_promise(promise)) {
		const current_component = get_current_component();
		promise.then(
			(value) => {
				lifecycle_set_current_component(current_component);
				update(info.then, 1, info.value, value);
				lifecycle_set_current_component(null);
			},
			(error) => {
				lifecycle_set_current_component(current_component);
				update(info.catch, 2, info.error, error);
				lifecycle_set_current_component(null);
				if (!info.hasCatch) {
					throw error;
				}
			}
		);
		// if we previously had a then/catch block, destroy it
		if (info.current !== info.pending) {
			update(info.pending, 0);
			return true;
		}
	} else {
		if (info.current !== info.then) {
			update(info.then, 1, info.value, promise);
			return true;
		}
		info.resolved = /** @type {T} */ (promise);
	}
}

/** @returns {void} */
function update_await_block_branch(info, ctx, dirty) {
	const child_ctx = ctx.slice();
	const { resolved } = info;
	if (info.current === info.then) {
		child_ctx[info.value] = resolved;
	}
	if (info.current === info.catch) {
		child_ctx[info.error] = resolved;
	}
	info.block.p(child_ctx, dirty);
}

;// ../../node_modules/svelte/src/runtime/internal/each.js



// general each functions:

function each_ensure_array_like(array_like_or_iterator) {
	return array_like_or_iterator?.length !== undefined
		? array_like_or_iterator
		: Array.from(array_like_or_iterator);
}

// keyed each functions:

/** @returns {void} */
function destroy_block(block, lookup) {
	block.d(1);
	lookup.delete(block.key);
}

/** @returns {void} */
function outro_and_destroy_block(block, lookup) {
	transition_out(block, 1, 1, () => {
		lookup.delete(block.key);
	});
}

/** @returns {void} */
function fix_and_destroy_block(block, lookup) {
	block.f();
	destroy_block(block, lookup);
}

/** @returns {void} */
function fix_and_outro_and_destroy_block(block, lookup) {
	block.f();
	outro_and_destroy_block(block, lookup);
}

/** @returns {any[]} */
function update_keyed_each(
	old_blocks,
	dirty,
	get_key,
	dynamic,
	ctx,
	list,
	lookup,
	node,
	destroy,
	create_each_block,
	next,
	get_context
) {
	let o = old_blocks.length;
	let n = list.length;
	let i = o;
	const old_indexes = {};
	while (i--) old_indexes[old_blocks[i].key] = i;
	const new_blocks = [];
	const new_lookup = new Map();
	const deltas = new Map();
	const updates = [];
	i = n;
	while (i--) {
		const child_ctx = get_context(ctx, list, i);
		const key = get_key(child_ctx);
		let block = lookup.get(key);
		if (!block) {
			block = create_each_block(key, child_ctx);
			block.c();
		} else if (dynamic) {
			// defer updates until all the DOM shuffling is done
			updates.push(() => block.p(child_ctx, dirty));
		}
		new_lookup.set(key, (new_blocks[i] = block));
		if (key in old_indexes) deltas.set(key, Math.abs(i - old_indexes[key]));
	}
	const will_move = new Set();
	const did_move = new Set();
	/** @returns {void} */
	function insert(block) {
		transition_in(block, 1);
		block.m(node, next);
		lookup.set(block.key, block);
		next = block.first;
		n--;
	}
	while (o && n) {
		const new_block = new_blocks[n - 1];
		const old_block = old_blocks[o - 1];
		const new_key = new_block.key;
		const old_key = old_block.key;
		if (new_block === old_block) {
			// do nothing
			next = new_block.first;
			o--;
			n--;
		} else if (!new_lookup.has(old_key)) {
			// remove old block
			destroy(old_block, lookup);
			o--;
		} else if (!lookup.has(new_key) || will_move.has(new_key)) {
			insert(new_block);
		} else if (did_move.has(old_key)) {
			o--;
		} else if (deltas.get(new_key) > deltas.get(old_key)) {
			did_move.add(new_key);
			insert(new_block);
		} else {
			will_move.add(old_key);
			o--;
		}
	}
	while (o--) {
		const old_block = old_blocks[o];
		if (!new_lookup.has(old_block.key)) destroy(old_block, lookup);
	}
	while (n) insert(new_blocks[n - 1]);
	run_all(updates);
	return new_blocks;
}

/** @returns {void} */
function validate_each_keys(ctx, list, get_context, get_key) {
	const keys = new Map();
	for (let i = 0; i < list.length; i++) {
		const key = get_key(get_context(ctx, list, i));
		if (keys.has(key)) {
			let value = '';
			try {
				value = `with value '${String(key)}' `;
			} catch (e) {
				// can't stringify
			}
			throw new Error(
				`Cannot have duplicate keys in a keyed each: Keys at index ${keys.get(
					key
				)} and ${i} ${value}are duplicates`
			);
		}
		keys.set(key, i);
	}
}

;// ../../node_modules/svelte/src/shared/boolean_attributes.js
const _boolean_attributes = /** @type {const} */ ([
	'allowfullscreen',
	'allowpaymentrequest',
	'async',
	'autofocus',
	'autoplay',
	'checked',
	'controls',
	'default',
	'defer',
	'disabled',
	'formnovalidate',
	'hidden',
	'inert',
	'ismap',
	'loop',
	'multiple',
	'muted',
	'nomodule',
	'novalidate',
	'open',
	'playsinline',
	'readonly',
	'required',
	'reversed',
	'selected'
]);

/**
 * List of HTML boolean attributes (e.g. `<input disabled>`).
 * Source: https://html.spec.whatwg.org/multipage/indices.html
 *
 * @type {Set<string>}
 */
const boolean_attributes_boolean_attributes = new Set([..._boolean_attributes]);

/** @typedef {typeof _boolean_attributes[number]} BooleanAttributes */

;// ../../node_modules/svelte/src/runtime/internal/ssr.js








const invalid_attribute_name_character =
	/[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u;
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
// https://infra.spec.whatwg.org/#noncharacter

/** @returns {string} */
function spread(args, attrs_to_add) {
	const attributes = Object.assign({}, ...args);
	if (attrs_to_add) {
		const classes_to_add = attrs_to_add.classes;
		const styles_to_add = attrs_to_add.styles;
		if (classes_to_add) {
			if (attributes.class == null) {
				attributes.class = classes_to_add;
			} else {
				attributes.class += ' ' + classes_to_add;
			}
		}
		if (styles_to_add) {
			if (attributes.style == null) {
				attributes.style = style_object_to_string(styles_to_add);
			} else {
				attributes.style = style_object_to_string(
					merge_ssr_styles(attributes.style, styles_to_add)
				);
			}
		}
	}
	let str = '';
	Object.keys(attributes).forEach((name) => {
		if (invalid_attribute_name_character.test(name)) return;
		const value = attributes[name];
		if (value === true) str += ' ' + name;
		else if (boolean_attributes.has(name.toLowerCase())) {
			if (value) str += ' ' + name;
		} else if (value != null) {
			str += ` ${name}="${value}"`;
		}
	});
	return str;
}

/** @returns {{}} */
function merge_ssr_styles(style_attribute, style_directive) {
	const style_object = {};
	for (const individual_style of style_attribute.split(';')) {
		const colon_index = individual_style.indexOf(':');
		const name = individual_style.slice(0, colon_index).trim();
		const value = individual_style.slice(colon_index + 1).trim();
		if (!name) continue;
		style_object[name] = value;
	}
	for (const name in style_directive) {
		const value = style_directive[name];
		if (value) {
			style_object[name] = value;
		} else {
			delete style_object[name];
		}
	}
	return style_object;
}

function escape_attribute_value(value) {
	// keep booleans, null, and undefined for the sake of `spread`
	const should_escape = typeof value === 'string' || (value && typeof value === 'object');
	return should_escape ? escape(value, true) : value;
}

/** @returns {{}} */
function escape_object(obj) {
	const result = {};
	for (const key in obj) {
		result[key] = escape_attribute_value(obj[key]);
	}
	return result;
}

/** @returns {string} */
function each(items, fn) {
	items = ensure_array_like(items);
	let str = '';
	for (let i = 0; i < items.length; i += 1) {
		str += fn(items[i], i);
	}
	return str;
}

const missing_component = {
	$$render: () => ''
};

function validate_component(component, name) {
	if (!component || !component.$$render) {
		if (name === 'svelte:component') name += ' this={...}';
		throw new Error(
			`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a <${name}>.`
		);
	}
	return component;
}

/** @returns {string} */
function debug(file, line, column, values) {
	console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`); // eslint-disable-line no-console
	console.log(values); // eslint-disable-line no-console
	return '';
}

let on_destroy;

/** @returns {{ render: (props?: {}, { $$slots, context }?: { $$slots?: {}; context?: Map<any, any>; }) => { html: any; css: { code: string; map: any; }; head: string; }; $$render: (result: any, props: any, bindings: any, slots: any, context: any) => any; }} */
function create_ssr_component(fn) {
	function $$render(result, props, bindings, slots, context) {
		const parent_component = current_component;
		const $$ = {
			on_destroy,
			context: new Map(context || (parent_component ? parent_component.$$.context : [])),
			// these will be immediately discarded
			on_mount: [],
			before_update: [],
			after_update: [],
			callbacks: blank_object()
		};
		set_current_component({ $$ });
		const html = fn(result, props, bindings, slots);
		set_current_component(parent_component);
		return html;
	}
	return {
		render: (props = {}, { $$slots = {}, context = new Map() } = {}) => {
			on_destroy = [];
			const result = { title: '', head: '', css: new Set() };
			const html = $$render(result, props, {}, $$slots, context);
			run_all(on_destroy);
			return {
				html,
				css: {
					code: Array.from(result.css)
						.map((css) => css.code)
						.join('\n'),
					map: null // TODO
				},
				head: result.title + result.head
			};
		},
		$$render
	};
}

/** @returns {string} */
function add_attribute(name, value, boolean) {
	if (value == null || (boolean && !value)) return '';
	const assignment = boolean && value === true ? '' : `="${escape(value, true)}"`;
	return ` ${name}${assignment}`;
}

/** @returns {string} */
function add_classes(classes) {
	return classes ? ` class="${classes}"` : '';
}

/** @returns {string} */
function style_object_to_string(style_object) {
	return Object.keys(style_object)
		.filter((key) => style_object[key] != null && style_object[key] !== '')
		.map((key) => `${key}: ${escape_attribute_value(style_object[key])};`)
		.join(' ');
}

/** @returns {string} */
function add_styles(style_object) {
	const styles = style_object_to_string(style_object);
	return styles ? ` style="${styles}"` : '';
}

;// ../../node_modules/svelte/src/runtime/internal/Component.js






/** @returns {void} */
function bind(component, name, callback) {
	const index = component.$$.props[name];
	if (index !== undefined) {
		component.$$.bound[index] = callback;
		callback(component.$$.ctx[index]);
	}
}

/** @returns {void} */
function create_component(block) {
	block && block.c();
}

/** @returns {void} */
function claim_component(block, parent_nodes) {
	block && block.l(parent_nodes);
}

/** @returns {void} */
function mount_component(component, target, anchor) {
	const { fragment, after_update } = component.$$;
	fragment && fragment.m(target, anchor);
	// onMount happens before the initial afterUpdate
	scheduler_add_render_callback(() => {
		const new_on_destroy = component.$$.on_mount.map(run).filter(utils_is_function);
		// if the component was destroyed immediately
		// it will update the `$$.on_destroy` reference to `null`.
		// the destructured on_destroy may still reference to the old array
		if (component.$$.on_destroy) {
			component.$$.on_destroy.push(...new_on_destroy);
		} else {
			// Edge case - component was destroyed immediately,
			// most likely as a result of a binding initialising
			utils_run_all(new_on_destroy);
		}
		component.$$.on_mount = [];
	});
	after_update.forEach(scheduler_add_render_callback);
}

/** @returns {void} */
function destroy_component(component, detaching) {
	const $$ = component.$$;
	if ($$.fragment !== null) {
		flush_render_callbacks($$.after_update);
		utils_run_all($$.on_destroy);
		$$.fragment && $$.fragment.d(detaching);
		// TODO null out other refs, including component.$$ (but need to
		// preserve final state?)
		$$.on_destroy = $$.fragment = null;
		$$.ctx = [];
	}
}

/** @returns {void} */
function make_dirty(component, i) {
	if (component.$$.dirty[0] === -1) {
		dirty_components.push(component);
		schedule_update();
		component.$$.dirty.fill(0);
	}
	component.$$.dirty[(i / 31) | 0] |= 1 << i % 31;
}

// TODO: Document the other params
/**
 * @param {SvelteComponent} component
 * @param {import('./public.js').ComponentConstructorOptions} options
 *
 * @param {import('./utils.js')['not_equal']} not_equal Used to compare props and state values.
 * @param {(target: Element | ShadowRoot) => void} [append_styles] Function that appends styles to the DOM when the component is first initialised.
 * This will be the `add_css` function from the compiled component.
 *
 * @returns {void}
 */
function init(
	component,
	options,
	instance,
	create_fragment,
	not_equal,
	props,
	append_styles = null,
	dirty = [-1]
) {
	const parent_component = lifecycle_current_component;
	lifecycle_set_current_component(component);
	/** @type {import('./private.js').T$$} */
	const $$ = (component.$$ = {
		fragment: null,
		ctx: [],
		// state
		props,
		update: utils_noop,
		not_equal,
		bound: utils_blank_object(),
		// lifecycle
		on_mount: [],
		on_destroy: [],
		on_disconnect: [],
		before_update: [],
		after_update: [],
		context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
		// everything else
		callbacks: utils_blank_object(),
		dirty,
		skip_bound: false,
		root: options.target || parent_component.$$.root
	});
	append_styles && append_styles($$.root);
	let ready = false;
	$$.ctx = instance
		? instance(component, options.props || {}, (i, ret, ...rest) => {
				const value = rest.length ? rest[0] : ret;
				if ($$.ctx && not_equal($$.ctx[i], ($$.ctx[i] = value))) {
					if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value);
					if (ready) make_dirty(component, i);
				}
				return ret;
		  })
		: [];
	$$.update();
	ready = true;
	utils_run_all($$.before_update);
	// `false` as a special case of no DOM component
	$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
	if (options.target) {
		if (options.hydrate) {
			start_hydrating();
			// TODO: what is the correct type here?
			// @ts-expect-error
			const nodes = children(options.target);
			$$.fragment && $$.fragment.l(nodes);
			nodes.forEach(dom_detach);
		} else {
			// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
			$$.fragment && $$.fragment.c();
		}
		if (options.intro) transitions_transition_in(component.$$.fragment);
		mount_component(component, options.target, options.anchor);
		end_hydrating();
		flush();
	}
	lifecycle_set_current_component(parent_component);
}

let SvelteElement;

if (typeof HTMLElement === 'function') {
	SvelteElement = class extends HTMLElement {
		/** The Svelte component constructor */
		$$ctor;
		/** Slots */
		$$s;
		/** The Svelte component instance */
		$$c;
		/** Whether or not the custom element is connected */
		$$cn = false;
		/** Component props data */
		$$d = {};
		/** `true` if currently in the process of reflecting component props back to attributes */
		$$r = false;
		/** @type {Record<string, CustomElementPropDefinition>} Props definition (name, reflected, type etc) */
		$$p_d = {};
		/** @type {Record<string, Function[]>} Event listeners */
		$$l = {};
		/** @type {Map<Function, Function>} Event listener unsubscribe functions */
		$$l_u = new Map();

		constructor($$componentCtor, $$slots, use_shadow_dom) {
			super();
			this.$$ctor = $$componentCtor;
			this.$$s = $$slots;
			if (use_shadow_dom) {
				this.attachShadow({ mode: 'open' });
			}
		}

		addEventListener(type, listener, options) {
			// We can't determine upfront if the event is a custom event or not, so we have to
			// listen to both. If someone uses a custom event with the same name as a regular
			// browser event, this fires twice - we can't avoid that.
			this.$$l[type] = this.$$l[type] || [];
			this.$$l[type].push(listener);
			if (this.$$c) {
				const unsub = this.$$c.$on(type, listener);
				this.$$l_u.set(listener, unsub);
			}
			super.addEventListener(type, listener, options);
		}

		removeEventListener(type, listener, options) {
			super.removeEventListener(type, listener, options);
			if (this.$$c) {
				const unsub = this.$$l_u.get(listener);
				if (unsub) {
					unsub();
					this.$$l_u.delete(listener);
				}
			}
		}

		async connectedCallback() {
			this.$$cn = true;
			if (!this.$$c) {
				// We wait one tick to let possible child slot elements be created/mounted
				await Promise.resolve();
				if (!this.$$cn || this.$$c) {
					return;
				}
				function create_slot(name) {
					return () => {
						let node;
						const obj = {
							c: function create() {
								node = dom_element('slot');
								if (name !== 'default') {
									dom_attr(node, 'name', name);
								}
							},
							/**
							 * @param {HTMLElement} target
							 * @param {HTMLElement} [anchor]
							 */
							m: function mount(target, anchor) {
								dom_insert(target, node, anchor);
							},
							d: function destroy(detaching) {
								if (detaching) {
									dom_detach(node);
								}
							}
						};
						return obj;
					};
				}
				const $$slots = {};
				const existing_slots = get_custom_elements_slots(this);
				for (const name of this.$$s) {
					if (name in existing_slots) {
						$$slots[name] = [create_slot(name)];
					}
				}
				for (const attribute of this.attributes) {
					// this.$$data takes precedence over this.attributes
					const name = this.$$g_p(attribute.name);
					if (!(name in this.$$d)) {
						this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, 'toProp');
					}
				}
				// Port over props that were set programmatically before ce was initialized
				for (const key in this.$$p_d) {
					if (!(key in this.$$d) && this[key] !== undefined) {
						this.$$d[key] = this[key]; // don't transform, these were set through JavaScript
						delete this[key]; // remove the property that shadows the getter/setter
					}
				}
				this.$$c = new this.$$ctor({
					target: this.shadowRoot || this,
					props: {
						...this.$$d,
						$$slots,
						$$scope: {
							ctx: []
						}
					}
				});

				// Reflect component props as attributes
				const reflect_attributes = () => {
					this.$$r = true;
					for (const key in this.$$p_d) {
						this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]];
						if (this.$$p_d[key].reflect) {
							const attribute_value = get_custom_element_value(
								key,
								this.$$d[key],
								this.$$p_d,
								'toAttribute'
							);
							if (attribute_value == null) {
								this.removeAttribute(this.$$p_d[key].attribute || key);
							} else {
								this.setAttribute(this.$$p_d[key].attribute || key, attribute_value);
							}
						}
					}
					this.$$r = false;
				};
				this.$$c.$$.after_update.push(reflect_attributes);
				reflect_attributes(); // once initially because after_update is added too late for first render

				for (const type in this.$$l) {
					for (const listener of this.$$l[type]) {
						const unsub = this.$$c.$on(type, listener);
						this.$$l_u.set(listener, unsub);
					}
				}
				this.$$l = {};
			}
		}

		// We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte
		// and setting attributes through setAttribute etc, this is helpful
		attributeChangedCallback(attr, _oldValue, newValue) {
			if (this.$$r) return;
			attr = this.$$g_p(attr);
			this.$$d[attr] = get_custom_element_value(attr, newValue, this.$$p_d, 'toProp');
			this.$$c?.$set({ [attr]: this.$$d[attr] });
		}

		disconnectedCallback() {
			this.$$cn = false;
			// In a microtask, because this could be a move within the DOM
			Promise.resolve().then(() => {
				if (!this.$$cn && this.$$c) {
					this.$$c.$destroy();
					this.$$c = undefined;
				}
			});
		}

		$$g_p(attribute_name) {
			return (
				Object.keys(this.$$p_d).find(
					(key) =>
						this.$$p_d[key].attribute === attribute_name ||
						(!this.$$p_d[key].attribute && key.toLowerCase() === attribute_name)
				) || attribute_name
			);
		}
	};
}

/**
 * @param {string} prop
 * @param {any} value
 * @param {Record<string, CustomElementPropDefinition>} props_definition
 * @param {'toAttribute' | 'toProp'} [transform]
 */
function get_custom_element_value(prop, value, props_definition, transform) {
	const type = props_definition[prop]?.type;
	value = type === 'Boolean' && typeof value !== 'boolean' ? value != null : value;
	if (!transform || !props_definition[prop]) {
		return value;
	} else if (transform === 'toAttribute') {
		switch (type) {
			case 'Object':
			case 'Array':
				return value == null ? null : JSON.stringify(value);
			case 'Boolean':
				return value ? '' : null;
			case 'Number':
				return value == null ? null : value;
			default:
				return value;
		}
	} else {
		switch (type) {
			case 'Object':
			case 'Array':
				return value && JSON.parse(value);
			case 'Boolean':
				return value; // conversion already handled above
			case 'Number':
				return value != null ? +value : value;
			default:
				return value;
		}
	}
}

/**
 * @internal
 *
 * Turn a Svelte component into a custom element.
 * @param {import('./public.js').ComponentType} Component  A Svelte component constructor
 * @param {Record<string, CustomElementPropDefinition>} props_definition  The props to observe
 * @param {string[]} slots  The slots to create
 * @param {string[]} accessors  Other accessors besides the ones for props the component has
 * @param {boolean} use_shadow_dom  Whether to use shadow DOM
 * @param {(ce: new () => HTMLElement) => new () => HTMLElement} [extend]
 */
function create_custom_element(
	Component,
	props_definition,
	slots,
	accessors,
	use_shadow_dom,
	extend
) {
	let Class = class extends SvelteElement {
		constructor() {
			super(Component, slots, use_shadow_dom);
			this.$$p_d = props_definition;
		}
		static get observedAttributes() {
			return Object.keys(props_definition).map((key) =>
				(props_definition[key].attribute || key).toLowerCase()
			);
		}
	};
	Object.keys(props_definition).forEach((prop) => {
		Object.defineProperty(Class.prototype, prop, {
			get() {
				return this.$$c && prop in this.$$c ? this.$$c[prop] : this.$$d[prop];
			},
			set(value) {
				value = get_custom_element_value(prop, value, props_definition);
				this.$$d[prop] = value;
				this.$$c?.$set({ [prop]: value });
			}
		});
	});
	accessors.forEach((accessor) => {
		Object.defineProperty(Class.prototype, accessor, {
			get() {
				return this.$$c?.[accessor];
			}
		});
	});
	if (extend) {
		// @ts-expect-error - assigning here is fine
		Class = extend(Class);
	}
	Component.element = /** @type {any} */ (Class);
	return Class;
}

/**
 * Base class for Svelte components. Used when dev=false.
 *
 * @template {Record<string, any>} [Props=any]
 * @template {Record<string, any>} [Events=any]
 */
class SvelteComponent {
	/**
	 * ### PRIVATE API
	 *
	 * Do not use, may change at any time
	 *
	 * @type {any}
	 */
	$$ = undefined;
	/**
	 * ### PRIVATE API
	 *
	 * Do not use, may change at any time
	 *
	 * @type {any}
	 */
	$$set = undefined;

	/** @returns {void} */
	$destroy() {
		destroy_component(this, 1);
		this.$destroy = utils_noop;
	}

	/**
	 * @template {Extract<keyof Events, string>} K
	 * @param {K} type
	 * @param {((e: Events[K]) => void) | null | undefined} callback
	 * @returns {() => void}
	 */
	$on(type, callback) {
		if (!utils_is_function(callback)) {
			return utils_noop;
		}
		const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
		callbacks.push(callback);
		return () => {
			const index = callbacks.indexOf(callback);
			if (index !== -1) callbacks.splice(index, 1);
		};
	}

	/**
	 * @param {Partial<Props>} props
	 * @returns {void}
	 */
	$set(props) {
		if (this.$$set && !is_empty(props)) {
			this.$$.skip_bound = true;
			this.$$set(props);
			this.$$.skip_bound = false;
		}
	}
}

/**
 * @typedef {Object} CustomElementPropDefinition
 * @property {string} [attribute]
 * @property {boolean} [reflect]
 * @property {'String'|'Boolean'|'Number'|'Array'|'Object'} [type]
 */

;// ../../node_modules/svelte/src/runtime/internal/dev.js







/**
 * @template T
 * @param {string} type
 * @param {T} [detail]
 * @returns {void}
 */
function dispatch_dev(type, detail) {
	document.dispatchEvent(custom_event(type, { version: VERSION, ...detail }, { bubbles: true }));
}

/**
 * @param {Node} target
 * @param {Node} node
 * @returns {void}
 */
function append_dev(target, node) {
	dispatch_dev('SvelteDOMInsert', { target, node });
	append(target, node);
}

/**
 * @param {Node} target
 * @param {Node} node
 * @returns {void}
 */
function append_hydration_dev(target, node) {
	dispatch_dev('SvelteDOMInsert', { target, node });
	append_hydration(target, node);
}

/**
 * @param {Node} target
 * @param {Node} node
 * @param {Node} [anchor]
 * @returns {void}
 */
function insert_dev(target, node, anchor) {
	dispatch_dev('SvelteDOMInsert', { target, node, anchor });
	insert(target, node, anchor);
}

/** @param {Node} target
 * @param {Node} node
 * @param {Node} [anchor]
 * @returns {void}
 */
function insert_hydration_dev(target, node, anchor) {
	dispatch_dev('SvelteDOMInsert', { target, node, anchor });
	insert_hydration(target, node, anchor);
}

/**
 * @param {Node} node
 * @returns {void}
 */
function detach_dev(node) {
	dispatch_dev('SvelteDOMRemove', { node });
	detach(node);
}

/**
 * @param {Node} before
 * @param {Node} after
 * @returns {void}
 */
function detach_between_dev(before, after) {
	while (before.nextSibling && before.nextSibling !== after) {
		detach_dev(before.nextSibling);
	}
}

/**
 * @param {Node} after
 * @returns {void}
 */
function detach_before_dev(after) {
	while (after.previousSibling) {
		detach_dev(after.previousSibling);
	}
}

/**
 * @param {Node} before
 * @returns {void}
 */
function detach_after_dev(before) {
	while (before.nextSibling) {
		detach_dev(before.nextSibling);
	}
}

/**
 * @param {Node} node
 * @param {string} event
 * @param {EventListenerOrEventListenerObject} handler
 * @param {boolean | AddEventListenerOptions | EventListenerOptions} [options]
 * @param {boolean} [has_prevent_default]
 * @param {boolean} [has_stop_propagation]
 * @param {boolean} [has_stop_immediate_propagation]
 * @returns {() => void}
 */
function listen_dev(
	node,
	event,
	handler,
	options,
	has_prevent_default,
	has_stop_propagation,
	has_stop_immediate_propagation
) {
	const modifiers =
		options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
	if (has_prevent_default) modifiers.push('preventDefault');
	if (has_stop_propagation) modifiers.push('stopPropagation');
	if (has_stop_immediate_propagation) modifiers.push('stopImmediatePropagation');
	dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
	const dispose = listen(node, event, handler, options);
	return () => {
		dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
		dispose();
	};
}

/**
 * @param {Element} node
 * @param {string} attribute
 * @param {string} [value]
 * @returns {void}
 */
function attr_dev(node, attribute, value) {
	attr(node, attribute, value);
	if (value == null) dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
	else dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
}

/**
 * @param {Element} node
 * @param {string} property
 * @param {any} [value]
 * @returns {void}
 */
function prop_dev(node, property, value) {
	node[property] = value;
	dispatch_dev('SvelteDOMSetProperty', { node, property, value });
}

/**
 * @param {HTMLElement} node
 * @param {string} property
 * @param {any} [value]
 * @returns {void}
 */
function dataset_dev(node, property, value) {
	node.dataset[property] = value;
	dispatch_dev('SvelteDOMSetDataset', { node, property, value });
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @returns {void}
 */
function set_data_dev(text, data) {
	data = '' + data;
	if (text.data === data) return;
	dispatch_dev('SvelteDOMSetData', { node: text, data });
	text.data = /** @type {string} */ (data);
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @returns {void}
 */
function set_data_contenteditable_dev(text, data) {
	data = '' + data;
	if (text.wholeText === data) return;
	dispatch_dev('SvelteDOMSetData', { node: text, data });
	text.data = /** @type {string} */ (data);
}

/**
 * @param {Text} text
 * @param {unknown} data
 * @param {string} attr_value
 * @returns {void}
 */
function set_data_maybe_contenteditable_dev(text, data, attr_value) {
	if (~contenteditable_truthy_values.indexOf(attr_value)) {
		set_data_contenteditable_dev(text, data);
	} else {
		set_data_dev(text, data);
	}
}

function ensure_array_like_dev(arg) {
	if (
		typeof arg !== 'string' &&
		!(arg && typeof arg === 'object' && 'length' in arg) &&
		!(typeof Symbol === 'function' && arg && Symbol.iterator in arg)
	) {
		throw new Error('{#each} only works with iterable values.');
	}
	return ensure_array_like(arg);
}

/**
 * @returns {void} */
function validate_slots(name, slot, keys) {
	for (const slot_key of Object.keys(slot)) {
		if (!~keys.indexOf(slot_key)) {
			console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
		}
	}
}

/**
 * @param {unknown} tag
 * @returns {void}
 */
function validate_dynamic_element(tag) {
	const is_string = typeof tag === 'string';
	if (tag && !is_string) {
		throw new Error('<svelte:element> expects "this" attribute to be a string.');
	}
}

/**
 * @param {undefined | string} tag
 * @returns {void}
 */
function validate_void_dynamic_element(tag) {
	if (tag && is_void(tag)) {
		console.warn(`<svelte:element this="${tag}"> is self-closing and cannot have content.`);
	}
}

function construct_svelte_component_dev(component, props) {
	const error_message = 'this={...} of <svelte:component> should specify a Svelte component.';
	try {
		const instance = new component(props);
		if (!instance.$$ || !instance.$set || !instance.$on || !instance.$destroy) {
			throw new Error(error_message);
		}
		return instance;
	} catch (err) {
		const { message } = err;
		if (typeof message === 'string' && message.indexOf('is not a constructor') !== -1) {
			throw new Error(error_message);
		} else {
			throw err;
		}
	}
}

/**
 * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.
 *
 * Can be used to create strongly typed Svelte components.
 *
 * #### Example:
 *
 * You have component library on npm called `component-library`, from which
 * you export a component called `MyComponent`. For Svelte+TypeScript users,
 * you want to provide typings. Therefore you create a `index.d.ts`:
 * ```ts
 * import { SvelteComponent } from "svelte";
 * export class MyComponent extends SvelteComponent<{foo: string}> {}
 * ```
 * Typing this makes it possible for IDEs like VS Code with the Svelte extension
 * to provide intellisense and to use the component like this in a Svelte file
 * with TypeScript:
 * ```svelte
 * <script lang="ts">
 * 	import { MyComponent } from "component-library";
 * </script>
 * <MyComponent foo={'bar'} />
 * ```
 * @template {Record<string, any>} [Props=any]
 * @template {Record<string, any>} [Events=any]
 * @template {Record<string, any>} [Slots=any]
 * @extends {SvelteComponent<Props, Events>}
 */
class SvelteComponentDev extends SvelteComponent {
	/**
	 * For type checking capabilities only.
	 * Does not exist at runtime.
	 * ### DO NOT USE!
	 *
	 * @type {Props}
	 */
	$$prop_def;
	/**
	 * For type checking capabilities only.
	 * Does not exist at runtime.
	 * ### DO NOT USE!
	 *
	 * @type {Events}
	 */
	$$events_def;
	/**
	 * For type checking capabilities only.
	 * Does not exist at runtime.
	 * ### DO NOT USE!
	 *
	 * @type {Slots}
	 */
	$$slot_def;

	/** @param {import('./public.js').ComponentConstructorOptions<Props>} options */
	constructor(options) {
		if (!options || (!options.target && !options.$$inline)) {
			throw new Error("'target' is a required option");
		}
		super();
	}

	/** @returns {void} */
	$destroy() {
		super.$destroy();
		this.$destroy = () => {
			console.warn('Component was already destroyed'); // eslint-disable-line no-console
		};
	}

	/** @returns {void} */
	$capture_state() {}

	/** @returns {void} */
	$inject_state() {}
}
/**
 * @template {Record<string, any>} [Props=any]
 * @template {Record<string, any>} [Events=any]
 * @template {Record<string, any>} [Slots=any]
 * @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512
 * @extends {SvelteComponentDev<Props, Events, Slots>}
 */
class SvelteComponentTyped extends (/* unused pure expression or super */ null && (SvelteComponentDev)) {}

/** @returns {() => void} */
function loop_guard(timeout) {
	const start = Date.now();
	return () => {
		if (Date.now() - start > timeout) {
			throw new Error('Infinite loop detected');
		}
	};
}

;// ../../node_modules/svelte/src/runtime/internal/index.js
















;// ../../node_modules/svelte/src/shared/version.js
// generated during release, do not modify

/**
 * The current version, as set in package.json.
 *
 * https://svelte.dev/docs/svelte-compiler#svelte-version
 * @type {string}
 */
const version_VERSION = '4.2.19';
const PUBLIC_VERSION = '4';

;// ../../node_modules/svelte/src/runtime/internal/disclose-version/index.js


if (typeof window !== 'undefined')
	// @ts-ignore
	(window.__svelte || (window.__svelte = { v: new Set() })).v.add(PUBLIC_VERSION);

;// ../../node_modules/arquero/src/op/functions/bin.js
/**
 * Truncate a value to a bin boundary.
 * Useful for creating equal-width histograms.
 * Values outside the [min, max] range will be mapped to
 * -Infinity (< min) or +Infinity (> max).
 * @param {number} value The value to bin.
 * @param {number} min The minimum bin boundary.
 * @param {number} max The maximum bin boundary.
 * @param {number} step The step size between bin boundaries.
 * @param {number} [offset=0] Offset in steps by which to adjust
 *  the bin value. An offset of 1 will return the next boundary.
 */
function bin(value, min, max, step, offset) {
  return value == null ? null
    : value < min ? -Infinity
    : value > max ? +Infinity
    : (
        value = Math.max(min, Math.min(value, max)),
        min + step * Math.floor(1e-14 + (value - min) / step + (offset || 0))
      );
}

;// ../../node_modules/arquero/src/util/is-date.js
/**
 * @param {*} value
 * @returns {value is Date}
 */
function isDate(value) {
  return value instanceof Date;
}

;// ../../node_modules/arquero/src/util/is-regexp.js
/**
 * @param {*} value
 * @returns {value is RegExp}
 */
function isRegExp(value) {
  return value instanceof RegExp;
}

;// ../../node_modules/arquero/src/util/is-object.js
function isObject(value) {
  return value === Object(value);
}

;// ../../node_modules/arquero/src/op/functions/equal.js




/**
 * Compare two values for equality, using join semantics in which null
 * !== null. If the inputs are object-valued, a deep equality check
 * of array entries or object key-value pairs is performed.
 * @param {*} a The first input.
 * @param {*} b The second input.
 * @return {boolean} True if equal, false if not.
 */
function equal(a, b) {
  return (a == null || b == null || a !== a || b !== b) ? false
    : a === b ? true
    : (isDate(a) || isDate(b)) ? +a === +b
    : (isRegExp(a) && isRegExp(b)) ? a + '' === b + ''
    : (isObject(a) && isObject(b)) ? deepEqual(a, b)
    : false;
}

function deepEqual(a, b) {
  if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
    return false;
  }

  if (a.length || b.length) {
    return arrayEqual(a, b);
  }

  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) {
    return false;
  }
  keysA.sort();
  keysB.sort();

  if (!arrayEqual(keysA, keysB, (a, b) => a === b)) {
    return false;
  }

  const n = keysA.length;
  for (let i = 0; i < n; ++i) {
    const k = keysA[i];
    if (!equal(a[k], b[k])) {
      return false;
    }
  }

  return true;
}

function arrayEqual(a, b, test = equal) {
  const n = a.length;
  if (n !== b.length) return false;

  for (let i = 0; i < n; ++i) {
    if (!test(a[i], b[i])) {
      return false;
    }
  }

  return true;
}

;// ../../node_modules/arquero/src/op/functions/recode.js
/**
 * Recodes an input value to an alternative value, based on a provided
 * value map. If a fallback value is specified, it will be returned when
 * a matching value is not found in the map; otherwise, the input value
 * is returned unchanged.
 * @template T
 * @param {T} value The value to recode. The value must be safely
 *  coercible to a string for lookup against the value map.
 * @param {Map|Record<string,any>} map An object or Map with input values
 *  for keys and output recoded values as values. If a non-Map object, only
 *  the object's own properties will be considered.
 * @param {T} [fallback] A default fallback value to use if the input
 *  value is not found in the value map.
 * @return {T} The recoded value.
 */
function recode(value, map, fallback) {
  if (map instanceof Map) {
    if (map.has(value)) return map.get(value);
  } else {
    const key = `${value}`;
    if (Object.hasOwn(map, key)) return map[key];
  }
  return fallback !== undefined ? fallback : value;
}

;// ../../node_modules/arquero/src/op/functions/sequence.js
/**
 * Returns an array containing an arithmetic sequence from the start value
 * to the stop value, in step increments. If step is positive, the last
 * element is the largest start + i * step less than stop; if step is
 * negative, the last element is the smallest start + i * step greater
 * than stop. If the returned array would contain an infinite number of
 * values, an empty range is returned.
 * @param {number} [start=0] The starting value of the sequence.
 * @param {number} [stop] The stopping value of the sequence.
 *  The stop value is exclusive; it is not included in the result.
 * @param {number} [step=1] The step increment between sequence values.
 * @return {number[]} The generated sequence.
 */
function sequence(start, stop, step) {
  let n = arguments.length;
  start = +start;
  stop = +stop;
  step = n < 2
    ? (stop = start, start = 0, 1)
    : n < 3 ? 1 : +step;

  n = Math.max(0, Math.ceil((stop - start) / step)) | 0;
  const seq = new Array(n);

  for (let i = 0; i < n; ++i) {
    seq[i] = start + i * step;
  }

  return seq;
}

;// ../../node_modules/arquero/src/util/null.js
/**
 * Default NULL (missing) value to use.
 */
const NULL = undefined;

;// ../../node_modules/arquero/src/util/is-array.js
/**
 * @param {*} value
 * @returns {value is Array}
 */
function is_array_isArray(value) {
  return Array.isArray(value);
}

;// ../../node_modules/arquero/src/util/is-typed-array.js
const TypedArray = Object.getPrototypeOf(Int8Array);

/**
 * @param {*} value
 * @return {value is import("../table/types.js").TypedArray}
 */
function isTypedArray(value) {
  return value instanceof TypedArray;
}

;// ../../node_modules/arquero/src/util/is-array-type.js



/**
 * @param {*} value
 * @return {value is (any[] | import('../table/types.js').TypedArray)}
 */
function isArrayType(value) {
  return is_array_isArray(value) || isTypedArray(value);
}

;// ../../node_modules/arquero/src/util/is-string.js
/**
 * @param {*} value
 * @return {value is String}
 */
function is_string_isString(value) {
  return typeof value === 'string';
}

;// ../../node_modules/arquero/src/util/is-valid.js
function is_valid_isValid(value) {
  return value != null && value === value;
}

;// ../../node_modules/arquero/src/op/functions/array.js





const isSeq = (seq) => isArrayType(seq) || is_string_isString(seq);

/**
 * Returns a new compacted array with invalid values
 * (`null`, `undefined`, `NaN`) removed.
 * @template T
 * @param {T[]} array The input array.
 * @return {T[]} A compacted array.
 */
function compact(array) {
  return isArrayType(array)
    ? array.filter(v => is_valid_isValid(v))
    : array;
}

/**
 * Merges two or more arrays in sequence, returning a new array.
 * @template T
 * @param {...(T|T[])} values The arrays to merge.
 * @return {T[]} The merged array.
 */
function concat(...values) {
  return [].concat(...values);
}

/**
 * Determines whether an *array* includes a certain *value* among its
 * entries, returning `true` or `false` as appropriate.
 * @template T
 * @param {T[]} sequence The input array value.
 * @param {T} value The value to search for.
 * @param {number} [index=0] The integer index to start searching
 *  from (default `0`).
 * @return {boolean} True if the value is included, false otherwise.
 */
function includes(sequence, value, index) {
  return isSeq(sequence)
    ? sequence.includes(value, index)
    : false;
}

/**
 * Returns the first index at which a given *value* can be found in the
 * *sequence* (array or string), or -1 if it is not present.
 * @template T
 * @param {T[]|string} sequence The input array or string value.
 * @param {T} value The value to search for.
 * @return {number} The index of the value, or -1 if not present.
 */
function indexof(sequence, value) {
  return isSeq(sequence)
    // @ts-ignore
    ? sequence.indexOf(value)
    : -1;
}

/**
 * Creates and returns a new string by concatenating all of the elements
 * in an *array* (or an array-like object), separated by commas or a
 * specified *delimiter* string. If the *array* has only one item, then
 * that item will be returned without using the delimiter.
 * @template T
 * @param {T[]} array The input array value.
 * @param {string} delim The delimiter string (default `','`).
 * @return {string} The joined string.
 */
function join(array, delim) {
  return isArrayType(array) ? array.join(delim) : NULL;
}

/**
 * Returns the last index at which a given *value* can be found in the
 * *sequence* (array or string), or -1 if it is not present.
 * @template T
 * @param {T[]|string} sequence The input array or string value.
 * @param {T} value The value to search for.
 * @return {number} The last index of the value, or -1 if not present.
 */
function lastindexof(sequence, value) {
  return isSeq(sequence)
    // @ts-ignore
    ? sequence.lastIndexOf(value)
    : -1;
}

/**
 * Returns the length of the input *sequence* (array or string).
 * @param {Array|string} sequence The input array or string value.
 * @return {number} The length of the sequence.
 */
function array_length(sequence) {
  return isSeq(sequence) ? sequence.length : 0;
}

/**
 * Returns a new array in which the given *property* has been extracted
 * for each element in the input *array*.
 * @param {Array} array The input array value.
 * @param {string} property The property name string to extract. Nested
 *  properties are not supported: the input `"a.b"` will indicates a
 *  property with that exact name, *not* a nested property `"b"` of
 *  the object `"a"`.
 * @return {Array} An array of plucked properties.
 */
function pluck(array, property) {
  return isArrayType(array)
    ? array.map(v => is_valid_isValid(v) ? v[property] : NULL)
    : NULL;
}

/**
 * Returns a new array or string with the element order reversed: the first
 * *sequence* element becomes the last, and the last *sequence* element
 * becomes the first. The input *sequence* is unchanged.
 * @template T
 * @param {T[]|string} sequence The input array or string value.
 * @return {T[]|string} The reversed sequence.
 */
function reverse(sequence) {
  return isArrayType(sequence) ? sequence.slice().reverse()
    : is_string_isString(sequence) ? sequence.split('').reverse().join('')
    : NULL;
}

/**
 * Returns a copy of a portion of the input *sequence* (array or string)
 * selected from *start* to *end* (*end* not included) where *start* and
 * *end* represent the index of items in the sequence.
 * @template T
 * @param {T[]|string} sequence The input array or string value.
 * @param {number} [start=0] The starting integer index to copy from
 *  (inclusive, default `0`).
 * @param {number} [end] The ending integer index to copy from (exclusive,
 *  default `sequence.length`).
 * @return {T[]|string} The sliced sequence.
 */
function slice(sequence, start, end) {
  return isSeq(sequence)
    ? sequence.slice(start, end)
    : NULL;
}

;// ../../node_modules/arquero/src/util/pad.js
function pad(value, width, char = '0') {
  const s = value + '';
  const len = s.length;
  return len < width ? Array(width - len + 1).join(char) + s : s;
}

;// ../../node_modules/arquero/src/util/format-date.js


const pad2 = v => (v < 10 ? '0' : '') + v;

const formatYear = year => year < 0 ? '-' + pad(-year, 6)
  : year > 9999 ? '+' + pad(year, 6)
  : pad(year, 4);

function formatISO(year, month, date, hours, min, sec, ms, utc, short) {
  const suffix = utc ? 'Z' : '';
  return formatYear(year) + '-' + pad2(month + 1) + '-' + pad2(date) + (
    !short || ms ? 'T' + pad2(hours) + ':' + pad2(min) + ':' + pad2(sec) + '.' + pad(ms, 3) + suffix
    : sec ? 'T' + pad2(hours) + ':' + pad2(min) + ':' + pad2(sec) + suffix
    : min || hours || !utc ? 'T' + pad2(hours) + ':' + pad2(min) + suffix
    : ''
  );
}

function formatDate(d, short) {
  return isNaN(d)
    ? 'Invalid Date'
    : formatISO(
      d.getFullYear(),
      d.getMonth(),
      d.getDate(),
      d.getHours(),
      d.getMinutes(),
      d.getSeconds(),
      d.getMilliseconds(),
      false, short
    );
}

function formatUTCDate(d, short) {
  return isNaN(d)
    ? 'Invalid Date'
    : formatISO(
      d.getUTCFullYear(),
      d.getUTCMonth(),
      d.getUTCDate(),
      d.getUTCHours(),
      d.getUTCMinutes(),
      d.getUTCSeconds(),
      d.getUTCMilliseconds(),
      true, short
    );
}

;// ../../node_modules/arquero/src/util/is-iso-date-string.js
const iso_re = /^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/;

/**
 * @param {string} value
 * @returns {boolean}
 */
function is_iso_date_string_isISODateString(value) {
  return value.match(iso_re) && !isNaN(Date.parse(value));
}

;// ../../node_modules/arquero/src/util/parse-iso-date.js


function parseISODate(value, parse = Date.parse) {
  return is_iso_date_string_isISODateString(value) ? parse(value) : value;
}

;// ../../node_modules/arquero/src/op/functions/date.js



const msMinute = 6e4;
const msDay = 864e5;
const msWeek = 6048e5;

const t0 = new Date();
const t1 = new Date();
const t = d => (
  t0.setTime(typeof d === 'string' ? parseISODate(d) : d),
  t0
);

/**
 * Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted
 * string for the given *date* in local timezone. The resulting string is
 * compatible with *parse_date* and JavaScript's built-in *Date.parse*.
 * @param {Date | number} date The input Date or timestamp value.
 * @param {boolean} [shorten=false] A boolean flag (default `false`)
 *  indicating if the formatted string should be shortened if possible.
 *  For example, the local date `2001-01-01` will shorten from
 *  `"2001-01-01T00:00:00.000"` to `"2001-01-01T00:00"`.
 * @return {string} The formatted date string in local time.
 */
function format_date(date, shorten) {
  return formatDate(t(date), !shorten);
}

/**
 * Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted
 * string for the given *date* in Coordinated Universal Time (UTC). The
 * resulting string is compatible with *parse_date* and JavaScript's
 * built-in *Date.parse*.
 * @param {Date | number} date The input Date or timestamp value.
 * @param {boolean} [shorten=false] A boolean flag (default `false`)
 *  indicating if the formatted string should be shortened if possible.
 *  For example, the the UTC date `2001-01-01` will shorten from
 *  `"2001-01-01T00:00:00.000Z"` to `"2001-01-01"`
 * @return {string} The formatted date string in UTC time.
 */
function format_utcdate(date, shorten){
  return formatUTCDate(t(date), !shorten);
}

/**
 * Returns the number of milliseconds elapsed since midnight, January 1,
 * 1970 Universal Coordinated Time (UTC).
 * @return {number} The timestamp for now.
 */
function date_now() {
  return Date.now();
}

/**
 * Returns the timestamp for a *date* as the number of milliseconds elapsed
 * since January 1, 1970 00:00:00 UTC.
 * @param {Date | number} date The input Date value.
 * @return {number} The timestamp value.
 */
function timestamp(date) {
  return +t(date);
}

/**
 * Creates and returns a new Date value. If no arguments are provided,
 * the current date and time are used.
 * @param {number} [year] The year.
 * @param {number} [month=0] The (zero-based) month.
 * @param {number} [date=1] The date within the month.
 * @param {number} [hours=0] The hour within the day.
 * @param {number} [minutes=0] The minute within the hour.
 * @param {number} [seconds=0] The second within the minute.
 * @param {number} [milliseconds=0] The milliseconds within the second.
 * @return {Date} The Date value.
 */
function datetime(year, month, date, hours, minutes, seconds, milliseconds) {
  return !arguments.length
    ? new Date(Date.now())
    : new Date(
        year,
        month || 0,
        date == null ? 1 : date,
        hours || 0,
        minutes || 0,
        seconds || 0,
        milliseconds || 0
      );
}

/**
 * Returns the year of the specified *date* according to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The year value in local time.
 */
function year(date) {
  return t(date).getFullYear();
}

/**
 * Returns the zero-based quarter of the specified *date* according to
 * local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The quarter value in local time.
 */
function quarter(date) {
  return Math.floor(t(date).getMonth() / 3);
}

/**
 * Returns the zero-based month of the specified *date* according to local
 * time. A value of `0` indicates January, `1` indicates February, and so on.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The month value in local time.
 */
function month(date) {
  return t(date).getMonth();
}

/**
 * Returns the week number of the year (0-53) for the specified *date*
 * according to local time. By default, Sunday is used as the first day
 * of the week. All days in a new year preceding the first Sunday are
 * considered to be in week 0.
 * @param {Date | number} date The input Date or timestamp value.
 * @param {number} firstday The number of first day of the week (default
 *  `0` for Sunday, `1` for Monday and so on).
 * @return {number} The week of the year in local time.
 */
function week(date, firstday) {
  const i = firstday || 0;
  t1.setTime(+date);
  t1.setDate(t1.getDate() - (t1.getDay() + 7 - i) % 7);
  t1.setHours(0, 0, 0, 0);
  t0.setTime(+date);
  t0.setMonth(0);
  t0.setDate(1);
  t0.setDate(1 - (t0.getDay() + 7 - i) % 7);
  t0.setHours(0, 0, 0, 0);
  const tz = (t1.getTimezoneOffset() - t0.getTimezoneOffset()) * msMinute;
  return Math.floor((1 + (+t1 - +t0) - tz) / msWeek);
}

/**
 * Returns the date (day of month) of the specified *date* according
 * to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The date (day of month) value.
 */
function date(date) {
  return t(date).getDate();
}

/**
 * Returns the day of the year (1-366) of the specified *date* according
 * to local time.
 * @param {Date | number} date A date or timestamp.
 * @return {number} The day of the year in local time.
 */
function dayofyear(date) {
  t1.setTime(+date);
  t1.setHours(0, 0, 0, 0);
  t0.setTime(+t1);
  t0.setMonth(0);
  t0.setDate(1);
  const tz = (t1.getTimezoneOffset() - t0.getTimezoneOffset()) * msMinute;
  return Math.floor(1 + ((+t1 - +t0) - tz) / msDay);
}

/**
 * Returns the Sunday-based day of the week (0-6) of the specified *date*
 * according to local time. A value of `0` indicates Sunday, `1` indicates
 * Monday, and so on.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The day of the week value in local time.
 */
function dayofweek(date) {
  return t(date).getDay();
}

/**
 * Returns the hour of the day for the specified *date* according
 * to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The hour value in local time.
 */
function hours(date) {
  return t(date).getHours();
}

/**
 * Returns the minute of the hour for the specified *date* according
 * to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The minutes value in local time.
 */
function minutes(date) {
  return t(date).getMinutes();
}

/**
 * Returns the seconds of the minute for the specified *date* according
 * to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The seconds value in local time.
 */
function seconds(date) {
  return t(date).getSeconds();
}

/**
 * Returns the milliseconds of the second for the specified *date* according
 * to local time.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The milliseconds value in local time.
 */
function milliseconds(date) {
  return t(date).getMilliseconds();
}

/**
 * Creates and returns a new Date value using Coordinated Universal Time
 * (UTC). If no arguments are provided, the current date and time are used.
 * @param {number} [year] The year.
 * @param {number} [month=0] The (zero-based) month.
 * @param {number} [date=1] The date within the month.
 * @param {number} [hours=0] The hour within the day.
 * @param {number} [minutes=0] The minute within the hour.
 * @param {number} [seconds=0] The second within the minute.
 * @param {number} [milliseconds=0] The milliseconds within the second.
 * @return {Date} The Date value.
 */
function utcdatetime(year, month, date, hours, minutes, seconds, milliseconds) {
  return !arguments.length
    ? new Date(Date.now())
    : new Date(Date.UTC(
        year,
        month || 0,
        date == null ? 1 : date,
        hours || 0,
        minutes || 0,
        seconds || 0,
        milliseconds || 0
      ));
}

/**
 * Returns the year of the specified *date* according to Coordinated
 * Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The year value in UTC time.
 */
function utcyear(date) {
  return t(date).getUTCFullYear();
}

/**
 * Returns the zero-based quarter of the specified *date* according to
 * Coordinated Universal Time (UTC)
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The quarter value in UTC time.
 */
function utcquarter(date) {
  return Math.floor(t(date).getUTCMonth() / 3);
}

/**
 * Returns the zero-based month of the specified *date* according to
 * Coordinated Universal Time (UTC). A value of `0` indicates January,
 * `1` indicates February, and so on.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The month value in UTC time.
 */
function utcmonth(date) {
  return t(date).getUTCMonth();
}

/**
 * Returns the week number of the year (0-53) for the specified *date*
 * according to Coordinated Universal Time (UTC). By default, Sunday is
 * used as the first day of the week. All days in a new year preceding the
 * first Sunday are considered to be in week 0.
 * @param {Date | number} date The input Date or timestamp value.
 * @param {number} firstday The number of first day of the week (default
 *  `0` for Sunday, `1` for Monday and so on).
 * @return {number} The week of the year in UTC time.
 */
function utcweek(date, firstday) {
  const i = firstday || 0;
  t1.setTime(+date);
  t1.setUTCDate(t1.getUTCDate() - (t1.getUTCDay() + 7 - i) % 7);
  t1.setUTCHours(0, 0, 0, 0);
  t0.setTime(+date);
  t0.setUTCMonth(0);
  t0.setUTCDate(1);
  t0.setUTCDate(1 - (t0.getUTCDay() + 7 - i) % 7);
  t0.setUTCHours(0, 0, 0, 0);
  return Math.floor((1 + (+t1 - +t0)) / msWeek);
}

/**
 * Returns the date (day of month) of the specified *date* according to
 * Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The date (day of month) value in UTC time.
 */
function utcdate(date) {
  return t(date).getUTCDate();
}

/**
 * Returns the day of the year (1-366) of the specified *date* according
 * to Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The day of the year in UTC time.
 */
function utcdayofyear(date) {
  t1.setTime(+date);
  t1.setUTCHours(0, 0, 0, 0);
  const t0 = Date.UTC(t1.getUTCFullYear(), 0, 1);
  return Math.floor(1 + (+t1 - t0) / msDay);
}

/**
 * Returns the Sunday-based day of the week (0-6) of the specified *date*
 * according to Coordinated Universal Time (UTC). A value of `0` indicates
 * Sunday, `1` indicates Monday, and so on.
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The day of the week in UTC time.
 */
function utcdayofweek(date) {
  return t(date).getUTCDay();
}

/**
 * Returns the hour of the day for the specified *date* according to
 * Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The hours value in UTC time.
 */
function utchours(date) {
  return t(date).getUTCHours();
}

/**
 * Returns the minute of the hour for the specified *date* according to
 * Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The minutes value in UTC time.
 */
function utcminutes(date) {
  return t(date).getUTCMinutes();
}

/**
 * Returns the seconds of the minute for the specified *date* according to
 * Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The seconds value in UTC time.
 */
function utcseconds(date) {
  return t(date).getUTCSeconds();
}

/**
 * Returns the milliseconds of the second for the specified *date* according to
 * Coordinated Universal Time (UTC).
 * @param {Date | number} date The input Date or timestamp value.
 * @return {number} The milliseconds value in UTC time.
 */
function utcmilliseconds(date) {
  return t(date).getUTCMilliseconds();
}

;// ../../node_modules/arquero/src/op/functions/json.js
/**
 * Parses a string *value* in JSON format, constructing the JavaScript
 * value or object described by the string.
 * @param {string} value The input string value.
 * @return {any} The parsed JSON.
 */
function parse_json(value) {
  return JSON.parse(value);
}

/**
 * Converts a JavaScript object or value to a JSON string.
 * @param {*} value The value to convert to a JSON string.
 * @return {string} The JSON string.
 */
function to_json(value) {
  return JSON.stringify(value);
}

;// ../../node_modules/arquero/src/util/random.js


let source = Math.random;

function random() {
  return source();
}

/**
 * Set a seed value for random number generation.
 * If the seed is a valid number, a 32-bit linear congruential generator
 * with the given seed will be used to generate random values.
 * If the seed is null, undefined, or not a valid number, the random
 * number generator will revert to Math.random.
 * @param {number} seed The random seed value. Should either be an
 *  integer or a fraction between 0 and 1.
 */
function seed(seed) {
  source = isValid(seed) && isFinite(seed = +seed) ? random_lcg(seed) : Math.random;
}

function random_lcg(seed) {
  const a = 0x19660D;
  const c = 0x3C6EF35F;
  const m = 1 / 0x100000000;
  seed = (0 <= seed && seed < 1 ? seed / m : Math.abs(seed)) | 0;

  // Random numbers using a Linear Congruential Generator with seed value
  // https://en.wikipedia.org/wiki/Linear_congruential_generator
  return () => (seed = a * seed + c | 0, m * (seed >>> 0));
}

;// ../../node_modules/arquero/src/op/functions/math.js


/**
 * Return a random floating point number between 0 (inclusive) and 1
 * (exclusive). By default uses *Math.random*. Use the *seed* method
 * to instead use a seeded random number generator.
 * @return {number} A pseudorandom number between 0 and 1.
 */
function math_random() {
  return random();
}

/**
 * Tests if the input *value* is not a number (`NaN`); equivalent
 * to *Number.isNaN*.
 * @param {*} value The value to test.
 * @return {boolean} True if the value is not a number, false otherwise.
 */
function is_nan(value) {
  return Number.isNaN(value);
}

/**
 * Tests if the input *value* is finite; equivalent to *Number.isFinite*.
 * @param {*} value The value to test.
 * @return {boolean} True if the value is finite, false otherwise.
 */
function is_finite(value) {
  return Number.isFinite(value);
}

/**
 * Returns the absolute value of the input *value*; equivalent to *Math.abs*.
 * @param {number} value The input number value.
 * @return {number} The absolute value.
 */
function abs(value) {
  return Math.abs(value);
}

/**
 * Returns the cube root value of the input *value*; equivalent to
 * *Math.cbrt*.
 * @param {number} value The input number value.
 * @return {number} The cube root value.
 */
function cbrt(value) {
  return Math.cbrt(value);
}

/**
 * Returns the ceiling of the input *value*, the nearest integer equal to
 * or greater than the input; equivalent to *Math.ceil*.
 * @param {number} value The input number value.
 * @return {number} The ceiling value.
 */
function ceil(value) {
  return Math.ceil(value);
}

/**
 * Returns the number of leading zero bits in the 32-bit binary
 * representation of a number *value*; equivalent to *Math.clz32*.
 * @param {number} value The input number value.
 * @return {number} The leading zero bits value.
 */
function clz32(value) {
  return Math.clz32(value);
}

/**
 * Returns *e<sup>value</sup>*, where *e* is Euler's number, the base of the
 * natural logarithm; equivalent to *Math.exp*.
 * @param {number} value The input number value.
 * @return {number} The base-e exponentiated value.
 */
function exp(value) {
  return Math.exp(value);
}

/**
 * Returns *e<sup>value</sup> - 1*, where *e* is Euler's number, the base of
 * the natural logarithm; equivalent to *Math.expm1*.
 * @param {number} value The input number value.
 * @return {number} The base-e exponentiated value minus 1.
 */
function expm1(value) {
  return Math.expm1(value);
}

/**
 * Returns the floor of the input *value*, the nearest integer equal to or
 * less than the input; equivalent to *Math.floor*.
 * @param {number} value The input number value.
 * @return {number} The floor value.
 */
function floor(value) {
  return Math.floor(value);
}

/**
 * Returns the nearest 32-bit single precision float representation of the
 * input number *value*; equivalent to *Math.fround*. Useful for translating
 * between 64-bit `Number` values and values from a `Float32Array`.
 * @param {number} value The input number value.
 * @return {number} The rounded value.
 */
function fround(value) {
  return Math.fround(value);
}

/**
 * Returns the greatest (maximum) value among the input *values*; equivalent
 * to *Math.max*. This is _not_ an aggregate function, see *op.max* to
 * compute a maximum value across multiple rows.
 * @param {...number} values The input number values.
 * @return {number} The greatest (maximum) value among the inputs.
 */
function math_greatest(...values) {
  return Math.max(...values);
}

/**
 * Returns the least (minimum) value among the input *values*; equivalent
 * to *Math.min*. This is _not_ an aggregate function, see *op.min* to
 * compute a minimum value across multiple rows.
 * @param {...number} values The input number values.
 * @return {number} The least (minimum) value among the inputs.
 */
function least(...values) {
  return Math.min(...values);
}

/**
 * Returns the natural logarithm (base *e*) of a number *value*; equivalent
 * to *Math.log*.
 * @param {number} value The input number value.
 * @return {number} The base-e log value.
 */
function log(value) {
  return Math.log(value);
}

/**
 * Returns the base 10 logarithm of a number *value*; equivalent
 * to *Math.log10*.
 * @param {number} value The input number value.
 * @return {number} The base-10 log value.
 */
function log10(value) {
  return Math.log10(value);
}

/**
 * Returns the natural logarithm (base *e*) of 1 + a number *value*;
 * equivalent to *Math.log1p*.
 * @param {number} value The input number value.
 * @return {number} The base-e log of value + 1.
 */
function log1p(value) {
  return Math.log1p(value);
}

/**
 * Returns the base 2 logarithm of a number *value*; equivalent
 * to *Math.log2*.
 * @param {number} value The input number value.
 * @return {number} The base-2 log value.
 */
function log2(value) {
  return Math.log2(value);
}

/**
 * Returns the *base* raised to the *exponent* power, that is,
 * *base*<sup>*exponent*</sup>; equivalent to *Math.pow*.
 * @param {number} base The base number value.
 * @param {number} exponent The exponent number value.
 * @return {number} The exponentiated value.
 */
function pow(base, exponent) {
  return Math.pow(base, exponent);
}

/**
 * Returns the value of a number rounded to the nearest integer;
 * equivalent to *Math.round*.
 * @param {number} value The input number value.
 * @return {number} The rounded value.
 */
function round(value) {
  return Math.round(value);
}

/**
 * Returns either a positive or negative +/- 1, indicating the sign of the
 * input *value*; equivalent to *Math.sign*.
 * @param {number} value The input number value.
 * @return {number} The sign of the value.
 */
function sign(value) {
  return Math.sign(value);
}

/**
 * Returns the square root of the input *value*; equivalent to *Math.sqrt*.
 * @param {number} value The input number value.
 * @return {number} The square root value.
 */
function sqrt(value) {
  return Math.sqrt(value);
}

/**
 * Returns the integer part of a number by removing any fractional digits;
 * equivalent to *Math.trunc*.
 * @param {number} value The input number value.
 * @return {number} The truncated value.
 */
function trunc(value) {
  return Math.trunc(value);
}

/**
 * Converts the input *radians* value to degrees.
 * @param {number} radians The input radians value.
 * @return {number} The value in degrees
 */
function math_degrees(radians) {
  return 180 * radians / Math.PI;
}

/**
 * Converts the input *degrees* value to radians.
 * @param {number} degrees The input degrees value.
 * @return {number} The value in radians.
 */
function math_radians(degrees) {
  return Math.PI * degrees / 180;
}

/**
 * Returns the arc-cosine (in radians) of a number *value*;
 * equivalent to *Math.acos*.
 * @param {number} value The input number value.
 * @return {number} The arc-cosine value.
 */
function acos(value) {
  return Math.acos(value);
}

/**
 * Returns the hyperbolic arc-cosine of a number *value*;
 * equivalent to *Math.acosh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic arc-cosine value.
 */
function acosh(value) {
  return Math.acosh(value);
}

/**
 * Returns the arc-sine (in radians) of a number *value*;
 * equivalent to *Math.asin*.
 * @param {number} value The input number value.
 * @return {number} The arc-sine value.
 */
function asin(value) {
  return Math.asin(value);
}

/**
 * Returns the hyperbolic arc-sine of a number *value*;
 * equivalent to *Math.asinh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic arc-sine value.
 */
function asinh(value) {
  return Math.asinh(value);
}

/**
 * Returns the arc-tangent (in radians) of a number *value*;
 * equivalent to *Math.atan*.
 * @param {number} value The input number value.
 * @return {number} The arc-tangent value.
 */
function atan(value) {
  return Math.atan(value);
}

/**
 * Returns the angle in the plane (in radians) between the positive x-axis
 * and the ray from (0, 0) to the point (*x*, *y*);
 * equivalent to *Math.atan2*.
 * @param {number} y The y coordinate of the point.
 * @param {number} x The x coordinate of the point.
 * @return {number} The arc-tangent angle.
 */
function atan2(y, x) {
  return Math.atan2(y, x);
}

/**
 * Returns the hyperbolic arc-tangent of a number *value*;
 * equivalent to *Math.atanh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic arc-tangent value.
 */
function atanh(value) {
  return Math.atanh(value);
}

/**
 * Returns the cosine (in radians) of a number *value*;
 * equivalent to *Math.cos*.
 * @param {number} value The input number value.
 * @return {number} The cosine value.
 */
function cos(value) {
  return Math.cos(value);
}

/**
 * Returns the hyperbolic cosine (in radians) of a number *value*;
 * equivalent to *Math.cosh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic cosine value.
 */
function cosh(value) {
  return Math.cosh(value);
}

/**
 * Returns the sine (in radians) of a number *value*;
 * equivalent to *Math.sin*.
 * @param {number} value The input number value.
 * @return {number} The sine value.
 */
function sin(value) {
  return Math.sin(value);
}

/**
 * Returns the hyperbolic sine (in radians) of a number *value*;
 * equivalent to *Math.sinh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic sine value.
 */
function sinh(value) {
  return Math.sinh(value);
}

/**
 * Returns the tangent (in radians) of a number *value*;
 * equivalent to *Math.tan*.
 * @param {number} value The input number value.
 * @return {number} The tangent value.
 */
function tan(value) {
  return Math.tan(value);
}

/**
 * Returns the hyperbolic tangent (in radians) of a number *value*;
 * equivalent to *Math.tanh*.
 * @param {number} value The input number value.
 * @return {number} The hyperbolic tangent value.
 */
function tanh(value) {
  return Math.tanh(value);
}

;// ../../node_modules/arquero/src/util/is-map.js
/**
 * @param {*} value
 * @return {value is Map}
 */
function isMap(value) {
  return value instanceof Map;
}

;// ../../node_modules/arquero/src/util/is-set.js
/**
 * @param {*} value
 * @return {value is Set}
 */
function isSet(value) {
  return value instanceof Set;
}

;// ../../node_modules/arquero/src/util/is-map-or-set.js



/**
 * @param {*} value
 * @return {value is Map | Set}
 */
function isMapOrSet(value) {
  return isMap(value) || isSet(value);
}

;// ../../node_modules/arquero/src/op/functions/object.js




function array(iter) {
  return Array.from(iter);
}

/**
 * Returns a boolean indicating whether the *object* has the specified *key*
 * as its own property (as opposed to inheriting it). If the *object* is a
 * *Map* or *Set* instance, the *has* method will be invoked directly on the
 * object, otherwise *Object.hasOwnProperty* is used.
 * @template {string | number} K
 * @template V
 * @param {Map<K, V>|Set<K>|Record<K, V>} object The object, Map, or Set to
 *  test for property membership.
 * @param {K} key The property key to test for.
 * @return {boolean} True if the object has the given key, false otherwise.
 */
function has(object, key) {
  return isMapOrSet(object) ? object.has(key)
    : object != null ? Object.hasOwn(object, `${key}`)
    : false;
}

/**
 * Returns an array of a given *object*'s own enumerable property names. If
 * the *object* is a *Map* instance, the *keys* method will be invoked
 * directly on the object, otherwise *Object.keys* is used.
 * @template {string | number} K
 * @template V
 * @param {Map<K, V>|Record<K, V>} object The input object or Map value.
 * @return {K[]} An array of property key name strings.
 */
function keys(object) {
  return isMap(object) ? array(object.keys())
    : object != null ? /** @type {K[]} */(Object.keys(object))
    : [];
}

/**
 * Returns an array of a given *object*'s own enumerable property values. If
 * the *object* is a *Map* or *Set* instance, the *values* method will be
 * invoked directly on the object, otherwise *Object.values* is used.
 * @template {string | number} K
 * @template V
 * @param {Map<K, V> | Set<V> | Record<K, V>} object The input object, Map,
 *  or Set value.
 * @return {V[]} An array of property values.
 */
function values(object) {
  return isMapOrSet(object) ? array(object.values())
    : object != null ? Object.values(object)
    : [];
}

/**
 * Returns an array of a given *object*'s own enumerable keyed property
 * `[key, value]` pairs. If the *object* is a *Map* or *Set* instance, the
 * *entries* method will be invoked directly on the object, otherwise
 * *Object.entries* is used.
 * @template {string | number} K
 * @template V
 * @param {Map<K, V> | Set<V> | Record<K, V>} object The input object, Map,
 *  or Set value.
 * @return {[K, V][]} An array of property values.
 */
function object_entries(object) {
  return isMapOrSet(object) ? array(object.entries())
    : object != null ? /** @type {[K, V][]} */(Object.entries(object))
    : [];
}

/**
 * Returns a new object given iterable *entries* of `[key, value]` pairs.
 * This method is Arquero's version of the *Object.fromEntries* method.
 * @template {string | number} K
 * @template V
 * @param {Iterable<[K, V]>} entries An iterable collection of `[key, value]`
 *  pairs, such as an array of two-element arrays or a *Map*.
 * @return {Record<K, V>} An object of consolidated key-value pairs.
 */
function object(entries) {
  return entries
    ? /** @type {Record<K, V>} */(Object.fromEntries(entries))
    : NULL;
}

;// ../../node_modules/arquero/src/op/functions/string.js
/**
 * Parses a string *value* and returns a Date instance. Beware: this method
 * uses JavaScript's *Date.parse()* functionality, which is inconsistently
 * implemented across browsers. That said,
 * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted strings such
 * as those produced by *op.format_date* and *op.format_utcdate* should be
 * supported across platforms. Note that "bare" ISO date strings such as
 * `"2001-01-01"` are interpreted by JavaScript as indicating midnight of
 * that day in Coordinated Universal Time (UTC), *not* local time. To
 * indicate the local timezone, an ISO string can include additional time
 * components and no `Z` suffix: `"2001-01-01T00:00"`.
 * @param {*} value The input value.
 * @return {Date} The parsed date value.
 */
function parse_date(value) {
  return value == null ? value : new Date(value);
}

/**
 * Parses a string *value* and returns a floating point number.
 * @param {*} value The input value.
 * @return {number} The parsed number value.
 */
function parse_float(value) {
  return value == null ? value : Number.parseFloat(value);
}

/**
 * Parses a string *value* and returns an integer of the specified radix
 * (the base in mathematical numeral systems).
 * @param {*} value The input value.
 * @param {number} [radix] An integer between 2 and 36 that represents the
 *  radix (the base in mathematical numeral systems) of the string. Be
 *  careful: this does not default to 10! If *radix* is `undefined`, `0`,
 *  or unspecified, JavaScript assumes the following: If the input string
 *  begins with `"0x"` or `"0X"` (a zero, followed by lowercase or
 *  uppercase X), the radix is assumed to be 16 and the rest of the string
 *  is parsed as a hexidecimal number. If the input string begins with `"0"`
 *  (a zero), the radix is assumed to be 8 (octal) or 10 (decimal). Exactly
 *  which radix is chosen is implementation-dependent.  If the input string
 *  begins with any other value, the radix is 10 (decimal).
 * @return {number} The parsed integer value.
 */
function parse_int(value, radix) {
  return value == null ? value : Number.parseInt(value, radix);
}

/**
 * Determines whether a string *value* ends with the characters of a
 * specified *search* string, returning `true` or `false` as appropriate.
 * @param {any} value The input string value.
 * @param {string} search The search string to test for.
 * @param {number} [length] If provided, used as the length of *value*
 *  (default `value.length`).
 * @return {boolean} True if the value ends with the search string,
 *  false otherwise.
 */
function endswith(value, search, length) {
  return value == null ? false : String(value).endsWith(search, length);
}

/**
 * Retrieves the result of matching a string *value* against a regular
 * expression *regexp*. If no *index* is specified, returns an array
 * whose contents depend on the presence or absence of the regular
 * expression global (`g`) flag, or `null` if no matches are found. If the
 * `g` flag is used, all results matching the complete regular expression
 * will be returned, but capturing groups will not. If the `g` flag is not
 * used, only the first complete match and its related capturing groups are
 * returned.
 *
 * If specified, the *index* looks up a value of the resulting match. If
 * *index* is a number, the corresponding index of the result array is
 * returned. If *index* is a string, the value of the corresponding
 * named capture group is returned, or `null` if there is no such group.
 * @param {*} value The input string value.
 * @param {*} regexp The regular expression to match against.
 * @param {number|string} index The index into the match result array
 *  or capture group.
 * @return {string|string[]} The match result.
 */
function match(value, regexp, index) {
  const m = value == null ? value : String(value).match(regexp);
  return index == null || m == null ? m
    : typeof index === 'number' ? m[index]
    : m.groups ? m.groups[index]
    : null;
}

/**
 * Returns the Unicode normalization form of the string *value*.
 * @param {*} value The input value to normalize.
 * @param {string} form The Unicode normalization form, one of
 *  `'NFC'` (default, canonical decomposition, followed by canonical
 *  composition), `'NFD'` (canonical decomposition), `'NFKC'` (compatibility
 *  decomposition, followed by canonical composition),
 *  or `'NFKD'` (compatibility decomposition).
 * @return {string} The normalized string value.
 */
function normalize(value, form) {
  return value == null ? value : String(value).normalize(form);
}

/**
 * Pad a string *value* with a given *fill* string (applied from the end of
 * *value* and repeated, if needed) so that the resulting string reaches a
 * given *length*.
 * @param {*} value The input value to pad.
 * @param {number} length The length of the resulting string once the
 *  *value* string has been padded. If the length is lower than
 *  `value.length`, the *value* string will be returned as-is.
 * @param {string} [fill] The string to pad the *value* string with
 *  (default `''`). If *fill* is too long to stay within the target
 *  *length*, it will be truncated: for left-to-right languages the
 *  left-most part and for right-to-left languages the right-most will
 *  be applied.
 * @return {string} The padded string.
 */
function padend(value, length, fill) {
  return value == null ? value : String(value).padEnd(length, fill);
}

/**
 * Pad a string *value* with a given *fill* string (applied from the start
 * of *value* and repeated, if needed) so that the resulting string reaches
 * a given *length*.
 * @param {*} value The input value to pad.
 * @param {number} length The length of the resulting string once the
 *  *value* string has been padded. If the length is lower than
 *  `value.length`, the *value* string will be returned as-is.
 * @param {string} [fill] The string to pad the *value* string with
 *  (default `''`). If *fill* is too long to stay within the target
 *  *length*, it will be truncated: for left-to-right languages the
 *  left-most part and for right-to-left languages the right-most will
 *  be applied.
 * @return {string} The padded string.
 */
function padstart(value, length, fill) {
  return value == null ? value : String(value).padStart(length, fill);
}

/**
 * Returns the string *value* converted to upper case.
 * @param {*} value The input string value.
 * @return {string} The upper case string.
 */
function upper(value) {
  return value == null ? value : String(value).toUpperCase();
}

/**
 * Returns the string *value* converted to lower case.
 * @param {*} value The input string value.
 * @return {string} The lower case string.
 */
function lower(value) {
  return value == null ? value : String(value).toLowerCase();
}

/**
 * Returns a new string which contains the specified *number* of copies of
 * the *value* string concatenated together.
 * @param {*} value The input string to repeat.
 * @param {*} number An integer between `0` and `+Infinity`, indicating the
 *  number of times to repeat the string.
 * @return {string} The repeated string.
 */
function string_repeat(value, number) {
  return value == null ? value : String(value).repeat(number);
}

/**
 * Returns a new string with some or all matches of a *pattern* replaced by
 * a *replacement*. The *pattern* can be a string or a regular expression,
 * and the *replacement* must be a string. If *pattern* is a string, only
 * the first occurrence will be replaced; to make multiple replacements, use
 * a regular expression *pattern* with a `g` (global) flag.
 * @param {*} value The input string value.
 * @param {*} pattern The pattern string or regular expression to replace.
 * @param {*} replacement The replacement string to use.
 * @return {string} The string with patterns replaced.
 */
function replace(value, pattern, replacement) {
  return value == null
    ? value
    : String(value).replace(pattern, String(replacement));
}

/**
 * Divides a string *value* into an ordered list of substrings based on a
 * *separator* pattern, puts these substrings into an array, and returns the
 * array.
 * @param {*} value The input string value.
 * @param {*} separator A string or regular expression pattern describing
 *  where each split should occur.
 * @param {number} [limit] An integer specifying a limit on the number of
 *  substrings to be included in the array.
 * @return {string[]}
 */
function split(value, separator, limit) {
  return value == null ? [] : String(value).split(separator, limit);
}

/**
 * Determines whether a string *value* starts with the characters of a
 * specified *search* string, returning `true` or `false` as appropriate.
 * @param {*} value The input string value.
 * @param {string} search The search string to test for.
 * @param {number} [position=0] The position in the *value* string at which
 *  to begin searching (default `0`).
 * @return {boolean} True if the string starts with the search pattern,
 *  false otherwise.
 */
function startswith(value, search, position) {
  return value == null ? false : String(value).startsWith(search, position);
}

/**
 * Returns the part of the string *value* between the *start* and *end*
 * indexes, or to the end of the string.
 * @param {*} value The input string value.
 * @param {number} [start=0] The index of the first character to include in
 *  the returned substring (default `0`).
 * @param {number} [end] The index of the first character to exclude from
 *  the returned substring (default `value.length`).
 * @return {string} The substring.
 */
function substring(value, start, end) {
  return value == null ? value : String(value).substring(start, end);
}

/**
 * Returns a new string with whitespace removed from both ends of the input
 * *value* string. Whitespace in this context is all the whitespace
 * characters (space, tab, no-break space, etc.) and all the line terminator
 * characters (LF, CR, etc.).
 * @param {*} value The input string value to trim.
 * @return {string} The trimmed string.
 */
function trim(value) {
  return value == null ? value : String(value).trim();
}

;// ../../node_modules/arquero/src/op/functions/index.js












const functions_functions = {
  bin: bin,
  equal: equal,
  recode: recode,
  sequence: sequence,
  ...array_namespaceObject,
  ...date_namespaceObject,
  ...json_namespaceObject,
  ...math_namespaceObject,
  ...object_namespaceObject,
  ...string_namespaceObject
};

;// ../../node_modules/arquero/src/util/to-array.js


function toArray(value) {
  return value != null
    ? (is_array_isArray(value) ? value : [value])
    : [];
}

;// ../../node_modules/arquero/src/util/is-bigint.js
/**
 * @param {*} value
 * @returns {value is bigint}
 */
function isBigInt(value) {
  return typeof value === 'bigint';
}

;// ../../node_modules/arquero/src/util/to-string.js


function to_string_toString(v) {
  return v === undefined ? v + ''
    : isBigInt(v) ? v + 'n'
    : JSON.stringify(v);
}

;// ../../node_modules/arquero/src/op/op-api.js




class Op {
  constructor(name, fields, params) {
    this.name = name;
    this.fields = fields;
    this.params = params;
  }
  toString() {
    const args = [
      ...this.fields.map(f => `d[${to_string_toString(f)}]`),
      ...this.params.map(to_string_toString)
    ];
    return `d => op.${this.name}(${args})`;
  }
  toObject() {
    return { expr: this.toString(), func: true };
  }
}

/**
 * @param {string} name
 * @param {any | any[]} [fields]
 * @param {any | any[]} [params]
 */
function op_api_op(name, fields = [], params = []) {
  return new Op(name, toArray(fields), toArray(params));
}

const any = (field) => op_api_op('any', field);
const count = () => op_api_op('count');
const array_agg = (field) => op_api_op('array_agg', field);
const array_agg_distinct = (field) => op_api_op('array_agg_distinct', field);
const map_agg = (key, value) => op_api_op('map_agg', [key, value]);
const object_agg = (key, value) => op_api_op('object_agg', [key, value]);
const entries_agg = (key, value) => op_api_op('entries_agg', [key, value]);

/**
 * @typedef {import('../table/types.js').Struct} Struct
 */

/**
 * All table expression operations including normal functions,
 * aggregate functions, and window functions.
 */
const op_api_opApi = {
  ...functions_functions,

  /**
   * Generate an object representing the current table row.
   * @param {...string} names The column names to include in the object.
   *  If unspecified, all columns are included.
   * @return {Struct} The generated row object.
   */
  row_object: (...names) => op_api_op('row_object', null, names.flat()),

  /**
   * Aggregate function to count the number of records (rows).
   * @returns {number} The count of records.
   */
  count,

  /**
   * Aggregate function returning an arbitrary observed value.
   * @template T
   * @param {T} field The data field.
   * @return {T} An arbitrary observed value.
   */
  any,

  /**
   * Aggregate function to collect an array of values.
   * @template T
   * @param {T} field The data field.
   * @return {Array<T>} A list of values.
   */
  array_agg,

  /**
   * Aggregate function to collect an array of distinct (unique) values.
   * @template T
   * @param {T} field The data field.
   * @return {Array<T>} An array of unique values.
   */
  array_agg_distinct,

  /**
   * Aggregate function to create an object given input key and value fields.
   * @template K, V
   * @param {K} key The object key field.
   * @param {V} value The object value field.
   * @return {Record<K, V>} An object of key-value pairs.
   */
  object_agg,

  /**
   * Aggregate function to create a Map given input key and value fields.
   * @template K, V
   * @param {K} key The object key field.
   * @param {V} value The object value field.
   * @return {Map<K, V>} A Map of key-value pairs.
   */
  map_agg,

  /**
   * Aggregate function to create an array in the style of Object.entries()
   * given input key and value fields.
   * @template K, V
   * @param {K} key The object key field.
   * @param {V} value The object value field.
   * @return {[K, V][]} An array of [key, value] arrays.
   */
  entries_agg,

  /**
   * Aggregate function to count the number of valid values.
   * Invalid values are null, undefined, or NaN.
   * @param {*} field The data field.
   * @return {number} The count of valid values.
   */
  // @ts-ignore
  valid: (field) => op_api_op('valid', field),

  /**
   * Aggregate function to count the number of invalid values.
   * Invalid values are null, undefined, or NaN.
   * @param {*} field The data field.
   * @return {number} The count of invalid values.
   */
  // @ts-ignore
  invalid: (field) => op_api_op('invalid', field),

  /**
   * Aggregate function to count the number of distinct values.
   * @param {*} field The data field.
   * @return {number} The count of distinct values.
   */
  // @ts-ignore
  distinct: (field) => op_api_op('distinct', field),

  /**
   * Aggregate function to determine the mode (most frequent) value.
   * @template T
   * @param {T} field The data field.
   * @return {T} The mode value.
   */
  // @ts-ignore
  mode: (field) => op_api_op('mode', field),

  /**
   * Aggregate function to sum values.
   * @param {*} field The data field.
   * @return {number} The sum of the values.
   */
  // @ts-ignore
  sum: (field) => op_api_op('sum', field),

  /**
   * Aggregate function to multiply values.
   * @param {*} field The data field.
   * @return {number} The product of the values.
   */
  // @ts-ignore
  product: (field) => op_api_op('product', field),

  /**
   * Aggregate function for the mean (average) value.
   * @param {*} field The data field.
   * @return {number} The mean (average) of the values.
   */
  // @ts-ignore
  mean: (field) => op_api_op('mean', field),

  /**
   * Aggregate function for the average (mean) value.
   * @param {*} field The data field.
   * @return {number} The average (mean) of the values.
   */
  // @ts-ignore
  average: (field) => op_api_op('average', field),

  /**
   * Aggregate function for the sample variance.
   * @param {*} field The data field.
   * @return {number} The sample variance of the values.
   */
  // @ts-ignore
  variance: (field) => op_api_op('variance', field),

  /**
   * Aggregate function for the population variance.
   * @param {*} field The data field.
   * @return {number} The population variance of the values.
   */
  // @ts-ignore
  variancep: (field) => op_api_op('variancep', field),

  /**
   * Aggregate function for the sample standard deviation.
   * @param {*} field The data field.
   * @return {number} The sample standard deviation of the values.
   */
  // @ts-ignore
  stdev: (field) => op_api_op('stdev', field),

  /**
   * Aggregate function for the population standard deviation.
   * @param {*} field The data field.
   * @return {number} The population standard deviation of the values.
   */
  // @ts-ignore
  stdevp: (field) => op_api_op('stdevp', field),

  /**
   * Aggregate function for the minimum value.
   * @template T
   * @param {T} field The data field.
   * @return {T} The minimum value.
   */
  // @ts-ignore
  min: (field) => op_api_op('min', field),

  /**
   * Aggregate function for the maximum value.
   * @template T
   * @param {T} field The data field.
   * @return {T} The maximum value.
   */
  // @ts-ignore
  max: (field) => op_api_op('max', field),

  /**
   * Aggregate function to compute the quantile boundary
   * of a data field for a probability threshold.
   * @param {*} field The data field.
   * @param {number} p The probability threshold.
   * @return {number} The quantile value.
   */
  // @ts-ignore
  quantile: (field, p) => op_api_op('quantile', field, p),

  /**
   * Aggregate function for the median value.
   * This is a shorthand for the 0.5 quantile value.
   * @param {*} field The data field.
   * @return {number} The median value.
   */
  // @ts-ignore
  median: (field) => op_api_op('median', field),

  /**
   * Aggregate function for the sample covariance between two variables.
   * @param {*} field1 The first data field.
   * @param {*} field2 The second data field.
   * @return {number} The sample covariance of the values.
   */
  // @ts-ignore
  covariance: (field1, field2) => op_api_op('covariance', [field1, field2]),

  /**
   * Aggregate function for the population covariance between two variables.
   * @param {*} field1 The first data field.
   * @param {*} field2 The second data field.
   * @return {number} The population covariance of the values.
   */
  // @ts-ignore
  covariancep: (field1, field2) => op_api_op('covariancep', [field1, field2]),

  /**
   * Aggregate function for the product-moment correlation between two variables.
   * To instead compute a rank correlation, compute the average ranks for each
   * variable and then apply this function to the result.
   * @param {*} field1 The first data field.
   * @param {*} field2 The second data field.
   * @return {number} The correlation between the field values.
   */
  // @ts-ignore
  corr: (field1, field2) => op_api_op('corr', [field1, field2]),

  /**
   * Aggregate function for calculating a binning scheme in terms of
   * the minimum bin boundary, maximum bin boundary, and step size.
   * @param {*} field The data field.
   * @param {number} [maxbins=15] The maximum number of allowed bins.
   * @param {boolean} [nice=true] Flag indicating if the bin min and max
   *  should snap to "nice" human-friendly values.
   * @param {number} [minstep] The minimum allowed step size between bins.
   * @param {number} [step] The exact step size to use between bins.
   *  If specified, the maxbins and minstep arguments are ignored.
   * @return {[number, number, number]} The bin [min, max, and step] values.
   */
  // @ts-ignore
  bins: (field, maxbins, nice, minstep, step) => op_api_op(
    'bins',
    field,
    [maxbins, nice, minstep, step]
  ),

  /**
   * Window function to assign consecutive row numbers, starting from 1.
   * @return {number} The row number value.
   */
  // @ts-ignore
  row_number: () => op_api_op('row_number'),

  /**
   * Window function to assign a rank to each value in a group, starting
   * from 1. Peer values are assigned the same rank. Subsequent ranks
   * reflect the number of prior values: if the first two values tie for
   * rank 1, the third value is assigned rank 3.
   * @return {number} The rank value.
   */
  // @ts-ignore
  rank: () => op_api_op('rank'),

  /**
   * Window function to assign a fractional (average) rank to each value in
   * a group, starting from 1. Peer values are assigned the average of their
   * indices: if the first two values tie, both will be assigned rank 1.5.
   * @return {number} The peer-averaged rank value.
   */
  // @ts-ignore
  avg_rank: () => op_api_op('avg_rank'),

  /**
   * Window function to assign a dense rank to each value in a group,
   * starting from 1. Peer values are assigned the same rank. Subsequent
   * ranks do not reflect the number of prior values: if the first two
   * values tie for rank 1, the third value is assigned rank 2.
   * @return {number} The dense rank value.
   */
  // @ts-ignore
  dense_rank: () => op_api_op('dense_rank'),

  /**
   * Window function to assign a percentage rank to each value in a group.
   * The percent is calculated as (rank - 1) / (group_size - 1).
   * @return {number} The percentage rank value.
   */
  // @ts-ignore
  percent_rank: () => op_api_op('percent_rank'),

  /**
   * Window function to assign a cumulative distribution value between 0 and 1
   * to each value in a group.
   * @return {number} The cumulative distribution value.
   */
  // @ts-ignore
  cume_dist: () => op_api_op('cume_dist'),

  /**
   * Window function to assign a quantile (e.g., percentile) value to each
   * value in a group. Accepts an integer parameter indicating the number of
   * buckets to use (e.g., 100 for percentiles, 5 for quintiles).
   * @param {number} num The number of buckets for ntile calculation.
   * @return {number} The quantile value.
   */
  // @ts-ignore
  ntile: (num) => op_api_op('ntile', null, num),

  /**
   * Window function to assign a value that precedes the current value by
   * a specified number of positions. If no such value exists, returns a
   * default value instead.
   * @template T
   * @param {T} field The data field.
   * @param {number} [offset=1] The lag offset from the current value.
   * @param {T} [defaultValue=undefined] The default value.
   * @return {T} The lagging value.
   */
  // @ts-ignore
  lag: (field, offset, defaultValue) => op_api_op('lag', field, [offset, defaultValue]),

  /**
   * Window function to assign a value that follows the current value by
   * a specified number of positions. If no such value exists, returns a
   * default value instead.
   * @template T
   * @param {T} field The data field.
   * @param {number} [offset=1] The lead offset from the current value.
   * @param {T} [defaultValue=undefined] The default value.
   * @return {T} The leading value.
   */
  // @ts-ignore
  lead: (field, offset, defaultValue) => op_api_op('lead', field, [offset, defaultValue]),

  /**
   * Window function to assign the first value in a sliding window frame.
   * @template T
   * @param {T} field The data field.
   * @return {T} The first value in the current frame.
   */
  // @ts-ignore
  first_value: (field) => op_api_op('first_value', field),

  /**
   * Window function to assign the last value in a sliding window frame.
   * @template T
   * @param {T} field The data field.
   * @return {T} The last value in the current frame.
   */
  // @ts-ignore
  last_value: (field) => op_api_op('last_value', field),

  /**
   * Window function to assign the nth value in a sliding window frame
   * (counting from 1), or undefined if no such value exists.
   * @template T
   * @param {T} field The data field.
   * @param {number} nth The nth position, starting from 1.
   * @return {T} The nth value in the current frame.
   */
  // @ts-ignore
  nth_value: (field, nth) => op_api_op('nth_value', field, nth),

  /**
   * Window function to fill in missing values with preceding values.
   * @template T
   * @param {T} field The data field.
   * @param {T} [defaultValue=undefined] The default value.
   * @return {T} The current value if valid, otherwise the first preceding
   *  valid value. If no such value exists, returns the default value.
   */
  // @ts-ignore
  fill_down: (field, defaultValue) => op_api_op('fill_down', field, defaultValue),

  /**
   * Window function to fill in missing values with subsequent values.
   * @template T
   * @param {T} field The data field.
   * @param {T} [defaultValue=undefined] The default value.
   * @return {T} The current value if valid, otherwise the first subsequent
   *  valid value. If no such value exists, returns the default value.
   */
  // @ts-ignore
  fill_up: (field, defaultValue) => op_api_op('fill_up', field, defaultValue)
};

;// ../../node_modules/arquero/src/util/error.js
function error_error(message, cause) {
  // @ts-ignore
  throw Error(message, { cause });
}

;// ../../node_modules/arquero/src/util/unique-name.js


function uniqueName(names, name) {
  names = isMapOrSet(names) ? names : new Set(names);
  let uname = name;
  let index = 0;

  while (names.has(uname)) {
    uname = name + ++index;
  }

  return uname;
}

;// ../../node_modules/arquero/src/util/is-function.js
/**
 * @param {*} value
 * @returns {value is Function}
 */
function is_function_isFunction(value) {
  return typeof value === 'function';
}

;// ../../node_modules/arquero/src/util/repeat.js


function repeat_repeat(reps, value) {
  const result = Array(reps);
  if (is_function_isFunction(value)) {
    for (let i = 0; i < reps; ++i) {
      result[i] = value(i);
    }
  } else {
    result.fill(value);
  }
  return result;
}

;// ../../node_modules/arquero/src/util/bins.js
function bins(min, max, maxbins = 15, nice = true, minstep = 0, step) {
  const base = 10;
  const logb = Math.LN10;

  if (step == null) {
    const level = Math.ceil(Math.log(maxbins) / logb);
    const span = (max - min) || Math.abs(min) || 1;
    const div = [5, 2];

    step = Math.max(
      minstep,
      Math.pow(base, Math.round(Math.log(span) / logb) - level)
    );

    // increase step size if too many bins
    while (Math.ceil(span / step) > maxbins) {
      step *= base;
    }

    // decrease step size if it stays within maxbins
    const n = div.length;
    for (let i = 0; i < n; ++i) {
      const v = step / div[i];
      if (v >= minstep && span / v <= maxbins) {
        step = v;
      }
    }
  }

  // snap to "nice" boundaries
  if (nice) {
    let v = Math.log(step);
    const precision = v >= 0 ? 0 : ~~(-v / logb) + 1;
    const eps = Math.pow(base, -precision - 1);
    v = Math.floor(min / step + eps) * step;
    min = min < v ? v - step : v;
    max = Math.ceil(max / step) * step;
  }

  return [
    min,
    max === min ? min + step : max,
    step
  ];
}

;// ../../node_modules/arquero/src/util/key-function.js





function key(value) {
  const type = typeof value;
  return type === 'string' ? `"${value}"`
    : type !== 'object' || !value ? value
    : isDate(value) ? +value
    : is_array_isArray(value) || isTypedArray(value) ? `[${value.map(key)}]`
    : isRegExp(value) ? value + ''
    : objectKey(value);
}

function objectKey(value) {
  let s = '{';
  let i = -1;
  for (const k in value) {
    if (++i > 0) s += ',';
    s += `"${k}":${key(value[k])}`;
  }
  s += '}';
  return s;
}

function keyFunction(get, nulls) {
  const n = get.length;
  return n === 1
    ? (row, data) => key(get[0](row, data))
    : (row, data) => {
        let s = '';
        for (let i = 0; i < n; ++i) {
          if (i > 0) s += '|';
          const v = get[i](row, data);
          if (nulls && (v == null || v !== v)) return null;
          s += key(v);
        }
        return s;
      };
}

;// ../../node_modules/arquero/src/util/distinct-map.js


function distinctMap() {
  const map = new Map();
  return {
    count() {
      return map.size;
    },
    values() {
      return Array.from(map.values(), _ => _.v);
    },
    increment(v) {
      const k = key(v);
      const e = map.get(k);
      e ? ++e.n : map.set(k, { v, n: 1 });
    },
    decrement(v) {
      const k = key(v);
      const e = map.get(k);
      e.n === 1 ? map.delete(k) : --e.n;
    },
    forEach(fn) {
      map.forEach(({ v, n }) => fn(v, n));
    }
  };
}

;// ../../node_modules/arquero/src/util/no-op.js
function no_op_noop() {}

;// ../../node_modules/arquero/src/util/product.js
function product(values, start = 0, stop = values.length) {
  let prod = values[start++];

  for (let i = start; i < stop; ++i) {
    prod *= values[i];
  }

  return prod;
}

;// ../../node_modules/arquero/src/op/aggregate-functions.js







/**
 * Initialize an aggregate operator.
 */
function initOp(op) {
  op.init = op.init || no_op_noop;
  op.add = op.add || no_op_noop;
  op.rem = op.rem || no_op_noop;
  return op;
}

function initProduct(s, value) {
  s.product_v = false;
  return s.product = value;
}

/**
 * Initialize an aggregate operator.
 * @callback AggregateInit
 * @param {object} state The aggregate state object.
 * @return {void}
 */

/**
 * Add a value to an aggregate operator.
 * @callback AggregateAdd
 * @param {object} state The aggregate state object.
 * @param {*} value The value to add.
 * @return {void}
 */

/**
 * Remove a value from an aggregate operator.
 * @callback AggregateRem
 * @param {object} state The aggregate state object.
 * @param {*} value The value to remove.
 * @return {void}
 */

/**
 * Retrive an output value from an aggregate operator.
 * @callback AggregateValue
 * @param {object} state The aggregate state object.
 * @return {*} The output value.
 */

/**
 * An operator instance for an aggregate function.
 * @typedef {object} AggregateOperator
 * @property {AggregateInit} init Initialize the operator.
 * @property {AggregateAdd} [add] Add a value to the operator state.
 * @property {AggregateRem} [rem] Remove a value from the operator state.
 * @property {AggregateValue} value Retrieve an output value.
 */

/**
 * Create a new aggregate operator instance.
 * @callback AggregateCreate
 * @param {...any} params The aggregate operator parameters.
 * @return {AggregateOperator} The instantiated aggregate operator.
 */

/**
 * An operator definition for an aggregate function.
 * @typedef {object} AggregateDef
 * @property {AggregateCreate} create Create a new operator instance.
 * @property {number[]} param Two-element array containing the
 *  counts of input fields and additional parameters.
 * @property {string[]} [req] Names of operators required by this one.
 * @property {string[]} [stream] Names of operators required by this one
 *  for streaming operations (value removes).
 */

/**
 * Aggregate operator definitions.
 */
const aggregate_functions_aggregateFunctions = {
  /** @type {AggregateDef} */
  count: {
    create: () => initOp({
      value: s => s.count
    }),
    param: []
  },

  /** @type {AggregateDef} */
  array_agg: {
    create: () => initOp({
      init: s => s.values = true,
      value: s => s.list.values(s.stream)
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  object_agg: {
    create: () => initOp({
      init:  s => s.values = true,
      value: s => Object.fromEntries(s.list.values())
    }),
    param: [2]
  },

  /** @type {AggregateDef} */
  map_agg: {
    create: () => initOp({
      init:  s => s.values = true,
      value: s => new Map(s.list.values())
    }),
    param: [2]
  },

  /** @type {AggregateDef} */
  entries_agg: {
    create: () => initOp({
      init:  s => s.values = true,
      value: s => s.list.values(s.stream)
    }),
    param: [2]
  },

  /** @type {AggregateDef} */
  any: {
    create: () => initOp({
      add: (s, v) => { if (s.any == null) s.any = v; },
      value: s => s.valid ? s.any : NULL
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  valid: {
    create: () => initOp({
      value: s => s.valid
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  invalid: {
    create: () => initOp({
      value: s => s.count - s.valid
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  distinct: {
    create: () => ({
      init: s => s.distinct = distinctMap(),
      value: s => s.distinct.count() + (s.valid === s.count ? 0 : 1),
      add: (s, v) => s.distinct.increment(v),
      rem: (s, v) => s.distinct.decrement(v)
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  array_agg_distinct: {
    create: () => initOp({
      value: s => s.distinct.values()
    }),
    param: [1],
    req: ['distinct']
  },

  /** @type {AggregateDef} */
  mode: {
    create: () => initOp({
      value: s => {
        let mode = NULL;
        let max = 0;
        s.distinct.forEach((value, count) => {
          if (count > max) {
            max = count;
            mode = value;
          }
        });
        return mode;
      }
    }),
    param: [1],
    req: ['distinct']
  },

  /** @type {AggregateDef} */
  sum: {
    create: () => ({
      init:  s => s.sum = 0,
      value: s => s.valid ? s.sum : NULL,
      add: (s, v) => isBigInt(v)
        ? (s.sum === 0 ? s.sum = v : s.sum += v)
        : s.sum += +v,
      rem: (s, v) => s.sum -= v
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  product: {
    create: () => ({
      init:  s => initProduct(s, 1),
      value: s => s.valid
        ? (
            s.product_v
              ? initProduct(s, product(s.list.values()))
              : s.product
          )
        : undefined,
      add: (s, v) => isBigInt(v)
        ? (s.product === 1 ? s.product = v : s.product *= v)
        : s.product *= v,
      rem: (s, v) => (v == 0 || v === Infinity || v === -Infinity)
        ? s.product_v = true
        : s.product /= v
    }),
    param: [1],
    stream: ['array_agg']
  },

  /** @type {AggregateDef} */
  mean: {
    create: () => ({
      init: s => s.mean = 0,
      value: s => s.valid ? s.mean : NULL,
      add: (s, v) => {
        s.mean_d = v - s.mean;
        s.mean += s.mean_d / s.valid;
      },
      rem: (s, v) => {
        s.mean_d = v - s.mean;
        s.mean -= s.valid ? s.mean_d / s.valid : s.mean;
      }
    }),
    param: [1]
  },

  /** @type {AggregateDef} */
  average: {
    create: () => initOp({
      value: s => s.valid ? s.mean : NULL
    }),
    param: [1],
    req: ['mean']
  },

  /** @type {AggregateDef} */
  variance: {
    create: () => ({
      init:  s => s.dev = 0,
      value: s => s.valid > 1 ? s.dev / (s.valid - 1) : NULL,
      add: (s, v) => s.dev += s.mean_d * (v - s.mean),
      rem: (s, v) => s.dev -= s.mean_d * (v - s.mean)
    }),
    param: [1],
    req: ['mean']
  },

  /** @type {AggregateDef} */
  variancep: {
    create: () => initOp({
      value: s => s.valid > 1 ? s.dev / s.valid : NULL
    }),
    param: [1],
    req: ['variance']
  },

  /** @type {AggregateDef} */
  stdev: {
    create: () => initOp({
      value: s => s.valid > 1 ? Math.sqrt(s.dev / (s.valid - 1)) : NULL
    }),
    param: [1],
    req: ['variance']
  },

  /** @type {AggregateDef} */
  stdevp: {
    create: () => initOp({
      value: s => s.valid > 1 ? Math.sqrt(s.dev / s.valid) : NULL
    }),
    param: [1],
    req: ['variance']
  },

  /** @type {AggregateDef} */
  min: {
    create: () => ({
      init:  s => s.min = NULL,
      value: s => s.min = (Number.isNaN(s.min) ? s.list.min() : s.min),
      add: (s, v) => { if (v < s.min || s.min === NULL) s.min = v; },
      rem: (s, v) => { if (v <= s.min) s.min = NaN; }
    }),
    param: [1],
    stream: ['array_agg']
  },

  /** @type {AggregateDef} */
  max: {
    create: () => ({
      init:  s => s.max = NULL,
      value: s => s.max = (Number.isNaN(s.max) ? s.list.max() : s.max),
      add: (s, v) => { if (v > s.max || s.max === NULL) s.max = v; },
      rem: (s, v) => { if (v >= s.max) s.max = NaN; }
    }),
    param: [1],
    stream: ['array_agg']
  },

  /** @type {AggregateDef} */
  quantile: {
    create: (p) => initOp({
      value: s => s.list.quantile(p)
    }),
    param: [1, 1],
    req: ['array_agg']
  },

  /** @type {AggregateDef} */
  median: {
    create: () => initOp({
      value: s => s.list.quantile(0.5)
    }),
    param: [1],
    req: ['array_agg']
  },

  /** @type {AggregateDef} */
  covariance: {
    create: () => ({
      init:  s => {
        s.cov = s.mean_x = s.mean_y = s.dev_x = s.dev_y = 0;
      },
      value: s => s.valid > 1 ? s.cov / (s.valid - 1) : NULL,
      add: (s, x, y) => {
        const dx = x - s.mean_x;
        const dy = y - s.mean_y;
        s.mean_x += dx / s.valid;
        s.mean_y += dy / s.valid;
        const dy2 = y - s.mean_y;
        s.dev_x += dx * (x - s.mean_x);
        s.dev_y += dy * dy2;
        s.cov += dx * dy2;
      },
      rem: (s, x, y) => {
        const dx = x - s.mean_x;
        const dy = y - s.mean_y;
        s.mean_x -= s.valid ? dx / s.valid : s.mean_x;
        s.mean_y -= s.valid ? dy / s.valid : s.mean_y;
        const dy2 = y - s.mean_y;
        s.dev_x -= dx * (x - s.mean_x);
        s.dev_y -= dy * dy2;
        s.cov -= dx * dy2;
      }
    }),
    param: [2]
  },

  /** @type {AggregateDef} */
  covariancep: {
    create: () => initOp({
      value: s => s.valid > 1 ? s.cov / s.valid : NULL
    }),
    param: [2],
    req: ['covariance']
  },

  /** @type {AggregateDef} */
  corr: {
    create: () => initOp({
      value: s => s.valid > 1
        ? s.cov / (Math.sqrt(s.dev_x) * Math.sqrt(s.dev_y))
        : NULL
    }),
    param: [2],
    req: ['covariance']
  },

  /** @type {AggregateDef} */
  bins: {
    create: (maxbins, nice, minstep, step) => initOp({
      value: s => bins(s.min, s.max, maxbins, nice, minstep, step)
    }),
    param: [1, 4],
    req: ['min', 'max']
  }
};

;// ../../node_modules/arquero/src/op/window-functions.js





/**
 * Initialize a window operator.
 * @callback WindowInit
 * @return {void}
 */

/**
 * A storage object for the state of the window.
 * @typedef {import('../verbs/window/window-state.js').windowState} WindowState
 */

/**
 * Retrieve an output value from a window operator.
 * @callback WindowValue
 * @param {WindowState} state The window state object.
 * @return {*} The output value.
 */

/**
 * Initialize an aggregate operator.
 * @typedef {import('./aggregate-functions.js').AggregateInit} AggregateInit
 */

/**
 * Retrive an output value from an aggregate operator.
 * @typedef {import('./aggregate-functions.js').AggregateValue} AggregateValue
 */

/**
 * An operator instance for a window function.
 * @typedef {object} WindowOperator
 * @property {AggregateInit} init Initialize the operator.
 * @property {AggregateValue} value Retrieve an output value.
 */

/**
 * Create a new window operator instance.
 * @callback WindowCreate
 * @param {...any} params The aggregate operator parameters.
 * @return {WindowOperator} The instantiated window operator.
 */

/**
 * Create a new aggregate operator instance.
 * @typedef {import('./aggregate-functions.js').AggregateCreate} AggregateCreate
 */

/**
 * An operator definition for a window function.
 * @typedef {object} WindowDef
 * @property {AggregateCreate} create Create a new operator instance.
 * @property {number[]} param Two-element array containing the
 *  counts of input fields and additional parameters.
 */

const rank = {
  create() {
    let rank;
    return {
      init: () => rank = 1,
      value: w => {
        const i = w.index;
        return (i && !w.peer(i)) ? (rank = i + 1) : rank;
      }
    };
  },
  param: []
};

const cume_dist = {
  create() {
    let cume;
    return {
      init: () => cume = 0,
      value: w => {
        const { index, peer, size } = w;
        let i = index;
        if (cume < i) {
          while (i + 1 < size && peer(i + 1)) ++i;
          cume = i;
        }
        return (1 + cume) / size;
      }
    };
  },
  param: []
};

/**
 * Window operator definitions.
 */
const window_functions_windowFunctions = {
  /** @type {WindowDef} */
  row_number: {
    create() {
      return {
        init: no_op_noop,
        value: w => w.index + 1
      };
    },
    param: []
  },

  /** @type {WindowDef} */
  rank,

  /** @type {WindowDef} */
  avg_rank: {
    create() {
      let j, rank;
      return {
        init: () => (j = -1, rank = 1),
        value: w => {
          const i = w.index;
          if (i >= j) {
            for (rank = j = i + 1; w.peer(j); rank += ++j);
            rank /= (j - i);
          }
          return rank;
        }
      };
    },
    param: []
  },

  /** @type {WindowDef} */
  dense_rank: {
    create() {
      let drank;
      return {
        init: () => drank = 1,
        value: w => {
          const i = w.index;
          return (i && !w.peer(i)) ? ++drank : drank;
        }
      };
    },
    param: []
  },

  /** @type {WindowDef} */
  percent_rank: {
    create() {
      const { init, value } = rank.create();
      return {
        init,
        value: w => (value(w) - 1) / (w.size - 1)
      };
    },
    param: []
  },

  /** @type {WindowDef} */
  cume_dist,

  /** @type {WindowDef} */
  ntile: {
    create(num) {
      num = +num;
      if (!(num > 0)) error_error('ntile num must be greater than zero.');
      const { init, value } = cume_dist.create();
      return {
        init,
        value: w => Math.ceil(num * value(w))
      };
    },
    param: [0, 1]
  },

  /** @type {WindowDef} */
  lag: {
    create(offset, defaultValue = NULL) {
      offset = +offset || 1;
      return {
        init: no_op_noop,
        value: (w, f) => {
          const i = w.index - offset;
          return i >= 0 ? w.value(i, f) : defaultValue;
        }
      };
    },
    param: [1, 2]
  },

  /** @type {WindowDef} */
  lead: {
    create(offset, defaultValue = NULL) {
      offset = +offset || 1;
      return {
        init: no_op_noop,
        value: (w, f) => {
          const i = w.index + offset;
          return i < w.size ? w.value(i, f) : defaultValue;
        }
      };
    },
    param: [1, 2]
  },

  /** @type {WindowDef} */
  first_value: {
    create() {
      return {
        init: no_op_noop,
        value: (w, f) => w.value(w.i0, f)
      };
    },
    param: [1]
  },

  /** @type {WindowDef} */
  last_value: {
    create() {
      return {
        init: no_op_noop,
        value: (w, f) => w.value(w.i1 - 1, f)
      };
    },
    param: [1]
  },

  /** @type {WindowDef} */
  nth_value: {
    create(nth) {
      nth = +nth;
      if (!(nth > 0)) error_error('nth_value nth must be greater than zero.');
      return {
        init: no_op_noop,
        value: (w, f) => {
          const i = w.i0 + (nth - 1);
          return i < w.i1 ? w.value(i, f) : NULL;
        }
      };
    },
    param: [1, 1]
  },

  /** @type {WindowDef} */
  fill_down: {
    create(defaultValue = NULL) {
      let value;
      return {
        init: () => value = defaultValue,
        value: (w, f) => {
          const v = w.value(w.index, f);
          return is_valid_isValid(v) ? (value = v) : value;
        }
      };
    },
    param: [1, 1]
  },

  /** @type {WindowDef} */
  fill_up: {
    create(defaultValue = NULL) {
      let value, idx;
      return {
        init: () => (value = defaultValue, idx = -1),
        value: (w, f) => w.index <= idx ? value
          : (idx = find(w, f, w.index)) >= 0 ? (value = w.value(idx, f))
          : (idx = w.size, value = defaultValue)
      };
    },
    param: [1, 1]
  }
};

function find(w, f, i) {
  for (const n = w.size; i < n; ++i) {
    if (is_valid_isValid(w.value(i, f))) return i;
  }
  return -1;
}

;// ../../node_modules/arquero/src/op/index.js








/**
 * Check if an aggregate function with the given name exists.
 * @param {string} name The name of the aggregate function.
 * @return {boolean} True if found, false otherwise.
 */
function hasAggregate(name) {
  return Object.hasOwn(aggregate_functions_aggregateFunctions, name);
}

/**
 * Check if a window function with the given name exists.
 * @param {string} name The name of the window function.
 * @return {boolean} True if found, false otherwise.
 */
function hasWindow(name) {
  return Object.hasOwn(window_functions_windowFunctions, name);
}

/**
 * Check if an expression function with the given name exists.
 * @param {string} name The name of the function.
 * @return {boolean} True if found, false otherwise.
 */
 function hasFunction(name) {
  return Object.hasOwn(functions_functions, name) || name === 'row_object';
}

/**
 * Get an aggregate function definition.
 * @param {string} name The name of the aggregate function.
 * @return {import('./aggregate-functions.js').AggregateDef}
 *  The aggregate function definition, or undefined if not found.
 */
function getAggregate(name) {
  return hasAggregate(name) && aggregate_functions_aggregateFunctions[name];
}

/**
 * Get a window function definition.
 * @param {string} name The name of the window function.
 * @return {import('./window-functions.js').WindowDef}
 *  The window function definition, or undefined if not found.
 */
function getWindow(name) {
  return hasWindow(name) && window_functions_windowFunctions[name];
}

/**
 * Get an expression function definition.
 * @param {string} name The name of the function.
 * @return {Function} The function instance, or undefined if not found.
 */
function getFunction(name) {
  return hasFunction(name) && functions[name];
}

;// ../../node_modules/arquero/src/util/concat.js
// eslint-disable-next-line no-unused-vars
function concat_concat(list, fn = ((x, i) => x), delim = '') {
  const n = list.length;
  if (!n) return '';

  let s = fn(list[0], 0);
  for (let i = 1; i < n; ++i) {
    s += delim + fn(list[i], i);
  }

  return s;
}

;// ../../node_modules/arquero/src/util/unroll.js
function unroll(args, code, ...lists) {
  const v = ['_', '$'];
  const a = v.slice(0, lists.length);
  a.push('"use strict"; const '
    + lists
        .map((l, j) => l.map((_, i) => `${v[j]}${i} = ${v[j]}[${i}]`).join(', '))
        .join(', ')
    + `; return (${args}) => ${code};`
  );
  return Function(...a)(...lists);
}

;// ../../node_modules/arquero/src/util/ascending.js
function ascending(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

;// ../../node_modules/arquero/src/util/max.js


function max(values, start = 0, stop = values.length) {
  let max = stop ? values[start++] : NULL;

  for (let i = start; i < stop; ++i) {
    if (max < values[i]) {
      max = values[i];
    }
  }

  return max;
}

;// ../../node_modules/arquero/src/util/min.js


function min(values, start = 0, stop = values.length) {
  let min = stop ? values[start++] : NULL;

  for (let i = start; i < stop; ++i) {
    if (min > values[i]) {
      min = values[i];
    }
  }

  return min;
}

;// ../../node_modules/arquero/src/util/to-numeric.js


function toNumeric(value) {
  return isBigInt(value) ? value : +value;
}

;// ../../node_modules/arquero/src/util/quantile.js




function quantile(values, p) {
  const n = values.length;

  if (!n) return NULL;
  if ((p = +p) <= 0 || n < 2) return toNumeric(values[0]);
  if (p >= 1) return toNumeric(values[n - 1]);

  const i = (n - 1) * p;
  const i0 = Math.floor(i);
  const v0 = toNumeric(values[i0]);
  return isBigInt(v0)
    ? v0
    // @ts-ignore
    : v0 + (toNumeric(values[i0 + 1]) - v0) * (i - i0);
}

;// ../../node_modules/arquero/src/util/value-list.js





class ValueList {
  constructor(values) {
    this._values = values || [];
    this._sorted = null;
    this._start = 0;
  }

  values(copy) {
    if (this._start) {
      this._values = this._values.slice(this._start);
      this._start = 0;
    }
    return copy
      ? this._values.slice()
      : this._values;
  }

  add(value) {
    this._values.push(value);
    this._sorted = null;
  }

  rem() {
    this._start += 1;
    this._sorted = null;
  }

  min() {
    return this._sorted && this._sorted.length
      ? this._sorted[0]
      : min(this._values, this._start);
  }

  max() {
    return this._sorted && this._sorted.length
      ? this._sorted[this._sorted.length - 1]
      : max(this._values, this._start);
  }

  quantile(p) {
    if (!this._sorted) {
      this._sorted = this.values(true);
      this._sorted.sort(ascending);
    }
    return quantile(this._sorted, p);
  }
}

;// ../../node_modules/arquero/src/verbs/reduce/reducer.js
/**
 * Abstract class for custom aggregation operations.
 */
class Reducer {
  constructor(outputs) {
    this._outputs = outputs;
  }

  size() {
    return this._outputs.length;
  }

  outputs() {
    return this._outputs;
  }

  // eslint-disable-next-line no-unused-vars
  init(columns) {
    return {};
  }

  // eslint-disable-next-line no-unused-vars
  add(state, row, data) {
    // no-op, subclasses should override
  }

  // eslint-disable-next-line no-unused-vars
  rem(state, row, data) {
    // no-op, subclasses should override
  }

  // eslint-disable-next-line no-unused-vars
  write(state, values, index) {
  }
}

;// ../../node_modules/arquero/src/verbs/reduce/field-reducer.js








const field_reducer_update = (ops, args, fn) => unroll(
  args,
  '{' + concat_concat(ops, (_, i) => `_${i}.${fn}(${args});`) + '}',
  ops
);

function fieldReducer(oplist, stream) {
  const { ops, output } = expand(oplist, stream);
  const fields = oplist[0].fields;
  const n = fields.length;
  const cls = n === 0 ? FieldReducer
    : n === 1 ? Field1Reducer
    : n === 2 ? Field2Reducer
    : error_error('Unsupported field count: ' + n);
  // @ts-ignore
  return new cls(fields, ops, output, stream);
}

function expand(oplist, stream) {
  const has = {};
  const ops = [];

  function add(name, params = []) {
    // check key
    const key = name + ':' + params;
    if (has[key]) return has[key];

    // get op instance
    const def = getAggregate(name);
    const op = def.create(...params);

    // add required dependencies
    if (stream < 0 && def.stream) {
      def.stream.forEach(name => add(name, []));
    }
    if (def.req) {
      def.req.forEach(name => add(name, []));
    }

    // update state
    has[key] = op;
    ops.push(op);

    return op;
  }

  const output = oplist.map(item => {
    const op = add(item.name, item.params);
    op.output = item.id;
    return op;
  });

  return { ops, output };
}

class FieldReducer extends Reducer {
  constructor(fields, ops, outputs, stream) {
    super(outputs);
    this._op = ops;
    this._fields = fields;
    this._stream = !!stream;
  }

  init() {
    const state = { count: 0, valid: 0, stream: this._stream };
    this._op.forEach(op => op.init(state));

    // value list requested
    if (state.values) {
      state.list = new ValueList();
    }

    return state;
  }

  write(state, values, index) {
    const op = this._outputs;
    const n = op.length;
    for (let i = 0; i < n; ++i) {
      values[op[i].output][index] = op[i].value(state);
    }
    return 1;
  }

  _add() {
  }

  _rem() {
  }

  add(state) {
    ++state.count;
  }

  rem(state) {
    --state.count;
  }
}

class Field1Reducer extends FieldReducer {
  constructor(fields, ops, outputs, stream) {
    super(fields, ops, outputs, stream);

    // unroll op invocations for performance
    const args = ['state', 'v1', 'v2'];
    this._add = field_reducer_update(ops, args, 'add');
    this._rem = field_reducer_update(ops, args, 'rem');
  }

  add(state, row, data) {
    const value = this._fields[0](row, data);
    ++state.count;
    if (is_valid_isValid(value)) {
      ++state.valid;
      if (state.list) state.list.add(value);
      this._add(state, value);
    }
  }

  rem(state, row, data) {
    const value = this._fields[0](row, data);
    --state.count;
    if (is_valid_isValid(value)) {
      --state.valid;
      if (state.list) state.list.rem();
      this._rem(state, value);
    }
  }
}

class Field2Reducer extends FieldReducer {
  constructor(fields, ops, outputs, stream) {
    super(fields, ops, outputs, stream);

    // unroll op invocations for performance
    const args = ['state', 'v1', 'v2'];
    this._add = field_reducer_update(ops, args, 'add');
    this._rem = field_reducer_update(ops, args, 'rem');
  }

  add(state, row, data) {
    const value1 = this._fields[0](row, data);
    const value2 = this._fields[1](row, data);
    ++state.count;
    if (is_valid_isValid(value1) && is_valid_isValid(value2)) {
      ++state.valid;
      if (state.list) state.list.add([value1, value2]);
      this._add(state, value1, value2);
    }
  }

  rem(state, row, data) {
    const value1 = this._fields[0](row, data);
    const value2 = this._fields[1](row, data);
    --state.count;
    if (is_valid_isValid(value1) && is_valid_isValid(value2)) {
      --state.valid;
      if (state.list) state.list.rem();
      this._rem(state, value1, value2);
    }
  }
}

;// ../../node_modules/arquero/src/verbs/reduce/util.js



function aggregateGet(table, ops, get) {
  if (ops.length) {
    const data = table.data();
    const { keys } = table.groups() || {};
    const result = aggregate(table, ops);
    const op = keys
      ? (name, row) => result[name][keys[row]]
      : name => result[name][0];
    get = get.map(f => row => f(row, data, op));
  }

  return get;
}

function aggregate(table, ops, result) {
  if (!ops.length) return result; // early exit

  // instantiate aggregators and result store
  const aggrs = reducers(ops);
  const groups = table.groups();
  const size = groups ? groups.size : 1;
  result = result || repeat_repeat(ops.length, () => Array(size));

  // compute aggregates, extract results
  if (size > 1) {
    aggrs.forEach(aggr => {
      const cells = reduceGroups(table, aggr, groups);
      for (let i = 0; i < size; ++i) {
        aggr.write(cells[i], result, i);
      }
    });
  } else {
    aggrs.forEach(aggr => {
      const cell = reduceFlat(table, aggr);
      aggr.write(cell, result, 0);
    });
  }

  return result;
}

function reducers(ops, stream) {
  const aggrs = [];
  const fields = {};

  // group operators by field inputs
  for (const op of ops) {
    const key = op.fields.map(f => f + '').join(',');
    (fields[key] || (fields[key] = [])).push(op);
  }

  // generate a field reducer for each field
  for (const key in fields) {
    aggrs.push(fieldReducer(fields[key], stream));
  }

  return aggrs;
}

function reduceFlat(table, reducer) {
  // initialize aggregation cell
  const cell = reducer.init();

  // compute aggregate values
  // inline the following for performance:
  // table.scan((row, data) => reducer.add(cell, row, data));
  const data = table.data();
  const bits = table.mask();

  if (table.isOrdered()) {
    const idx = table.indices();
    const m = idx.length;
    for (let i = 0; i < m; ++i) {
      reducer.add(cell, idx[i], data);
    }
  } else if (bits) {
    for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
      reducer.add(cell, i, data);
    }
  } else {
    const n = table.totalRows();
    for (let i = 0; i < n; ++i) {
      reducer.add(cell, i, data);
    }
  }

  return cell;
}

function reduceGroups(table, reducer, groups) {
  const { keys, size } = groups;

  // initialize aggregation cells
  const cells = repeat_repeat(size, () => reducer.init());

  // compute aggregate values
  // inline the following for performance:
  // table.scan((row, data) => reducer.add(cells[keys[row]], row, data));
  const data = table.data();

  if (table.isOrdered()) {
    const idx = table.indices();
    const m = idx.length;
    for (let i = 0; i < m; ++i) {
      const row = idx[i];
      reducer.add(cells[keys[row]], row, data);
    }
  } else if (table.isFiltered()) {
    const bits = table.mask();
    for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
      reducer.add(cells[keys[i]], i, data);
    }
  } else {
    const n = table.totalRows();
    for (let i = 0; i < n; ++i) {
      reducer.add(cells[keys[i]], i, data);
    }
  }

  return cells;
}

function groupOutput(cols, groups) {
  const { get, names, rows, size } = groups;

  // write group values to output columns
  const m = names.length;
  for (let j = 0; j < m; ++j) {
    const col = cols.add(names[j], Array(size));
    const val = get[j];
    for (let i = 0; i < size; ++i) {
      col[i] = val(rows[i]);
    }
  }
}

;// ../../node_modules/arquero/src/util/entries.js



function entries_entries(value) {
  return is_array_isArray(value) ? value
    : isMap(value) ? value.entries()
    : value ? Object.entries(value)
    : [];
}

;// ../../node_modules/arquero/src/expression/ast/constants.js
const ArrayPattern = 'ArrayPattern';
const ArrowFunctionExpression = 'ArrowFunctionExpression';
const FunctionExpression = 'FunctionExpression';
const Identifier = 'Identifier';
const Literal = 'Literal';
const MemberExpression = 'MemberExpression';
const ObjectExpression = 'ObjectExpression';
const ObjectPattern = 'ObjectPattern';
const Property = 'Property';

const Column = 'Column';
const Constant = 'Constant';
const Dictionary = 'Dictionary';
const constants_Function = 'Function';
const Parameter = 'Parameter';
const constants_Op = 'Op';

;// ../../node_modules/arquero/src/expression/ast/walk.js
function walk(node, ctx, visitors, parent) {
  const visit = visitors[node.type] || visitors['Default'];
  if (visit && visit(node, ctx, parent) === false) return;

  const walker = walkers[node.type];
  if (walker) walker(node, ctx, visitors);
}

const unary = (node, ctx, visitors) => {
  walk(node.argument, ctx, visitors, node);
};

const binary = (node, ctx, visitors) => {
  walk(node.left, ctx, visitors, node);
  walk(node.right, ctx, visitors, node);
};

const ternary = (node, ctx, visitors) => {
  walk(node.test, ctx, visitors, node);
  walk(node.consequent, ctx, visitors, node);
  if (node.alternate) walk(node.alternate, ctx, visitors, node);
};

const func = (node, ctx, visitors) => {
  list(node.params, ctx, visitors, node);
  walk(node.body, ctx, visitors, node);
};

const call = (node, ctx, visitors) => {
  walk(node.callee, ctx, visitors, node);
  list(node.arguments, ctx, visitors, node);
};

const list = (nodes, ctx, visitors, node) => {
  nodes.forEach(item => walk(item, ctx, visitors, node));
};

const walkers = {
  TemplateLiteral: (node, ctx, visitors) => {
    list(node.expressions, ctx, visitors, node);
    list(node.quasis, ctx, visitors, node);
  },
  MemberExpression: (node, ctx, visitors) => {
    walk(node.object, ctx, visitors, node);
    walk(node.property, ctx, visitors, node);
  },
  CallExpression: call,
  NewExpression: call,
  ArrayExpression: (node, ctx, visitors) => {
    list(node.elements, ctx, visitors, node);
  },
  AssignmentExpression: binary,
  AwaitExpression: unary,
  BinaryExpression: binary,
  LogicalExpression: binary,
  UnaryExpression: unary,
  UpdateExpression: unary,
  ConditionalExpression: ternary,
  ObjectExpression: (node, ctx, visitors) => {
    list(node.properties, ctx, visitors, node);
  },
  Property: (node, ctx, visitors) => {
    walk(node.key, ctx, visitors, node);
    walk(node.value, ctx, visitors, node);
  },

  ArrowFunctionExpression: func,
  FunctionExpression: func,
  FunctionDeclaration: func,

  VariableDeclaration: (node, ctx, visitors) => {
    list(node.declarations, ctx, visitors, node);
  },
  VariableDeclarator: (node, ctx, visitors) => {
    walk(node.id, ctx, visitors, node);
    walk(node.init, ctx, visitors, node);
  },
  SpreadElement: (node, ctx, visitors) => {
    walk(node.argument, ctx, visitors, node);
  },

  BlockStatement: (node, ctx, visitors) => {
    list(node.body, ctx, visitors, node);
  },
  ExpressionStatement: (node, ctx, visitors) => {
    walk(node.expression, ctx, visitors, node);
  },
  IfStatement: ternary,
  ForStatement: (node, ctx, visitors) => {
    walk(node.init, ctx, visitors, node);
    walk(node.test, ctx, visitors, node);
    walk(node.update, ctx, visitors, node);
    walk(node.body, ctx, visitors, node);
  },
  WhileStatement: (node, ctx, visitors) => {
    walk(node.test, ctx, visitors, node);
    walk(node.body, ctx, visitors, node);
  },
  DoWhileStatement: (node, ctx, visitors) => {
    walk(node.body, ctx, visitors, node);
    walk(node.test, ctx, visitors, node);
  },
  SwitchStatement: (node, ctx, visitors) => {
    walk(node.discriminant, ctx, visitors, node);
    list(node.cases, ctx, visitors, node);
  },
  SwitchCase: (node, ctx, visitors) => {
    if (node.test) walk(node.test, ctx, visitors, node);
    list(node.consequent, ctx, visitors, node);
  },
  ReturnStatement: unary,

  Program: (node, ctx, visitors) => {
    walk(node.body[0], ctx, visitors, node);
  }
};

;// ../../node_modules/arquero/src/expression/ast/clean.js


function strip(node) {
  delete node.start;
  delete node.end;
  delete node.optional;
}

function stripMember(node) {
  strip(node);
  delete node.object;
  delete node.property;
  delete node.computed;
  if (!node.table) delete node.table;
}

function clean(ast) {
  walk(ast, null, {
    Column: stripMember,
    Constant: stripMember,
    Default: strip
  });
  return ast;
}

;// ../../node_modules/arquero/src/expression/ast/util.js


function is(type, node) {
  return node && node.type === type;
}

function isFunctionExpression(node) {
  return is(FunctionExpression, node)
    || is(ArrowFunctionExpression, node);
}

;// ../../node_modules/arquero/src/expression/codegen.js



const visit = (node, opt) => {
  const f = visitors[node.type];
  return f
    ? f(node, opt)
    : error_error(`Unsupported expression construct: ${node.type}`);
};

const codegen_binary = (node, opt) => {
  return '(' + visit(node.left, opt) + ' ' + node.operator + ' ' + visit(node.right, opt) + ')';
};

const codegen_func = (node, opt) => {
  return '(' + codegen_list(node.params, opt) + ')=>' + visit(node.body, opt);
};

const codegen_call = (node, opt) => {
  return visit(node.callee, opt) + '(' + codegen_list(node.arguments, opt) + ')';
};

const codegen_list = (array, opt, delim = ',') => {
  return array.map(node => visit(node, opt)).join(delim);
};

const codegen_name = node => node.computed
  ? `[${to_string_toString(node.name)}]`
  : `.${node.name}`;

const ref = (node, opt, method) => {
  const table = node.table || '';
  return `data${table}${codegen_name(node)}.${method}(${opt.index}${table})`;
};

const get = (node, opt) => {
  const table = node.table || '';
  return `data${table}${codegen_name(node)}[${opt.index}${table}]`;
};

const visitors = {
  Constant: node => node.raw,
  Column: (node, opt) => node.array ? get(node, opt) : ref(node, opt, 'at'),
  Dictionary: (node, opt) => ref(node, opt, 'key'),
  Function: node => `fn.${node.name}`,
  Parameter: node => `$${codegen_name(node)}`,
  Op: (node, opt) => `op(${to_string_toString(node.name)},${opt.op || opt.index})`,
  Literal: node => node.raw,
  Identifier: node => node.name,
  TemplateLiteral: (node, opt) => {
    const { quasis, expressions } = node;
    const n = expressions.length;
    let t = quasis[0].value.raw;
    for (let i = 0; i < n;) {
      t += '${' + visit(expressions[i], opt) + '}' + quasis[++i].value.raw;
    }
    return '`' + t + '`';
  },
  MemberExpression: (node, opt) => {
    const d = !node.computed;
    const o = visit(node.object, opt);
    const p = visit(node.property, opt);
    return o + (d ? '.' + p : '[' + p + ']');
  },
  CallExpression: codegen_call,
  NewExpression: (node, opt) => {
    return 'new ' + codegen_call(node, opt);
  },
  ArrayExpression: (node, opt) => {
    return '[' + codegen_list(node.elements, opt) + ']';
  },
  AssignmentExpression: codegen_binary,
  BinaryExpression: codegen_binary,
  LogicalExpression: codegen_binary,
  UnaryExpression: (node, opt) => {
    return '(' + node.operator + visit(node.argument, opt) + ')';
  },
  ConditionalExpression: (node, opt) => {
    return '(' + visit(node.test, opt) +
      '?' + visit(node.consequent, opt) +
      ':' + visit(node.alternate, opt) + ')';
  },
  ObjectExpression: (node, opt) => {
    return '({' + codegen_list(node.properties, opt) + '})';
  },
  Property: (node, opt) => {
    const key = visit(node.key, opt);
    return (node.computed ? `[${key}]` : key) + ':' + visit(node.value, opt);
  },

  ArrowFunctionExpression: codegen_func,
  FunctionExpression: codegen_func,
  FunctionDeclaration: codegen_func,

  ArrayPattern: (node, opt) => {
    return '[' + codegen_list(node.elements, opt) + ']';
  },
  ObjectPattern: (node, opt) => {
    return '{' + codegen_list(node.properties, opt) + '}';
  },
  VariableDeclaration: (node, opt) => {
    return node.kind + ' ' + codegen_list(node.declarations, opt, ',');
  },
  VariableDeclarator: (node, opt) => {
    return visit(node.id, opt) + '=' + visit(node.init, opt);
  },
  SpreadElement: (node, opt) => {
    return '...' + visit(node.argument, opt);
  },

  BlockStatement: (node, opt) => {
    return '{' + codegen_list(node.body, opt, ';') + ';}';
  },
  BreakStatement: () => {
    return 'break';
  },
  ExpressionStatement: (node, opt) => {
    return visit(node.expression, opt);
  },
  IfStatement: (node, opt) => {
    return 'if (' + visit(node.test, opt) + ')'
      + visit(node.consequent, opt)
      + (node.alternate ? ' else ' + visit(node.alternate, opt) : '');
  },
  SwitchStatement: (node, opt) => {
    return 'switch (' + visit(node.discriminant, opt) + ') {'
     + codegen_list(node.cases, opt, '')
     + '}';
  },
  SwitchCase: (node, opt) => {
    return (node.test ? 'case ' + visit(node.test, opt) : 'default')
      + ': '
      + codegen_list(node.consequent, opt, ';') + ';';
  },
  ReturnStatement: (node, opt) => {
    return 'return ' + visit(node.argument, opt);
  },
  Program: (node, opt) => visit(node.body[0], opt)
};

function codegen(node, opt = { index: 'row' }) {
  return visit(node, opt);
}

;// ../../node_modules/arquero/src/expression/compile.js


function _compile(code, fn, params) {
  code = `"use strict"; return ${code};`;
  return (Function('fn', '$', code))(fn, params);
}

const compile = {
  escape: (code, func, params) => _compile(code, func, params),
  expr:   (code, params) => _compile(`(row,data,op)=>${code}`, functions_functions, params),
  expr2:  (code, params) => _compile(`(row0,data0,row,data)=>${code}`, functions_functions, params),
  join:   (code, params) => _compile(`(row1,data1,row2,data2)=>${code}`, functions_functions, params),
  param:  (code, params) => _compile(code, functions_functions, params)
};

;// ../../node_modules/arquero/src/expression/rewrite.js




const dictOps = {
  '==': 1,
  '!=': 1,
  '===': 1,
  '!==': 1
};

/**
 * Rewrite AST node to be a table column reference.
 * Additionally optimizes dictionary column operations.
 * @param {object} ref AST node to rewrite to a column reference.
 * @param {string} name The name of the column.
 * @param {number} [index] The table index of the column.
 * @param {object} [col] The actual table column instance.
 * @param {object} [op] Parent AST node operating on the column reference.
 */
function rewrite(ref, name, index = 0, col = undefined, op = undefined) {
  ref.type = Column;
  ref.name = name;
  ref.table = index;

  // annotate arrays as such for optimized access
  if (isArrayType(col)) {
    ref.array = true;
  }

  // proceed only if has parent op and is a dictionary column
  if (op && col && is_function_isFunction(col.keyFor)) {
    // get other arg if op is an optimizeable operation
    const lit = dictOps[op.operator]
      ? op.left === ref ? op.right : op.left
      : op.callee && op.callee.name === 'equal'
      ? op.arguments[op.arguments[0] === ref ? 1 : 0]
      : null;

    // rewrite as dictionary lookup if other arg is a literal
    if (lit && lit.type === Literal) {
      rewriteDictionary(op, ref, lit, col.keyFor(lit.value));
    }
  }

  return ref;
}

function rewriteDictionary(op, ref, lit, key) {
  if (key < 0) {
    // value not in dictionary, rewrite op as false literal
    op.type = Literal;
    op.value = false;
    op.raw = 'false';
  } else {
    // rewrite ref as dict key access
    ref.type = Dictionary;

    // rewrite literal as target dict key
    lit.value = key;
    lit.raw = key + '';
  }

  return true;
}

;// ../../node_modules/arquero/src/expression/row-object.js








const row_object_ROW_OBJECT = 'row_object';

function rowObjectExpression(
  node,
  table,
  props = table.columnNames())
{
  node.type = ObjectExpression;

  const p = node.properties = [];
  for (const prop of entries_entries(props)) {
    const [name, key] = is_array_isArray(prop) ? prop : [prop, prop];
    p.push({
      type: Property,
      key: { type: Literal, raw: to_string_toString(key) },
      value: rewrite({ computed: true }, name, 0, table.column(name))
    });
  }

  return node;
}

function rowObjectCode(table, props) {
  return codegen(rowObjectExpression({}, table, props));
}

function rowObjectBuilder(table, props) {
  return compile.expr(rowObjectCode(table, props));
}

;// ../../node_modules/arquero/src/util/to-function.js


function toFunction(value) {
  return is_function_isFunction(value) ? value : () => value;
}

;// ../../node_modules/arquero/src/expression/parse-escape.js





const ERROR_ESC_AGGRONLY = 'Escaped functions are not valid as rollup or pivot values.';

function parseEscape(ctx, spec, params) {
  if (ctx.aggronly) error_error(ERROR_ESC_AGGRONLY);

  // generate escaped function invocation code
  const code = `(row,data)=>fn(${rowObjectCode(ctx.table)},$)`;

  return { escape: compile.escape(code, toFunction(spec.expr), params) };
}

;// ../../node_modules/acorn/dist/acorn.mjs
// This file was generated. Do not modify manually!
var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 80, 3, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 343, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 726, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];

// This file was generated. Do not modify manually!
var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 2, 60, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 42, 9, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 496, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191];

// This file was generated. Do not modify manually!
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65";

// This file was generated. Do not modify manually!
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";

// These are a run-length and offset encoded representation of the
// >0xffff code points that are a valid part of identifiers. The
// offset starts at 0x10000, and each pair of numbers represents an
// offset to the next range, and then a size of the range.

// Reserved word lists for various dialects of the language

var reservedWords = {
  3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
  5: "class enum extends super const export import",
  6: "enum",
  strict: "implements interface let package private protected public static yield",
  strictBind: "eval arguments"
};

// And the keywords

var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";

var keywords$1 = {
  5: ecma5AndLessKeywords,
  "5module": ecma5AndLessKeywords + " export import",
  6: ecma5AndLessKeywords + " const class extends export import super"
};

var keywordRelationalOperator = /^in(stanceof)?$/;

// ## Character categories

var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");

// This has a complexity linear to the value of the code. The
// assumption is that looking up astral identifier characters is
// rare.
function isInAstralSet(code, set) {
  var pos = 0x10000;
  for (var i = 0; i < set.length; i += 2) {
    pos += set[i];
    if (pos > code) { return false }
    pos += set[i + 1];
    if (pos >= code) { return true }
  }
  return false
}

// Test whether a given character code starts an identifier.

function isIdentifierStart(code, astral) {
  if (code < 65) { return code === 36 }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes)
}

// Test whether a given character is part of an identifier.

function isIdentifierChar(code, astral) {
  if (code < 48) { return code === 36 }
  if (code < 58) { return true }
  if (code < 65) { return false }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
}

// ## Token types

// The assignment of fine-grained, information-carrying type objects
// allows the tokenizer to store the information it has about a
// token in a way that is very cheap for the parser to look up.

// All token type variables start with an underscore, to make them
// easy to recognize.

// The `beforeExpr` property is used to disambiguate between regular
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// The `startsExpr` property is used to check if the token ends a
// `yield` expression. It is set on all token types that either can
// directly start an expression (like a quotation mark) or can
// continue an expression (like the body of a string).
//
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.

var TokenType = function TokenType(label, conf) {
  if ( conf === void 0 ) conf = {};

  this.label = label;
  this.keyword = conf.keyword;
  this.beforeExpr = !!conf.beforeExpr;
  this.startsExpr = !!conf.startsExpr;
  this.isLoop = !!conf.isLoop;
  this.isAssign = !!conf.isAssign;
  this.prefix = !!conf.prefix;
  this.postfix = !!conf.postfix;
  this.binop = conf.binop || null;
  this.updateContext = null;
};

function binop(name, prec) {
  return new TokenType(name, {beforeExpr: true, binop: prec})
}
var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};

// Map keyword names to token types.

var keywords = {};

// Succinct definitions of keyword token types
function kw(name, options) {
  if ( options === void 0 ) options = {};

  options.keyword = name;
  return keywords[name] = new TokenType(name, options)
}

var types$1 = {
  num: new TokenType("num", startsExpr),
  regexp: new TokenType("regexp", startsExpr),
  string: new TokenType("string", startsExpr),
  name: new TokenType("name", startsExpr),
  privateId: new TokenType("privateId", startsExpr),
  eof: new TokenType("eof"),

  // Punctuation token types.
  bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
  bracketR: new TokenType("]"),
  braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
  braceR: new TokenType("}"),
  parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
  parenR: new TokenType(")"),
  comma: new TokenType(",", beforeExpr),
  semi: new TokenType(";", beforeExpr),
  colon: new TokenType(":", beforeExpr),
  dot: new TokenType("."),
  question: new TokenType("?", beforeExpr),
  questionDot: new TokenType("?."),
  arrow: new TokenType("=>", beforeExpr),
  template: new TokenType("template"),
  invalidTemplate: new TokenType("invalidTemplate"),
  ellipsis: new TokenType("...", beforeExpr),
  backQuote: new TokenType("`", startsExpr),
  dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),

  // Operators. These carry several kinds of properties to help the
  // parser use them properly (the presence of these properties is
  // what categorizes them as operators).
  //
  // `binop`, when present, specifies that this operator is a binary
  // operator, and will refer to its precedence.
  //
  // `prefix` and `postfix` mark the operator as a prefix or postfix
  // unary operator.
  //
  // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
  // binary operators with a very low precedence, that should result
  // in AssignmentExpression nodes.

  eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
  assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
  incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
  prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
  logicalOR: binop("||", 1),
  logicalAND: binop("&&", 2),
  bitwiseOR: binop("|", 3),
  bitwiseXOR: binop("^", 4),
  bitwiseAND: binop("&", 5),
  equality: binop("==/!=/===/!==", 6),
  relational: binop("</>/<=/>=", 7),
  bitShift: binop("<</>>/>>>", 8),
  plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
  modulo: binop("%", 10),
  star: binop("*", 10),
  slash: binop("/", 10),
  starstar: new TokenType("**", {beforeExpr: true}),
  coalesce: binop("??", 1),

  // Keyword token types.
  _break: kw("break"),
  _case: kw("case", beforeExpr),
  _catch: kw("catch"),
  _continue: kw("continue"),
  _debugger: kw("debugger"),
  _default: kw("default", beforeExpr),
  _do: kw("do", {isLoop: true, beforeExpr: true}),
  _else: kw("else", beforeExpr),
  _finally: kw("finally"),
  _for: kw("for", {isLoop: true}),
  _function: kw("function", startsExpr),
  _if: kw("if"),
  _return: kw("return", beforeExpr),
  _switch: kw("switch"),
  _throw: kw("throw", beforeExpr),
  _try: kw("try"),
  _var: kw("var"),
  _const: kw("const"),
  _while: kw("while", {isLoop: true}),
  _with: kw("with"),
  _new: kw("new", {beforeExpr: true, startsExpr: true}),
  _this: kw("this", startsExpr),
  _super: kw("super", startsExpr),
  _class: kw("class", startsExpr),
  _extends: kw("extends", beforeExpr),
  _export: kw("export"),
  _import: kw("import", startsExpr),
  _null: kw("null", startsExpr),
  _true: kw("true", startsExpr),
  _false: kw("false", startsExpr),
  _in: kw("in", {beforeExpr: true, binop: 7}),
  _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
  _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
  _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
  _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
};

// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

var lineBreak = /\r\n?|\n|\u2028|\u2029/;
var lineBreakG = new RegExp(lineBreak.source, "g");

function isNewLine(code) {
  return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
}

function nextLineBreak(code, from, end) {
  if ( end === void 0 ) end = code.length;

  for (var i = from; i < end; i++) {
    var next = code.charCodeAt(i);
    if (isNewLine(next))
      { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 }
  }
  return -1
}

var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;

var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;

var acorn_ref = Object.prototype;
var acorn_hasOwnProperty = acorn_ref.hasOwnProperty;
var acorn_toString = acorn_ref.toString;

var hasOwn = Object.hasOwn || (function (obj, propName) { return (
  acorn_hasOwnProperty.call(obj, propName)
); });

var acorn_isArray = Array.isArray || (function (obj) { return (
  acorn_toString.call(obj) === "[object Array]"
); });

var regexpCache = Object.create(null);

function wordsRegexp(words) {
  return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$"))
}

function codePointToString(code) {
  // UTF-16 Decoding
  if (code <= 0xFFFF) { return String.fromCharCode(code) }
  code -= 0x10000;
  return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
}

var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/;

// These are used when `options.locations` is on, for the
// `startLoc` and `endLoc` properties.

var Position = function Position(line, col) {
  this.line = line;
  this.column = col;
};

Position.prototype.offset = function offset (n) {
  return new Position(this.line, this.column + n)
};

var SourceLocation = function SourceLocation(p, start, end) {
  this.start = start;
  this.end = end;
  if (p.sourceFile !== null) { this.source = p.sourceFile; }
};

// The `getLineInfo` function is mostly useful when the
// `locations` option is off (for performance reasons) and you
// want to find the line/column position for a given character
// offset. `input` should be the code string that the offset refers
// into.

function getLineInfo(input, offset) {
  for (var line = 1, cur = 0;;) {
    var nextBreak = nextLineBreak(input, cur, offset);
    if (nextBreak < 0) { return new Position(line, offset - cur) }
    ++line;
    cur = nextBreak;
  }
}

// A second argument must be given to configure the parser process.
// These options are recognized (only `ecmaVersion` is required):

var defaultOptions = {
  // `ecmaVersion` indicates the ECMAScript version to parse. Must be
  // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10
  // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"`
  // (the latest version the library supports). This influences
  // support for strict mode, the set of reserved words, and support
  // for new syntax features.
  ecmaVersion: null,
  // `sourceType` indicates the mode the code should be parsed in.
  // Can be either `"script"` or `"module"`. This influences global
  // strict mode and parsing of `import` and `export` declarations.
  sourceType: "script",
  // `onInsertedSemicolon` can be a callback that will be called when
  // a semicolon is automatically inserted. It will be passed the
  // position of the inserted semicolon as an offset, and if
  // `locations` is enabled, it is given the location as a `{line,
  // column}` object as second argument.
  onInsertedSemicolon: null,
  // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
  // trailing commas.
  onTrailingComma: null,
  // By default, reserved words are only enforced if ecmaVersion >= 5.
  // Set `allowReserved` to a boolean value to explicitly turn this on
  // an off. When this option has the value "never", reserved words
  // and keywords can also not be used as property names.
  allowReserved: null,
  // When enabled, a return at the top level is not considered an
  // error.
  allowReturnOutsideFunction: false,
  // When enabled, import/export statements are not constrained to
  // appearing at the top of the program, and an import.meta expression
  // in a script isn't considered an error.
  allowImportExportEverywhere: false,
  // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022.
  // When enabled, await identifiers are allowed to appear at the top-level scope,
  // but they are still not allowed in non-async functions.
  allowAwaitOutsideFunction: null,
  // When enabled, super identifiers are not constrained to
  // appearing in methods and do not raise an error when they appear elsewhere.
  allowSuperOutsideMethod: null,
  // When enabled, hashbang directive in the beginning of file is
  // allowed and treated as a line comment. Enabled by default when
  // `ecmaVersion` >= 2023.
  allowHashBang: false,
  // By default, the parser will verify that private properties are
  // only used in places where they are valid and have been declared.
  // Set this to false to turn such checks off.
  checkPrivateFields: true,
  // When `locations` is on, `loc` properties holding objects with
  // `start` and `end` properties in `{line, column}` form (with
  // line being 1-based and column 0-based) will be attached to the
  // nodes.
  locations: false,
  // A function can be passed as `onToken` option, which will
  // cause Acorn to call that function with object in the same
  // format as tokens returned from `tokenizer().getToken()`. Note
  // that you are not allowed to call the parser from the
  // callback—that will corrupt its internal state.
  onToken: null,
  // A function can be passed as `onComment` option, which will
  // cause Acorn to call that function with `(block, text, start,
  // end)` parameters whenever a comment is skipped. `block` is a
  // boolean indicating whether this is a block (`/* */`) comment,
  // `text` is the content of the comment, and `start` and `end` are
  // character offsets that denote the start and end of the comment.
  // When the `locations` option is on, two more parameters are
  // passed, the full `{line, column}` locations of the start and
  // end of the comments. Note that you are not allowed to call the
  // parser from the callback—that will corrupt its internal state.
  // When this option has an array as value, objects representing the
  // comments are pushed to it.
  onComment: null,
  // Nodes have their start and end characters offsets recorded in
  // `start` and `end` properties (directly on the node, rather than
  // the `loc` object, which holds line/column data. To also add a
  // [semi-standardized][range] `range` property holding a `[start,
  // end]` array with the same numbers, set the `ranges` option to
  // `true`.
  //
  // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
  ranges: false,
  // It is possible to parse multiple files into a single AST by
  // passing the tree produced by parsing the first file as
  // `program` option in subsequent parses. This will add the
  // toplevel forms of the parsed file to the `Program` (top) node
  // of an existing parse tree.
  program: null,
  // When `locations` is on, you can pass this to record the source
  // file in every node's `loc` object.
  sourceFile: null,
  // This value, if given, is stored in every node, whether
  // `locations` is on or off.
  directSourceFile: null,
  // When enabled, parenthesized expressions are represented by
  // (non-standard) ParenthesizedExpression nodes
  preserveParens: false
};

// Interpret and default an options object

var warnedAboutEcmaVersion = false;

function getOptions(opts) {
  var options = {};

  for (var opt in defaultOptions)
    { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; }

  if (options.ecmaVersion === "latest") {
    options.ecmaVersion = 1e8;
  } else if (options.ecmaVersion == null) {
    if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
      warnedAboutEcmaVersion = true;
      console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.");
    }
    options.ecmaVersion = 11;
  } else if (options.ecmaVersion >= 2015) {
    options.ecmaVersion -= 2009;
  }

  if (options.allowReserved == null)
    { options.allowReserved = options.ecmaVersion < 5; }

  if (!opts || opts.allowHashBang == null)
    { options.allowHashBang = options.ecmaVersion >= 14; }

  if (acorn_isArray(options.onToken)) {
    var tokens = options.onToken;
    options.onToken = function (token) { return tokens.push(token); };
  }
  if (acorn_isArray(options.onComment))
    { options.onComment = pushComment(options, options.onComment); }

  return options
}

function pushComment(options, array) {
  return function(block, text, start, end, startLoc, endLoc) {
    var comment = {
      type: block ? "Block" : "Line",
      value: text,
      start: start,
      end: end
    };
    if (options.locations)
      { comment.loc = new SourceLocation(this, startLoc, endLoc); }
    if (options.ranges)
      { comment.range = [start, end]; }
    array.push(comment);
  }
}

// Each scope gets a bitset that may contain these flags
var
    SCOPE_TOP = 1,
    SCOPE_FUNCTION = 2,
    SCOPE_ASYNC = 4,
    SCOPE_GENERATOR = 8,
    SCOPE_ARROW = 16,
    SCOPE_SIMPLE_CATCH = 32,
    SCOPE_SUPER = 64,
    SCOPE_DIRECT_SUPER = 128,
    SCOPE_CLASS_STATIC_BLOCK = 256,
    SCOPE_CLASS_FIELD_INIT = 512,
    SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK;

function functionFlags(async, generator) {
  return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
}

// Used in checkLVal* and declareName to determine the type of a binding
var
    BIND_NONE = 0, // Not a binding
    BIND_VAR = 1, // Var-style binding
    BIND_LEXICAL = 2, // Let- or const-style binding
    BIND_FUNCTION = 3, // Function declaration
    BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
    BIND_OUTSIDE = 5; // Special case for function names as bound inside the function

var Parser = function Parser(options, input, startPos) {
  this.options = options = getOptions(options);
  this.sourceFile = options.sourceFile;
  this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
  var reserved = "";
  if (options.allowReserved !== true) {
    reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3];
    if (options.sourceType === "module") { reserved += " await"; }
  }
  this.reservedWords = wordsRegexp(reserved);
  var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
  this.reservedWordsStrict = wordsRegexp(reservedStrict);
  this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
  this.input = String(input);

  // Used to signal to callers of `readWord1` whether the word
  // contained any escape sequences. This is needed because words with
  // escape sequences must not be interpreted as keywords.
  this.containsEsc = false;

  // Set up token state

  // The current position of the tokenizer in the input.
  if (startPos) {
    this.pos = startPos;
    this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
    this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
  } else {
    this.pos = this.lineStart = 0;
    this.curLine = 1;
  }

  // Properties of the current token:
  // Its type
  this.type = types$1.eof;
  // For tokens that include more information than their type, the value
  this.value = null;
  // Its start and end offset
  this.start = this.end = this.pos;
  // And, if locations are used, the {line, column} object
  // corresponding to those offsets
  this.startLoc = this.endLoc = this.curPosition();

  // Position information for the previous token
  this.lastTokEndLoc = this.lastTokStartLoc = null;
  this.lastTokStart = this.lastTokEnd = this.pos;

  // The context stack is used to superficially track syntactic
  // context to predict whether a regular expression is allowed in a
  // given position.
  this.context = this.initialContext();
  this.exprAllowed = true;

  // Figure out if it's a module code.
  this.inModule = options.sourceType === "module";
  this.strict = this.inModule || this.strictDirective(this.pos);

  // Used to signify the start of a potential arrow function
  this.potentialArrowAt = -1;
  this.potentialArrowInForAwait = false;

  // Positions to delayed-check that yield/await does not exist in default parameters.
  this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
  // Labels in scope.
  this.labels = [];
  // Thus-far undefined exports.
  this.undefinedExports = Object.create(null);

  // If enabled, skip leading hashbang line.
  if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
    { this.skipLineComment(2); }

  // Scope tracking for duplicate variable names (see scope.js)
  this.scopeStack = [];
  this.enterScope(SCOPE_TOP);

  // For RegExp validation
  this.regexpState = null;

  // The stack of private names.
  // Each element has two properties: 'declared' and 'used'.
  // When it exited from the outermost class definition, all used private names must be declared.
  this.privateNameStack = [];
};

var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } };

Parser.prototype.parse = function parse () {
  var node = this.options.program || this.startNode();
  this.nextToken();
  return this.parseTopLevel(node)
};

prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };

prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };

prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };

prototypeAccessors.canAwait.get = function () {
  for (var i = this.scopeStack.length - 1; i >= 0; i--) {
    var ref = this.scopeStack[i];
      var flags = ref.flags;
    if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) { return false }
    if (flags & SCOPE_FUNCTION) { return (flags & SCOPE_ASYNC) > 0 }
  }
  return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction
};

prototypeAccessors.allowSuper.get = function () {
  var ref = this.currentThisScope();
    var flags = ref.flags;
  return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod
};

prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };

prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };

prototypeAccessors.allowNewDotTarget.get = function () {
  for (var i = this.scopeStack.length - 1; i >= 0; i--) {
    var ref = this.scopeStack[i];
      var flags = ref.flags;
    if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) ||
        ((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) { return true }
  }
  return false
};

prototypeAccessors.inClassStaticBlock.get = function () {
  return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0
};

Parser.extend = function extend () {
    var plugins = [], len = arguments.length;
    while ( len-- ) plugins[ len ] = arguments[ len ];

  var cls = this;
  for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
  return cls
};

Parser.parse = function parse (input, options) {
  return new this(options, input).parse()
};

Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
  var parser = new this(options, input, pos);
  parser.nextToken();
  return parser.parseExpression()
};

Parser.tokenizer = function tokenizer (input, options) {
  return new this(options, input)
};

Object.defineProperties( Parser.prototype, prototypeAccessors );

var pp$9 = Parser.prototype;

// ## Parser utilities

var literal = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/;
pp$9.strictDirective = function(start) {
  if (this.options.ecmaVersion < 5) { return false }
  for (;;) {
    // Try to find string literal.
    skipWhiteSpace.lastIndex = start;
    start += skipWhiteSpace.exec(this.input)[0].length;
    var match = literal.exec(this.input.slice(start));
    if (!match) { return false }
    if ((match[1] || match[2]) === "use strict") {
      skipWhiteSpace.lastIndex = start + match[0].length;
      var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length;
      var next = this.input.charAt(end);
      return next === ";" || next === "}" ||
        (lineBreak.test(spaceAfter[0]) &&
         !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
    }
    start += match[0].length;

    // Skip semicolon, if any.
    skipWhiteSpace.lastIndex = start;
    start += skipWhiteSpace.exec(this.input)[0].length;
    if (this.input[start] === ";")
      { start++; }
  }
};

// Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.

pp$9.eat = function(type) {
  if (this.type === type) {
    this.next();
    return true
  } else {
    return false
  }
};

// Tests whether parsed token is a contextual keyword.

pp$9.isContextual = function(name) {
  return this.type === types$1.name && this.value === name && !this.containsEsc
};

// Consumes contextual keyword if possible.

pp$9.eatContextual = function(name) {
  if (!this.isContextual(name)) { return false }
  this.next();
  return true
};

// Asserts that following token is given contextual keyword.

pp$9.expectContextual = function(name) {
  if (!this.eatContextual(name)) { this.unexpected(); }
};

// Test whether a semicolon can be inserted at the current position.

pp$9.canInsertSemicolon = function() {
  return this.type === types$1.eof ||
    this.type === types$1.braceR ||
    lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

pp$9.insertSemicolon = function() {
  if (this.canInsertSemicolon()) {
    if (this.options.onInsertedSemicolon)
      { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
    return true
  }
};

// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.

pp$9.semicolon = function() {
  if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); }
};

pp$9.afterTrailingComma = function(tokType, notNext) {
  if (this.type === tokType) {
    if (this.options.onTrailingComma)
      { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
    if (!notNext)
      { this.next(); }
    return true
  }
};

// Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.

pp$9.expect = function(type) {
  this.eat(type) || this.unexpected();
};

// Raise an unexpected token error.

pp$9.unexpected = function(pos) {
  this.raise(pos != null ? pos : this.start, "Unexpected token");
};

var DestructuringErrors = function DestructuringErrors() {
  this.shorthandAssign =
  this.trailingComma =
  this.parenthesizedAssign =
  this.parenthesizedBind =
  this.doubleProto =
    -1;
};

pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) {
  if (!refDestructuringErrors) { return }
  if (refDestructuringErrors.trailingComma > -1)
    { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
  var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
  if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); }
};

pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
  if (!refDestructuringErrors) { return false }
  var shorthandAssign = refDestructuringErrors.shorthandAssign;
  var doubleProto = refDestructuringErrors.doubleProto;
  if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
  if (shorthandAssign >= 0)
    { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
  if (doubleProto >= 0)
    { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
};

pp$9.checkYieldAwaitInDefaultParams = function() {
  if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
    { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
  if (this.awaitPos)
    { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
};

pp$9.isSimpleAssignTarget = function(expr) {
  if (expr.type === "ParenthesizedExpression")
    { return this.isSimpleAssignTarget(expr.expression) }
  return expr.type === "Identifier" || expr.type === "MemberExpression"
};

var pp$8 = Parser.prototype;

// ### Statement parsing

// Parse a program. Initializes the parser, reads any number of
// statements, and wraps them in a Program node.  Optionally takes a
// `program` argument.  If present, the statements will be appended
// to its body instead of creating a new node.

pp$8.parseTopLevel = function(node) {
  var exports = Object.create(null);
  if (!node.body) { node.body = []; }
  while (this.type !== types$1.eof) {
    var stmt = this.parseStatement(null, true, exports);
    node.body.push(stmt);
  }
  if (this.inModule)
    { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
      {
        var name = list[i];

        this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
      } }
  this.adaptDirectivePrologue(node.body);
  this.next();
  node.sourceType = this.options.sourceType;
  return this.finishNode(node, "Program")
};

var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};

pp$8.isLet = function(context) {
  if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
  skipWhiteSpace.lastIndex = this.pos;
  var skip = skipWhiteSpace.exec(this.input);
  var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
  // For ambiguous cases, determine if a LexicalDeclaration (or only a
  // Statement) is allowed here. If context is not empty then only a Statement
  // is allowed. However, `let [` is an explicit negative lookahead for
  // ExpressionStatement, so special-case it first.
  if (nextCh === 91 || nextCh === 92) { return true } // '[', '\'
  if (context) { return false }

  if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral
  if (isIdentifierStart(nextCh, true)) {
    var pos = next + 1;
    while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; }
    if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true }
    var ident = this.input.slice(next, pos);
    if (!keywordRelationalOperator.test(ident)) { return true }
  }
  return false
};

// check 'async [no LineTerminator here] function'
// - 'async /*foo*/ function' is OK.
// - 'async /*\n*/ function' is invalid.
pp$8.isAsyncFunction = function() {
  if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
    { return false }

  skipWhiteSpace.lastIndex = this.pos;
  var skip = skipWhiteSpace.exec(this.input);
  var next = this.pos + skip[0].length, after;
  return !lineBreak.test(this.input.slice(this.pos, next)) &&
    this.input.slice(next, next + 8) === "function" &&
    (next + 8 === this.input.length ||
     !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00))
};

// Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
// regular expression literal. This is to handle cases like
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.

pp$8.parseStatement = function(context, topLevel, exports) {
  var starttype = this.type, node = this.startNode(), kind;

  if (this.isLet(context)) {
    starttype = types$1._var;
    kind = "let";
  }

  // Most types of statements are recognized by the keyword they
  // start with. Many are trivial to parse, some require a bit of
  // complexity.

  switch (starttype) {
  case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
  case types$1._debugger: return this.parseDebuggerStatement(node)
  case types$1._do: return this.parseDoStatement(node)
  case types$1._for: return this.parseForStatement(node)
  case types$1._function:
    // Function as sole body of either an if statement or a labeled statement
    // works, but not when it is part of a labeled statement that is the sole
    // body of an if statement.
    if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
    return this.parseFunctionStatement(node, false, !context)
  case types$1._class:
    if (context) { this.unexpected(); }
    return this.parseClass(node, true)
  case types$1._if: return this.parseIfStatement(node)
  case types$1._return: return this.parseReturnStatement(node)
  case types$1._switch: return this.parseSwitchStatement(node)
  case types$1._throw: return this.parseThrowStatement(node)
  case types$1._try: return this.parseTryStatement(node)
  case types$1._const: case types$1._var:
    kind = kind || this.value;
    if (context && kind !== "var") { this.unexpected(); }
    return this.parseVarStatement(node, kind)
  case types$1._while: return this.parseWhileStatement(node)
  case types$1._with: return this.parseWithStatement(node)
  case types$1.braceL: return this.parseBlock(true, node)
  case types$1.semi: return this.parseEmptyStatement(node)
  case types$1._export:
  case types$1._import:
    if (this.options.ecmaVersion > 10 && starttype === types$1._import) {
      skipWhiteSpace.lastIndex = this.pos;
      var skip = skipWhiteSpace.exec(this.input);
      var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
      if (nextCh === 40 || nextCh === 46) // '(' or '.'
        { return this.parseExpressionStatement(node, this.parseExpression()) }
    }

    if (!this.options.allowImportExportEverywhere) {
      if (!topLevel)
        { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
      if (!this.inModule)
        { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
    }
    return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports)

    // If the statement does not start with a statement keyword or a
    // brace, it's an ExpressionStatement or LabeledStatement. We
    // simply start parsing an expression, and afterwards, if the
    // next token is a colon and the expression was a simple
    // Identifier node, we switch to interpreting it as a label.
  default:
    if (this.isAsyncFunction()) {
      if (context) { this.unexpected(); }
      this.next();
      return this.parseFunctionStatement(node, true, !context)
    }

    var maybeName = this.value, expr = this.parseExpression();
    if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon))
      { return this.parseLabeledStatement(node, maybeName, expr, context) }
    else { return this.parseExpressionStatement(node, expr) }
  }
};

pp$8.parseBreakContinueStatement = function(node, keyword) {
  var isBreak = keyword === "break";
  this.next();
  if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; }
  else if (this.type !== types$1.name) { this.unexpected(); }
  else {
    node.label = this.parseIdent();
    this.semicolon();
  }

  // Verify that there is an actual destination to break or
  // continue to.
  var i = 0;
  for (; i < this.labels.length; ++i) {
    var lab = this.labels[i];
    if (node.label == null || lab.name === node.label.name) {
      if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
      if (node.label && isBreak) { break }
    }
  }
  if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
  return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
};

pp$8.parseDebuggerStatement = function(node) {
  this.next();
  this.semicolon();
  return this.finishNode(node, "DebuggerStatement")
};

pp$8.parseDoStatement = function(node) {
  this.next();
  this.labels.push(loopLabel);
  node.body = this.parseStatement("do");
  this.labels.pop();
  this.expect(types$1._while);
  node.test = this.parseParenExpression();
  if (this.options.ecmaVersion >= 6)
    { this.eat(types$1.semi); }
  else
    { this.semicolon(); }
  return this.finishNode(node, "DoWhileStatement")
};

// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
// loop is non-trivial. Basically, we have to parse the init `var`
// statement or expression, disallowing the `in` operator (see
// the second parameter to `parseExpression`), and then check
// whether the next token is `in` or `of`. When there is no init
// part (semicolon immediately after the opening parenthesis), it
// is a regular `for` loop.

pp$8.parseForStatement = function(node) {
  this.next();
  var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1;
  this.labels.push(loopLabel);
  this.enterScope(0);
  this.expect(types$1.parenL);
  if (this.type === types$1.semi) {
    if (awaitAt > -1) { this.unexpected(awaitAt); }
    return this.parseFor(node, null)
  }
  var isLet = this.isLet();
  if (this.type === types$1._var || this.type === types$1._const || isLet) {
    var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
    this.next();
    this.parseVar(init$1, true, kind);
    this.finishNode(init$1, "VariableDeclaration");
    if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
      if (this.options.ecmaVersion >= 9) {
        if (this.type === types$1._in) {
          if (awaitAt > -1) { this.unexpected(awaitAt); }
        } else { node.await = awaitAt > -1; }
      }
      return this.parseForIn(node, init$1)
    }
    if (awaitAt > -1) { this.unexpected(awaitAt); }
    return this.parseFor(node, init$1)
  }
  var startsWithLet = this.isContextual("let"), isForOf = false;
  var containsEsc = this.containsEsc;
  var refDestructuringErrors = new DestructuringErrors;
  var initPos = this.start;
  var init = awaitAt > -1
    ? this.parseExprSubscripts(refDestructuringErrors, "await")
    : this.parseExpression(true, refDestructuringErrors);
  if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
    if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt)
      if (this.type === types$1._in) { this.unexpected(awaitAt); }
      node.await = true;
    } else if (isForOf && this.options.ecmaVersion >= 8) {
      if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); }
      else if (this.options.ecmaVersion >= 9) { node.await = false; }
    }
    if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); }
    this.toAssignable(init, false, refDestructuringErrors);
    this.checkLValPattern(init);
    return this.parseForIn(node, init)
  } else {
    this.checkExpressionErrors(refDestructuringErrors, true);
  }
  if (awaitAt > -1) { this.unexpected(awaitAt); }
  return this.parseFor(node, init)
};

pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) {
  this.next();
  return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
};

pp$8.parseIfStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  // allow function declarations in branches, but only in non-strict mode
  node.consequent = this.parseStatement("if");
  node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null;
  return this.finishNode(node, "IfStatement")
};

pp$8.parseReturnStatement = function(node) {
  if (!this.inFunction && !this.options.allowReturnOutsideFunction)
    { this.raise(this.start, "'return' outside of function"); }
  this.next();

  // In `return` (and `break`/`continue`), the keywords with
  // optional arguments, we eagerly look for a semicolon or the
  // possibility to insert one.

  if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; }
  else { node.argument = this.parseExpression(); this.semicolon(); }
  return this.finishNode(node, "ReturnStatement")
};

pp$8.parseSwitchStatement = function(node) {
  this.next();
  node.discriminant = this.parseParenExpression();
  node.cases = [];
  this.expect(types$1.braceL);
  this.labels.push(switchLabel);
  this.enterScope(0);

  // Statements under must be grouped (by label) in SwitchCase
  // nodes. `cur` is used to keep the node that we are currently
  // adding statements to.

  var cur;
  for (var sawDefault = false; this.type !== types$1.braceR;) {
    if (this.type === types$1._case || this.type === types$1._default) {
      var isCase = this.type === types$1._case;
      if (cur) { this.finishNode(cur, "SwitchCase"); }
      node.cases.push(cur = this.startNode());
      cur.consequent = [];
      this.next();
      if (isCase) {
        cur.test = this.parseExpression();
      } else {
        if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
        sawDefault = true;
        cur.test = null;
      }
      this.expect(types$1.colon);
    } else {
      if (!cur) { this.unexpected(); }
      cur.consequent.push(this.parseStatement(null));
    }
  }
  this.exitScope();
  if (cur) { this.finishNode(cur, "SwitchCase"); }
  this.next(); // Closing brace
  this.labels.pop();
  return this.finishNode(node, "SwitchStatement")
};

pp$8.parseThrowStatement = function(node) {
  this.next();
  if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
    { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
  node.argument = this.parseExpression();
  this.semicolon();
  return this.finishNode(node, "ThrowStatement")
};

// Reused empty array added for node fields that are always empty.

var empty$1 = [];

pp$8.parseCatchClauseParam = function() {
  var param = this.parseBindingAtom();
  var simple = param.type === "Identifier";
  this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
  this.checkLValPattern(param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
  this.expect(types$1.parenR);

  return param
};

pp$8.parseTryStatement = function(node) {
  this.next();
  node.block = this.parseBlock();
  node.handler = null;
  if (this.type === types$1._catch) {
    var clause = this.startNode();
    this.next();
    if (this.eat(types$1.parenL)) {
      clause.param = this.parseCatchClauseParam();
    } else {
      if (this.options.ecmaVersion < 10) { this.unexpected(); }
      clause.param = null;
      this.enterScope(0);
    }
    clause.body = this.parseBlock(false);
    this.exitScope();
    node.handler = this.finishNode(clause, "CatchClause");
  }
  node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null;
  if (!node.handler && !node.finalizer)
    { this.raise(node.start, "Missing catch or finally clause"); }
  return this.finishNode(node, "TryStatement")
};

pp$8.parseVarStatement = function(node, kind, allowMissingInitializer) {
  this.next();
  this.parseVar(node, false, kind, allowMissingInitializer);
  this.semicolon();
  return this.finishNode(node, "VariableDeclaration")
};

pp$8.parseWhileStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  this.labels.push(loopLabel);
  node.body = this.parseStatement("while");
  this.labels.pop();
  return this.finishNode(node, "WhileStatement")
};

pp$8.parseWithStatement = function(node) {
  if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
  this.next();
  node.object = this.parseParenExpression();
  node.body = this.parseStatement("with");
  return this.finishNode(node, "WithStatement")
};

pp$8.parseEmptyStatement = function(node) {
  this.next();
  return this.finishNode(node, "EmptyStatement")
};

pp$8.parseLabeledStatement = function(node, maybeName, expr, context) {
  for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
    {
    var label = list[i$1];

    if (label.name === maybeName)
      { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
  } }
  var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null;
  for (var i = this.labels.length - 1; i >= 0; i--) {
    var label$1 = this.labels[i];
    if (label$1.statementStart === node.start) {
      // Update information about previous labels on this node
      label$1.statementStart = this.start;
      label$1.kind = kind;
    } else { break }
  }
  this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
  node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
  this.labels.pop();
  node.label = expr;
  return this.finishNode(node, "LabeledStatement")
};

pp$8.parseExpressionStatement = function(node, expr) {
  node.expression = expr;
  this.semicolon();
  return this.finishNode(node, "ExpressionStatement")
};

// Parse a semicolon-enclosed block of statements, handling `"use
// strict"` declarations when `allowStrict` is true (used for
// function bodies).

pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) {
  if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
  if ( node === void 0 ) node = this.startNode();

  node.body = [];
  this.expect(types$1.braceL);
  if (createNewLexicalScope) { this.enterScope(0); }
  while (this.type !== types$1.braceR) {
    var stmt = this.parseStatement(null);
    node.body.push(stmt);
  }
  if (exitStrict) { this.strict = false; }
  this.next();
  if (createNewLexicalScope) { this.exitScope(); }
  return this.finishNode(node, "BlockStatement")
};

// Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.

pp$8.parseFor = function(node, init) {
  node.init = init;
  this.expect(types$1.semi);
  node.test = this.type === types$1.semi ? null : this.parseExpression();
  this.expect(types$1.semi);
  node.update = this.type === types$1.parenR ? null : this.parseExpression();
  this.expect(types$1.parenR);
  node.body = this.parseStatement("for");
  this.exitScope();
  this.labels.pop();
  return this.finishNode(node, "ForStatement")
};

// Parse a `for`/`in` and `for`/`of` loop, which are almost
// same from parser's perspective.

pp$8.parseForIn = function(node, init) {
  var isForIn = this.type === types$1._in;
  this.next();

  if (
    init.type === "VariableDeclaration" &&
    init.declarations[0].init != null &&
    (
      !isForIn ||
      this.options.ecmaVersion < 8 ||
      this.strict ||
      init.kind !== "var" ||
      init.declarations[0].id.type !== "Identifier"
    )
  ) {
    this.raise(
      init.start,
      ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
    );
  }
  node.left = init;
  node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
  this.expect(types$1.parenR);
  node.body = this.parseStatement("for");
  this.exitScope();
  this.labels.pop();
  return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
};

// Parse a list of variable declarations.

pp$8.parseVar = function(node, isFor, kind, allowMissingInitializer) {
  node.declarations = [];
  node.kind = kind;
  for (;;) {
    var decl = this.startNode();
    this.parseVarId(decl, kind);
    if (this.eat(types$1.eq)) {
      decl.init = this.parseMaybeAssign(isFor);
    } else if (!allowMissingInitializer && kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
      this.unexpected();
    } else if (!allowMissingInitializer && decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) {
      this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
    } else {
      decl.init = null;
    }
    node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
    if (!this.eat(types$1.comma)) { break }
  }
  return node
};

pp$8.parseVarId = function(decl, kind) {
  decl.id = this.parseBindingAtom();
  this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
};

var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;

// Parse a function declaration or literal (depending on the
// `statement & FUNC_STATEMENT`).

// Remove `allowExpressionBody` for 7.0.0, as it is only called with false
pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) {
  this.initFunction(node);
  if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
    if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT))
      { this.unexpected(); }
    node.generator = this.eat(types$1.star);
  }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  if (statement & FUNC_STATEMENT) {
    node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent();
    if (node.id && !(statement & FUNC_HANGING_STATEMENT))
      // If it is a regular function declaration in sloppy mode, then it is
      // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
      // mode depends on properties of the current scope (see
      // treatFunctionsAsVar).
      { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
  }

  var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;
  this.enterScope(functionFlags(node.async, node.generator));

  if (!(statement & FUNC_STATEMENT))
    { node.id = this.type === types$1.name ? this.parseIdent() : null; }

  this.parseFunctionParams(node);
  this.parseFunctionBody(node, allowExpressionBody, false, forInit);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
};

pp$8.parseFunctionParams = function(node) {
  this.expect(types$1.parenL);
  node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
};

// Parse a class declaration or literal (depending on the
// `isStatement` parameter).

pp$8.parseClass = function(node, isStatement) {
  this.next();

  // ecma-262 14.6 Class Definitions
  // A class definition is always strict mode code.
  var oldStrict = this.strict;
  this.strict = true;

  this.parseClassId(node, isStatement);
  this.parseClassSuper(node);
  var privateNameMap = this.enterClassBody();
  var classBody = this.startNode();
  var hadConstructor = false;
  classBody.body = [];
  this.expect(types$1.braceL);
  while (this.type !== types$1.braceR) {
    var element = this.parseClassElement(node.superClass !== null);
    if (element) {
      classBody.body.push(element);
      if (element.type === "MethodDefinition" && element.kind === "constructor") {
        if (hadConstructor) { this.raiseRecoverable(element.start, "Duplicate constructor in the same class"); }
        hadConstructor = true;
      } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) {
        this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared"));
      }
    }
  }
  this.strict = oldStrict;
  this.next();
  node.body = this.finishNode(classBody, "ClassBody");
  this.exitClassBody();
  return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};

pp$8.parseClassElement = function(constructorAllowsSuper) {
  if (this.eat(types$1.semi)) { return null }

  var ecmaVersion = this.options.ecmaVersion;
  var node = this.startNode();
  var keyName = "";
  var isGenerator = false;
  var isAsync = false;
  var kind = "method";
  var isStatic = false;

  if (this.eatContextual("static")) {
    // Parse static init block
    if (ecmaVersion >= 13 && this.eat(types$1.braceL)) {
      this.parseClassStaticBlock(node);
      return node
    }
    if (this.isClassElementNameStart() || this.type === types$1.star) {
      isStatic = true;
    } else {
      keyName = "static";
    }
  }
  node.static = isStatic;
  if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) {
    if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) {
      isAsync = true;
    } else {
      keyName = "async";
    }
  }
  if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) {
    isGenerator = true;
  }
  if (!keyName && !isAsync && !isGenerator) {
    var lastValue = this.value;
    if (this.eatContextual("get") || this.eatContextual("set")) {
      if (this.isClassElementNameStart()) {
        kind = lastValue;
      } else {
        keyName = lastValue;
      }
    }
  }

  // Parse element name
  if (keyName) {
    // 'async', 'get', 'set', or 'static' were not a keyword contextually.
    // The last token is any of those. Make it the element name.
    node.computed = false;
    node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc);
    node.key.name = keyName;
    this.finishNode(node.key, "Identifier");
  } else {
    this.parseClassElementName(node);
  }

  // Parse element value
  if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) {
    var isConstructor = !node.static && checkKeyName(node, "constructor");
    var allowsDirectSuper = isConstructor && constructorAllowsSuper;
    // Couldn't move this check into the 'parseClassMethod' method for backward compatibility.
    if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); }
    node.kind = isConstructor ? "constructor" : kind;
    this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper);
  } else {
    this.parseClassField(node);
  }

  return node
};

pp$8.isClassElementNameStart = function() {
  return (
    this.type === types$1.name ||
    this.type === types$1.privateId ||
    this.type === types$1.num ||
    this.type === types$1.string ||
    this.type === types$1.bracketL ||
    this.type.keyword
  )
};

pp$8.parseClassElementName = function(element) {
  if (this.type === types$1.privateId) {
    if (this.value === "constructor") {
      this.raise(this.start, "Classes can't have an element named '#constructor'");
    }
    element.computed = false;
    element.key = this.parsePrivateIdent();
  } else {
    this.parsePropertyName(element);
  }
};

pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
  // Check key and flags
  var key = method.key;
  if (method.kind === "constructor") {
    if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
    if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
  } else if (method.static && checkKeyName(method, "prototype")) {
    this.raise(key.start, "Classes may not have a static property named prototype");
  }

  // Parse value
  var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);

  // Check value
  if (method.kind === "get" && value.params.length !== 0)
    { this.raiseRecoverable(value.start, "getter should have no params"); }
  if (method.kind === "set" && value.params.length !== 1)
    { this.raiseRecoverable(value.start, "setter should have exactly one param"); }
  if (method.kind === "set" && value.params[0].type === "RestElement")
    { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); }

  return this.finishNode(method, "MethodDefinition")
};

pp$8.parseClassField = function(field) {
  if (checkKeyName(field, "constructor")) {
    this.raise(field.key.start, "Classes can't have a field named 'constructor'");
  } else if (field.static && checkKeyName(field, "prototype")) {
    this.raise(field.key.start, "Classes can't have a static field named 'prototype'");
  }

  if (this.eat(types$1.eq)) {
    // To raise SyntaxError if 'arguments' exists in the initializer.
    this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER);
    field.value = this.parseMaybeAssign();
    this.exitScope();
  } else {
    field.value = null;
  }
  this.semicolon();

  return this.finishNode(field, "PropertyDefinition")
};

pp$8.parseClassStaticBlock = function(node) {
  node.body = [];

  var oldLabels = this.labels;
  this.labels = [];
  this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER);
  while (this.type !== types$1.braceR) {
    var stmt = this.parseStatement(null);
    node.body.push(stmt);
  }
  this.next();
  this.exitScope();
  this.labels = oldLabels;

  return this.finishNode(node, "StaticBlock")
};

pp$8.parseClassId = function(node, isStatement) {
  if (this.type === types$1.name) {
    node.id = this.parseIdent();
    if (isStatement)
      { this.checkLValSimple(node.id, BIND_LEXICAL, false); }
  } else {
    if (isStatement === true)
      { this.unexpected(); }
    node.id = null;
  }
};

pp$8.parseClassSuper = function(node) {
  node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null;
};

pp$8.enterClassBody = function() {
  var element = {declared: Object.create(null), used: []};
  this.privateNameStack.push(element);
  return element.declared
};

pp$8.exitClassBody = function() {
  var ref = this.privateNameStack.pop();
  var declared = ref.declared;
  var used = ref.used;
  if (!this.options.checkPrivateFields) { return }
  var len = this.privateNameStack.length;
  var parent = len === 0 ? null : this.privateNameStack[len - 1];
  for (var i = 0; i < used.length; ++i) {
    var id = used[i];
    if (!hasOwn(declared, id.name)) {
      if (parent) {
        parent.used.push(id);
      } else {
        this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class"));
      }
    }
  }
};

function isPrivateNameConflicted(privateNameMap, element) {
  var name = element.key.name;
  var curr = privateNameMap[name];

  var next = "true";
  if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) {
    next = (element.static ? "s" : "i") + element.kind;
  }

  // `class { get #a(){}; static set #a(_){} }` is also conflict.
  if (
    curr === "iget" && next === "iset" ||
    curr === "iset" && next === "iget" ||
    curr === "sget" && next === "sset" ||
    curr === "sset" && next === "sget"
  ) {
    privateNameMap[name] = "true";
    return false
  } else if (!curr) {
    privateNameMap[name] = next;
    return false
  } else {
    return true
  }
}

function checkKeyName(node, name) {
  var computed = node.computed;
  var key = node.key;
  return !computed && (
    key.type === "Identifier" && key.name === name ||
    key.type === "Literal" && key.value === name
  )
}

// Parses module export declaration.

pp$8.parseExportAllDeclaration = function(node, exports) {
  if (this.options.ecmaVersion >= 11) {
    if (this.eatContextual("as")) {
      node.exported = this.parseModuleExportName();
      this.checkExport(exports, node.exported, this.lastTokStart);
    } else {
      node.exported = null;
    }
  }
  this.expectContextual("from");
  if (this.type !== types$1.string) { this.unexpected(); }
  node.source = this.parseExprAtom();
  if (this.options.ecmaVersion >= 16)
    { node.attributes = this.parseWithClause(); }
  this.semicolon();
  return this.finishNode(node, "ExportAllDeclaration")
};

pp$8.parseExport = function(node, exports) {
  this.next();
  // export * from '...'
  if (this.eat(types$1.star)) {
    return this.parseExportAllDeclaration(node, exports)
  }
  if (this.eat(types$1._default)) { // export default ...
    this.checkExport(exports, "default", this.lastTokStart);
    node.declaration = this.parseExportDefaultDeclaration();
    return this.finishNode(node, "ExportDefaultDeclaration")
  }
  // export var|const|let|function|class ...
  if (this.shouldParseExportStatement()) {
    node.declaration = this.parseExportDeclaration(node);
    if (node.declaration.type === "VariableDeclaration")
      { this.checkVariableExport(exports, node.declaration.declarations); }
    else
      { this.checkExport(exports, node.declaration.id, node.declaration.id.start); }
    node.specifiers = [];
    node.source = null;
    if (this.options.ecmaVersion >= 16)
      { node.attributes = []; }
  } else { // export { x, y as z } [from '...']
    node.declaration = null;
    node.specifiers = this.parseExportSpecifiers(exports);
    if (this.eatContextual("from")) {
      if (this.type !== types$1.string) { this.unexpected(); }
      node.source = this.parseExprAtom();
      if (this.options.ecmaVersion >= 16)
        { node.attributes = this.parseWithClause(); }
    } else {
      for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
        // check for keywords used as local names
        var spec = list[i];

        this.checkUnreserved(spec.local);
        // check if export is defined
        this.checkLocalExport(spec.local);

        if (spec.local.type === "Literal") {
          this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`.");
        }
      }

      node.source = null;
      if (this.options.ecmaVersion >= 16)
        { node.attributes = []; }
    }
    this.semicolon();
  }
  return this.finishNode(node, "ExportNamedDeclaration")
};

pp$8.parseExportDeclaration = function(node) {
  return this.parseStatement(null)
};

pp$8.parseExportDefaultDeclaration = function() {
  var isAsync;
  if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) {
    var fNode = this.startNode();
    this.next();
    if (isAsync) { this.next(); }
    return this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync)
  } else if (this.type === types$1._class) {
    var cNode = this.startNode();
    return this.parseClass(cNode, "nullableID")
  } else {
    var declaration = this.parseMaybeAssign();
    this.semicolon();
    return declaration
  }
};

pp$8.checkExport = function(exports, name, pos) {
  if (!exports) { return }
  if (typeof name !== "string")
    { name = name.type === "Identifier" ? name.name : name.value; }
  if (hasOwn(exports, name))
    { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
  exports[name] = true;
};

pp$8.checkPatternExport = function(exports, pat) {
  var type = pat.type;
  if (type === "Identifier")
    { this.checkExport(exports, pat, pat.start); }
  else if (type === "ObjectPattern")
    { for (var i = 0, list = pat.properties; i < list.length; i += 1)
      {
        var prop = list[i];

        this.checkPatternExport(exports, prop);
      } }
  else if (type === "ArrayPattern")
    { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
      var elt = list$1[i$1];

        if (elt) { this.checkPatternExport(exports, elt); }
    } }
  else if (type === "Property")
    { this.checkPatternExport(exports, pat.value); }
  else if (type === "AssignmentPattern")
    { this.checkPatternExport(exports, pat.left); }
  else if (type === "RestElement")
    { this.checkPatternExport(exports, pat.argument); }
};

pp$8.checkVariableExport = function(exports, decls) {
  if (!exports) { return }
  for (var i = 0, list = decls; i < list.length; i += 1)
    {
    var decl = list[i];

    this.checkPatternExport(exports, decl.id);
  }
};

pp$8.shouldParseExportStatement = function() {
  return this.type.keyword === "var" ||
    this.type.keyword === "const" ||
    this.type.keyword === "class" ||
    this.type.keyword === "function" ||
    this.isLet() ||
    this.isAsyncFunction()
};

// Parses a comma-separated list of module exports.

pp$8.parseExportSpecifier = function(exports) {
  var node = this.startNode();
  node.local = this.parseModuleExportName();

  node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local;
  this.checkExport(
    exports,
    node.exported,
    node.exported.start
  );

  return this.finishNode(node, "ExportSpecifier")
};

pp$8.parseExportSpecifiers = function(exports) {
  var nodes = [], first = true;
  // export { x, y as z } [from '...']
  this.expect(types$1.braceL);
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    nodes.push(this.parseExportSpecifier(exports));
  }
  return nodes
};

// Parses import declaration.

pp$8.parseImport = function(node) {
  this.next();

  // import '...'
  if (this.type === types$1.string) {
    node.specifiers = empty$1;
    node.source = this.parseExprAtom();
  } else {
    node.specifiers = this.parseImportSpecifiers();
    this.expectContextual("from");
    node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected();
  }
  if (this.options.ecmaVersion >= 16)
    { node.attributes = this.parseWithClause(); }
  this.semicolon();
  return this.finishNode(node, "ImportDeclaration")
};

// Parses a comma-separated list of module imports.

pp$8.parseImportSpecifier = function() {
  var node = this.startNode();
  node.imported = this.parseModuleExportName();

  if (this.eatContextual("as")) {
    node.local = this.parseIdent();
  } else {
    this.checkUnreserved(node.imported);
    node.local = node.imported;
  }
  this.checkLValSimple(node.local, BIND_LEXICAL);

  return this.finishNode(node, "ImportSpecifier")
};

pp$8.parseImportDefaultSpecifier = function() {
  // import defaultObj, { x, y as z } from '...'
  var node = this.startNode();
  node.local = this.parseIdent();
  this.checkLValSimple(node.local, BIND_LEXICAL);
  return this.finishNode(node, "ImportDefaultSpecifier")
};

pp$8.parseImportNamespaceSpecifier = function() {
  var node = this.startNode();
  this.next();
  this.expectContextual("as");
  node.local = this.parseIdent();
  this.checkLValSimple(node.local, BIND_LEXICAL);
  return this.finishNode(node, "ImportNamespaceSpecifier")
};

pp$8.parseImportSpecifiers = function() {
  var nodes = [], first = true;
  if (this.type === types$1.name) {
    nodes.push(this.parseImportDefaultSpecifier());
    if (!this.eat(types$1.comma)) { return nodes }
  }
  if (this.type === types$1.star) {
    nodes.push(this.parseImportNamespaceSpecifier());
    return nodes
  }
  this.expect(types$1.braceL);
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    nodes.push(this.parseImportSpecifier());
  }
  return nodes
};

pp$8.parseWithClause = function() {
  var nodes = [];
  if (!this.eat(types$1._with)) {
    return nodes
  }
  this.expect(types$1.braceL);
  var attributeKeys = {};
  var first = true;
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    var attr = this.parseImportAttribute();
    var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
    if (hasOwn(attributeKeys, keyName))
      { this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'"); }
    attributeKeys[keyName] = true;
    nodes.push(attr);
  }
  return nodes
};

pp$8.parseImportAttribute = function() {
  var node = this.startNode();
  node.key = this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never");
  this.expect(types$1.colon);
  if (this.type !== types$1.string) {
    this.unexpected();
  }
  node.value = this.parseExprAtom();
  return this.finishNode(node, "ImportAttribute")
};

pp$8.parseModuleExportName = function() {
  if (this.options.ecmaVersion >= 13 && this.type === types$1.string) {
    var stringLiteral = this.parseLiteral(this.value);
    if (loneSurrogate.test(stringLiteral.value)) {
      this.raise(stringLiteral.start, "An export name cannot include a lone surrogate.");
    }
    return stringLiteral
  }
  return this.parseIdent(true)
};

// Set `ExpressionStatement#directive` property for directive prologues.
pp$8.adaptDirectivePrologue = function(statements) {
  for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
    statements[i].directive = statements[i].expression.raw.slice(1, -1);
  }
};
pp$8.isDirectiveCandidate = function(statement) {
  return (
    this.options.ecmaVersion >= 5 &&
    statement.type === "ExpressionStatement" &&
    statement.expression.type === "Literal" &&
    typeof statement.expression.value === "string" &&
    // Reject parenthesized strings.
    (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
  )
};

var pp$7 = Parser.prototype;

// Convert existing expression atom to assignable pattern
// if possible.

pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) {
  if (this.options.ecmaVersion >= 6 && node) {
    switch (node.type) {
    case "Identifier":
      if (this.inAsync && node.name === "await")
        { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
      break

    case "ObjectPattern":
    case "ArrayPattern":
    case "AssignmentPattern":
    case "RestElement":
      break

    case "ObjectExpression":
      node.type = "ObjectPattern";
      if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
      for (var i = 0, list = node.properties; i < list.length; i += 1) {
        var prop = list[i];

      this.toAssignable(prop, isBinding);
        // Early error:
        //   AssignmentRestProperty[Yield, Await] :
        //     `...` DestructuringAssignmentTarget[Yield, Await]
        //
        //   It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
        if (
          prop.type === "RestElement" &&
          (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
        ) {
          this.raise(prop.argument.start, "Unexpected token");
        }
      }
      break

    case "Property":
      // AssignmentProperty has type === "Property"
      if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
      this.toAssignable(node.value, isBinding);
      break

    case "ArrayExpression":
      node.type = "ArrayPattern";
      if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
      this.toAssignableList(node.elements, isBinding);
      break

    case "SpreadElement":
      node.type = "RestElement";
      this.toAssignable(node.argument, isBinding);
      if (node.argument.type === "AssignmentPattern")
        { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
      break

    case "AssignmentExpression":
      if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
      node.type = "AssignmentPattern";
      delete node.operator;
      this.toAssignable(node.left, isBinding);
      break

    case "ParenthesizedExpression":
      this.toAssignable(node.expression, isBinding, refDestructuringErrors);
      break

    case "ChainExpression":
      this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
      break

    case "MemberExpression":
      if (!isBinding) { break }

    default:
      this.raise(node.start, "Assigning to rvalue");
    }
  } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
  return node
};

// Convert list of expression atoms to binding list.

pp$7.toAssignableList = function(exprList, isBinding) {
  var end = exprList.length;
  for (var i = 0; i < end; i++) {
    var elt = exprList[i];
    if (elt) { this.toAssignable(elt, isBinding); }
  }
  if (end) {
    var last = exprList[end - 1];
    if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
      { this.unexpected(last.argument.start); }
  }
  return exprList
};

// Parses spread element.

pp$7.parseSpread = function(refDestructuringErrors) {
  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
  return this.finishNode(node, "SpreadElement")
};

pp$7.parseRestBinding = function() {
  var node = this.startNode();
  this.next();

  // RestElement inside of a function parameter must be an identifier
  if (this.options.ecmaVersion === 6 && this.type !== types$1.name)
    { this.unexpected(); }

  node.argument = this.parseBindingAtom();

  return this.finishNode(node, "RestElement")
};

// Parses lvalue (assignable) atom.

pp$7.parseBindingAtom = function() {
  if (this.options.ecmaVersion >= 6) {
    switch (this.type) {
    case types$1.bracketL:
      var node = this.startNode();
      this.next();
      node.elements = this.parseBindingList(types$1.bracketR, true, true);
      return this.finishNode(node, "ArrayPattern")

    case types$1.braceL:
      return this.parseObj(true)
    }
  }
  return this.parseIdent()
};

pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowModifiers) {
  var elts = [], first = true;
  while (!this.eat(close)) {
    if (first) { first = false; }
    else { this.expect(types$1.comma); }
    if (allowEmpty && this.type === types$1.comma) {
      elts.push(null);
    } else if (allowTrailingComma && this.afterTrailingComma(close)) {
      break
    } else if (this.type === types$1.ellipsis) {
      var rest = this.parseRestBinding();
      this.parseBindingListItem(rest);
      elts.push(rest);
      if (this.type === types$1.comma) { this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); }
      this.expect(close);
      break
    } else {
      elts.push(this.parseAssignableListItem(allowModifiers));
    }
  }
  return elts
};

pp$7.parseAssignableListItem = function(allowModifiers) {
  var elem = this.parseMaybeDefault(this.start, this.startLoc);
  this.parseBindingListItem(elem);
  return elem
};

pp$7.parseBindingListItem = function(param) {
  return param
};

// Parses assignment pattern around given atom if possible.

pp$7.parseMaybeDefault = function(startPos, startLoc, left) {
  left = left || this.parseBindingAtom();
  if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left }
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.right = this.parseMaybeAssign();
  return this.finishNode(node, "AssignmentPattern")
};

// The following three functions all verify that a node is an lvalue —
// something that can be bound, or assigned to. In order to do so, they perform
// a variety of checks:
//
// - Check that none of the bound/assigned-to identifiers are reserved words.
// - Record name declarations for bindings in the appropriate scope.
// - Check duplicate argument names, if checkClashes is set.
//
// If a complex binding pattern is encountered (e.g., object and array
// destructuring), the entire pattern is recursively checked.
//
// There are three versions of checkLVal*() appropriate for different
// circumstances:
//
// - checkLValSimple() shall be used if the syntactic construct supports
//   nothing other than identifiers and member expressions. Parenthesized
//   expressions are also correctly handled. This is generally appropriate for
//   constructs for which the spec says
//
//   > It is a Syntax Error if AssignmentTargetType of [the production] is not
//   > simple.
//
//   It is also appropriate for checking if an identifier is valid and not
//   defined elsewhere, like import declarations or function/class identifiers.
//
//   Examples where this is used include:
//     a += …;
//     import a from '…';
//   where a is the node to be checked.
//
// - checkLValPattern() shall be used if the syntactic construct supports
//   anything checkLValSimple() supports, as well as object and array
//   destructuring patterns. This is generally appropriate for constructs for
//   which the spec says
//
//   > It is a Syntax Error if [the production] is neither an ObjectLiteral nor
//   > an ArrayLiteral and AssignmentTargetType of [the production] is not
//   > simple.
//
//   Examples where this is used include:
//     (a = …);
//     const a = …;
//     try { … } catch (a) { … }
//   where a is the node to be checked.
//
// - checkLValInnerPattern() shall be used if the syntactic construct supports
//   anything checkLValPattern() supports, as well as default assignment
//   patterns, rest elements, and other constructs that may appear within an
//   object or array destructuring pattern.
//
//   As a special case, function parameters also use checkLValInnerPattern(),
//   as they also support defaults and rest constructs.
//
// These functions deliberately support both assignment and binding constructs,
// as the logic for both is exceedingly similar. If the node is the target of
// an assignment, then bindingType should be set to BIND_NONE. Otherwise, it
// should be set to the appropriate BIND_* constant, like BIND_VAR or
// BIND_LEXICAL.
//
// If the function is called with a non-BIND_NONE bindingType, then
// additionally a checkClashes object may be specified to allow checking for
// duplicate argument names. checkClashes is ignored if the provided construct
// is an assignment (i.e., bindingType is BIND_NONE).

pp$7.checkLValSimple = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  var isBind = bindingType !== BIND_NONE;

  switch (expr.type) {
  case "Identifier":
    if (this.strict && this.reservedWordsStrictBind.test(expr.name))
      { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
    if (isBind) {
      if (bindingType === BIND_LEXICAL && expr.name === "let")
        { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
      if (checkClashes) {
        if (hasOwn(checkClashes, expr.name))
          { this.raiseRecoverable(expr.start, "Argument name clash"); }
        checkClashes[expr.name] = true;
      }
      if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
    }
    break

  case "ChainExpression":
    this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
    break

  case "MemberExpression":
    if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); }
    break

  case "ParenthesizedExpression":
    if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); }
    return this.checkLValSimple(expr.expression, bindingType, checkClashes)

  default:
    this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue");
  }
};

pp$7.checkLValPattern = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  switch (expr.type) {
  case "ObjectPattern":
    for (var i = 0, list = expr.properties; i < list.length; i += 1) {
      var prop = list[i];

    this.checkLValInnerPattern(prop, bindingType, checkClashes);
    }
    break

  case "ArrayPattern":
    for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
      var elem = list$1[i$1];

    if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); }
    }
    break

  default:
    this.checkLValSimple(expr, bindingType, checkClashes);
  }
};

pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  switch (expr.type) {
  case "Property":
    // AssignmentProperty has type === "Property"
    this.checkLValInnerPattern(expr.value, bindingType, checkClashes);
    break

  case "AssignmentPattern":
    this.checkLValPattern(expr.left, bindingType, checkClashes);
    break

  case "RestElement":
    this.checkLValPattern(expr.argument, bindingType, checkClashes);
    break

  default:
    this.checkLValPattern(expr, bindingType, checkClashes);
  }
};

// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design


var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
  this.token = token;
  this.isExpr = !!isExpr;
  this.preserveSpace = !!preserveSpace;
  this.override = override;
  this.generator = !!generator;
};

var types = {
  b_stat: new TokContext("{", false),
  b_expr: new TokContext("{", true),
  b_tmpl: new TokContext("${", false),
  p_stat: new TokContext("(", false),
  p_expr: new TokContext("(", true),
  q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
  f_stat: new TokContext("function", false),
  f_expr: new TokContext("function", true),
  f_expr_gen: new TokContext("function", true, false, null, true),
  f_gen: new TokContext("function", false, false, null, true)
};

var pp$6 = Parser.prototype;

pp$6.initialContext = function() {
  return [types.b_stat]
};

pp$6.curContext = function() {
  return this.context[this.context.length - 1]
};

pp$6.braceIsBlock = function(prevType) {
  var parent = this.curContext();
  if (parent === types.f_expr || parent === types.f_stat)
    { return true }
  if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr))
    { return !parent.isExpr }

  // The check for `tt.name && exprAllowed` detects whether we are
  // after a `yield` or `of` construct. See the `updateContext` for
  // `tt.name`.
  if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed)
    { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
  if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow)
    { return true }
  if (prevType === types$1.braceL)
    { return parent === types.b_stat }
  if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name)
    { return false }
  return !this.exprAllowed
};

pp$6.inGeneratorContext = function() {
  for (var i = this.context.length - 1; i >= 1; i--) {
    var context = this.context[i];
    if (context.token === "function")
      { return context.generator }
  }
  return false
};

pp$6.updateContext = function(prevType) {
  var update, type = this.type;
  if (type.keyword && prevType === types$1.dot)
    { this.exprAllowed = false; }
  else if (update = type.updateContext)
    { update.call(this, prevType); }
  else
    { this.exprAllowed = type.beforeExpr; }
};

// Used to handle edge cases when token context could not be inferred correctly during tokenization phase

pp$6.overrideContext = function(tokenCtx) {
  if (this.curContext() !== tokenCtx) {
    this.context[this.context.length - 1] = tokenCtx;
  }
};

// Token-specific context update code

types$1.parenR.updateContext = types$1.braceR.updateContext = function() {
  if (this.context.length === 1) {
    this.exprAllowed = true;
    return
  }
  var out = this.context.pop();
  if (out === types.b_stat && this.curContext().token === "function") {
    out = this.context.pop();
  }
  this.exprAllowed = !out.isExpr;
};

types$1.braceL.updateContext = function(prevType) {
  this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
  this.exprAllowed = true;
};

types$1.dollarBraceL.updateContext = function() {
  this.context.push(types.b_tmpl);
  this.exprAllowed = true;
};

types$1.parenL.updateContext = function(prevType) {
  var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while;
  this.context.push(statementParens ? types.p_stat : types.p_expr);
  this.exprAllowed = true;
};

types$1.incDec.updateContext = function() {
  // tokExprAllowed stays unchanged
};

types$1._function.updateContext = types$1._class.updateContext = function(prevType) {
  if (prevType.beforeExpr && prevType !== types$1._else &&
      !(prevType === types$1.semi && this.curContext() !== types.p_stat) &&
      !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
      !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat))
    { this.context.push(types.f_expr); }
  else
    { this.context.push(types.f_stat); }
  this.exprAllowed = false;
};

types$1.colon.updateContext = function() {
  if (this.curContext().token === "function") { this.context.pop(); }
  this.exprAllowed = true;
};

types$1.backQuote.updateContext = function() {
  if (this.curContext() === types.q_tmpl)
    { this.context.pop(); }
  else
    { this.context.push(types.q_tmpl); }
  this.exprAllowed = false;
};

types$1.star.updateContext = function(prevType) {
  if (prevType === types$1._function) {
    var index = this.context.length - 1;
    if (this.context[index] === types.f_expr)
      { this.context[index] = types.f_expr_gen; }
    else
      { this.context[index] = types.f_gen; }
  }
  this.exprAllowed = true;
};

types$1.name.updateContext = function(prevType) {
  var allowed = false;
  if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) {
    if (this.value === "of" && !this.exprAllowed ||
        this.value === "yield" && this.inGeneratorContext())
      { allowed = true; }
  }
  this.exprAllowed = allowed;
};

// A recursive descent parser operates by defining functions for all
// syntactic elements, and recursively calling those, each function
// advancing the input stream and returning an AST node. Precedence
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
// instead of `(!x)[1]` is handled by the fact that the parser
// function that parses unary prefix operators is called first, and
// in turn calls the function that parses `[]` subscripts — that
// way, it'll receive the node for `x[1]` already parsed, and wraps
// *that* in the unary operator node.
//
// Acorn uses an [operator precedence parser][opp] to handle binary
// operator precedence, because it is much more compact than using
// the technique outlined above, which uses different, nesting
// functions to specify precedence, for all of the ten binary
// precedence levels that JavaScript defines.
//
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser


var pp$5 = Parser.prototype;

// Check if property name clashes with already added.
// Object/class getters and setters are not allowed to clash —
// either with each other or with an init property — and in
// strict mode, init properties are also not allowed to be repeated.

pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) {
  if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
    { return }
  if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
    { return }
  var key = prop.key;
  var name;
  switch (key.type) {
  case "Identifier": name = key.name; break
  case "Literal": name = String(key.value); break
  default: return
  }
  var kind = prop.kind;
  if (this.options.ecmaVersion >= 6) {
    if (name === "__proto__" && kind === "init") {
      if (propHash.proto) {
        if (refDestructuringErrors) {
          if (refDestructuringErrors.doubleProto < 0) {
            refDestructuringErrors.doubleProto = key.start;
          }
        } else {
          this.raiseRecoverable(key.start, "Redefinition of __proto__ property");
        }
      }
      propHash.proto = true;
    }
    return
  }
  name = "$" + name;
  var other = propHash[name];
  if (other) {
    var redefinition;
    if (kind === "init") {
      redefinition = this.strict && other.init || other.get || other.set;
    } else {
      redefinition = other.init || other[kind];
    }
    if (redefinition)
      { this.raiseRecoverable(key.start, "Redefinition of property"); }
  } else {
    other = propHash[name] = {
      init: false,
      get: false,
      set: false
    };
  }
  other[kind] = true;
};

// ### Expression parsing

// These nest, from the most general expression type at the top to
// 'atomic', nondivisible expression types at the bottom. Most of
// the functions will simply let the function(s) below them parse,
// and, *if* the syntactic construct they handle is present, wrap
// the AST node that the inner parser gave them in another node.

// Parse a full expression. The optional arguments are used to
// forbid the `in` operator (in for loops initalization expressions)
// and provide reference for storing '=' operator inside shorthand
// property assignment in contexts where both object expression
// and object pattern might appear (so it's possible to raise
// delayed syntax error at correct position).

pp$5.parseExpression = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeAssign(forInit, refDestructuringErrors);
  if (this.type === types$1.comma) {
    var node = this.startNodeAt(startPos, startLoc);
    node.expressions = [expr];
    while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); }
    return this.finishNode(node, "SequenceExpression")
  }
  return expr
};

// Parse an assignment expression. This includes applications of
// operators like `+=`.

pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) {
  if (this.isContextual("yield")) {
    if (this.inGenerator) { return this.parseYield(forInit) }
    // The tokenizer will assume an expression is allowed after
    // `yield`, but this isn't that kind of yield
    else { this.exprAllowed = false; }
  }

  var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1;
  if (refDestructuringErrors) {
    oldParenAssign = refDestructuringErrors.parenthesizedAssign;
    oldTrailingComma = refDestructuringErrors.trailingComma;
    oldDoubleProto = refDestructuringErrors.doubleProto;
    refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
  } else {
    refDestructuringErrors = new DestructuringErrors;
    ownDestructuringErrors = true;
  }

  var startPos = this.start, startLoc = this.startLoc;
  if (this.type === types$1.parenL || this.type === types$1.name) {
    this.potentialArrowAt = this.start;
    this.potentialArrowInForAwait = forInit === "await";
  }
  var left = this.parseMaybeConditional(forInit, refDestructuringErrors);
  if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
  if (this.type.isAssign) {
    var node = this.startNodeAt(startPos, startLoc);
    node.operator = this.value;
    if (this.type === types$1.eq)
      { left = this.toAssignable(left, false, refDestructuringErrors); }
    if (!ownDestructuringErrors) {
      refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
    }
    if (refDestructuringErrors.shorthandAssign >= left.start)
      { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
    if (this.type === types$1.eq)
      { this.checkLValPattern(left); }
    else
      { this.checkLValSimple(left); }
    node.left = left;
    this.next();
    node.right = this.parseMaybeAssign(forInit);
    if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; }
    return this.finishNode(node, "AssignmentExpression")
  } else {
    if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
  }
  if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
  if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
  return left
};

// Parse a ternary conditional (`?:`) operator.

pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprOps(forInit, refDestructuringErrors);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  if (this.eat(types$1.question)) {
    var node = this.startNodeAt(startPos, startLoc);
    node.test = expr;
    node.consequent = this.parseMaybeAssign();
    this.expect(types$1.colon);
    node.alternate = this.parseMaybeAssign(forInit);
    return this.finishNode(node, "ConditionalExpression")
  }
  return expr
};

// Start the precedence parser.

pp$5.parseExprOps = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit)
};

// Parse binary operators with the operator precedence parsing
// algorithm. `left` is the left-hand side of the operator.
// `minPrec` provides context that allows the function to stop and
// defer further parser to one of its callers when it encounters an
// operator that has a lower precedence than the set it is parsing.

pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) {
  var prec = this.type.binop;
  if (prec != null && (!forInit || this.type !== types$1._in)) {
    if (prec > minPrec) {
      var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND;
      var coalesce = this.type === types$1.coalesce;
      if (coalesce) {
        // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
        // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
        prec = types$1.logicalAND.binop;
      }
      var op = this.value;
      this.next();
      var startPos = this.start, startLoc = this.startLoc;
      var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit);
      var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
      if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) {
        this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
      }
      return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit)
    }
  }
  return left
};

pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) {
  if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); }
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.operator = op;
  node.right = right;
  return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
};

// Parse unary operators, both prefix and postfix.

pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) {
  var startPos = this.start, startLoc = this.startLoc, expr;
  if (this.isContextual("await") && this.canAwait) {
    expr = this.parseAwait(forInit);
    sawUnary = true;
  } else if (this.type.prefix) {
    var node = this.startNode(), update = this.type === types$1.incDec;
    node.operator = this.value;
    node.prefix = true;
    this.next();
    node.argument = this.parseMaybeUnary(null, true, update, forInit);
    this.checkExpressionErrors(refDestructuringErrors, true);
    if (update) { this.checkLValSimple(node.argument); }
    else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument))
      { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
    else if (node.operator === "delete" && isPrivateFieldAccess(node.argument))
      { this.raiseRecoverable(node.start, "Private fields can not be deleted"); }
    else { sawUnary = true; }
    expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
  } else if (!sawUnary && this.type === types$1.privateId) {
    if ((forInit || this.privateNameStack.length === 0) && this.options.checkPrivateFields) { this.unexpected(); }
    expr = this.parsePrivateIdent();
    // only could be private fields in 'in', such as #x in obj
    if (this.type !== types$1._in) { this.unexpected(); }
  } else {
    expr = this.parseExprSubscripts(refDestructuringErrors, forInit);
    if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
    while (this.type.postfix && !this.canInsertSemicolon()) {
      var node$1 = this.startNodeAt(startPos, startLoc);
      node$1.operator = this.value;
      node$1.prefix = false;
      node$1.argument = expr;
      this.checkLValSimple(expr);
      this.next();
      expr = this.finishNode(node$1, "UpdateExpression");
    }
  }

  if (!incDec && this.eat(types$1.starstar)) {
    if (sawUnary)
      { this.unexpected(this.lastTokStart); }
    else
      { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) }
  } else {
    return expr
  }
};

function isLocalVariableAccess(node) {
  return (
    node.type === "Identifier" ||
    node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression)
  )
}

function isPrivateFieldAccess(node) {
  return (
    node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" ||
    node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) ||
    node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression)
  )
}

// Parse call, dot, and `[]`-subscript expressions.

pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprAtom(refDestructuringErrors, forInit);
  if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
    { return expr }
  var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit);
  if (refDestructuringErrors && result.type === "MemberExpression") {
    if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
    if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
    if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; }
  }
  return result
};

pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) {
  var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
      this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
      this.potentialArrowAt === base.start;
  var optionalChained = false;

  while (true) {
    var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);

    if (element.optional) { optionalChained = true; }
    if (element === base || element.type === "ArrowFunctionExpression") {
      if (optionalChained) {
        var chainNode = this.startNodeAt(startPos, startLoc);
        chainNode.expression = element;
        element = this.finishNode(chainNode, "ChainExpression");
      }
      return element
    }

    base = element;
  }
};

pp$5.shouldParseAsyncArrow = function() {
  return !this.canInsertSemicolon() && this.eat(types$1.arrow)
};

pp$5.parseSubscriptAsyncArrow = function(startPos, startLoc, exprList, forInit) {
  return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit)
};

pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
  var optionalSupported = this.options.ecmaVersion >= 11;
  var optional = optionalSupported && this.eat(types$1.questionDot);
  if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); }

  var computed = this.eat(types$1.bracketL);
  if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) {
    var node = this.startNodeAt(startPos, startLoc);
    node.object = base;
    if (computed) {
      node.property = this.parseExpression();
      this.expect(types$1.bracketR);
    } else if (this.type === types$1.privateId && base.type !== "Super") {
      node.property = this.parsePrivateIdent();
    } else {
      node.property = this.parseIdent(this.options.allowReserved !== "never");
    }
    node.computed = !!computed;
    if (optionalSupported) {
      node.optional = optional;
    }
    base = this.finishNode(node, "MemberExpression");
  } else if (!noCalls && this.eat(types$1.parenL)) {
    var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
    this.yieldPos = 0;
    this.awaitPos = 0;
    this.awaitIdentPos = 0;
    var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
    if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) {
      this.checkPatternErrors(refDestructuringErrors, false);
      this.checkYieldAwaitInDefaultParams();
      if (this.awaitIdentPos > 0)
        { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      this.awaitIdentPos = oldAwaitIdentPos;
      return this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit)
    }
    this.checkExpressionErrors(refDestructuringErrors, true);
    this.yieldPos = oldYieldPos || this.yieldPos;
    this.awaitPos = oldAwaitPos || this.awaitPos;
    this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
    var node$1 = this.startNodeAt(startPos, startLoc);
    node$1.callee = base;
    node$1.arguments = exprList;
    if (optionalSupported) {
      node$1.optional = optional;
    }
    base = this.finishNode(node$1, "CallExpression");
  } else if (this.type === types$1.backQuote) {
    if (optional || optionalChained) {
      this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
    }
    var node$2 = this.startNodeAt(startPos, startLoc);
    node$2.tag = base;
    node$2.quasi = this.parseTemplate({isTagged: true});
    base = this.finishNode(node$2, "TaggedTemplateExpression");
  }
  return base
};

// Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.

pp$5.parseExprAtom = function(refDestructuringErrors, forInit, forNew) {
  // If a division operator appears in an expression position, the
  // tokenizer got confused, and we force it to read a regexp instead.
  if (this.type === types$1.slash) { this.readRegexp(); }

  var node, canBeArrow = this.potentialArrowAt === this.start;
  switch (this.type) {
  case types$1._super:
    if (!this.allowSuper)
      { this.raise(this.start, "'super' keyword outside a method"); }
    node = this.startNode();
    this.next();
    if (this.type === types$1.parenL && !this.allowDirectSuper)
      { this.raise(node.start, "super() call outside constructor of a subclass"); }
    // The `super` keyword can appear at below:
    // SuperProperty:
    //     super [ Expression ]
    //     super . IdentifierName
    // SuperCall:
    //     super ( Arguments )
    if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL)
      { this.unexpected(); }
    return this.finishNode(node, "Super")

  case types$1._this:
    node = this.startNode();
    this.next();
    return this.finishNode(node, "ThisExpression")

  case types$1.name:
    var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
    var id = this.parseIdent(false);
    if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) {
      this.overrideContext(types.f_expr);
      return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit)
    }
    if (canBeArrow && !this.canInsertSemicolon()) {
      if (this.eat(types$1.arrow))
        { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) }
      if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc &&
          (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) {
        id = this.parseIdent(false);
        if (this.canInsertSemicolon() || !this.eat(types$1.arrow))
          { this.unexpected(); }
        return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit)
      }
    }
    return id

  case types$1.regexp:
    var value = this.value;
    node = this.parseLiteral(value.value);
    node.regex = {pattern: value.pattern, flags: value.flags};
    return node

  case types$1.num: case types$1.string:
    return this.parseLiteral(this.value)

  case types$1._null: case types$1._true: case types$1._false:
    node = this.startNode();
    node.value = this.type === types$1._null ? null : this.type === types$1._true;
    node.raw = this.type.keyword;
    this.next();
    return this.finishNode(node, "Literal")

  case types$1.parenL:
    var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit);
    if (refDestructuringErrors) {
      if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
        { refDestructuringErrors.parenthesizedAssign = start; }
      if (refDestructuringErrors.parenthesizedBind < 0)
        { refDestructuringErrors.parenthesizedBind = start; }
    }
    return expr

  case types$1.bracketL:
    node = this.startNode();
    this.next();
    node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors);
    return this.finishNode(node, "ArrayExpression")

  case types$1.braceL:
    this.overrideContext(types.b_expr);
    return this.parseObj(false, refDestructuringErrors)

  case types$1._function:
    node = this.startNode();
    this.next();
    return this.parseFunction(node, 0)

  case types$1._class:
    return this.parseClass(this.startNode(), false)

  case types$1._new:
    return this.parseNew()

  case types$1.backQuote:
    return this.parseTemplate()

  case types$1._import:
    if (this.options.ecmaVersion >= 11) {
      return this.parseExprImport(forNew)
    } else {
      return this.unexpected()
    }

  default:
    return this.parseExprAtomDefault()
  }
};

pp$5.parseExprAtomDefault = function() {
  this.unexpected();
};

pp$5.parseExprImport = function(forNew) {
  var node = this.startNode();

  // Consume `import` as an identifier for `import.meta`.
  // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
  if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); }
  this.next();

  if (this.type === types$1.parenL && !forNew) {
    return this.parseDynamicImport(node)
  } else if (this.type === types$1.dot) {
    var meta = this.startNodeAt(node.start, node.loc && node.loc.start);
    meta.name = "import";
    node.meta = this.finishNode(meta, "Identifier");
    return this.parseImportMeta(node)
  } else {
    this.unexpected();
  }
};

pp$5.parseDynamicImport = function(node) {
  this.next(); // skip `(`

  // Parse node.source.
  node.source = this.parseMaybeAssign();

  if (this.options.ecmaVersion >= 16) {
    if (!this.eat(types$1.parenR)) {
      this.expect(types$1.comma);
      if (!this.afterTrailingComma(types$1.parenR)) {
        node.options = this.parseMaybeAssign();
        if (!this.eat(types$1.parenR)) {
          this.expect(types$1.comma);
          if (!this.afterTrailingComma(types$1.parenR)) {
            this.unexpected();
          }
        }
      } else {
        node.options = null;
      }
    } else {
      node.options = null;
    }
  } else {
    // Verify ending.
    if (!this.eat(types$1.parenR)) {
      var errorPos = this.start;
      if (this.eat(types$1.comma) && this.eat(types$1.parenR)) {
        this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
      } else {
        this.unexpected(errorPos);
      }
    }
  }

  return this.finishNode(node, "ImportExpression")
};

pp$5.parseImportMeta = function(node) {
  this.next(); // skip `.`

  var containsEsc = this.containsEsc;
  node.property = this.parseIdent(true);

  if (node.property.name !== "meta")
    { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); }
  if (containsEsc)
    { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); }
  if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere)
    { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); }

  return this.finishNode(node, "MetaProperty")
};

pp$5.parseLiteral = function(value) {
  var node = this.startNode();
  node.value = value;
  node.raw = this.input.slice(this.start, this.end);
  if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); }
  this.next();
  return this.finishNode(node, "Literal")
};

pp$5.parseParenExpression = function() {
  this.expect(types$1.parenL);
  var val = this.parseExpression();
  this.expect(types$1.parenR);
  return val
};

pp$5.shouldParseArrow = function(exprList) {
  return !this.canInsertSemicolon()
};

pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) {
  var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
  if (this.options.ecmaVersion >= 6) {
    this.next();

    var innerStartPos = this.start, innerStartLoc = this.startLoc;
    var exprList = [], first = true, lastIsComma = false;
    var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
    this.yieldPos = 0;
    this.awaitPos = 0;
    // Do not save awaitIdentPos to allow checking awaits nested in parameters
    while (this.type !== types$1.parenR) {
      first ? first = false : this.expect(types$1.comma);
      if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) {
        lastIsComma = true;
        break
      } else if (this.type === types$1.ellipsis) {
        spreadStart = this.start;
        exprList.push(this.parseParenItem(this.parseRestBinding()));
        if (this.type === types$1.comma) {
          this.raiseRecoverable(
            this.start,
            "Comma is not permitted after the rest element"
          );
        }
        break
      } else {
        exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
      }
    }
    var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc;
    this.expect(types$1.parenR);

    if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(types$1.arrow)) {
      this.checkPatternErrors(refDestructuringErrors, false);
      this.checkYieldAwaitInDefaultParams();
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      return this.parseParenArrowList(startPos, startLoc, exprList, forInit)
    }

    if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
    if (spreadStart) { this.unexpected(spreadStart); }
    this.checkExpressionErrors(refDestructuringErrors, true);
    this.yieldPos = oldYieldPos || this.yieldPos;
    this.awaitPos = oldAwaitPos || this.awaitPos;

    if (exprList.length > 1) {
      val = this.startNodeAt(innerStartPos, innerStartLoc);
      val.expressions = exprList;
      this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
    } else {
      val = exprList[0];
    }
  } else {
    val = this.parseParenExpression();
  }

  if (this.options.preserveParens) {
    var par = this.startNodeAt(startPos, startLoc);
    par.expression = val;
    return this.finishNode(par, "ParenthesizedExpression")
  } else {
    return val
  }
};

pp$5.parseParenItem = function(item) {
  return item
};

pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) {
  return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit)
};

// New's precedence is slightly tricky. It must allow its argument to
// be a `[]` or dot subscript expression, but not a call — at least,
// not without wrapping it in parentheses. Thus, it uses the noCalls
// argument to parseSubscripts to prevent it from consuming the
// argument list.

var acorn_empty = [];

pp$5.parseNew = function() {
  if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
  var node = this.startNode();
  this.next();
  if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) {
    var meta = this.startNodeAt(node.start, node.loc && node.loc.start);
    meta.name = "new";
    node.meta = this.finishNode(meta, "Identifier");
    this.next();
    var containsEsc = this.containsEsc;
    node.property = this.parseIdent(true);
    if (node.property.name !== "target")
      { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); }
    if (containsEsc)
      { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); }
    if (!this.allowNewDotTarget)
      { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); }
    return this.finishNode(node, "MetaProperty")
  }
  var startPos = this.start, startLoc = this.startLoc;
  node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false);
  if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); }
  else { node.arguments = acorn_empty; }
  return this.finishNode(node, "NewExpression")
};

// Parse template expression.

pp$5.parseTemplateElement = function(ref) {
  var isTagged = ref.isTagged;

  var elem = this.startNode();
  if (this.type === types$1.invalidTemplate) {
    if (!isTagged) {
      this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
    }
    elem.value = {
      raw: this.value.replace(/\r\n?/g, "\n"),
      cooked: null
    };
  } else {
    elem.value = {
      raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
      cooked: this.value
    };
  }
  this.next();
  elem.tail = this.type === types$1.backQuote;
  return this.finishNode(elem, "TemplateElement")
};

pp$5.parseTemplate = function(ref) {
  if ( ref === void 0 ) ref = {};
  var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;

  var node = this.startNode();
  this.next();
  node.expressions = [];
  var curElt = this.parseTemplateElement({isTagged: isTagged});
  node.quasis = [curElt];
  while (!curElt.tail) {
    if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); }
    this.expect(types$1.dollarBraceL);
    node.expressions.push(this.parseExpression());
    this.expect(types$1.braceR);
    node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
  }
  this.next();
  return this.finishNode(node, "TemplateLiteral")
};

pp$5.isAsyncProp = function(prop) {
  return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
    (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) &&
    !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

// Parse an object literal or binding pattern.

pp$5.parseObj = function(isPattern, refDestructuringErrors) {
  var node = this.startNode(), first = true, propHash = {};
  node.properties = [];
  this.next();
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    var prop = this.parseProperty(isPattern, refDestructuringErrors);
    if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
    node.properties.push(prop);
  }
  return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
};

pp$5.parseProperty = function(isPattern, refDestructuringErrors) {
  var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
  if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) {
    if (isPattern) {
      prop.argument = this.parseIdent(false);
      if (this.type === types$1.comma) {
        this.raiseRecoverable(this.start, "Comma is not permitted after the rest element");
      }
      return this.finishNode(prop, "RestElement")
    }
    // Parse argument.
    prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
    // To disallow trailing comma via `this.toAssignable()`.
    if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
      refDestructuringErrors.trailingComma = this.start;
    }
    // Finish
    return this.finishNode(prop, "SpreadElement")
  }
  if (this.options.ecmaVersion >= 6) {
    prop.method = false;
    prop.shorthand = false;
    if (isPattern || refDestructuringErrors) {
      startPos = this.start;
      startLoc = this.startLoc;
    }
    if (!isPattern)
      { isGenerator = this.eat(types$1.star); }
  }
  var containsEsc = this.containsEsc;
  this.parsePropertyName(prop);
  if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
    isAsync = true;
    isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star);
    this.parsePropertyName(prop);
  } else {
    isAsync = false;
  }
  this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
  return this.finishNode(prop, "Property")
};

pp$5.parseGetterSetter = function(prop) {
  var kind = prop.key.name;
  this.parsePropertyName(prop);
  prop.value = this.parseMethod(false);
  prop.kind = kind;
  var paramCount = prop.kind === "get" ? 0 : 1;
  if (prop.value.params.length !== paramCount) {
    var start = prop.value.start;
    if (prop.kind === "get")
      { this.raiseRecoverable(start, "getter should have no params"); }
    else
      { this.raiseRecoverable(start, "setter should have exactly one param"); }
  } else {
    if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
      { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
  }
};

pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
  if ((isGenerator || isAsync) && this.type === types$1.colon)
    { this.unexpected(); }

  if (this.eat(types$1.colon)) {
    prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
    prop.kind = "init";
  } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) {
    if (isPattern) { this.unexpected(); }
    prop.method = true;
    prop.value = this.parseMethod(isGenerator, isAsync);
    prop.kind = "init";
  } else if (!isPattern && !containsEsc &&
             this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
             (prop.key.name === "get" || prop.key.name === "set") &&
             (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) {
    if (isGenerator || isAsync) { this.unexpected(); }
    this.parseGetterSetter(prop);
  } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
    if (isGenerator || isAsync) { this.unexpected(); }
    this.checkUnreserved(prop.key);
    if (prop.key.name === "await" && !this.awaitIdentPos)
      { this.awaitIdentPos = startPos; }
    if (isPattern) {
      prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
    } else if (this.type === types$1.eq && refDestructuringErrors) {
      if (refDestructuringErrors.shorthandAssign < 0)
        { refDestructuringErrors.shorthandAssign = this.start; }
      prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
    } else {
      prop.value = this.copyNode(prop.key);
    }
    prop.kind = "init";
    prop.shorthand = true;
  } else { this.unexpected(); }
};

pp$5.parsePropertyName = function(prop) {
  if (this.options.ecmaVersion >= 6) {
    if (this.eat(types$1.bracketL)) {
      prop.computed = true;
      prop.key = this.parseMaybeAssign();
      this.expect(types$1.bracketR);
      return prop.key
    } else {
      prop.computed = false;
    }
  }
  return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
};

// Initialize empty function node.

pp$5.initFunction = function(node) {
  node.id = null;
  if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
  if (this.options.ecmaVersion >= 8) { node.async = false; }
};

// Parse object or class method.

pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
  var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;

  this.initFunction(node);
  if (this.options.ecmaVersion >= 6)
    { node.generator = isGenerator; }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;
  this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));

  this.expect(types$1.parenL);
  node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
  this.parseFunctionBody(node, false, true, false);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, "FunctionExpression")
};

// Parse arrow function expression with given parameters.

pp$5.parseArrowExpression = function(node, params, isAsync, forInit) {
  var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;

  this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
  this.initFunction(node);
  if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }

  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;

  node.params = this.toAssignableList(params, true);
  this.parseFunctionBody(node, true, false, forInit);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, "ArrowFunctionExpression")
};

// Parse function body and check parameters.

pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) {
  var isExpression = isArrowFunction && this.type !== types$1.braceL;
  var oldStrict = this.strict, useStrict = false;

  if (isExpression) {
    node.body = this.parseMaybeAssign(forInit);
    node.expression = true;
    this.checkParams(node, false);
  } else {
    var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
    if (!oldStrict || nonSimple) {
      useStrict = this.strictDirective(this.end);
      // If this is a strict mode function, verify that argument names
      // are not repeated, and it does not try to bind the words `eval`
      // or `arguments`.
      if (useStrict && nonSimple)
        { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
    }
    // Start a new scope with regard to labels and the `inFunction`
    // flag (restore them to their old value afterwards).
    var oldLabels = this.labels;
    this.labels = [];
    if (useStrict) { this.strict = true; }

    // Add the params to varDeclaredNames to ensure that an error is thrown
    // if a let/const declaration in the function clashes with one of the params.
    this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
    // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
    if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); }
    node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
    node.expression = false;
    this.adaptDirectivePrologue(node.body.body);
    this.labels = oldLabels;
  }
  this.exitScope();
};

pp$5.isSimpleParamList = function(params) {
  for (var i = 0, list = params; i < list.length; i += 1)
    {
    var param = list[i];

    if (param.type !== "Identifier") { return false
  } }
  return true
};

// Checks function params for various disallowed patterns such as using "eval"
// or "arguments" and duplicate parameters.

pp$5.checkParams = function(node, allowDuplicates) {
  var nameHash = Object.create(null);
  for (var i = 0, list = node.params; i < list.length; i += 1)
    {
    var param = list[i];

    this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash);
  }
};

// Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with
// nothing in between them to be parsed as `null` (which is needed
// for array literals).

pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
  var elts = [], first = true;
  while (!this.eat(close)) {
    if (!first) {
      this.expect(types$1.comma);
      if (allowTrailingComma && this.afterTrailingComma(close)) { break }
    } else { first = false; }

    var elt = (void 0);
    if (allowEmpty && this.type === types$1.comma)
      { elt = null; }
    else if (this.type === types$1.ellipsis) {
      elt = this.parseSpread(refDestructuringErrors);
      if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0)
        { refDestructuringErrors.trailingComma = this.start; }
    } else {
      elt = this.parseMaybeAssign(false, refDestructuringErrors);
    }
    elts.push(elt);
  }
  return elts
};

pp$5.checkUnreserved = function(ref) {
  var start = ref.start;
  var end = ref.end;
  var name = ref.name;

  if (this.inGenerator && name === "yield")
    { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
  if (this.inAsync && name === "await")
    { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
  if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments")
    { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); }
  if (this.inClassStaticBlock && (name === "arguments" || name === "await"))
    { this.raise(start, ("Cannot use " + name + " in class static initialization block")); }
  if (this.keywords.test(name))
    { this.raise(start, ("Unexpected keyword '" + name + "'")); }
  if (this.options.ecmaVersion < 6 &&
    this.input.slice(start, end).indexOf("\\") !== -1) { return }
  var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
  if (re.test(name)) {
    if (!this.inAsync && name === "await")
      { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
    this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
  }
};

// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.

pp$5.parseIdent = function(liberal) {
  var node = this.parseIdentNode();
  this.next(!!liberal);
  this.finishNode(node, "Identifier");
  if (!liberal) {
    this.checkUnreserved(node);
    if (node.name === "await" && !this.awaitIdentPos)
      { this.awaitIdentPos = node.start; }
  }
  return node
};

pp$5.parseIdentNode = function() {
  var node = this.startNode();
  if (this.type === types$1.name) {
    node.name = this.value;
  } else if (this.type.keyword) {
    node.name = this.type.keyword;

    // To fix https://github.com/acornjs/acorn/issues/575
    // `class` and `function` keywords push new context into this.context.
    // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
    // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
    if ((node.name === "class" || node.name === "function") &&
      (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
      this.context.pop();
    }
    this.type = types$1.name;
  } else {
    this.unexpected();
  }
  return node
};

pp$5.parsePrivateIdent = function() {
  var node = this.startNode();
  if (this.type === types$1.privateId) {
    node.name = this.value;
  } else {
    this.unexpected();
  }
  this.next();
  this.finishNode(node, "PrivateIdentifier");

  // For validating existence
  if (this.options.checkPrivateFields) {
    if (this.privateNameStack.length === 0) {
      this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class"));
    } else {
      this.privateNameStack[this.privateNameStack.length - 1].used.push(node);
    }
  }

  return node
};

// Parses yield expression inside generator.

pp$5.parseYield = function(forInit) {
  if (!this.yieldPos) { this.yieldPos = this.start; }

  var node = this.startNode();
  this.next();
  if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) {
    node.delegate = false;
    node.argument = null;
  } else {
    node.delegate = this.eat(types$1.star);
    node.argument = this.parseMaybeAssign(forInit);
  }
  return this.finishNode(node, "YieldExpression")
};

pp$5.parseAwait = function(forInit) {
  if (!this.awaitPos) { this.awaitPos = this.start; }

  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeUnary(null, true, false, forInit);
  return this.finishNode(node, "AwaitExpression")
};

var pp$4 = Parser.prototype;

// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.

pp$4.raise = function(pos, message) {
  var loc = getLineInfo(this.input, pos);
  message += " (" + loc.line + ":" + loc.column + ")";
  if (this.sourceFile) {
    message += " in " + this.sourceFile;
  }
  var err = new SyntaxError(message);
  err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
  throw err
};

pp$4.raiseRecoverable = pp$4.raise;

pp$4.curPosition = function() {
  if (this.options.locations) {
    return new Position(this.curLine, this.pos - this.lineStart)
  }
};

var pp$3 = Parser.prototype;

var Scope = function Scope(flags) {
  this.flags = flags;
  // A list of var-declared names in the current lexical scope
  this.var = [];
  // A list of lexically-declared names in the current lexical scope
  this.lexical = [];
  // A list of lexically-declared FunctionDeclaration names in the current lexical scope
  this.functions = [];
};

// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.

pp$3.enterScope = function(flags) {
  this.scopeStack.push(new Scope(flags));
};

pp$3.exitScope = function() {
  this.scopeStack.pop();
};

// The spec says:
// > At the top level of a function, or script, function declarations are
// > treated like var declarations rather than like lexical declarations.
pp$3.treatFunctionsAsVarInScope = function(scope) {
  return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
};

pp$3.declareName = function(name, bindingType, pos) {
  var redeclared = false;
  if (bindingType === BIND_LEXICAL) {
    var scope = this.currentScope();
    redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
    scope.lexical.push(name);
    if (this.inModule && (scope.flags & SCOPE_TOP))
      { delete this.undefinedExports[name]; }
  } else if (bindingType === BIND_SIMPLE_CATCH) {
    var scope$1 = this.currentScope();
    scope$1.lexical.push(name);
  } else if (bindingType === BIND_FUNCTION) {
    var scope$2 = this.currentScope();
    if (this.treatFunctionsAsVar)
      { redeclared = scope$2.lexical.indexOf(name) > -1; }
    else
      { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
    scope$2.functions.push(name);
  } else {
    for (var i = this.scopeStack.length - 1; i >= 0; --i) {
      var scope$3 = this.scopeStack[i];
      if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
          !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
        redeclared = true;
        break
      }
      scope$3.var.push(name);
      if (this.inModule && (scope$3.flags & SCOPE_TOP))
        { delete this.undefinedExports[name]; }
      if (scope$3.flags & SCOPE_VAR) { break }
    }
  }
  if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
};

pp$3.checkLocalExport = function(id) {
  // scope.functions must be empty as Module code is always strict.
  if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
      this.scopeStack[0].var.indexOf(id.name) === -1) {
    this.undefinedExports[id.name] = id;
  }
};

pp$3.currentScope = function() {
  return this.scopeStack[this.scopeStack.length - 1]
};

pp$3.currentVarScope = function() {
  for (var i = this.scopeStack.length - 1;; i--) {
    var scope = this.scopeStack[i];
    if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) { return scope }
  }
};

// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
pp$3.currentThisScope = function() {
  for (var i = this.scopeStack.length - 1;; i--) {
    var scope = this.scopeStack[i];
    if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) &&
        !(scope.flags & SCOPE_ARROW)) { return scope }
  }
};

var extension_Node = function Node(parser, pos, loc) {
  this.type = "";
  this.start = pos;
  this.end = 0;
  if (parser.options.locations)
    { this.loc = new SourceLocation(parser, loc); }
  if (parser.options.directSourceFile)
    { this.sourceFile = parser.options.directSourceFile; }
  if (parser.options.ranges)
    { this.range = [pos, 0]; }
};

// Start an AST node, attaching a start offset.

var pp$2 = Parser.prototype;

pp$2.startNode = function() {
  return new extension_Node(this, this.start, this.startLoc)
};

pp$2.startNodeAt = function(pos, loc) {
  return new extension_Node(this, pos, loc)
};

// Finish an AST node, adding `type` and `end` properties.

function finishNodeAt(node, type, pos, loc) {
  node.type = type;
  node.end = pos;
  if (this.options.locations)
    { node.loc.end = loc; }
  if (this.options.ranges)
    { node.range[1] = pos; }
  return node
}

pp$2.finishNode = function(node, type) {
  return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
};

// Finish node at given position

pp$2.finishNodeAt = function(node, type, pos, loc) {
  return finishNodeAt.call(this, node, type, pos, loc)
};

pp$2.copyNode = function(node) {
  var newNode = new extension_Node(this, node.start, this.startLoc);
  for (var prop in node) { newNode[prop] = node[prop]; }
  return newNode
};

// This file was generated by "bin/generate-unicode-script-values.js". Do not modify manually!
var scriptValuesAddedInUnicode = "Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz";

// This file contains Unicode properties extracted from the ECMAScript specification.
// The lists are extracted like so:
// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)

// #table-binary-unicode-properties
var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS";
var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
var ecma11BinaryProperties = ecma10BinaryProperties;
var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict";
var ecma13BinaryProperties = ecma12BinaryProperties;
var ecma14BinaryProperties = ecma13BinaryProperties;

var unicodeBinaryProperties = {
  9: ecma9BinaryProperties,
  10: ecma10BinaryProperties,
  11: ecma11BinaryProperties,
  12: ecma12BinaryProperties,
  13: ecma13BinaryProperties,
  14: ecma14BinaryProperties
};

// #table-binary-unicode-properties-of-strings
var ecma14BinaryPropertiesOfStrings = "Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji";

var unicodeBinaryPropertiesOfStrings = {
  9: "",
  10: "",
  11: "",
  12: "",
  13: "",
  14: ecma14BinaryPropertiesOfStrings
};

// #table-unicode-general-category-values
var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu";

// #table-unicode-script-values
var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb";
var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi";
var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith";
var ecma14ScriptValues = ecma13ScriptValues + " " + scriptValuesAddedInUnicode;

var unicodeScriptValues = {
  9: ecma9ScriptValues,
  10: ecma10ScriptValues,
  11: ecma11ScriptValues,
  12: ecma12ScriptValues,
  13: ecma13ScriptValues,
  14: ecma14ScriptValues
};

var acorn_data = {};
function buildUnicodeData(ecmaVersion) {
  var d = acorn_data[ecmaVersion] = {
    binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
    binaryOfStrings: wordsRegexp(unicodeBinaryPropertiesOfStrings[ecmaVersion]),
    nonBinary: {
      General_Category: wordsRegexp(unicodeGeneralCategoryValues),
      Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
    }
  };
  d.nonBinary.Script_Extensions = d.nonBinary.Script;

  d.nonBinary.gc = d.nonBinary.General_Category;
  d.nonBinary.sc = d.nonBinary.Script;
  d.nonBinary.scx = d.nonBinary.Script_Extensions;
}

for (var i = 0, acorn_list = [9, 10, 11, 12, 13, 14]; i < acorn_list.length; i += 1) {
  var ecmaVersion = acorn_list[i];

  buildUnicodeData(ecmaVersion);
}

var pp$1 = Parser.prototype;

// Track disjunction structure to determine whether a duplicate
// capture group name is allowed because it is in a separate branch.
var BranchID = function BranchID(parent, base) {
  // Parent disjunction branch
  this.parent = parent;
  // Identifies this set of sibling branches
  this.base = base || this;
};

BranchID.prototype.separatedFrom = function separatedFrom (alt) {
  // A branch is separate from another branch if they or any of
  // their parents are siblings in a given disjunction
  for (var self = this; self; self = self.parent) {
    for (var other = alt; other; other = other.parent) {
      if (self.base === other.base && self !== other) { return true }
    }
  }
  return false
};

BranchID.prototype.sibling = function sibling () {
  return new BranchID(this.parent, this.base)
};

var RegExpValidationState = function RegExpValidationState(parser) {
  this.parser = parser;
  this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : "");
  this.unicodeProperties = acorn_data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion];
  this.source = "";
  this.flags = "";
  this.start = 0;
  this.switchU = false;
  this.switchV = false;
  this.switchN = false;
  this.pos = 0;
  this.lastIntValue = 0;
  this.lastStringValue = "";
  this.lastAssertionIsQuantifiable = false;
  this.numCapturingParens = 0;
  this.maxBackReference = 0;
  this.groupNames = Object.create(null);
  this.backReferenceNames = [];
  this.branchID = null;
};

RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
  var unicodeSets = flags.indexOf("v") !== -1;
  var unicode = flags.indexOf("u") !== -1;
  this.start = start | 0;
  this.source = pattern + "";
  this.flags = flags;
  if (unicodeSets && this.parser.options.ecmaVersion >= 15) {
    this.switchU = true;
    this.switchV = true;
    this.switchN = true;
  } else {
    this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
    this.switchV = false;
    this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
  }
};

RegExpValidationState.prototype.raise = function raise (message) {
  this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
};

// If u flag is given, this returns the code point at the index (it combines a surrogate pair).
// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
RegExpValidationState.prototype.at = function at (i, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var s = this.source;
  var l = s.length;
  if (i >= l) {
    return -1
  }
  var c = s.charCodeAt(i);
  if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
    return c
  }
  var next = s.charCodeAt(i + 1);
  return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
};

RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var s = this.source;
  var l = s.length;
  if (i >= l) {
    return l
  }
  var c = s.charCodeAt(i), next;
  if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
      (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
    return i + 1
  }
  return i + 2
};

RegExpValidationState.prototype.current = function current (forceU) {
    if ( forceU === void 0 ) forceU = false;

  return this.at(this.pos, forceU)
};

RegExpValidationState.prototype.lookahead = function lookahead (forceU) {
    if ( forceU === void 0 ) forceU = false;

  return this.at(this.nextIndex(this.pos, forceU), forceU)
};

RegExpValidationState.prototype.advance = function advance (forceU) {
    if ( forceU === void 0 ) forceU = false;

  this.pos = this.nextIndex(this.pos, forceU);
};

RegExpValidationState.prototype.eat = function eat (ch, forceU) {
    if ( forceU === void 0 ) forceU = false;

  if (this.current(forceU) === ch) {
    this.advance(forceU);
    return true
  }
  return false
};

RegExpValidationState.prototype.eatChars = function eatChars (chs, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var pos = this.pos;
  for (var i = 0, list = chs; i < list.length; i += 1) {
    var ch = list[i];

      var current = this.at(pos, forceU);
    if (current === -1 || current !== ch) {
      return false
    }
    pos = this.nextIndex(pos, forceU);
  }
  this.pos = pos;
  return true
};

/**
 * Validate the flags part of a given RegExpLiteral.
 *
 * @param {RegExpValidationState} state The state to validate RegExp.
 * @returns {void}
 */
pp$1.validateRegExpFlags = function(state) {
  var validFlags = state.validFlags;
  var flags = state.flags;

  var u = false;
  var v = false;

  for (var i = 0; i < flags.length; i++) {
    var flag = flags.charAt(i);
    if (validFlags.indexOf(flag) === -1) {
      this.raise(state.start, "Invalid regular expression flag");
    }
    if (flags.indexOf(flag, i + 1) > -1) {
      this.raise(state.start, "Duplicate regular expression flag");
    }
    if (flag === "u") { u = true; }
    if (flag === "v") { v = true; }
  }
  if (this.options.ecmaVersion >= 15 && u && v) {
    this.raise(state.start, "Invalid regular expression flag");
  }
};

function hasProp(obj) {
  for (var _ in obj) { return true }
  return false
}

/**
 * Validate the pattern part of a given RegExpLiteral.
 *
 * @param {RegExpValidationState} state The state to validate RegExp.
 * @returns {void}
 */
pp$1.validateRegExpPattern = function(state) {
  this.regexp_pattern(state);

  // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
  // parsing contains a |GroupName|, reparse with the goal symbol
  // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
  // exception if _P_ did not conform to the grammar, if any elements of _P_
  // were not matched by the parse, or if any Early Error conditions exist.
  if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) {
    state.switchN = true;
    this.regexp_pattern(state);
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
pp$1.regexp_pattern = function(state) {
  state.pos = 0;
  state.lastIntValue = 0;
  state.lastStringValue = "";
  state.lastAssertionIsQuantifiable = false;
  state.numCapturingParens = 0;
  state.maxBackReference = 0;
  state.groupNames = Object.create(null);
  state.backReferenceNames.length = 0;
  state.branchID = null;

  this.regexp_disjunction(state);

  if (state.pos !== state.source.length) {
    // Make the same messages as V8.
    if (state.eat(0x29 /* ) */)) {
      state.raise("Unmatched ')'");
    }
    if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
      state.raise("Lone quantifier brackets");
    }
  }
  if (state.maxBackReference > state.numCapturingParens) {
    state.raise("Invalid escape");
  }
  for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
    var name = list[i];

    if (!state.groupNames[name]) {
      state.raise("Invalid named capture referenced");
    }
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
pp$1.regexp_disjunction = function(state) {
  var trackDisjunction = this.options.ecmaVersion >= 16;
  if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); }
  this.regexp_alternative(state);
  while (state.eat(0x7C /* | */)) {
    if (trackDisjunction) { state.branchID = state.branchID.sibling(); }
    this.regexp_alternative(state);
  }
  if (trackDisjunction) { state.branchID = state.branchID.parent; }

  // Make the same message as V8.
  if (this.regexp_eatQuantifier(state, true)) {
    state.raise("Nothing to repeat");
  }
  if (state.eat(0x7B /* { */)) {
    state.raise("Lone quantifier brackets");
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
pp$1.regexp_alternative = function(state) {
  while (state.pos < state.source.length && this.regexp_eatTerm(state)) {}
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
pp$1.regexp_eatTerm = function(state) {
  if (this.regexp_eatAssertion(state)) {
    // Handle `QuantifiableAssertion Quantifier` alternative.
    // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
    // is a QuantifiableAssertion.
    if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
      // Make the same message as V8.
      if (state.switchU) {
        state.raise("Invalid quantifier");
      }
    }
    return true
  }

  if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
    this.regexp_eatQuantifier(state);
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
pp$1.regexp_eatAssertion = function(state) {
  var start = state.pos;
  state.lastAssertionIsQuantifiable = false;

  // ^, $
  if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
    return true
  }

  // \b \B
  if (state.eat(0x5C /* \ */)) {
    if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
      return true
    }
    state.pos = start;
  }

  // Lookahead / Lookbehind
  if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
    var lookbehind = false;
    if (this.options.ecmaVersion >= 9) {
      lookbehind = state.eat(0x3C /* < */);
    }
    if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
      this.regexp_disjunction(state);
      if (!state.eat(0x29 /* ) */)) {
        state.raise("Unterminated group");
      }
      state.lastAssertionIsQuantifiable = !lookbehind;
      return true
    }
  }

  state.pos = start;
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
pp$1.regexp_eatQuantifier = function(state, noError) {
  if ( noError === void 0 ) noError = false;

  if (this.regexp_eatQuantifierPrefix(state, noError)) {
    state.eat(0x3F /* ? */);
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
pp$1.regexp_eatQuantifierPrefix = function(state, noError) {
  return (
    state.eat(0x2A /* * */) ||
    state.eat(0x2B /* + */) ||
    state.eat(0x3F /* ? */) ||
    this.regexp_eatBracedQuantifier(state, noError)
  )
};
pp$1.regexp_eatBracedQuantifier = function(state, noError) {
  var start = state.pos;
  if (state.eat(0x7B /* { */)) {
    var min = 0, max = -1;
    if (this.regexp_eatDecimalDigits(state)) {
      min = state.lastIntValue;
      if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
        max = state.lastIntValue;
      }
      if (state.eat(0x7D /* } */)) {
        // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
        if (max !== -1 && max < min && !noError) {
          state.raise("numbers out of order in {} quantifier");
        }
        return true
      }
    }
    if (state.switchU && !noError) {
      state.raise("Incomplete quantifier");
    }
    state.pos = start;
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
pp$1.regexp_eatAtom = function(state) {
  return (
    this.regexp_eatPatternCharacters(state) ||
    state.eat(0x2E /* . */) ||
    this.regexp_eatReverseSolidusAtomEscape(state) ||
    this.regexp_eatCharacterClass(state) ||
    this.regexp_eatUncapturingGroup(state) ||
    this.regexp_eatCapturingGroup(state)
  )
};
pp$1.regexp_eatReverseSolidusAtomEscape = function(state) {
  var start = state.pos;
  if (state.eat(0x5C /* \ */)) {
    if (this.regexp_eatAtomEscape(state)) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatUncapturingGroup = function(state) {
  var start = state.pos;
  if (state.eat(0x28 /* ( */)) {
    if (state.eat(0x3F /* ? */)) {
      if (this.options.ecmaVersion >= 16) {
        var addModifiers = this.regexp_eatModifiers(state);
        var hasHyphen = state.eat(0x2D /* - */);
        if (addModifiers || hasHyphen) {
          for (var i = 0; i < addModifiers.length; i++) {
            var modifier = addModifiers.charAt(i);
            if (addModifiers.indexOf(modifier, i + 1) > -1) {
              state.raise("Duplicate regular expression modifiers");
            }
          }
          if (hasHyphen) {
            var removeModifiers = this.regexp_eatModifiers(state);
            if (!addModifiers && !removeModifiers && state.current() === 0x3A /* : */) {
              state.raise("Invalid regular expression modifiers");
            }
            for (var i$1 = 0; i$1 < removeModifiers.length; i$1++) {
              var modifier$1 = removeModifiers.charAt(i$1);
              if (
                removeModifiers.indexOf(modifier$1, i$1 + 1) > -1 ||
                addModifiers.indexOf(modifier$1) > -1
              ) {
                state.raise("Duplicate regular expression modifiers");
              }
            }
          }
        }
      }
      if (state.eat(0x3A /* : */)) {
        this.regexp_disjunction(state);
        if (state.eat(0x29 /* ) */)) {
          return true
        }
        state.raise("Unterminated group");
      }
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatCapturingGroup = function(state) {
  if (state.eat(0x28 /* ( */)) {
    if (this.options.ecmaVersion >= 9) {
      this.regexp_groupSpecifier(state);
    } else if (state.current() === 0x3F /* ? */) {
      state.raise("Invalid group");
    }
    this.regexp_disjunction(state);
    if (state.eat(0x29 /* ) */)) {
      state.numCapturingParens += 1;
      return true
    }
    state.raise("Unterminated group");
  }
  return false
};
// RegularExpressionModifiers ::
//   [empty]
//   RegularExpressionModifiers RegularExpressionModifier
pp$1.regexp_eatModifiers = function(state) {
  var modifiers = "";
  var ch = 0;
  while ((ch = state.current()) !== -1 && isRegularExpressionModifier(ch)) {
    modifiers += codePointToString(ch);
    state.advance();
  }
  return modifiers
};
// RegularExpressionModifier :: one of
//   `i` `m` `s`
function isRegularExpressionModifier(ch) {
  return ch === 0x69 /* i */ || ch === 0x6d /* m */ || ch === 0x73 /* s */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
pp$1.regexp_eatExtendedAtom = function(state) {
  return (
    state.eat(0x2E /* . */) ||
    this.regexp_eatReverseSolidusAtomEscape(state) ||
    this.regexp_eatCharacterClass(state) ||
    this.regexp_eatUncapturingGroup(state) ||
    this.regexp_eatCapturingGroup(state) ||
    this.regexp_eatInvalidBracedQuantifier(state) ||
    this.regexp_eatExtendedPatternCharacter(state)
  )
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
pp$1.regexp_eatInvalidBracedQuantifier = function(state) {
  if (this.regexp_eatBracedQuantifier(state, true)) {
    state.raise("Nothing to repeat");
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
pp$1.regexp_eatSyntaxCharacter = function(state) {
  var ch = state.current();
  if (isSyntaxCharacter(ch)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }
  return false
};
function isSyntaxCharacter(ch) {
  return (
    ch === 0x24 /* $ */ ||
    ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
    ch === 0x2E /* . */ ||
    ch === 0x3F /* ? */ ||
    ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
    ch >= 0x7B /* { */ && ch <= 0x7D /* } */
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
// But eat eager.
pp$1.regexp_eatPatternCharacters = function(state) {
  var start = state.pos;
  var ch = 0;
  while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
    state.advance();
  }
  return state.pos !== start
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
pp$1.regexp_eatExtendedPatternCharacter = function(state) {
  var ch = state.current();
  if (
    ch !== -1 &&
    ch !== 0x24 /* $ */ &&
    !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
    ch !== 0x2E /* . */ &&
    ch !== 0x3F /* ? */ &&
    ch !== 0x5B /* [ */ &&
    ch !== 0x5E /* ^ */ &&
    ch !== 0x7C /* | */
  ) {
    state.advance();
    return true
  }
  return false
};

// GroupSpecifier ::
//   [empty]
//   `?` GroupName
pp$1.regexp_groupSpecifier = function(state) {
  if (state.eat(0x3F /* ? */)) {
    if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); }
    var trackDisjunction = this.options.ecmaVersion >= 16;
    var known = state.groupNames[state.lastStringValue];
    if (known) {
      if (trackDisjunction) {
        for (var i = 0, list = known; i < list.length; i += 1) {
          var altID = list[i];

          if (!altID.separatedFrom(state.branchID))
            { state.raise("Duplicate capture group name"); }
        }
      } else {
        state.raise("Duplicate capture group name");
      }
    }
    if (trackDisjunction) {
      (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID);
    } else {
      state.groupNames[state.lastStringValue] = true;
    }
  }
};

// GroupName ::
//   `<` RegExpIdentifierName `>`
// Note: this updates `state.lastStringValue` property with the eaten name.
pp$1.regexp_eatGroupName = function(state) {
  state.lastStringValue = "";
  if (state.eat(0x3C /* < */)) {
    if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
      return true
    }
    state.raise("Invalid capture group name");
  }
  return false
};

// RegExpIdentifierName ::
//   RegExpIdentifierStart
//   RegExpIdentifierName RegExpIdentifierPart
// Note: this updates `state.lastStringValue` property with the eaten name.
pp$1.regexp_eatRegExpIdentifierName = function(state) {
  state.lastStringValue = "";
  if (this.regexp_eatRegExpIdentifierStart(state)) {
    state.lastStringValue += codePointToString(state.lastIntValue);
    while (this.regexp_eatRegExpIdentifierPart(state)) {
      state.lastStringValue += codePointToString(state.lastIntValue);
    }
    return true
  }
  return false
};

// RegExpIdentifierStart ::
//   UnicodeIDStart
//   `$`
//   `_`
//   `\` RegExpUnicodeEscapeSequence[+U]
pp$1.regexp_eatRegExpIdentifierStart = function(state) {
  var start = state.pos;
  var forceU = this.options.ecmaVersion >= 11;
  var ch = state.current(forceU);
  state.advance(forceU);

  if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
    ch = state.lastIntValue;
  }
  if (isRegExpIdentifierStart(ch)) {
    state.lastIntValue = ch;
    return true
  }

  state.pos = start;
  return false
};
function isRegExpIdentifierStart(ch) {
  return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
}

// RegExpIdentifierPart ::
//   UnicodeIDContinue
//   `$`
//   `_`
//   `\` RegExpUnicodeEscapeSequence[+U]
//   <ZWNJ>
//   <ZWJ>
pp$1.regexp_eatRegExpIdentifierPart = function(state) {
  var start = state.pos;
  var forceU = this.options.ecmaVersion >= 11;
  var ch = state.current(forceU);
  state.advance(forceU);

  if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
    ch = state.lastIntValue;
  }
  if (isRegExpIdentifierPart(ch)) {
    state.lastIntValue = ch;
    return true
  }

  state.pos = start;
  return false
};
function isRegExpIdentifierPart(ch) {
  return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
pp$1.regexp_eatAtomEscape = function(state) {
  if (
    this.regexp_eatBackReference(state) ||
    this.regexp_eatCharacterClassEscape(state) ||
    this.regexp_eatCharacterEscape(state) ||
    (state.switchN && this.regexp_eatKGroupName(state))
  ) {
    return true
  }
  if (state.switchU) {
    // Make the same message as V8.
    if (state.current() === 0x63 /* c */) {
      state.raise("Invalid unicode escape");
    }
    state.raise("Invalid escape");
  }
  return false
};
pp$1.regexp_eatBackReference = function(state) {
  var start = state.pos;
  if (this.regexp_eatDecimalEscape(state)) {
    var n = state.lastIntValue;
    if (state.switchU) {
      // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
      if (n > state.maxBackReference) {
        state.maxBackReference = n;
      }
      return true
    }
    if (n <= state.numCapturingParens) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatKGroupName = function(state) {
  if (state.eat(0x6B /* k */)) {
    if (this.regexp_eatGroupName(state)) {
      state.backReferenceNames.push(state.lastStringValue);
      return true
    }
    state.raise("Invalid named reference");
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
pp$1.regexp_eatCharacterEscape = function(state) {
  return (
    this.regexp_eatControlEscape(state) ||
    this.regexp_eatCControlLetter(state) ||
    this.regexp_eatZero(state) ||
    this.regexp_eatHexEscapeSequence(state) ||
    this.regexp_eatRegExpUnicodeEscapeSequence(state, false) ||
    (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
    this.regexp_eatIdentityEscape(state)
  )
};
pp$1.regexp_eatCControlLetter = function(state) {
  var start = state.pos;
  if (state.eat(0x63 /* c */)) {
    if (this.regexp_eatControlLetter(state)) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatZero = function(state) {
  if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
    state.lastIntValue = 0;
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
pp$1.regexp_eatControlEscape = function(state) {
  var ch = state.current();
  if (ch === 0x74 /* t */) {
    state.lastIntValue = 0x09; /* \t */
    state.advance();
    return true
  }
  if (ch === 0x6E /* n */) {
    state.lastIntValue = 0x0A; /* \n */
    state.advance();
    return true
  }
  if (ch === 0x76 /* v */) {
    state.lastIntValue = 0x0B; /* \v */
    state.advance();
    return true
  }
  if (ch === 0x66 /* f */) {
    state.lastIntValue = 0x0C; /* \f */
    state.advance();
    return true
  }
  if (ch === 0x72 /* r */) {
    state.lastIntValue = 0x0D; /* \r */
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
pp$1.regexp_eatControlLetter = function(state) {
  var ch = state.current();
  if (isControlLetter(ch)) {
    state.lastIntValue = ch % 0x20;
    state.advance();
    return true
  }
  return false
};
function isControlLetter(ch) {
  return (
    (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
    (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) {
  if ( forceU === void 0 ) forceU = false;

  var start = state.pos;
  var switchU = forceU || state.switchU;

  if (state.eat(0x75 /* u */)) {
    if (this.regexp_eatFixedHexDigits(state, 4)) {
      var lead = state.lastIntValue;
      if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
        var leadSurrogateEnd = state.pos;
        if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
          var trail = state.lastIntValue;
          if (trail >= 0xDC00 && trail <= 0xDFFF) {
            state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
            return true
          }
        }
        state.pos = leadSurrogateEnd;
        state.lastIntValue = lead;
      }
      return true
    }
    if (
      switchU &&
      state.eat(0x7B /* { */) &&
      this.regexp_eatHexDigits(state) &&
      state.eat(0x7D /* } */) &&
      isValidUnicode(state.lastIntValue)
    ) {
      return true
    }
    if (switchU) {
      state.raise("Invalid unicode escape");
    }
    state.pos = start;
  }

  return false
};
function isValidUnicode(ch) {
  return ch >= 0 && ch <= 0x10FFFF
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
pp$1.regexp_eatIdentityEscape = function(state) {
  if (state.switchU) {
    if (this.regexp_eatSyntaxCharacter(state)) {
      return true
    }
    if (state.eat(0x2F /* / */)) {
      state.lastIntValue = 0x2F; /* / */
      return true
    }
    return false
  }

  var ch = state.current();
  if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
pp$1.regexp_eatDecimalEscape = function(state) {
  state.lastIntValue = 0;
  var ch = state.current();
  if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
    do {
      state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
      state.advance();
    } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
    return true
  }
  return false
};

// Return values used by character set parsing methods, needed to
// forbid negation of sets that can match strings.
var CharSetNone = 0; // Nothing parsed
var CharSetOk = 1; // Construct parsed, cannot contain strings
var CharSetString = 2; // Construct parsed, can contain strings

// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
pp$1.regexp_eatCharacterClassEscape = function(state) {
  var ch = state.current();

  if (isCharacterClassEscape(ch)) {
    state.lastIntValue = -1;
    state.advance();
    return CharSetOk
  }

  var negate = false;
  if (
    state.switchU &&
    this.options.ecmaVersion >= 9 &&
    ((negate = ch === 0x50 /* P */) || ch === 0x70 /* p */)
  ) {
    state.lastIntValue = -1;
    state.advance();
    var result;
    if (
      state.eat(0x7B /* { */) &&
      (result = this.regexp_eatUnicodePropertyValueExpression(state)) &&
      state.eat(0x7D /* } */)
    ) {
      if (negate && result === CharSetString) { state.raise("Invalid property name"); }
      return result
    }
    state.raise("Invalid property name");
  }

  return CharSetNone
};

function isCharacterClassEscape(ch) {
  return (
    ch === 0x64 /* d */ ||
    ch === 0x44 /* D */ ||
    ch === 0x73 /* s */ ||
    ch === 0x53 /* S */ ||
    ch === 0x77 /* w */ ||
    ch === 0x57 /* W */
  )
}

// UnicodePropertyValueExpression ::
//   UnicodePropertyName `=` UnicodePropertyValue
//   LoneUnicodePropertyNameOrValue
pp$1.regexp_eatUnicodePropertyValueExpression = function(state) {
  var start = state.pos;

  // UnicodePropertyName `=` UnicodePropertyValue
  if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
    var name = state.lastStringValue;
    if (this.regexp_eatUnicodePropertyValue(state)) {
      var value = state.lastStringValue;
      this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
      return CharSetOk
    }
  }
  state.pos = start;

  // LoneUnicodePropertyNameOrValue
  if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
    var nameOrValue = state.lastStringValue;
    return this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue)
  }
  return CharSetNone
};

pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
  if (!hasOwn(state.unicodeProperties.nonBinary, name))
    { state.raise("Invalid property name"); }
  if (!state.unicodeProperties.nonBinary[name].test(value))
    { state.raise("Invalid property value"); }
};

pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
  if (state.unicodeProperties.binary.test(nameOrValue)) { return CharSetOk }
  if (state.switchV && state.unicodeProperties.binaryOfStrings.test(nameOrValue)) { return CharSetString }
  state.raise("Invalid property name");
};

// UnicodePropertyName ::
//   UnicodePropertyNameCharacters
pp$1.regexp_eatUnicodePropertyName = function(state) {
  var ch = 0;
  state.lastStringValue = "";
  while (isUnicodePropertyNameCharacter(ch = state.current())) {
    state.lastStringValue += codePointToString(ch);
    state.advance();
  }
  return state.lastStringValue !== ""
};

function isUnicodePropertyNameCharacter(ch) {
  return isControlLetter(ch) || ch === 0x5F /* _ */
}

// UnicodePropertyValue ::
//   UnicodePropertyValueCharacters
pp$1.regexp_eatUnicodePropertyValue = function(state) {
  var ch = 0;
  state.lastStringValue = "";
  while (isUnicodePropertyValueCharacter(ch = state.current())) {
    state.lastStringValue += codePointToString(ch);
    state.advance();
  }
  return state.lastStringValue !== ""
};
function isUnicodePropertyValueCharacter(ch) {
  return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
}

// LoneUnicodePropertyNameOrValue ::
//   UnicodePropertyValueCharacters
pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
  return this.regexp_eatUnicodePropertyValue(state)
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
pp$1.regexp_eatCharacterClass = function(state) {
  if (state.eat(0x5B /* [ */)) {
    var negate = state.eat(0x5E /* ^ */);
    var result = this.regexp_classContents(state);
    if (!state.eat(0x5D /* ] */))
      { state.raise("Unterminated character class"); }
    if (negate && result === CharSetString)
      { state.raise("Negated character class may contain strings"); }
    return true
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassContents
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
pp$1.regexp_classContents = function(state) {
  if (state.current() === 0x5D /* ] */) { return CharSetOk }
  if (state.switchV) { return this.regexp_classSetExpression(state) }
  this.regexp_nonEmptyClassRanges(state);
  return CharSetOk
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
pp$1.regexp_nonEmptyClassRanges = function(state) {
  while (this.regexp_eatClassAtom(state)) {
    var left = state.lastIntValue;
    if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
      var right = state.lastIntValue;
      if (state.switchU && (left === -1 || right === -1)) {
        state.raise("Invalid character class");
      }
      if (left !== -1 && right !== -1 && left > right) {
        state.raise("Range out of order in character class");
      }
    }
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
pp$1.regexp_eatClassAtom = function(state) {
  var start = state.pos;

  if (state.eat(0x5C /* \ */)) {
    if (this.regexp_eatClassEscape(state)) {
      return true
    }
    if (state.switchU) {
      // Make the same message as V8.
      var ch$1 = state.current();
      if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
        state.raise("Invalid class escape");
      }
      state.raise("Invalid escape");
    }
    state.pos = start;
  }

  var ch = state.current();
  if (ch !== 0x5D /* ] */) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
pp$1.regexp_eatClassEscape = function(state) {
  var start = state.pos;

  if (state.eat(0x62 /* b */)) {
    state.lastIntValue = 0x08; /* <BS> */
    return true
  }

  if (state.switchU && state.eat(0x2D /* - */)) {
    state.lastIntValue = 0x2D; /* - */
    return true
  }

  if (!state.switchU && state.eat(0x63 /* c */)) {
    if (this.regexp_eatClassControlLetter(state)) {
      return true
    }
    state.pos = start;
  }

  return (
    this.regexp_eatCharacterClassEscape(state) ||
    this.regexp_eatCharacterEscape(state)
  )
};

// https://tc39.es/ecma262/#prod-ClassSetExpression
// https://tc39.es/ecma262/#prod-ClassUnion
// https://tc39.es/ecma262/#prod-ClassIntersection
// https://tc39.es/ecma262/#prod-ClassSubtraction
pp$1.regexp_classSetExpression = function(state) {
  var result = CharSetOk, subResult;
  if (this.regexp_eatClassSetRange(state)) ; else if (subResult = this.regexp_eatClassSetOperand(state)) {
    if (subResult === CharSetString) { result = CharSetString; }
    // https://tc39.es/ecma262/#prod-ClassIntersection
    var start = state.pos;
    while (state.eatChars([0x26, 0x26] /* && */)) {
      if (
        state.current() !== 0x26 /* & */ &&
        (subResult = this.regexp_eatClassSetOperand(state))
      ) {
        if (subResult !== CharSetString) { result = CharSetOk; }
        continue
      }
      state.raise("Invalid character in character class");
    }
    if (start !== state.pos) { return result }
    // https://tc39.es/ecma262/#prod-ClassSubtraction
    while (state.eatChars([0x2D, 0x2D] /* -- */)) {
      if (this.regexp_eatClassSetOperand(state)) { continue }
      state.raise("Invalid character in character class");
    }
    if (start !== state.pos) { return result }
  } else {
    state.raise("Invalid character in character class");
  }
  // https://tc39.es/ecma262/#prod-ClassUnion
  for (;;) {
    if (this.regexp_eatClassSetRange(state)) { continue }
    subResult = this.regexp_eatClassSetOperand(state);
    if (!subResult) { return result }
    if (subResult === CharSetString) { result = CharSetString; }
  }
};

// https://tc39.es/ecma262/#prod-ClassSetRange
pp$1.regexp_eatClassSetRange = function(state) {
  var start = state.pos;
  if (this.regexp_eatClassSetCharacter(state)) {
    var left = state.lastIntValue;
    if (state.eat(0x2D /* - */) && this.regexp_eatClassSetCharacter(state)) {
      var right = state.lastIntValue;
      if (left !== -1 && right !== -1 && left > right) {
        state.raise("Range out of order in character class");
      }
      return true
    }
    state.pos = start;
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassSetOperand
pp$1.regexp_eatClassSetOperand = function(state) {
  if (this.regexp_eatClassSetCharacter(state)) { return CharSetOk }
  return this.regexp_eatClassStringDisjunction(state) || this.regexp_eatNestedClass(state)
};

// https://tc39.es/ecma262/#prod-NestedClass
pp$1.regexp_eatNestedClass = function(state) {
  var start = state.pos;
  if (state.eat(0x5B /* [ */)) {
    var negate = state.eat(0x5E /* ^ */);
    var result = this.regexp_classContents(state);
    if (state.eat(0x5D /* ] */)) {
      if (negate && result === CharSetString) {
        state.raise("Negated character class may contain strings");
      }
      return result
    }
    state.pos = start;
  }
  if (state.eat(0x5C /* \ */)) {
    var result$1 = this.regexp_eatCharacterClassEscape(state);
    if (result$1) {
      return result$1
    }
    state.pos = start;
  }
  return null
};

// https://tc39.es/ecma262/#prod-ClassStringDisjunction
pp$1.regexp_eatClassStringDisjunction = function(state) {
  var start = state.pos;
  if (state.eatChars([0x5C, 0x71] /* \q */)) {
    if (state.eat(0x7B /* { */)) {
      var result = this.regexp_classStringDisjunctionContents(state);
      if (state.eat(0x7D /* } */)) {
        return result
      }
    } else {
      // Make the same message as V8.
      state.raise("Invalid escape");
    }
    state.pos = start;
  }
  return null
};

// https://tc39.es/ecma262/#prod-ClassStringDisjunctionContents
pp$1.regexp_classStringDisjunctionContents = function(state) {
  var result = this.regexp_classString(state);
  while (state.eat(0x7C /* | */)) {
    if (this.regexp_classString(state) === CharSetString) { result = CharSetString; }
  }
  return result
};

// https://tc39.es/ecma262/#prod-ClassString
// https://tc39.es/ecma262/#prod-NonEmptyClassString
pp$1.regexp_classString = function(state) {
  var count = 0;
  while (this.regexp_eatClassSetCharacter(state)) { count++; }
  return count === 1 ? CharSetOk : CharSetString
};

// https://tc39.es/ecma262/#prod-ClassSetCharacter
pp$1.regexp_eatClassSetCharacter = function(state) {
  var start = state.pos;
  if (state.eat(0x5C /* \ */)) {
    if (
      this.regexp_eatCharacterEscape(state) ||
      this.regexp_eatClassSetReservedPunctuator(state)
    ) {
      return true
    }
    if (state.eat(0x62 /* b */)) {
      state.lastIntValue = 0x08; /* <BS> */
      return true
    }
    state.pos = start;
    return false
  }
  var ch = state.current();
  if (ch < 0 || ch === state.lookahead() && isClassSetReservedDoublePunctuatorCharacter(ch)) { return false }
  if (isClassSetSyntaxCharacter(ch)) { return false }
  state.advance();
  state.lastIntValue = ch;
  return true
};

// https://tc39.es/ecma262/#prod-ClassSetReservedDoublePunctuator
function isClassSetReservedDoublePunctuatorCharacter(ch) {
  return (
    ch === 0x21 /* ! */ ||
    ch >= 0x23 /* # */ && ch <= 0x26 /* & */ ||
    ch >= 0x2A /* * */ && ch <= 0x2C /* , */ ||
    ch === 0x2E /* . */ ||
    ch >= 0x3A /* : */ && ch <= 0x40 /* @ */ ||
    ch === 0x5E /* ^ */ ||
    ch === 0x60 /* ` */ ||
    ch === 0x7E /* ~ */
  )
}

// https://tc39.es/ecma262/#prod-ClassSetSyntaxCharacter
function isClassSetSyntaxCharacter(ch) {
  return (
    ch === 0x28 /* ( */ ||
    ch === 0x29 /* ) */ ||
    ch === 0x2D /* - */ ||
    ch === 0x2F /* / */ ||
    ch >= 0x5B /* [ */ && ch <= 0x5D /* ] */ ||
    ch >= 0x7B /* { */ && ch <= 0x7D /* } */
  )
}

// https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator
pp$1.regexp_eatClassSetReservedPunctuator = function(state) {
  var ch = state.current();
  if (isClassSetReservedPunctuator(ch)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator
function isClassSetReservedPunctuator(ch) {
  return (
    ch === 0x21 /* ! */ ||
    ch === 0x23 /* # */ ||
    ch === 0x25 /* % */ ||
    ch === 0x26 /* & */ ||
    ch === 0x2C /* , */ ||
    ch === 0x2D /* - */ ||
    ch >= 0x3A /* : */ && ch <= 0x3E /* > */ ||
    ch === 0x40 /* @ */ ||
    ch === 0x60 /* ` */ ||
    ch === 0x7E /* ~ */
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
pp$1.regexp_eatClassControlLetter = function(state) {
  var ch = state.current();
  if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
    state.lastIntValue = ch % 0x20;
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp$1.regexp_eatHexEscapeSequence = function(state) {
  var start = state.pos;
  if (state.eat(0x78 /* x */)) {
    if (this.regexp_eatFixedHexDigits(state, 2)) {
      return true
    }
    if (state.switchU) {
      state.raise("Invalid escape");
    }
    state.pos = start;
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
pp$1.regexp_eatDecimalDigits = function(state) {
  var start = state.pos;
  var ch = 0;
  state.lastIntValue = 0;
  while (isDecimalDigit(ch = state.current())) {
    state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
    state.advance();
  }
  return state.pos !== start
};
function isDecimalDigit(ch) {
  return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
pp$1.regexp_eatHexDigits = function(state) {
  var start = state.pos;
  var ch = 0;
  state.lastIntValue = 0;
  while (isHexDigit(ch = state.current())) {
    state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
    state.advance();
  }
  return state.pos !== start
};
function isHexDigit(ch) {
  return (
    (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
    (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
    (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
  )
}
function hexToInt(ch) {
  if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
    return 10 + (ch - 0x41 /* A */)
  }
  if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
    return 10 + (ch - 0x61 /* a */)
  }
  return ch - 0x30 /* 0 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
// Allows only 0-377(octal) i.e. 0-255(decimal).
pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) {
  if (this.regexp_eatOctalDigit(state)) {
    var n1 = state.lastIntValue;
    if (this.regexp_eatOctalDigit(state)) {
      var n2 = state.lastIntValue;
      if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
        state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
      } else {
        state.lastIntValue = n1 * 8 + n2;
      }
    } else {
      state.lastIntValue = n1;
    }
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
pp$1.regexp_eatOctalDigit = function(state) {
  var ch = state.current();
  if (isOctalDigit(ch)) {
    state.lastIntValue = ch - 0x30; /* 0 */
    state.advance();
    return true
  }
  state.lastIntValue = 0;
  return false
};
function isOctalDigit(ch) {
  return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp$1.regexp_eatFixedHexDigits = function(state, length) {
  var start = state.pos;
  state.lastIntValue = 0;
  for (var i = 0; i < length; ++i) {
    var ch = state.current();
    if (!isHexDigit(ch)) {
      state.pos = start;
      return false
    }
    state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
    state.advance();
  }
  return true
};

// Object type used to represent tokens. Note that normally, tokens
// simply exist as properties on the parser object. This is only
// used for the onToken callback and the external tokenizer.

var Token = function Token(p) {
  this.type = p.type;
  this.value = p.value;
  this.start = p.start;
  this.end = p.end;
  if (p.options.locations)
    { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
  if (p.options.ranges)
    { this.range = [p.start, p.end]; }
};

// ## Tokenizer

var pp = Parser.prototype;

// Move to the next token

pp.next = function(ignoreEscapeSequenceInKeyword) {
  if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
    { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
  if (this.options.onToken)
    { this.options.onToken(new Token(this)); }

  this.lastTokEnd = this.end;
  this.lastTokStart = this.start;
  this.lastTokEndLoc = this.endLoc;
  this.lastTokStartLoc = this.startLoc;
  this.nextToken();
};

pp.getToken = function() {
  this.next();
  return new Token(this)
};

// If we're in an ES6 environment, make parsers iterable
if (typeof Symbol !== "undefined")
  { pp[Symbol.iterator] = function() {
    var this$1$1 = this;

    return {
      next: function () {
        var token = this$1$1.getToken();
        return {
          done: token.type === types$1.eof,
          value: token
        }
      }
    }
  }; }

// Toggle strict mode. Re-reads the next number or string to please
// pedantic tests (`"use strict"; 010;` should fail).

// Read a single token, updating the parser object's token-related
// properties.

pp.nextToken = function() {
  var curContext = this.curContext();
  if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }

  this.start = this.pos;
  if (this.options.locations) { this.startLoc = this.curPosition(); }
  if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) }

  if (curContext.override) { return curContext.override(this) }
  else { this.readToken(this.fullCharCodeAtPos()); }
};

pp.readToken = function(code) {
  // Identifier or keyword. '\uXXXX' sequences are allowed in
  // identifiers, so '\' also dispatches to that.
  if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
    { return this.readWord() }

  return this.getTokenFromCode(code)
};

pp.fullCharCodeAtPos = function() {
  var code = this.input.charCodeAt(this.pos);
  if (code <= 0xd7ff || code >= 0xdc00) { return code }
  var next = this.input.charCodeAt(this.pos + 1);
  return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00
};

pp.skipBlockComment = function() {
  var startLoc = this.options.onComment && this.curPosition();
  var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
  if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
  this.pos = end + 2;
  if (this.options.locations) {
    for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) {
      ++this.curLine;
      pos = this.lineStart = nextBreak;
    }
  }
  if (this.options.onComment)
    { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
                           startLoc, this.curPosition()); }
};

pp.skipLineComment = function(startSkip) {
  var start = this.pos;
  var startLoc = this.options.onComment && this.curPosition();
  var ch = this.input.charCodeAt(this.pos += startSkip);
  while (this.pos < this.input.length && !isNewLine(ch)) {
    ch = this.input.charCodeAt(++this.pos);
  }
  if (this.options.onComment)
    { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
                           startLoc, this.curPosition()); }
};

// Called at the start of the parse and after every token. Skips
// whitespace and comments, and.

pp.skipSpace = function() {
  loop: while (this.pos < this.input.length) {
    var ch = this.input.charCodeAt(this.pos);
    switch (ch) {
    case 32: case 160: // ' '
      ++this.pos;
      break
    case 13:
      if (this.input.charCodeAt(this.pos + 1) === 10) {
        ++this.pos;
      }
    case 10: case 8232: case 8233:
      ++this.pos;
      if (this.options.locations) {
        ++this.curLine;
        this.lineStart = this.pos;
      }
      break
    case 47: // '/'
      switch (this.input.charCodeAt(this.pos + 1)) {
      case 42: // '*'
        this.skipBlockComment();
        break
      case 47:
        this.skipLineComment(2);
        break
      default:
        break loop
      }
      break
    default:
      if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
        ++this.pos;
      } else {
        break loop
      }
    }
  }
};

// Called at the end of every token. Sets `end`, `val`, and
// maintains `context` and `exprAllowed`, and skips the space after
// the token, so that the next one's `start` will point at the
// right position.

pp.finishToken = function(type, val) {
  this.end = this.pos;
  if (this.options.locations) { this.endLoc = this.curPosition(); }
  var prevType = this.type;
  this.type = type;
  this.value = val;

  this.updateContext(prevType);
};

// ### Token reading

// This is the function that is called to fetch the next token. It
// is somewhat obscure, because it works in character codes rather
// than characters, and because operator parsing has been inlined
// into it.
//
// All in the name of speed.
//
pp.readToken_dot = function() {
  var next = this.input.charCodeAt(this.pos + 1);
  if (next >= 48 && next <= 57) { return this.readNumber(true) }
  var next2 = this.input.charCodeAt(this.pos + 2);
  if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
    this.pos += 3;
    return this.finishToken(types$1.ellipsis)
  } else {
    ++this.pos;
    return this.finishToken(types$1.dot)
  }
};

pp.readToken_slash = function() { // '/'
  var next = this.input.charCodeAt(this.pos + 1);
  if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.slash, 1)
};

pp.readToken_mult_modulo_exp = function(code) { // '%*'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  var tokentype = code === 42 ? types$1.star : types$1.modulo;

  // exponentiation operator ** and **=
  if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
    ++size;
    tokentype = types$1.starstar;
    next = this.input.charCodeAt(this.pos + 2);
  }

  if (next === 61) { return this.finishOp(types$1.assign, size + 1) }
  return this.finishOp(tokentype, size)
};

pp.readToken_pipe_amp = function(code) { // '|&'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) {
    if (this.options.ecmaVersion >= 12) {
      var next2 = this.input.charCodeAt(this.pos + 2);
      if (next2 === 61) { return this.finishOp(types$1.assign, 3) }
    }
    return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2)
  }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1)
};

pp.readToken_caret = function() { // '^'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.bitwiseXOR, 1)
};

pp.readToken_plus_min = function(code) { // '+-'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) {
    if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
        (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
      // A `-->` line comment
      this.skipLineComment(3);
      this.skipSpace();
      return this.nextToken()
    }
    return this.finishOp(types$1.incDec, 2)
  }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.plusMin, 1)
};

pp.readToken_lt_gt = function(code) { // '<>'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  if (next === code) {
    size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
    if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) }
    return this.finishOp(types$1.bitShift, size)
  }
  if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
      this.input.charCodeAt(this.pos + 3) === 45) {
    // `<!--`, an XML-style comment that should be interpreted as a line comment
    this.skipLineComment(4);
    this.skipSpace();
    return this.nextToken()
  }
  if (next === 61) { size = 2; }
  return this.finishOp(types$1.relational, size)
};

pp.readToken_eq_excl = function(code) { // '=!'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
  if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
    this.pos += 2;
    return this.finishToken(types$1.arrow)
  }
  return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1)
};

pp.readToken_question = function() { // '?'
  var ecmaVersion = this.options.ecmaVersion;
  if (ecmaVersion >= 11) {
    var next = this.input.charCodeAt(this.pos + 1);
    if (next === 46) {
      var next2 = this.input.charCodeAt(this.pos + 2);
      if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) }
    }
    if (next === 63) {
      if (ecmaVersion >= 12) {
        var next2$1 = this.input.charCodeAt(this.pos + 2);
        if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) }
      }
      return this.finishOp(types$1.coalesce, 2)
    }
  }
  return this.finishOp(types$1.question, 1)
};

pp.readToken_numberSign = function() { // '#'
  var ecmaVersion = this.options.ecmaVersion;
  var code = 35; // '#'
  if (ecmaVersion >= 13) {
    ++this.pos;
    code = this.fullCharCodeAtPos();
    if (isIdentifierStart(code, true) || code === 92 /* '\' */) {
      return this.finishToken(types$1.privateId, this.readWord1())
    }
  }

  this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};

pp.getTokenFromCode = function(code) {
  switch (code) {
  // The interpretation of a dot depends on whether it is followed
  // by a digit or another two dots.
  case 46: // '.'
    return this.readToken_dot()

  // Punctuation tokens.
  case 40: ++this.pos; return this.finishToken(types$1.parenL)
  case 41: ++this.pos; return this.finishToken(types$1.parenR)
  case 59: ++this.pos; return this.finishToken(types$1.semi)
  case 44: ++this.pos; return this.finishToken(types$1.comma)
  case 91: ++this.pos; return this.finishToken(types$1.bracketL)
  case 93: ++this.pos; return this.finishToken(types$1.bracketR)
  case 123: ++this.pos; return this.finishToken(types$1.braceL)
  case 125: ++this.pos; return this.finishToken(types$1.braceR)
  case 58: ++this.pos; return this.finishToken(types$1.colon)

  case 96: // '`'
    if (this.options.ecmaVersion < 6) { break }
    ++this.pos;
    return this.finishToken(types$1.backQuote)

  case 48: // '0'
    var next = this.input.charCodeAt(this.pos + 1);
    if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
    if (this.options.ecmaVersion >= 6) {
      if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
      if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
    }

  // Anything else beginning with a digit is an integer, octal
  // number, or float.
  case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
    return this.readNumber(false)

  // Quotes produce strings.
  case 34: case 39: // '"', "'"
    return this.readString(code)

  // Operators are parsed inline in tiny state machines. '=' (61) is
  // often referred to. `finishOp` simply skips the amount of
  // characters it is given as second argument, and returns a token
  // of the type given by its first argument.
  case 47: // '/'
    return this.readToken_slash()

  case 37: case 42: // '%*'
    return this.readToken_mult_modulo_exp(code)

  case 124: case 38: // '|&'
    return this.readToken_pipe_amp(code)

  case 94: // '^'
    return this.readToken_caret()

  case 43: case 45: // '+-'
    return this.readToken_plus_min(code)

  case 60: case 62: // '<>'
    return this.readToken_lt_gt(code)

  case 61: case 33: // '=!'
    return this.readToken_eq_excl(code)

  case 63: // '?'
    return this.readToken_question()

  case 126: // '~'
    return this.finishOp(types$1.prefix, 1)

  case 35: // '#'
    return this.readToken_numberSign()
  }

  this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};

pp.finishOp = function(type, size) {
  var str = this.input.slice(this.pos, this.pos + size);
  this.pos += size;
  return this.finishToken(type, str)
};

pp.readRegexp = function() {
  var escaped, inClass, start = this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
    var ch = this.input.charAt(this.pos);
    if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
    if (!escaped) {
      if (ch === "[") { inClass = true; }
      else if (ch === "]" && inClass) { inClass = false; }
      else if (ch === "/" && !inClass) { break }
      escaped = ch === "\\";
    } else { escaped = false; }
    ++this.pos;
  }
  var pattern = this.input.slice(start, this.pos);
  ++this.pos;
  var flagsStart = this.pos;
  var flags = this.readWord1();
  if (this.containsEsc) { this.unexpected(flagsStart); }

  // Validate pattern
  var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
  state.reset(start, pattern, flags);
  this.validateRegExpFlags(state);
  this.validateRegExpPattern(state);

  // Create Literal#value property value.
  var value = null;
  try {
    value = new RegExp(pattern, flags);
  } catch (e) {
    // ESTree requires null if it failed to instantiate RegExp object.
    // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
  }

  return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value})
};

// Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits.

pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) {
  // `len` is used for character escape sequences. In that case, disallow separators.
  var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined;

  // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b)
  // and isn't fraction part nor exponent part. In that case, if the first digit
  // is zero then disallow separators.
  var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;

  var start = this.pos, total = 0, lastCode = 0;
  for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
    var code = this.input.charCodeAt(this.pos), val = (void 0);

    if (allowSeparators && code === 95) {
      if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); }
      if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); }
      if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); }
      lastCode = code;
      continue
    }

    if (code >= 97) { val = code - 97 + 10; } // a
    else if (code >= 65) { val = code - 65 + 10; } // A
    else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
    else { val = Infinity; }
    if (val >= radix) { break }
    lastCode = code;
    total = total * radix + val;
  }

  if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); }
  if (this.pos === start || len != null && this.pos - start !== len) { return null }

  return total
};

function stringToNumber(str, isLegacyOctalNumericLiteral) {
  if (isLegacyOctalNumericLiteral) {
    return parseInt(str, 8)
  }

  // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value.
  return parseFloat(str.replace(/_/g, ""))
}

function stringToBigInt(str) {
  if (typeof BigInt !== "function") {
    return null
  }

  // `BigInt(value)` throws syntax error if the string contains numeric separators.
  return BigInt(str.replace(/_/g, ""))
}

pp.readRadixNumber = function(radix) {
  var start = this.pos;
  this.pos += 2; // 0x
  var val = this.readInt(radix);
  if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
  if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
    val = stringToBigInt(this.input.slice(start, this.pos));
    ++this.pos;
  } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
  return this.finishToken(types$1.num, val)
};

// Read an integer, octal integer, or floating-point number.

pp.readNumber = function(startsWithDot) {
  var start = this.pos;
  if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); }
  var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
  if (octal && this.strict) { this.raise(start, "Invalid number"); }
  var next = this.input.charCodeAt(this.pos);
  if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
    var val$1 = stringToBigInt(this.input.slice(start, this.pos));
    ++this.pos;
    if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
    return this.finishToken(types$1.num, val$1)
  }
  if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
  if (next === 46 && !octal) { // '.'
    ++this.pos;
    this.readInt(10);
    next = this.input.charCodeAt(this.pos);
  }
  if ((next === 69 || next === 101) && !octal) { // 'eE'
    next = this.input.charCodeAt(++this.pos);
    if (next === 43 || next === 45) { ++this.pos; } // '+-'
    if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
  }
  if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }

  var val = stringToNumber(this.input.slice(start, this.pos), octal);
  return this.finishToken(types$1.num, val)
};

// Read a string value, interpreting backslash-escapes.

pp.readCodePoint = function() {
  var ch = this.input.charCodeAt(this.pos), code;

  if (ch === 123) { // '{'
    if (this.options.ecmaVersion < 6) { this.unexpected(); }
    var codePos = ++this.pos;
    code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
    ++this.pos;
    if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
  } else {
    code = this.readHexChar(4);
  }
  return code
};

pp.readString = function(quote) {
  var out = "", chunkStart = ++this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
    var ch = this.input.charCodeAt(this.pos);
    if (ch === quote) { break }
    if (ch === 92) { // '\'
      out += this.input.slice(chunkStart, this.pos);
      out += this.readEscapedChar(false);
      chunkStart = this.pos;
    } else if (ch === 0x2028 || ch === 0x2029) {
      if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); }
      ++this.pos;
      if (this.options.locations) {
        this.curLine++;
        this.lineStart = this.pos;
      }
    } else {
      if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); }
      ++this.pos;
    }
  }
  out += this.input.slice(chunkStart, this.pos++);
  return this.finishToken(types$1.string, out)
};

// Reads template string tokens.

var INVALID_TEMPLATE_ESCAPE_ERROR = {};

pp.tryReadTemplateToken = function() {
  this.inTemplateElement = true;
  try {
    this.readTmplToken();
  } catch (err) {
    if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
      this.readInvalidTemplateToken();
    } else {
      throw err
    }
  }

  this.inTemplateElement = false;
};

pp.invalidStringToken = function(position, message) {
  if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
    throw INVALID_TEMPLATE_ESCAPE_ERROR
  } else {
    this.raise(position, message);
  }
};

pp.readTmplToken = function() {
  var out = "", chunkStart = this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
    var ch = this.input.charCodeAt(this.pos);
    if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
      if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) {
        if (ch === 36) {
          this.pos += 2;
          return this.finishToken(types$1.dollarBraceL)
        } else {
          ++this.pos;
          return this.finishToken(types$1.backQuote)
        }
      }
      out += this.input.slice(chunkStart, this.pos);
      return this.finishToken(types$1.template, out)
    }
    if (ch === 92) { // '\'
      out += this.input.slice(chunkStart, this.pos);
      out += this.readEscapedChar(true);
      chunkStart = this.pos;
    } else if (isNewLine(ch)) {
      out += this.input.slice(chunkStart, this.pos);
      ++this.pos;
      switch (ch) {
      case 13:
        if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
      case 10:
        out += "\n";
        break
      default:
        out += String.fromCharCode(ch);
        break
      }
      if (this.options.locations) {
        ++this.curLine;
        this.lineStart = this.pos;
      }
      chunkStart = this.pos;
    } else {
      ++this.pos;
    }
  }
};

// Reads a template token to search for the end, without validating any escape sequences
pp.readInvalidTemplateToken = function() {
  for (; this.pos < this.input.length; this.pos++) {
    switch (this.input[this.pos]) {
    case "\\":
      ++this.pos;
      break

    case "$":
      if (this.input[this.pos + 1] !== "{") { break }
      // fall through
    case "`":
      return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos))

    case "\r":
      if (this.input[this.pos + 1] === "\n") { ++this.pos; }
      // fall through
    case "\n": case "\u2028": case "\u2029":
      ++this.curLine;
      this.lineStart = this.pos + 1;
      break
    }
  }
  this.raise(this.start, "Unterminated template");
};

// Used to read escaped characters

pp.readEscapedChar = function(inTemplate) {
  var ch = this.input.charCodeAt(++this.pos);
  ++this.pos;
  switch (ch) {
  case 110: return "\n" // 'n' -> '\n'
  case 114: return "\r" // 'r' -> '\r'
  case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
  case 117: return codePointToString(this.readCodePoint()) // 'u'
  case 116: return "\t" // 't' -> '\t'
  case 98: return "\b" // 'b' -> '\b'
  case 118: return "\u000b" // 'v' -> '\u000b'
  case 102: return "\f" // 'f' -> '\f'
  case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
  case 10: // ' \n'
    if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
    return ""
  case 56:
  case 57:
    if (this.strict) {
      this.invalidStringToken(
        this.pos - 1,
        "Invalid escape sequence"
      );
    }
    if (inTemplate) {
      var codePos = this.pos - 1;

      this.invalidStringToken(
        codePos,
        "Invalid escape sequence in template string"
      );
    }
  default:
    if (ch >= 48 && ch <= 55) {
      var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
      var octal = parseInt(octalStr, 8);
      if (octal > 255) {
        octalStr = octalStr.slice(0, -1);
        octal = parseInt(octalStr, 8);
      }
      this.pos += octalStr.length - 1;
      ch = this.input.charCodeAt(this.pos);
      if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
        this.invalidStringToken(
          this.pos - 1 - octalStr.length,
          inTemplate
            ? "Octal literal in template string"
            : "Octal literal in strict mode"
        );
      }
      return String.fromCharCode(octal)
    }
    if (isNewLine(ch)) {
      // Unicode new line characters after \ get removed from output in both
      // template literals and strings
      if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
      return ""
    }
    return String.fromCharCode(ch)
  }
};

// Used to read character escape sequences ('\x', '\u', '\U').

pp.readHexChar = function(len) {
  var codePos = this.pos;
  var n = this.readInt(16, len);
  if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
  return n
};

// Read an identifier, and return it as a string. Sets `this.containsEsc`
// to whether the word contained a '\u' escape.
//
// Incrementally adds only escaped chars, adding other chunks as-is
// as a micro-optimization.

pp.readWord1 = function() {
  this.containsEsc = false;
  var word = "", first = true, chunkStart = this.pos;
  var astral = this.options.ecmaVersion >= 6;
  while (this.pos < this.input.length) {
    var ch = this.fullCharCodeAtPos();
    if (isIdentifierChar(ch, astral)) {
      this.pos += ch <= 0xffff ? 1 : 2;
    } else if (ch === 92) { // "\"
      this.containsEsc = true;
      word += this.input.slice(chunkStart, this.pos);
      var escStart = this.pos;
      if (this.input.charCodeAt(++this.pos) !== 117) // "u"
        { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
      ++this.pos;
      var esc = this.readCodePoint();
      if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
        { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
      word += codePointToString(esc);
      chunkStart = this.pos;
    } else {
      break
    }
    first = false;
  }
  return word + this.input.slice(chunkStart, this.pos)
};

// Read an identifier or keyword token. Will check for reserved
// words when necessary.

pp.readWord = function() {
  var word = this.readWord1();
  var type = types$1.name;
  if (this.keywords.test(word)) {
    type = keywords[word];
  }
  return this.finishToken(type, word)
};

// Acorn is a tiny, fast JavaScript parser written in JavaScript.
//
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
// various contributors and released under an MIT license.
//
// Git repositories for Acorn are available at
//
//     http://marijnhaverbeke.nl/git/acorn
//     https://github.com/acornjs/acorn.git
//
// Please use the [github bug tracker][ghbt] to report issues.
//
// [ghbt]: https://github.com/acornjs/acorn/issues
//
// [walk]: util/walk.js


var version = "8.14.1";

Parser.acorn = {
  Parser: Parser,
  version: version,
  defaultOptions: defaultOptions,
  Position: Position,
  SourceLocation: SourceLocation,
  getLineInfo: getLineInfo,
  Node: extension_Node,
  TokenType: TokenType,
  tokTypes: types$1,
  keywordTypes: keywords,
  TokContext: TokContext,
  tokContexts: types,
  isIdentifierChar: isIdentifierChar,
  isIdentifierStart: isIdentifierStart,
  Token: Token,
  isNewLine: isNewLine,
  lineBreak: lineBreak,
  lineBreakG: lineBreakG,
  nonASCIIwhitespace: nonASCIIwhitespace
};

// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and returns
// an abstract syntax tree as specified by the [ESTree spec][estree].
//
// [estree]: https://github.com/estree/estree

function parse(input, options) {
  return Parser.parse(input, options)
}

// This function tries to parse a single expression at a given
// offset in a string. Useful for parsing mixed-language formats
// that embed JavaScript expressions.

function parseExpressionAt(input, pos, options) {
  return Parser.parseExpressionAt(input, pos, options)
}

// Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenizer` export provides an interface to the tokenizer.

function tokenizer(input, options) {
  return Parser.tokenizer(input, options)
}



;// ../../node_modules/arquero/src/expression/constants.js
const constants = {
  undefined: 'void(0)',
  Infinity:  'Number.POSITIVE_INFINITY',
  NaN:       'Number.NaN',
  E:         'Math.E',
  LN2:       'Math.LN2',
  LN10:      'Math.LN10',
  LOG2E:     'Math.LOG2E',
  LOG10E:    'Math.LOG10E',
  PI:        'Math.PI',
  SQRT1_2:   'Math.SQRT1_2',
  SQRT2:     'Math.SQRT2'
};

;// ../../node_modules/arquero/src/util/is-number.js
/**
 * @param {*} value
 * @returns {value is number}
 */
function is_number_isNumber(value) {
  return typeof value === 'number';
}

;// ../../node_modules/arquero/src/expression/parse-expression.js














const PARSER_OPT = { ecmaVersion: 11 };
const DEFAULT_PARAM_ID = '$';
const DEFAULT_TUPLE_ID = 'd';
const DEFAULT_TUPLE_ID1 = 'd1';
const DEFAULT_TUPLE_ID2 = 'd2';

const NO = msg => (node, ctx) => ctx.error(node, msg + ' not allowed');
const ERROR_AGGREGATE = NO('Aggregate function');
const ERROR_WINDOW = NO('Window function');
const ERROR_ARGUMENT = 'Invalid argument';
const ERROR_COLUMN = 'Invalid column reference';
const ERROR_AGGRONLY = ERROR_COLUMN + ' (must be input to an aggregate function)';
const ERROR_FUNCTION = 'Invalid function call';
const ERROR_MEMBER = 'Invalid member expression';
const ERROR_OP_PARAMETER = 'Invalid operator parameter';
const ERROR_PARAM = 'Invalid param reference';
const ERROR_VARIABLE = 'Invalid variable reference';
const ERROR_VARIABLE_OP = 'Variable not accessible in operator call';
const ERROR_DECLARATION = 'Unsupported variable declaration';
const ERROR_DESTRUCTURE = 'Unsupported destructuring pattern';
const ERROR_CLOSURE = 'Table expressions do not support closures';
const ERROR_ESCAPE = 'Use aq.escape(fn) to use a function as-is (including closures)';
const ERROR_USE_PARAMS = 'use table.params({ name: value }) to define dynamic parameters';
const ERROR_ADD_FUNCTION = 'use aq.addFunction(name, fn) to add new op functions';
const ERROR_VARIABLE_NOTE = `\nNote: ${ERROR_CLOSURE}. ${ERROR_ESCAPE}, or ${ERROR_USE_PARAMS}.`;
const ERROR_FUNCTION_NOTE = `\nNote: ${ERROR_CLOSURE}. ${ERROR_ESCAPE}, or ${ERROR_ADD_FUNCTION}.`;
const ERROR_ROW_OBJECT = `The ${row_object_ROW_OBJECT} method is not valid in multi-table expressions.`;

function parseExpression(ctx, spec) {
  const ast = parseAST(spec);
  let node = ctx.root = ast;
  ctx.spec = spec;
  ctx.tuple = null;
  ctx.tuple1 = null;
  ctx.tuple2 = null;
  ctx.$param = null;
  ctx.$op = 0;
  ctx.scope = new Set();
  ctx.paramsRef = new Map();
  ctx.columnRef = new Map();

  // parse input column parameters
  // if no function def, assume default tuple identifiers
  if (isFunctionExpression(node)) {
    parseFunction(node, ctx);
    node = node.body;
  } else if (ctx.join) {
    ctx.scope.add(ctx.tuple1 = DEFAULT_TUPLE_ID1);
    ctx.scope.add(ctx.tuple2 = DEFAULT_TUPLE_ID2);
    ctx.scope.add(ctx.$param = DEFAULT_PARAM_ID);
  } else {
    ctx.scope.add(ctx.tuple = DEFAULT_TUPLE_ID);
    ctx.scope.add(ctx.$param = DEFAULT_PARAM_ID);
  }

  // rewrite column references & function calls
  walk(node, ctx, parse_expression_visitors);

  return ctx.root;
}

function parseAST(expr) {
  try {
    const code = expr.field ? fieldRef(expr)
      : is_array_isArray(expr) ? to_string_toString(expr)
      : expr;
    // @ts-ignore
    return parse(`expr=(${code})`, PARSER_OPT).body[0].expression.right;
  } catch (err) { // eslint-disable-line no-unused-vars
    error_error(`Expression parse error: ${expr+''}`);
  }
}

function fieldRef(expr) {
  const col = JSON.stringify(expr+'');
  return !(expr.table || 0) ? `d=>d[${col}]` : `(a,b)=>b[${col}]`;
}

const parse_expression_visitors = {
  FunctionDeclaration: NO('Function definitions'),
  ForStatement: NO('For loops'),
  ForOfStatement: NO('For-of loops'),
  ForInStatement: NO('For-in loops'),
  WhileStatement: NO('While loops'),
  DoWhileStatement: NO('Do-while loops'),
  AwaitExpression: NO('Await expressions'),
  ArrowFunctionExpression: NO('Function definitions'),
  AssignmentExpression: NO('Assignments'),
  FunctionExpression: NO('Function definitions'),
  NewExpression: NO('Use of "new"'),
  UpdateExpression: NO('Update expressions'),

  VariableDeclarator(node, ctx) {
    handleDeclaration(node.id, ctx);
  },
  Identifier(node, ctx, parent) {
    if (handleIdentifier(node, ctx, parent) && !ctx.scope.has(node.name)) {
      // handle identifier passed responsibility here
      // raise error if identifier not defined in scope
      ctx.error(node, ERROR_VARIABLE, ERROR_VARIABLE_NOTE);
    }
  },
  CallExpression(node, ctx) {
    const name = functionName(node.callee);
    const def = getAggregate(name) || getWindow(name);

    // parse operator and rewrite invocation
    if (def) {
      if ((ctx.join || ctx.aggregate === false) && hasAggregate(name)) {
        ERROR_AGGREGATE(node, ctx);
      }
      if ((ctx.join || ctx.window === false) && hasWindow(name)) {
        ERROR_WINDOW(node, ctx);
      }

      ctx.$op = 1;
      if (ctx.ast) {
        updateFunctionNode(node, name, ctx);
        node.arguments.forEach(arg => walk(arg, ctx, opVisitors));
      } else {
        const op = ctx.op(parseOperator(ctx, def, name, node.arguments));
        Object.assign(node, { type: constants_Op, name: op.id });
      }
      ctx.$op = 0;
      return false;
    } else if (hasFunction(name)) {
      updateFunctionNode(node, name, ctx);
    } else {
      ctx.error(node, ERROR_FUNCTION, ERROR_FUNCTION_NOTE);
    }
  },
  MemberExpression(node, ctx, parent) {
    const { object, property } = node;

    // bail if left head is not an identifier
    // in this case we will recurse and handle it later
    if (!is(Identifier, object)) return;
    const { name } = object;

    // allow use of Math prefix to access constant values
    if (isMath(node) && is(Identifier, property)
        && Object.hasOwn(constants, property.name)) {
      updateConstantNode(node, property.name);
      return;
    }

    const index = name === ctx.tuple ? 0
      : name === ctx.tuple1 ? 1
      : name === ctx.tuple2 ? 2
      : -1;

    if (index >= 0) {
      // replace member expression with column ref
      return spliceMember(node, index, ctx, checkColumn, parent);
    } else if (name === ctx.$param) {
      // replace member expression with param ref
      return spliceMember(node, index, ctx, checkParam);
    } else if (ctx.paramsRef.has(name)) {
      updateParameterNode(node, ctx.paramsRef.get(name));
    } else if (ctx.columnRef.has(name)) {
      updateColumnNode(object, name, ctx, node);
    } else if (Object.hasOwn(ctx.params, name)) {
      updateParameterNode(object, name);
    }
  }
};

function spliceMember(node, index, ctx, check, parent) {
  const { property, computed } = node;
  let name;

  if (!computed) {
    name = property.name;
  } else if (is(Literal, property)) {
    name = property.value;
  } else try {
    // visit subtree to ensure nodes are rewritten as needed
    // then compile the code to compute the property name
    walk(property, ctx, parse_expression_visitors, node);
    name = ctx.param(property);
  } catch (e) { // eslint-disable-line no-unused-vars
    ctx.error(node, ERROR_MEMBER);
  }

  check(node, name, index, ctx, parent);
  return false;
}

const opVisitors = {
  ...parse_expression_visitors,
  VariableDeclarator: NO('Variable declaration in operator call'),
  Identifier(node, ctx, parent) {
    if (handleIdentifier(node, ctx, parent)) {
      ctx.error(node, ERROR_VARIABLE_OP);
    }
  },
  CallExpression(node, ctx) {
    const name = functionName(node.callee);

    // rewrite if built-in function
    if (hasFunction(name)) {
      updateFunctionNode(node, name, ctx);
    } else {
      ctx.error(node, ERROR_FUNCTION, ERROR_FUNCTION_NOTE);
    }
  }
};

function parseFunction(node, ctx) {
  if (node.generator) NO('Generator functions')(node, ctx);
  if (node.async) NO('Async functions')(node, ctx);

  const { params } = node;
  const len = params.length;
  const setc = index => (name, key) => ctx.columnRef.set(name, [key, index]);
  const setp = (name, key) => ctx.paramsRef.set(name, key);

  if (!len) {
    // do nothing
  } else if (ctx.join) {
    parseRef(ctx, params[0], 'tuple1', setc(1));
    if (len > 1) parseRef(ctx, params[1], 'tuple2', setc(2));
    if (len > 2) parseRef(ctx, params[2], '$param', setp);
  } else {
    parseRef(ctx, params[0], 'tuple', setc(0));
    if (len > 1) parseRef(ctx, params[1], '$param', setp);
  }

  ctx.root = node.body;
}

function parseRef(ctx, node, refName, alias) {
  if (is(Identifier, node)) {
    ctx.scope.add(node.name);
    ctx[refName] = node.name;
  } else if (is(ObjectPattern, node)) {
    node.properties.forEach(p => {
      const key = is(Identifier, p.key) ? p.key.name
        : is(Literal, p.key) ? p.key.value
        : ctx.error(p, ERROR_ARGUMENT);
      if (!is(Identifier, p.value)) {
        ctx.error(p.value, ERROR_DESTRUCTURE);
      }
      alias(p.value.name, key);
    });
  }
}

function parseOperator(ctx, def, name, args) {
  const fields = [];
  const params = [];
  const idxFields = def.param[0] || 0;
  const idxParams = idxFields + (def.param[1] || 0);

  args.forEach((arg, index) => {
    if (index < idxFields) {
      walk(arg, ctx, opVisitors);
      fields.push(ctx.field(arg));
    } else if (index < idxParams) {
      walk(arg, ctx, opVisitors);
      params.push(ctx.param(arg));
    } else {
      ctx.error(arg, ERROR_OP_PARAMETER);
    }
  });

  return { name, fields, params, ...(ctx.spec.window || {}) };
}

function functionName(node) {
  return is(Identifier, node) ? node.name
    : !is(MemberExpression, node) ? null
    : isMath(node) ? rewriteMath(node.property.name)
    : node.property.name;
}

function isMath(node) {
  return is(Identifier, node.object) && node.object.name === 'Math';
}

function rewriteMath(name) {
  return name === 'max' ? 'greatest'
    : name === 'min' ? 'least'
    : name;
}

function handleIdentifier(node, ctx, parent) {
  const { name } = node;

  if (is(MemberExpression, parent) && parent.property === node) {
    // do nothing: check head node, not nested properties
  } else if (is(Property, parent) && parent.key === node) {
    // do nothing: identifiers allowed in object expressions
  } else if (ctx.paramsRef.has(name)) {
    updateParameterNode(node, ctx.paramsRef.get(name));
  } else if (ctx.columnRef.has(name)) {
    updateColumnNode(node, name, ctx, parent);
  } else if (Object.hasOwn(ctx.params, name)) {
    updateParameterNode(node, name);
  } else if (Object.hasOwn(constants, name)) {
    updateConstantNode(node, name);
  } else {
    return true;
  }
}

function checkColumn(node, name, index, ctx, parent) {
  // check column existence if we have a backing table
  const table = index === 0 ? ctx.table
    : index > 0 ? ctx.join[index - 1]
    : null;
  const col = table && table.column(name);
  if (table && !col) {
    ctx.error(node, ERROR_COLUMN);
  }

  // check if column reference is valid in current context
  if (ctx.aggronly && !ctx.$op) {
    ctx.error(node, ERROR_AGGRONLY);
  }

  // rewrite ast node as a column access
  rewrite(node, name, index, col, parent);
}

function updateColumnNode(node, key, ctx, parent) {
  const [name, index] = ctx.columnRef.get(key);
  checkColumn(node, name, index, ctx, parent);
}

function checkParam(node, name, index, ctx) {
  if (ctx.params && !Object.hasOwn(ctx.params, name)) {
    ctx.error(node, ERROR_PARAM);
  }
  updateParameterNode(node, name);
}

function updateParameterNode(node, name) {
  node.type = Parameter;
  node.name = name;
}

function updateConstantNode(node, name) {
  node.type = Constant;
  node.name = name;
  node.raw = constants[name];
}

function updateFunctionNode(node, name, ctx) {
  if (name === row_object_ROW_OBJECT) {
    const t = ctx.table;
    if (!t) ctx.error(node, ERROR_ROW_OBJECT);
    rowObjectExpression(node, t,
      node.arguments.length
        ? node.arguments.map(node => {
            const col = ctx.param(node);
            const name = is_number_isNumber(col) ? t.columnName(col) : col;
            if (!t.column(name)) ctx.error(node, ERROR_COLUMN);
            return name;
          })
        : t.columnNames()
    );
  } else {
    node.callee = { type: constants_Function, name };
  }
}

function handleDeclaration(node, ctx) {
  if (is(Identifier, node)) {
    ctx.scope.add(node.name);
  } else if (is(ArrayPattern, node)) {
    node.elements.forEach(elm => handleDeclaration(elm, ctx));
  } else if (is(ObjectPattern, node)) {
    node.properties.forEach(prop => handleDeclaration(prop.value, ctx));
  } else {
    ctx.error(node.id, ERROR_DECLARATION);
  }
}

;// ../../node_modules/arquero/src/expression/parse.js












const ANNOTATE = { [Column]: 1, [constants_Op]: 1 };

function parse_parse(input, opt = {}) {
  const generate = opt.generate || codegen;
  const compiler = opt.compiler || compile;
  const params = getParams(opt);
  const fields = {};
  const opcall = {};
  const names = [];
  const exprs = [];
  let fieldId = 0;
  let opId = -1;

  const compileExpr = opt.join ? compiler.join
    : opt.index == 1 ? compiler.expr2
    : compiler.expr;

  // parser context
  const ctx = {
    op(op) {
      const key = opKey(op);
      return opcall[key] || (op.id = ++opId, opcall[key] = op);
    },
    field(node) {
      const code = generate(node);
      return fields[code] || (fields[code] = ++fieldId);
    },
    param(node) {
      return is(Literal, node)
        ? node.value
        : compiler.param(generate(node), params);
    },
    value(name, node) {
      names.push(name);
      const e = node.escape || (opt.ast
        ? clean(node)
        : compileExpr(generate(node), params));
      exprs.push(e);
      // annotate expression if it is a direct column or op access
      // this permits downstream optimizations
      if (ANNOTATE[node.type] && e !== node && isObject(e)) {
        e.field = node.name;
      }
    },
    error(node, msg, note = '') {
      // both expresions and fields are parsed
      // with added code prefixes of length 6!
      const i = node.start - 6;
      const j = node.end - 6;
      const snippet = String(ctx.spec).slice(i, j);
      error_error(`${msg}: "${snippet}"${note}`);
    }
  };

  // copy all options to context, potentially overwriting methods
  Object.assign(ctx, opt, { params });

  // parse each expression
  for (const [name, value] of entries_entries(input)) {
    ctx.value(
      name + '',
      value.escape
        ? parseEscape(ctx, value, params)
        : parseExpression(ctx, value)
    );
  }

  // return expression asts if requested
  if (opt.ast) {
    return { names, exprs };
  }

  // compile input field accessors
  const f = [];
  for (const key in fields) {
    f[fields[key]] = compiler.expr(key, params);
  }

  // resolve input fields to operations
  const ops = Object.values(opcall);
  ops.forEach(op => op.fields = op.fields.map(id => f[id]));

  return { names, exprs, ops };
}

function opKey(op) {
  let key = `${op.name}(${op.fields.concat(op.params).join(',')})`;
  if (op.frame) {
    const frame = op.frame.map(v => Number.isFinite(v) ? Math.abs(v) : -1);
    key += `[${frame},${!!op.peers}]`;
  }
  return key;
}

function getParams(opt) {
  return (opt.table ? getTableParams(opt.table)
    : opt.join ? {
        ...getTableParams(opt.join[1]),
        ...getTableParams(opt.join[0])
      }
    : {}) || {};
}

function getTableParams(table) {
  return table && is_function_isFunction(table.params) ? table.params() : {};
}

;// ../../node_modules/arquero/src/helpers/wrap.js


/**
 * Annotate an expression in an object wrapper.
 * @param {string|Function|object} expr An expression to annotate.
 * @param {object} properties The properties to annotate with.
 * @return {object} A new wrapped expression object.
 */
function wrap(expr, properties) {
  return expr && expr.expr
    ? new Wrapper({ ...expr, ...properties })
    : new Wrapper(properties, expr);
}

class Wrapper {
  constructor(properties, expr) {
    this.expr = expr;
    Object.assign(this, properties);
  }
  toString() {
    return String(this.expr);
  }
  toObject() {
    return {
      ...this,
      expr: this.toString(),
      ...(is_function_isFunction(this.expr) ? { func: true } : {})
    };
  }
}

;// ../../node_modules/arquero/src/helpers/field.js


/**
 * Annotate an expression to indicate it is a string field reference.
 * @param {string|object} expr The column name, or an existing wrapped
 *  expression for a column name.
 * @param {string} [name] The column name to use. If provided, will
 *  overwrite the input expression value.
 * @param {number} [table=0] The table index of the field, in case of
 *  expressions over multiple tables.
 * @return A wrapped expression for a named column.
 * @example field('colA')
 */
function field(expr, name, table = 0) {
  const props = table ? { field: true, table } : { field: true };
  return wrap(
    expr,
    name ? { expr: name, ...props } : props
  );
}

;// ../../node_modules/arquero/src/util/assign.js


function assign_assign(map, pairs) {
  for (const [key, value] of entries_entries(pairs)) {
    map.set(key, value);
  }
  return map;
}

;// ../../node_modules/arquero/src/helpers/selection.js










function resolve(table, sel, map = new Map()) {
  sel = is_number_isNumber(sel) ? table.columnName(sel) : sel;

  if (is_string_isString(sel)) {
    map.set(sel, sel);
  } else if (is_array_isArray(sel)) {
    sel.forEach(r => resolve(table, r, map));
  } else if (is_function_isFunction(sel)) {
    resolve(table, sel(table), map);
  } else if (isObject(sel)) {
    assign_assign(map, sel);
  } else {
    error_error(`Invalid column selection: ${to_string_toString(sel)}`);
  }

  return map;
}

function decorate(value, toObject) {
  value.toObject = toObject;
  return value;
}

function toObject(value) {
  return is_array_isArray(value) ? value.map(toObject)
    : value && value.toObject ? value.toObject()
    : value;
}

/**
 * Proxy type for SelectHelper function.
 * @typedef {import('../table/types.js').SelectHelper} SelectHelper
 */

/**
 * Select all columns in a table.
 * Returns a function-valued selection compatible with {@link Table#select}.
 * @return {SelectHelper} Selection function compatible with select().
 */
function selection_all() {
  return decorate(
    table => table.columnNames(),
    () => ({ all: [] })
  );
}

/**
 * Negate a column selection, selecting all other columns in a table.
 * Returns a function-valued selection compatible with {@link Table#select}.
 * @param {...any} selection The selection to negate. May be a column name,
 *  column index, array of either, or a selection function (e.g., from range).
 * @return {SelectHelper} Selection function compatible with select().
 */
function not(...selection) {
  selection = selection.flat();
  return decorate(
    table => {
      const drop = resolve(table, selection);
      return table.columnNames(name => !drop.has(name));
    },
    () => ({ not: toObject(selection) })
  );
}

/**
 * Select a contiguous range of columns.
 * @param {string|number} start The name/index of the first selected column.
 * @param {string|number} end The name/index of the last selected column.
 * @return {SelectHelper} Selection function compatible with select().
 */
function range(start, end) {
  return decorate(
    table => {
      let i = isNumber(start) ? start : table.columnIndex(start);
      let j = isNumber(end) ? end : table.columnIndex(end);
      if (j < i) { const t = j; j = i; i = t; }
      return table.columnNames().slice(i, j + 1);
    },
    () => ({ range: [start, end] })
  );
}

/**
 * Select all columns whose names match a pattern.
 * @param {string|RegExp} pattern A string or regular expression pattern to match.
 * @return {SelectHelper} Selection function compatible with select().
 */
function matches(pattern) {
  if (isString(pattern)) pattern = RegExp(escapeRegExp(pattern));
  return decorate(
    // @ts-ignore
    table => table.columnNames(name => pattern.test(name)),
    // @ts-ignore
    () => ({ matches: [pattern.source, pattern.flags] })
  );
}

/**
 * Select all columns whose names start with a string.
 * @param {string} string The string to match at the start of the column name.
 * @return {SelectHelper} Selection function compatible with select().
 */
function selection_startswith(string) {
  return matches(RegExp('^' + escapeRegExp(string)));
}

/**
 * Select all columns whose names end with a string.
 * @param {string} string The string to match at the end of the column name.
 * @return {SelectHelper} Selection function compatible with select().
 */
function selection_endswith(string) {
  return matches(RegExp(escapeRegExp(string) + '$'));
}

;// ../../node_modules/arquero/src/verbs/util/parse.js











function parseValue(name, table, params, options = { window: false }) {
  const exprs = new Map();

  const marshal = param => {
    param = is_number_isNumber(param) ? table.columnName(param) : param;
    is_string_isString(param) ? exprs.set(param, field(param))
      : is_function_isFunction(param) ? resolve(table, param).forEach(marshal)
      : isObject(param) ? assign_assign(exprs, param)
      : error_error(`Invalid ${name} value: ${param+''}`);
  };

  toArray(params).forEach(marshal);

  if (options.preparse) {
    options.preparse(exprs);
  }

  return parse_parse(exprs, { table, ...options });
}

;// ../../node_modules/arquero/src/verbs/groupby.js




function groupby(table, ...values) {
  return _groupby(table, parseValue('groupby', table, values.flat()));
}

function _groupby(table, exprs) {
  return table.create({
    groups: createGroups(table, exprs)
  });
}

function createGroups(table, { names = [], exprs = [], ops = [] }) {
  const n = names.length;
  if (n === 0) return null;

  // check for optimized path when grouping by a single field
  // use pre-calculated groups if available
  if (n === 1 && !table.isFiltered() && exprs[0].field) {
    const col = table.column(exprs[0].field);
    if (col.groups) return col.groups(names);
  }

  let get = aggregateGet(table, ops, exprs);
  const getKey = keyFunction(get);
  const nrows = table.totalRows();
  const keys = new Uint32Array(nrows);
  const index = {};
  const rows = [];

  // inline table scan for performance
  const data = table.data();
  const bits = table.mask();
  if (bits) {
    for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
      const key = getKey(i, data) + '';
      keys[i] = (index[key] ??= rows.push(i) - 1);
    }
  } else {
    for (let i = 0; i < nrows; ++i) {
      const key = getKey(i, data) + '';
      keys[i] = (index[key] ??= rows.push(i) - 1);
    }
  }

  if (!ops.length) {
    // capture data in closure, so no interaction with select
    get = get.map(f => row => f(row, data));
  }

  return { keys, get, names, rows, size: rows.length };
}

;// ../../node_modules/arquero/src/table/ColumnSet.js
/**
 * Return a new column set instance.
 * @param {import('./Table.js').Table} [table] A base table whose columns
 *  should populate the returned set. If unspecified, create an empty set.
 * @return {ColumnSet} The column set.
 */
function columnSet(table) {
  return table
    ? new ColumnSet({ ...table.data() }, table.columnNames())
    : new ColumnSet();
}

/** An editable collection of named columns. */
class ColumnSet {
  /**
   * Create a new column set instance.
   * @param {import('./types.js').ColumnData} [data] Initial column data.
   * @param {string[]} [names] Initial column names.
   */
  constructor(data, names) {
    this.data = data || {};
    this.names = names || [];
  }

  /**
   * Add a new column to this set and return the column values.
   * @template {import('./types.js').ColumnType} T
   * @param {string} name The column name.
   * @param {T} values The column values.
   * @return {T} The provided column values.
   */
  add(name, values) {
    if (!this.has(name)) this.names.push(name + '');
    return this.data[name] = values;
  }

  /**
   * Test if this column set has a columns with the given name.
   * @param {string} name A column name
   * @return {boolean} True if this set contains a column with the given name,
   *  false otherwise.
   */
  has(name) {
    return Object.hasOwn(this.data, name);
  }

  /**
   * Add a groupby specification to this column set.
   * @param {import('./types.js').GroupBySpec} groups A groupby specification.
   * @return {this} This column set.
   */
  groupby(groups) {
    this.groups = groups;
    return this;
  }

  /**
   * Create a new table with the contents of this column set, using the same
   * type as a given prototype table. The new table does not inherit the
   * filter, groupby, or orderby state of the prototype.
   * @template {import('./Table.js').Table} T
   * @param {T} proto A prototype table
   * @return {T} The new table.
   */
  new(proto) {
    const { data, names, groups = null } = this;
    return proto.create({ data, names, groups, filter: null, order: null });
  }

  /**
   * Create a derived table with the contents of this column set, using the same
   * type as a given prototype table. The new table will inherit the filter,
   * groupby, and orderby state of the prototype.
   * @template {import('./Table.js').Table} T
   * @param {T} proto A prototype table
   * @return {T} The new table.
   */
  derive(proto) {
    return proto.create(this);
  }
}

;// ../../node_modules/arquero/src/verbs/rollup.js




function rollup_rollup(table, values) {
  return _rollup(table, parse_parse(values, { table, aggronly: true, window: false }));
}

function _rollup(table, { names, exprs, ops = [] }) {
  // output data
  const cols = columnSet();
  const groups = table.groups();

  // write groupby fields to output
  if (groups) groupOutput(cols, groups);

  // compute and write aggregate output
  output(names, exprs, groups, aggregate(table, ops), cols);

  // return output table
  return cols.new(table);
}

function output(names, exprs, groups, result = [], cols) {
  if (!exprs.length) return;
  const size = groups ? groups.size : 1;
  const op = (id, row) => result[id][row];
  const n = names.length;

  for (let i = 0; i < n; ++i) {
    const get = exprs[i];
    if (get.field != null) {
      // if expression is op only, use aggregates directly
      cols.add(names[i], result[get.field]);
    } else if (size > 1) {
      // if multiple groups, evaluate expression for each
      const col = cols.add(names[i], Array(size));
      for (let j = 0; j < size; ++j) {
        col[j] = get(j, null, op);
      }
    } else {
      // if only one group, no need to loop
      cols.add(names[i], [ get(0, null, op) ]);
    }
  }
}

;// ../../node_modules/arquero/src/verbs/select.js





function select_select(table, ...columns) {
  return _select(table, resolve(table, columns.flat()));
}

function _select(table, columns) {
  const cols = columnSet();

  columns.forEach((value, curr) => {
    const next = is_string_isString(value) ? value : curr;
    if (next) {
      const col = table.column(curr) || error_error(`Unrecognized column: ${curr}`);
      cols.add(next, col);
    }
  });

  return cols.derive(table);
}

;// ../../node_modules/arquero/src/table/regroup.js







/**
 * Regroup table rows in response to a BitSet filter.
 * @param {import('./types.js').GroupBySpec} groups The current groupby specification.
 * @param {import('./BitSet.js').BitSet} filter The filter to apply.
 */
function regroup(groups, filter) {
  if (!groups || !filter) return groups;

  // check for presence of rows for each group
  const { keys, rows, size } = groups;
  const map = new Uint32Array(size);
  filter.scan(row => map[keys[row]] = 1);

  // check sum, exit early if all groups occur
  const sum = map.reduce((sum, val) => sum + val, 0);
  if (sum === size) return groups;

  // create group index map, filter exemplar rows
  const _rows = Array(sum);
  let _size = 0;
  for (let i = 0; i < size; ++i) {
    if (map[i]) _rows[map[i] = _size++] = rows[i];
  }

  // re-index the group keys
  const _keys = new Uint32Array(keys.length);
  filter.scan(row => _keys[row] = map[keys[row]]);

  return { ...groups, keys: _keys, rows: _rows, size: _size };
}

/**
 * Regroup table rows in response to a re-indexing.
 * This operation may or may not involve filtering of rows.
 * @param {import('./types.js').GroupBySpec} groups
 *  The current groupby specification.
 * @param {Function} scan Function to scan new row indices.
 * @param {boolean} filter Flag indicating if filtering may occur.
 * @param {number} nrows The number of rows in the new table.
 */
function reindex(groups, scan, filter, nrows) {
  const { keys, rows, size } = groups;
  let _rows = rows;
  let _size = size;
  let map = null;

  if (filter) {
    // check for presence of rows for each group
    map = new Int32Array(size);
    scan(row => map[keys[row]] = 1);

    // check sum, regroup if not all groups occur
    const sum = map.reduce((sum, val) => sum + val, 0);
    if (sum !== size) {
      // create group index map, filter exemplar rows
      _rows = Array(sum);
      _size = 0;
      for (let i = 0; i < size; ++i) {
        if (map[i]) _rows[map[i] = _size++] = rows[i];
      }
    }
  }

  // re-index the group keys
  let r = -1;
  const _keys = new Uint32Array(nrows);
  const fn = _size !== size
    ? row => _keys[++r] = map[keys[row]]
    : row => _keys[++r] = keys[row];
  scan(fn);

  return { ...groups, keys: _keys, rows: _rows, size: _size };
}

function nest(table, idx, obj, type) {
  const agg = type === 'map' || type === true ? map_agg
    : type === 'entries' ? entries_agg
    : type === 'object' ? object_agg
    : error_error('groups option must be "map", "entries", or "object".');

  const { names } = table.groups();
  const col = uniqueName(table.columnNames(), '_');

  // create table with one column of row objects
  // then aggregate into per-group arrays
  let t = select_select(table, {}).reify(idx).create({ data: { [col]: obj } });
  t = rollup_rollup(t, { [col]: array_agg(col) });

  // create nested structures for each level of grouping
  for (let i = names.length; --i >= 0;) {
    t = rollup_rollup(
        groupby(t, names.slice(0, i)),
        // @ts-ignore
        { [col]: agg(names[i], col) }
      );
  }

  // return the final aggregated structure
  return t.get(col);
}

;// ../../node_modules/arquero/src/util/array-type.js


/**
 * @param {*} column
 * @returns {ArrayConstructor | import('../table/types.js').TypedArrayConstructor}
 */
function arrayType(column) {
  // @ts-ignore
  return isTypedArray(column) ? column.constructor : Array;
}

;// ../../node_modules/arquero/src/table/Table.js









/**
 * Base class representing a column-oriented data table.
 */
class Table {
  /**
   * Instantiate a Table instance.
   * @param {import('./types.js').ColumnData} columns
   *  An object mapping column names to values.
   * @param {string[]} [names]
   *  An ordered list of column names.
   * @param {import('./BitSet.js').BitSet} [filter]
   *  A filtering BitSet.
   * @param {import('./types.js').GroupBySpec} [group]
   *  A groupby specification.
   * @param {import('./types.js').RowComparator} [order]
   *  A row comparator function.
   * @param {import('./types.js').Params} [params]
   *  An object mapping parameter names to values.
   */
  constructor(columns, names, filter, group, order, params) {
    const data = Object.freeze({ ...columns });
    names = names?.slice() ?? Object.keys(data);
    const nrows = names.length ? data[names[0]].length : 0;
    /**
     * @private
     * @type {readonly string[]}
     */
    this._names = Object.freeze(names);
    /**
     * @private
     * @type {import('./types.js').ColumnData}
     */
    this._data = data;
    /**
     * @private
     * @type {number}
     */
    this._total = nrows;
    /**
     * @private
     * @type {number}
     */
    this._nrows = filter?.count() ?? nrows;
    /**
     * @private
     * @type {import('./BitSet.js').BitSet}
     */
    this._mask = filter ?? null;
    /**
     * @private
     * @type {import('./types.js').GroupBySpec}
     */
    this._group = group ?? null;
    /**
     * @private
     * @type {import('./types.js').RowComparator}
     */
    this._order = order ?? null;
    /**
     * @private
     * @type {import('./types.js').Params}
     */
    this._params = params;
    /**
     * @private
     * @type {Uint32Array}
     */
    this._index = null;
    /**
     * @private
     * @type {number[][] | Uint32Array[]}
     */
    this._partitions = null;
  }

  /**
   * Create a new table with the same type as this table.
   * The new table may have different data, filter, grouping, or ordering
   * based on the values of the optional configuration argument. If a
   * setting is not specified, it is inherited from the current table.
   * @param {import('./types.js').CreateOptions} [options]
   *  Creation options for the new table.
   * @return {this} A newly created table.
   */
  create({
    data = undefined,
    names = undefined,
    filter = undefined,
    groups = undefined,
    order = undefined
  } = {}) {
    const f = filter !== undefined ? filter : this.mask();
    // @ts-ignore
    return new this.constructor(
      data || this._data,
      names || (!data ? this._names : null),
      f,
      groups !== undefined ? groups : regroup(this._group, filter && f),
      order !== undefined ? order : this._order,
      this._params
    );
  }

  /**
   * Get or set table expression parameter values.
   * If called with no arguments, returns the current parameter values
   * as an object. Otherwise, adds the provided parameters to this
   * table's parameter set and returns the table. Any prior parameters
   * with names matching the input parameters are overridden.
   * @param {import('./types.js').Params} [values]
   *  The parameter values.
   * @return {this|import('./types.js').Params}
   *  The current parameter values (if called with no arguments) or this table.
   */
  params(values) {
    if (arguments.length) {
      if (values) {
        this._params = { ...this._params, ...values };
      }
      return this;
    } else {
      return this._params;
    }
  }

  /**
   * Provide an informative object string tag.
   */
  get [Symbol.toStringTag]() {
    if (!this._names) return 'Object'; // bail if called on prototype
    const nr = this.numRows();
    const nc = this.numCols();
    const plural = v => v !== 1 ? 's' : '';
    return `Table: ${nc} col${plural(nc)} x ${nr} row${plural(nr)}`
      + (this.isFiltered() ? ` (${this.totalRows()} backing)` : '')
      + (this.isGrouped() ? `, ${this._group.size} groups` : '')
      + (this.isOrdered() ? ', ordered' : '');
  }

  /**
   * Indicates if the table has a filter applied.
   * @return {boolean} True if filtered, false otherwise.
   */
  isFiltered() {
    return !!this._mask;
  }

  /**
   * Indicates if the table has a groupby specification.
   * @return {boolean} True if grouped, false otherwise.
   */
  isGrouped() {
    return !!this._group;
  }

  /**
   * Indicates if the table has a row order comparator.
   * @return {boolean} True if ordered, false otherwise.
   */
  isOrdered() {
    return !!this._order;
  }

  /**
   * Get the backing column data for this table.
   * @return {import('./types.js').ColumnData}
   *  Object of named column instances.
   */
  data() {
    return this._data;
  }

  /**
   * Returns the filter bitset mask, if defined.
   * @return {import('./BitSet.js').BitSet} The filter bitset mask.
   */
  mask() {
    return this._mask;
  }

  /**
   * Returns the groupby specification, if defined.
   * @return {import('./types.js').GroupBySpec} The groupby specification.
   */
  groups() {
    return this._group;
  }

  /**
   * Returns the row order comparator function, if specified.
   * @return {import('./types.js').RowComparator}
   *  The row order comparator function.
   */
  comparator() {
    return this._order;
  }

  /**
   * The total number of rows in this table, counting both
   * filtered and unfiltered rows.
   * @return {number} The number of total rows.
   */
  totalRows() {
    return this._total;
  }

  /**
   * The number of active rows in this table. This number may be
   * less than the *totalRows* if the table has been filtered.
   * @return {number} The number of rows.
   */
  numRows() {
    return this._nrows;
  }

  /**
   * The number of active rows in this table. This number may be
   * less than the *totalRows* if the table has been filtered.
   * @return {number} The number of rows.
   */
  get size() {
    return this._nrows;
  }

  /**
   * The number of columns in this table.
   * @return {number} The number of columns.
   */
  numCols() {
    return this._names.length;
  }

  /**
   * Filter function invoked for each column name.
   * @callback NameFilter
   * @param {string} name The column name.
   * @param {number} index The column index.
   * @param {string[]} array The array of names.
   * @return {boolean} Returns true to retain the column name.
   */

  /**
   * The table column names, optionally filtered.
   * @param {NameFilter} [filter] An optional filter function.
   *  If unspecified, all column names are returned.
   * @return {string[]} An array of matching column names.
   */
  columnNames(filter) {
    return filter ? this._names.filter(filter) : this._names.slice();
  }

  /**
   * The column name at the given index.
   * @param {number} index The column index.
   * @return {string} The column name,
   *  or undefined if the index is out of range.
   */
  columnName(index) {
    return this._names[index];
  }

  /**
   * The column index for the given name.
   * @param {string} name The column name.
   * @return {number} The column index, or -1 if the name is not found.
   */
  columnIndex(name) {
    return this._names.indexOf(name);
  }

  /**
   * Get the column instance with the given name.
   * @param {string} name The column name.
   * @return {import('./types.js').ColumnType | undefined}
   *  The named column, or undefined if it does not exist.
   */
  column(name) {
    return this._data[name];
  }

  /**
   * Get the column instance at the given index position.
   * @param {number} index The zero-based column index.
   * @return {import('./types.js').ColumnType | undefined}
   *  The column, or undefined if it does not exist.
   */
  columnAt(index) {
    return this._data[this._names[index]];
  }

  /**
   * Get an array of values contained in a column. The resulting array
   * respects any table filter or orderby criteria.
   * @param {string} name The column name.
   * @param {ArrayConstructor | import('./types.js').TypedArrayConstructor} [constructor=Array]
   *  The array constructor for instantiating the output array.
   * @return {import('./types.js').DataValue[] | import('./types.js').TypedArray}
   *  The array of column values.
   */
  array(name, constructor = Array) {
    const column = this.column(name);
    const array = new constructor(this.numRows());
    let idx = -1;
    this.scan(row => array[++idx] = column.at(row), true);
    return array;
  }

  /**
   * Get the value for the given column and row.
   * @param {string} name The column name.
   * @param {number} [row=0] The row index, defaults to zero if not specified.
   * @return {import('./types.js').DataValue} The table value at (column, row).
   */
  get(name, row = 0) {
    const column = this.column(name);
    return this.isFiltered() || this.isOrdered()
      ? column.at(this.indices()[row])
      : column.at(row);
  }

  /**
   * Returns an accessor ("getter") function for a column. The returned
   * function takes a row index as its single argument and returns the
   * corresponding column value.
   * @param {string} name The column name.
   * @return {import('./types.js').ColumnGetter} The column getter function.
   */
  getter(name) {
    const column = this.column(name);
    const indices = this.isFiltered() || this.isOrdered() ? this.indices() : null;
    if (indices) {
      return row => column.at(indices[row]);
    } else if (column) {
      return row => column.at(row);
    } else {
      error_error(`Unrecognized column: ${name}`);
    }
  }

  /**
   * Returns an object representing a table row.
   * @param {number} [row=0] The row index, defaults to zero if not specified.
   * @return {object} A row object with named properties for each column.
   */
  object(row = 0) {
    return objectBuilder(this)(row);
  }

  /**
   * Returns an array of objects representing table rows.
   * @param {import('./types.js').ObjectsOptions} [options]
   *  The options for row object generation.
   * @return {object[]} An array of row objects.
   */
  objects(options = {}) {
    const { grouped, limit, offset } = options;

    // generate array of row objects
    const names = resolve(this, options.columns || selection_all());
    const createRow = rowObjectBuilder(this, names);
    const obj = [];
    this.scan(
      (row, data) => obj.push(createRow(row, data)),
      true, limit, offset
    );

    // produce nested output as requested
    if (grouped && this.isGrouped()) {
      const idx = [];
      this.scan(row => idx.push(row), true, limit, offset);
      return nest(this, idx, obj, grouped);
    }

    return obj;
  }

  /**
   * Returns an iterator over objects representing table rows.
   * @return {Iterator<object>} An iterator over row objects.
   */
  *[Symbol.iterator]() {
    const createRow = objectBuilder(this);
    const n = this.numRows();
    for (let i = 0; i < n; ++i) {
      yield createRow(i);
    }
  }

  /**
   * Returns an iterator over column values.
   * @return {Iterator<object>} An iterator over row objects.
   */
  *values(name) {
    const get = this.getter(name);
    const n = this.numRows();
    for (let i = 0; i < n; ++i) {
      yield get(i);
    }
  }

  /**
   * Print the contents of this table using the console.table() method.
   * @param {import('./types.js').PrintOptions|number} options
   *  The options for row object generation, determining which rows and
   *  columns are printed. If number-valued, specifies the row limit.
   * @return {this} The table instance.
   */
  print(options = {}) {
    const opt = is_number_isNumber(options)
      ? { limit: +options }
      // @ts-ignore
      : { ...options, limit: 10 };

    const obj = this.objects({ ...opt, grouped: false });
    const msg = `${this[Symbol.toStringTag]}. Showing ${obj.length} rows.`;

    console.log(msg);   // eslint-disable-line no-console
    console.table(obj); // eslint-disable-line no-console
    return this;
  }

  /**
   * Returns an array of indices for all rows passing the table filter.
   * @param {boolean} [order=true] A flag indicating if the returned
   *  indices should be sorted if this table is ordered. If false, the
   *  returned indices may or may not be sorted.
   * @return {Uint32Array} An array of row indices.
   */
  indices(order = true) {
    if (this._index) return this._index;

    const n = this.numRows();
    const index = new Uint32Array(n);
    const ordered = this.isOrdered();
    const bits = this.mask();
    let row = -1;

    // inline the following for performance:
    // this.scan(row => index[++i] = row);
    if (bits) {
      for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
        index[++row] = i;
      }
    } else {
      for (let i = 0; i < n; ++i) {
        index[++row] = i;
      }
    }

    // sort index vector
    if (order && ordered) {
      const { _order, _data } = this;
      index.sort((a, b) => _order(a, b, _data));
    }

    // save indices if they reflect table metadata
    if (order || !ordered) {
      this._index = index;
    }

    return index;
  }

  /**
   * Returns an array of indices for each group in the table.
   * If the table is not grouped, the result is the same as
   * the *indices* method, but wrapped within an array.
   * @param {boolean} [order=true] A flag indicating if the returned
   *  indices should be sorted if this table is ordered. If false, the
   *  returned indices may or may not be sorted.
   * @return {number[][] | Uint32Array[]} An array of row index arrays, one
   *  per group. The indices will be filtered if the table is filtered.
   */
  partitions(order = true) {
    // return partitions if already generated
    if (this._partitions) {
      return this._partitions;
    }

    // if not grouped, return a single partition
    if (!this.isGrouped()) {
      return [ this.indices(order) ];
    }

    // generate partitions
    const { keys, size } = this._group;
    const part = repeat_repeat(size, () => []);

    // populate partitions, don't sort if indices don't exist
    // inline the following for performance:
    // this.scan(row => part[keys[row]].push(row), sort);
    const sort = this._index;
    const bits = this.mask();
    const n = this.numRows();
    if (sort && this.isOrdered()) {
      for (let i = 0, r; i < n; ++i) {
        r = sort[i];
        part[keys[r]].push(r);
      }
    } else if (bits) {
      for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
        part[keys[i]].push(i);
      }
    } else {
      for (let i = 0; i < n; ++i) {
        part[keys[i]].push(i);
      }
    }

    // if ordered but not yet sorted, sort partitions directly
    if (order && !sort && this.isOrdered()) {
      const compare = this._order;
      const data = this._data;
      for (let i = 0; i < size; ++i) {
        part[i].sort((a, b) => compare(a, b, data));
      }
    }

    // save partitions if they reflect table metadata
    if (order || !this.isOrdered()) {
      this._partitions = part;
    }

    return part;
  }

  /**
   * Create a new fully-materialized instance of this table.
   * All filter and orderby settings are removed from the new table.
   * Instead, the backing data itself is filtered and ordered as needed.
   * @param {number[]} [indices] Ordered row indices to materialize.
   *  If unspecified, all rows passing the table filter are used.
   * @return {this} A reified table.
   */
  reify(indices) {
    const nrows = indices ? indices.length : this.numRows();
    const names = this._names;
    let data, groups;

    if (!indices && !this.isOrdered()) {
      if (!this.isFiltered()) {
        return this; // data already reified
      } else if (nrows === this.totalRows()) {
        data = this.data(); // all rows pass filter, skip copy
      }
    }

    if (!data) {
      const scan = indices ? f => indices.forEach(f) : f => this.scan(f, true);
      const ncols = names.length;
      data = {};

      for (let i = 0; i < ncols; ++i) {
        const name = names[i];
        const prev = this.column(name);
        const curr = data[name] = new (arrayType(prev))(nrows);
        let r = -1;
        // optimize array access
        isArrayType(prev)
          ? scan(row => curr[++r] = prev[row])
          : scan(row => curr[++r] = prev.at(row));
      }

      if (this.isGrouped()) {
        groups = reindex(this.groups(), scan, !!indices, nrows);
      }
    }

    return this.create({ data, names, groups, filter: null, order: null });
  }

  /**
   * Callback function to cancel a table scan.
   * @callback ScanStop
   * @return {void}
   */

  /**
   * Callback function invoked for each row of a table scan.
   * @callback ScanVisitor
   * @param {number} [row] The table row index.
   * @param {import('./types.js').ColumnData} [data]
   *  The backing table data store.
   * @param {ScanStop} [stop] Function to stop the scan early.
   *  Callees can invoke this function to prevent future calls.
   * @return {void}
   */

  /**
   * Perform a table scan, visiting each row of the table.
   * If this table is filtered, only rows passing the filter are visited.
   * @param {ScanVisitor} fn Callback invoked for each row of the table.
   * @param {boolean} [order=false] Indicates if the table should be
   *  scanned in the order determined by *orderby*. This
   *  argument has no effect if the table is unordered.
   * @property {number} [limit=Infinity] The maximum number of rows to scan.
   * @property {number} [offset=0] The row offset indicating how many
   *  initial rows to skip.
   */
  scan(fn, order, limit = Infinity, offset = 0) {
    const filter = this._mask;
    const nrows = this._nrows;
    const data = this._data;

    let i = offset || 0;
    if (i > nrows) return;

    const n = Math.min(nrows, i + limit);
    const stop = () => i = this._total;

    if (order && this.isOrdered() || filter && this._index) {
      const index = this.indices();
      const data = this._data;
      for (; i < n; ++i) {
        fn(index[i], data, stop);
      }
    } else if (filter) {
      let c = n - i + 1;
      for (i = filter.nth(i); --c && i > -1; i = filter.next(i + 1)) {
        fn(i, data, stop);
      }
    } else {
      for (; i < n; ++i) {
        fn(i, data, stop);
      }
    }
  }
}

function objectBuilder(table) {
  let b = table._builder;

  if (!b) {
    const createRow = rowObjectBuilder(table);
    const data = table.data();
    if (table.isOrdered() || table.isFiltered()) {
      const indices = table.indices();
      b = row => createRow(indices[row], data);
    } else {
      b = row => createRow(row, data);
    }
    table._builder = b;
  }

  return b;
}

;// ../../node_modules/arquero/src/verbs/assign.js




function verbs_assign_assign(table, ...others) {
  others = others.flat();
  const nrows = table.numRows();
  const base = table.reify();
  const cols = columnSet(base).groupby(base.groups());
  others.forEach(input => {
    input = input instanceof Table ? input : new Table(input);
    if (input.numRows() !== nrows) error_error('Assign row counts do not match');
    input = input.reify();
    input.columnNames(name => cols.add(name, input.column(name)));
  });
  return cols.new(table);
}

;// ../../node_modules/arquero/src/verbs/concat.js



function verbs_concat_concat(table, ...others) {
  others = others.flat();
  const trows = table.numRows();
  const nrows = trows + others.reduce((n, t) => n + t.numRows(), 0);
  if (trows === nrows) return table;

  const tables = [table, ...others];
  const cols = columnSet();

  table.columnNames().forEach(name => {
    const arr = Array(nrows);
    let row = 0;
    tables.forEach(table => {
      const col = table.column(name) || { at: () => NULL };
      table.scan(trow => arr[row++] = col.at(trow));
    });
    cols.add(name, arr);
  });

  return cols.new(table);
}

;// ../../node_modules/arquero/src/verbs/relocate.js




function relocate(table, columns, {
  before = undefined,
  after = undefined
} = {}) {
  const bef = before != null;
  const aft = after != null;

  if (!(bef || aft)) {
    error_error('relocate requires a before or after option.');
  }
  if (bef && aft) {
    error_error('relocate accepts only one of the before or after options.');
  }

  columns = resolve(table, columns);
  const anchors = [...resolve(table, bef ? before : after).keys()];
  const anchor = bef ? anchors[0] : anchors.pop();
  const select = new Map();

  // marshal inputs to select in desired order
  table.columnNames().forEach(name => {
    // check if we should assign the current column
    const assign = !columns.has(name);

    // at anchor column, insert relocated columns
    if (name === anchor) {
      if (aft && assign) select.set(name, name);
      for (const [key, value] of columns) {
        select.set(key, value);
      }
      if (aft) return; // exit if current column has been handled
    }

    if (assign) select.set(name, name);
  });

  return _select(table, select);
}

;// ../../node_modules/arquero/src/util/bisector.js
function bisector(compare) {
  return {
    left(a, x, lo, hi) {
      if (lo == null) lo = 0;
      if (hi == null) hi = a.length;
      while (lo < hi) {
        const mid = lo + hi >>> 1;
        if (compare(a[mid], x) < 0) lo = mid + 1;
        else hi = mid;
      }
      return lo;
    },
    right(a, x, lo, hi) {
      if (lo == null) lo = 0;
      if (hi == null) hi = a.length;
      while (lo < hi) {
        const mid = lo + hi >>> 1;
        if (compare(a[mid], x) > 0) hi = mid;
        else lo = mid + 1;
      }
      return lo;
    }
  };
}

;// ../../node_modules/arquero/src/verbs/window/window-state.js





const bisect = bisector(ascending);

function windowState(data, frame, adjust, ops, aggrs) {
  let rows, peer, cells, result, key;
  const isPeer = index => peer[index - 1] === peer[index];
  const numOps = ops.length;
  const numAgg = aggrs.length;

  const evaluate = ops.length
    ? unroll(
        ['w', 'r', 'k'],
        '{' + concat_concat(ops, (_, i) => `r[_${i}.id][k]=_${i}.value(w,_${i}.get);`) + '}',
        ops
      )
    : () => {};

  const w = {
    i0: 0,
    i1: 0,
    index: 0,
    size: 0,
    peer: isPeer,

    init(partition, peers, results, group) {
      w.index = w.i0 = w.i1 = 0;
      w.size = peers.length;
      rows = partition;
      peer = peers;
      result = results;
      key = group;

      // initialize aggregates
      cells = aggrs ? aggrs.map(aggr => aggr.init()) : null;

      // initialize window ops
      for (let i = 0; i < numOps; ++i) {
        ops[i].init();
      }

      return w;
    },

    value(index, get) {
      return get(rows[index], data);
    },

    step(idx) {
      const [f0, f1] = frame;
      const n = w.size;
      const p0 = w.i0;
      const p1 = w.i1;

      w.i0 = f0 != null ? Math.max(0, idx - Math.abs(f0)) : 0;
      w.i1 = f1 != null ? Math.min(n, idx + Math.abs(f1) + 1) : n;
      w.index = idx;

      if (adjust) {
        if (w.i0 > 0 && isPeer(w.i0)) {
          w.i0 = bisect.left(peer, peer[w.i0]);
        }
        if (w.i1 < n && isPeer(w.i1)) {
          w.i1 = bisect.right(peer, peer[w.i1 - 1]);
        }
      }

      // evaluate aggregates
      for (let i = 0; i < numAgg; ++i) {
        const aggr = aggrs[i];
        const cell = cells[i];
        for (let j = p0; j < w.i0; ++j) {
          aggr.rem(cell, rows[j], data);
        }
        for (let j = p1; j < w.i1; ++j) {
          aggr.add(cell, rows[j], data);
        }
        aggr.write(cell, result, key);
      }

      // evaluate window ops
      evaluate(w, result, key);

      return result;
    }
  };

  return w;
}

;// ../../node_modules/arquero/src/verbs/window/window.js






const frameValue = op =>
  (op.frame || [null, null]).map(v => Number.isFinite(v) ? Math.abs(v) : null);

const peersValue = op => !!op.peers;

function windowOp(spec) {
  const { id, name, fields = [], params = [] } = spec;
  return {
    ...getWindow(name).create(...params),
    get: fields.length ? fields[0] : null,
    id
  };
}

function window_window(table, cols, exprs, result = {}, ops) {
  // instantiate window states
  const data = table.data();
  const states = windowStates(ops, data);
  const nstate = states.length;

  const write = unroll(
    ['r', 'd', 'op'],
    '{' + concat_concat(cols, (_, i) => `_${i}[r] = $${i}(r, d, op);`) + '}',
    cols, exprs
  );

  // scan each ordered partition
  table.partitions().forEach((rows, key) => {
    const size = rows.length;
    const peers = windowPeers(table, rows);

    // initialize window states
    for (let i = 0; i < nstate; ++i) {
      states[i].init(rows, peers, result, key);
    }

    // calculate window values per-row
    const op = id => result[id][key];
    for (let index = 0; index < size; ++index) {
      // advance window frame, updates result object
      for (let i = 0; i < nstate; ++i) {
        states[i].step(index);
      }
      write(rows[index], data, op);
    }
  });
}

function windowStates(ops, data) {
  const map = {};

  // group operations by window frame parameters
  ops.forEach(op => {
    const frame = frameValue(op);
    const peers = peersValue(op);
    const key = `${frame},${peers}`;
    const { aggOps, winOps } = map[key] || (map[key] = {
      frame,
      peers,
      aggOps: [],
      winOps: []
    });
    hasAggregate(op.name)
      ? aggOps.push(op)
      : winOps.push(windowOp(op));
  });

  return Object.values(map).map(_ => windowState(
    data, _.frame, _.peers, _.winOps,
    reducers(_.aggOps, _.frame[0] != null ? -1 : 1)
  ));
}

function windowPeers(table, rows) {
  if (table.isOrdered()) {
    // generate peer ids for sort equality checking
    const compare = table.comparator();
    const data = table.data();
    const nrows = rows.length;
    const peers = new Uint32Array(nrows);
    for (let i = 1, index = 0; i < nrows; ++i) {
      peers[i] = compare(rows[i - 1], rows[i], data) ? ++index : index;
    }
    return peers;
  } else {
    // no sort, no peers: reuse row indices as peer ids
    return rows;
  }
}

;// ../../node_modules/arquero/src/verbs/derive.js








function isWindowed(op) {
  return hasWindow(op.name) ||
    op.frame && (
      Number.isFinite(op.frame[0]) ||
      Number.isFinite(op.frame[1])
    );
}

function derive(table, values, options = {}) {
  const dt = _derive(table, parse_parse(values, { table }), options);

  return options.drop || (options.before == null && options.after == null)
    ? dt
    : relocate(
        dt,
        Object.keys(values).filter(name => !table.column(name)),
        options
      );
}

function _derive(table, { names, exprs, ops = [] }, options = {}) {
  // instantiate output data
  const total = table.totalRows();
  const cols = columnSet(options.drop ? null : table);
  const data = names.map(name => cols.add(name, Array(total)));

  // analyze operations, compute non-windowed aggregates
  const [ aggOps, winOps ] = segmentOps(ops);

  const size = table.isGrouped() ? table.groups().size : 1;
  const result = aggregate(
    table, aggOps,
    repeat_repeat(ops.length, () => Array(size))
  );

  // perform table scans to generate output values
  winOps.length
    ? window_window(table, data, exprs, result, winOps)
    : derive_output(table, data, exprs, result);

  return cols.derive(table);
}

function segmentOps(ops) {
  const aggOps = [];
  const winOps = [];
  const n = ops.length;

  for (let i = 0; i < n; ++i) {
    const op = ops[i];
    op.id = i;
    (isWindowed(op) ? winOps : aggOps).push(op);
  }

  return [aggOps, winOps];
}

function derive_output(table, cols, exprs, result) {
  const bits = table.mask();
  const data = table.data();
  const { keys } = table.groups() || {};
  const op = keys
    ? (id, row) => result[id][keys[row]]
    : id => result[id][0];

  const m = cols.length;
  for (let j = 0; j < m; ++j) {
    const get = exprs[j];
    const col = cols[j];

    // inline the following for performance:
    // table.scan((i, data) => col[i] = get(i, data, op));
    if (bits) {
      for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
        col[i] = get(i, data, op);
      }
    } else {
      const n = table.totalRows();
      for (let i = 0; i < n; ++i) {
        col[i] = get(i, data, op);
      }
    }
  }
}

;// ../../node_modules/arquero/src/table/BitSet.js
const ONE = 0x80000000;
const ALL = 0xFFFFFFFF;

/**
 * Represent an indexable set of bits.
 */
class BitSet {
  /**
   * Instantiate a new BitSet instance.
   * @param {number} size The number of bits.
   */
  constructor(size) {
    this._size = size;
    this._bits = new Uint32Array(Math.ceil(size / 32));
  }

  /**
   * The number of bits.
   * @return {number}
   */
  get length() {
    return this._size;
  }

  /**
   * The number of bits set to one.
   * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
   * @return {number}
   */
  count() {
    const n = this._bits.length;
    let count = 0;
    for (let i = 0; i < n; ++i) {
      for (let b = this._bits[i]; b; ++count) {
        b &= b - 1;
      }
    }
    return count;
  }

  /**
   * Get the bit at a given index.
   * @param {number} i The bit index.
   */
  get(i) {
    return this._bits[i >> 5] & (ONE >>> i);
  }

  /**
   * Set the bit at a given index to one.
   * @param {number} i The bit index.
   */
  set(i) {
    this._bits[i >> 5] |= (ONE >>> i);
  }

  /**
   * Clear the bit at a given index to zero.
   * @param {number} i The bit index.
   */
  clear(i) {
    this._bits[i >> 5] &= ~(ONE >>> i);
  }

  /**
   * Scan the bits, invoking a callback function with the index of
   * each non-zero bit.
   * @param {(i: number) => void} fn A callback function.
   */
  scan(fn) {
    for (let i = this.next(0); i >= 0; i = this.next(i + 1)) {
      fn(i);
    }
  }

  /**
   * Get the next non-zero bit starting from a given index.
   * @param {number} i The bit index.
   */
  next(i) {
    const bits = this._bits;
    const n = bits.length;

    let index = i >> 5;
    let curr = bits[index] & (ALL >>> i);

    for (; index < n; curr = bits[++index]) {
      if (curr !== 0) {
        return (index << 5) + Math.clz32(curr);
      }
    }

    return -1;
  }

  /**
   * Return the index of the nth non-zero bit.
   * @param {number} n The number of non-zero bits to advance.
   * @return {number} The index of the nth non-zero bit.
   */
  nth(n) {
    let i = this.next(0);
    while (n-- && i >= 0) i = this.next(i + 1);
    return i;
  }

  /**
   * Negate all bits in this bitset.
   * Modifies this BitSet in place.
   * @return {this}
   */
  not() {
    const bits = this._bits;
    const n = bits.length;

    // invert all bits
    for (let i = 0; i < n; ++i) {
      bits[i] = ~bits[i];
    }

    // unset extraneous trailing bits
    const tail = this._size % 32;
    if (tail) {
      bits[n - 1] &= ONE >> (tail - 1);
    }

    return this;
  }

  /**
   * Compute the logical AND of this BitSet and another.
   * @param {BitSet} bitset The BitSet to combine with.
   * @return {BitSet} This BitSet updated with the logical AND.
   */
  and(bitset) {
    if (bitset) {
      const a = this._bits;
      const b = bitset._bits;
      const n = a.length;

      for (let i = 0; i < n; ++i) {
        a[i] &= b[i];
      }
    }
    return this;
  }

  /**
   * Compute the logical OR of this BitSet and another.
   * @param {BitSet} bitset The BitSet to combine with.
   * @return {BitSet} This BitSet updated with the logical OR.
   */
  or(bitset) {
    if (bitset) {
      const a = this._bits;
      const b = bitset._bits;
      const n = a.length;

      for (let i = 0; i < n; ++i) {
        a[i] |= b[i];
      }
    }
    return this;
  }
}

;// ../../node_modules/arquero/src/verbs/filter.js




function filter(table, criteria) {
  const test = parse_parse({ p: criteria }, { table });
  let predicate = test.exprs[0];
  if (test.ops.length) {
    const data = _derive(table, test, { drop: true }).column('p');
    predicate = row => data.at(row);
  }
  return _filter(table, predicate);
}

function _filter(table, predicate) {
  const n = table.totalRows();
  const bits = table.mask();
  const data = table.data();
  const filter = new BitSet(n);

  // inline the following for performance:
  // table.scan((row, data) => { if (predicate(row, data)) filter.set(row); });
  if (bits) {
    for (let i = bits.next(0); i >= 0; i = bits.next(i + 1)) {
      if (predicate(i, data)) filter.set(i);
    }
  } else {
    for (let i = 0; i < n; ++i) {
      if (predicate(i, data)) filter.set(i);
    }
  }

  return table.create({ filter });
}

;// ../../node_modules/arquero/src/verbs/dedupe.js



function dedupe(table, ...keys) {
  keys = keys.flat();
  const gt = groupby(table, keys.length ? keys : table.columnNames());
  return filter(gt, 'row_number() === 1').ungroup().reify();
}

;// ../../node_modules/arquero/src/verbs/join/lookup.js
function rowLookup(table, hash) {
  const lut = new Map();
  table.scan((row, data) => {
    const key = hash(row, data);
    if (key != null && key === key) {
      lut.set(key, row);
    }
  });
  return lut;
}

function indexLookup(idx, data, hash) {
  const lut = new Map();
  const n = idx.length;
  for (let i = 0; i < n; ++i) {
    const row = idx[i];
    const key = hash(row, data);
    if (key != null && key === key) {
      lut.has(key)
        ? lut.get(key).push(i)
        : lut.set(key, [i]);
    }
  }
  return lut;
}

;// ../../node_modules/arquero/src/util/intersect.js
function intersect(a, b) {
  const set = new Set(b);
  return a.filter(x => set.has(x));
}

;// ../../node_modules/arquero/src/verbs/util/parse-key.js










function parseKey(name, table, params) {
  const exprs = new Map();

  toArray(params).forEach((param, i) => {
    param = is_number_isNumber(param) ? table.columnName(param) : param;
    is_string_isString(param) ? exprs.set(i, field(param))
      : is_function_isFunction(param) || isObject(param) && param.expr ? exprs.set(i, param)
      : error_error(`Invalid ${name} key value: ${param+''}`);
  });

  const fn = parse_parse(exprs, { table, aggregate: false, window: false });
  return keyFunction(fn.exprs, true);
}

;// ../../node_modules/arquero/src/verbs/util/join-keys.js






function inferKeys(tableL, tableR, on) {
  if (!on) {
    // perform natural join if join condition not provided
    const isect = intersect(tableL.columnNames(), tableR.columnNames());
    if (!isect.length) error_error('Natural join requires shared column names.');
    on = [isect, isect];
  } else if (is_string_isString(on)) {
    on = [on, on];
  } else if (is_array_isArray(on) && on.length === 1) {
    on = [on[0], on[0]];
  }

  return on;
}

function keyPredicate(tableL, tableR, onL, onR) {
  if (onL.length !== onR.length) {
    error_error('Mismatched number of join keys');
  }
  return [
    parseKey('join', tableL, onL),
    parseKey('join', tableR, onR)
  ];
}

;// ../../node_modules/arquero/src/verbs/join-filter.js







function semijoin(tableL, tableR, on) {
  return join_filter(tableL, tableR, on, { anti: false });
}

function antijoin(tableL, tableR, on) {
  return join_filter(tableL, tableR, on, { anti: true });
}

function join_filter(tableL, tableR, on, options) {
  on = inferKeys(tableL, tableR, on);

  const predicate = is_array_isArray(on)
    ? keyPredicate(tableL, tableR, ...on.map(toArray))
    : parse_parse({ on }, { join: [tableL, tableR] }).exprs[0];

  return _join_filter(tableL, tableR, predicate, options);
}

function _join_filter(tableL, tableR, predicate, options = {}) {
  // calculate semi-join filter mask
  const filter = new BitSet(tableL.totalRows());
  const join = is_array_isArray(predicate) ? hashSemiJoin : loopSemiJoin;
  join(filter, tableL, tableR, predicate);

  // if anti-join, negate the filter
  if (options.anti) {
    filter.not().and(tableL.mask());
  }

  return tableL.create({ filter });
}

function hashSemiJoin(filter, tableL, tableR, [keyL, keyR]) {
  // build lookup table
  const lut = rowLookup(tableR, keyR);

  // scan table, update filter with matches
  tableL.scan((rowL, data) => {
    const rowR = lut.get(keyL(rowL, data));
    if (rowR >= 0) filter.set(rowL);
  });
}

function loopSemiJoin(filter, tableL, tableR, predicate) {
  const nL = tableL.numRows();
  const nR = tableR.numRows();
  const dataL = tableL.data();
  const dataR = tableR.data();

  if (tableL.isFiltered() || tableR.isFiltered()) {
    // use indices as at least one table is filtered
    const idxL = tableL.indices(false);
    const idxR = tableR.indices(false);
    for (let i = 0; i < nL; ++i) {
      const rowL = idxL[i];
      for (let j = 0; j < nR; ++j) {
        if (predicate(rowL, dataL, idxR[j], dataR)) {
          filter.set(rowL);
          break;
        }
      }
    }
  } else {
    // no filters, enumerate row indices directly
    for (let i = 0; i < nL; ++i) {
      for (let j = 0; j < nR; ++j) {
        if (predicate(i, dataL, j, dataR)) {
          filter.set(i);
          break;
        }
      }
    }
  }
}

;// ../../node_modules/arquero/src/verbs/except.js



function except(table, ...others) {
  others = others.flat();
  if (others.length === 0) return table;
  const names = table.columnNames();
  return dedupe(others.reduce((a, b) => antijoin(a, b.select(names)), table));
}

;// ../../node_modules/arquero/src/verbs/unroll.js





function unroll_unroll(table, values, options) {
  return _unroll(
    table,
    parseValue('unroll', table, values),
    options && options.drop
      ? { ...options, drop: parseValue('unroll', table, options.drop).names }
      : options
  );
}

function _unroll(table, { names = [], exprs = [], ops = [] }, options = {}) {
  if (!names.length) return table;

  const limit = options.limit > 0 ? +options.limit : Infinity;
  const index = options.index
    ? options.index === true ? 'index' : options.index + ''
    : null;
  const drop = new Set(options.drop);
  const get = aggregateGet(table, ops, exprs);

  // initialize output columns
  const cols = columnSet();
  const nset = new Set(names);
  const priors = [];
  const copies = [];
  const unroll = [];

  // original and copied columns
  table.columnNames().forEach(name => {
    if (!drop.has(name)) {
      const col = cols.add(name, []);
      if (!nset.has(name)) {
        priors.push(table.column(name));
        copies.push(col);
      }
    }
  });

  // unrolled output columns
  names.forEach(name => {
    if (!drop.has(name)) {
      if (!cols.has(name)) cols.add(name, []);
      unroll.push(cols.data[name]);
    }
  });

  // index column, if requested
  const icol = index ? cols.add(index, []) : null;

  let start = 0;
  const m = priors.length;
  const n = unroll.length;

  const copy = (row, maxlen) => {
    for (let i = 0; i < m; ++i) {
      copies[i].length = start + maxlen;
      copies[i].fill(priors[i].at(row), start, start + maxlen);
    }
  };

  const indices = icol
    ? (row, maxlen) => {
        for (let i = 0; i < maxlen; ++i) {
          icol[row + i] = i;
        }
      }
    : () => {};

  if (n === 1) {
    // optimize common case of one array-valued column
    const fn = get[0];
    const col = unroll[0];

    table.scan((row, data) => {
      // extract array data
      const array = toArray(fn(row, data));
      const maxlen = Math.min(array.length, limit);

      // copy original table data
      copy(row, maxlen);

      // copy unrolled array data
      for (let j = 0; j < maxlen; ++j) {
        col[start + j] = array[j];
      }

      // fill in array indices
      indices(start, maxlen);

      start += maxlen;
    });
  } else {
    table.scan((row, data) => {
      let maxlen = 0;

      // extract parallel array data
      const arrays = get.map(fn => {
        const value = toArray(fn(row, data));
        maxlen = Math.min(Math.max(maxlen, value.length), limit);
        return value;
      });

      // copy original table data
      copy(row, maxlen);

      // copy unrolled array data
      for (let i = 0; i < n; ++i) {
        const col = unroll[i];
        const arr = arrays[i];
        for (let j = 0; j < maxlen; ++j) {
          col[start + j] = arr[j];
        }
      }

      // fill in array indices
      indices(start, maxlen);

      start += maxlen;
    });
  }

  return cols.new(table);
}

;// ../../node_modules/arquero/src/verbs/fold.js




function fold(table, values, options) {
  return _fold(table, parseValue('fold', table, values), options);
}

function _fold(table, { names = [], exprs = [], ops = [] }, options = {}) {
  if (names.length === 0) return table;

  const [k = 'key', v = 'value'] = options.as || [];
  const vals = aggregateGet(table, ops, exprs);

  return _unroll(
    table,
    {
      names: [k, v],
      exprs: [() => names, (row, data) => vals.map(fn => fn(row, data))]
    },
    { ...options, drop: names }
  );
}

;// ../../node_modules/arquero/src/verbs/ungroup.js
function ungroup_ungroup(table) {
  return table.isGrouped()
    ? table.create({ groups: null })
    : table;
}

;// ../../node_modules/arquero/src/verbs/impute.js













function impute(table, values, options = {}) {
  values = parse_parse(values, { table });

  values.names.forEach(name =>
    table.column(name) ? 0 : error_error(`Invalid impute column ${to_string_toString(name)}`)
  );

  if (options.expand) {
    const opt = { preparse, window: false, aggronly: true };
    const params = parseValue('impute', table, options.expand, opt);
    const result = _rollup(ungroup_ungroup(table), params);
    return _impute(
      table, values, params.names,
      params.names.map(name => result.get(name, 0))
    );
  } else {
    return _impute(table, values);
  }
}

// map direct field reference to "unique" aggregate
function preparse(map) {
  map.forEach((value, key) =>
    value.field ? map.set(key, array_agg_distinct(value + '')) : 0
  );
}

function _impute(table, values, keys, arrays) {
  const write = keys && keys.length;
  table = write ? impute_expand(table, keys, arrays) : table;
  const { names, exprs, ops } = values;
  const gets = aggregateGet(table, ops, exprs);
  const cols = write ? null : columnSet(table);
  const rows = table.totalRows();

  names.forEach((name, i) => {
    const col = table.column(name);
    const out = write ? col : cols.add(name, Array(rows));
    const get = gets[i];

    table.scan(idx => {
      const v = col.at(idx);
      out[idx] = !is_valid_isValid(v) ? get(idx) : v;
    });
  });

  return write ? table : table.create(cols);
}

function impute_expand(table, keys, values) {
  const groups = table.groups();
  const data = table.data();

  // expansion keys and accessors
  const keyNames = (groups ? groups.names : []).concat(keys);
  const keyGet = (groups ? groups.get : [])
    .concat(keys.map(key => table.getter(key)));

  // build hash of existing rows
  const hash = new Set();
  const keyTable = keyFunction(keyGet);
  table.scan((idx, data) => hash.add(keyTable(idx, data)));

  // initialize output table data
  const names = table.columnNames();
  const cols = columnSet();
  const out = names.map(name => cols.add(name, []));
  names.forEach((name, i) => {
    const old = data[name];
    const col = out[i];
    table.scan(row => col.push(old.at(row)));
  });

  // enumerate expanded value sets and augment output table
  const keyEnum = keyFunction(keyGet.map((k, i) => a => a[i]));
  const set = unroll(
    'v',
    '{' + out.map((_, i) => `_${i}.push(v[$${i}]);`).join('') + '}',
    out, names.map(name => keyNames.indexOf(name))
  );

  if (groups) {
    let row = groups.keys.length;
    const prod = values.reduce((p, a) => p * a.length, groups.size);
    const keys = new Uint32Array(prod + (row - hash.size));
    keys.set(groups.keys);
    enumerate(groups, values, (vec, idx) => {
      if (!hash.has(keyEnum(vec))) {
        set(vec);
        keys[row++] = idx[0];
      }
    });
    cols.groupby({ ...groups, keys });
  } else {
    enumerate(groups, values, vec => {
      if (!hash.has(keyEnum(vec))) set(vec);
    });
  }

  return cols.new(table);
}

function enumerate(groups, values, callback) {
  const offset = groups ? groups.get.length : 0;
  const pad = groups ? 1 : 0;
  const len = pad + values.length;
  const lens = new Int32Array(len);
  const idxs = new Int32Array(len);
  const set = [];

  if (groups) {
    const { get, rows, size } = groups;
    lens[0] = size;
    set.push((vec, idx) => {
      const row = rows[idx];
      for (let i = 0; i < offset; ++i) {
        vec[i] = get[i](row);
      }
    });
  }

  values.forEach((a, i) => {
    const j = i + offset;
    lens[i + pad] = a.length;
    set.push((vec, idx) => vec[j] = a[idx]);
  });

  const vec = Array(offset + values.length);

  // initialize value vector
  for (let i = 0; i < len; ++i) {
    set[i](vec, 0);
  }
  callback(vec, idxs);

  // enumerate all combinations of values
  for (let i = len - 1; i >= 0;) {
    const idx = ++idxs[i];
    if (idx < lens[i]) {
      set[i](vec, idx);
      callback(vec, idxs);
      i = len - 1;
    } else {
      idxs[i] = 0;
      set[i](vec, 0);
      --i;
    }
  }
}

;// ../../node_modules/arquero/src/verbs/intersect.js



function intersect_intersect(table, ...others) {
  others = others.flat();
  const names = table.columnNames();
  return others.length
    ? dedupe(others.reduce((a, b) => semijoin(a, b.select(names)), table))
    : table.reify([]);
}

;// ../../node_modules/arquero/src/verbs/join.js













const OPT_L = { aggregate: false, window: false };
const OPT_R = { ...OPT_L, index: 1 };
const NONE = -Infinity;

function cross(table, other, values, options) {
  return join_join(
    table,
    other,
    () => true,
    values,
    { ...options, left: true, right: true }
  );
}

function join_join(tableL, tableR, on, values, options = {}) {
  on = inferKeys(tableL, tableR, on);
  const optParse = { join: [tableL, tableR] };
  let predicate;

  if (is_array_isArray(on)) {
    const [onL, onR] = on.map(toArray);
    predicate = keyPredicate(tableL, tableR, onL, onR);

    if (!values) {
      // infer output columns, suppress duplicated key columns
      values = inferValues(tableL, onL, onR, options);
    }
  } else {
    predicate = parse_parse({ on }, optParse).exprs[0];

    if (!values) {
      // include all table columns if values not provided
      values = [selection_all(), selection_all()];
    }
  }

  return _join(
    tableL, tableR, predicate,
    join_parseValues(tableL, tableR, values, optParse, options && options.suffix),
    options
  );
}

function inferValues(tableL, onL, onR, options) {
  const isect = [];
  onL.forEach((s, i) => is_string_isString(s) && s === onR[i] ? isect.push(s) : 0);
  const vR = not(isect);

  if (options.left && options.right) {
    // for full join, merge shared key columns together
    const shared = new Set(isect);
    return [
      tableL.columnNames().map(s => {
        const c = `[${to_string_toString(s)}]`;
        return shared.has(s)
          ? { [s]: `(a, b) => a${c} == null ? b${c} : a${c}` }
          : s;
      }),
      vR
    ];
  }

  return options.right ? [vR, selection_all()] : [selection_all(), vR];
}

function join_parseValues(tableL, tableR, values, optParse, suffix = []) {
  if (is_array_isArray(values)) {
    let vL, vR, vJ, n = values.length;
    vL = vR = vJ = { names: [], exprs: [] };

    if (n--) {
      vL = parseValue('join', tableL, values[0], optParse);
    }
    if (n--) {
      vR = parseValue('join', tableR, values[1], OPT_R);
    }
    if (n--) {
      vJ = parse_parse(values[2], optParse);
    }

    // handle name collisions
    const rename = new Set();
    const namesL = new Set(vL.names);
    vR.names.forEach(name => {
      if (namesL.has(name)) {
        rename.add(name);
      }
    });
    if (rename.size) {
      suffix[0] !== '' && rekey(vL.names, rename, suffix[0] || '_1');
      suffix[1] !== '' && rekey(vR.names, rename, suffix[1] || '_2');
    }

    return {
      names: vL.names.concat(vR.names, vJ.names),
      exprs: vL.exprs.concat(vR.exprs, vJ.exprs)
    };
  } else {
    return parse_parse(values, optParse);
  }
}

function rekey(names, rename, suffix) {
  names.forEach((name, i) => rename.has(name)
    ? (names[i] = name + suffix)
    : 0);
}

function emitter(columns, getters) {
  const args = ['i', 'a', 'j', 'b'];
  return unroll(
    args,
    '{' + concat_concat(columns, (_, i) => `_${i}.push($${i}(${args}));`) + '}',
    columns, getters
  );
}

function _join(tableL, tableR, predicate, { names, exprs }, options = {}) {
  // initialize data for left table
  const dataL = tableL.data();
  const idxL = tableL.indices(false);
  const nL = idxL.length;
  const hitL = new Int32Array(nL);

  // initialize data for right table
  const dataR = tableR.data();
  const idxR = tableR.indices(false);
  const nR = idxR.length;
  const hitR = new Int32Array(nR);

  // initialize output data
  const ncols = names.length;
  const cols = columnSet();
  const columns = Array(ncols);
  const getters = Array(ncols);
  for (let i = 0; i < names.length; ++i) {
    columns[i] = cols.add(names[i], []);
    getters[i] = exprs[i];
  }
  const emit = emitter(columns, getters);

  // perform join
  const join = is_array_isArray(predicate) ? hashJoin : loopJoin;
  join(emit, predicate, dataL, dataR, idxL, idxR, hitL, hitR, nL, nR);

  if (options.left) {
    for (let i = 0; i < nL; ++i) {
      if (!hitL[i]) {
        emit(idxL[i], dataL, NONE, dataR);
      }
    }
  }

  if (options.right) {
    for (let j = 0; j < nR; ++j) {
      if (!hitR[j]) {
        emit(NONE, dataL, idxR[j], dataR);
      }
    }
  }

  return cols.new(tableL);
}

function loopJoin(emit, predicate, dataL, dataR, idxL, idxR, hitL, hitR, nL, nR) {
  // perform nested-loops join
  for (let i = 0; i < nL; ++i) {
    const rowL = idxL[i];
    for (let j = 0; j < nR; ++j) {
      const rowR = idxR[j];
      if (predicate(rowL, dataL, rowR, dataR)) {
        emit(rowL, dataL, rowR, dataR);
        hitL[i] = 1;
        hitR[j] = 1;
      }
    }
  }
}

function hashJoin(emit, [keyL, keyR], dataL, dataR, idxL, idxR, hitL, hitR, nL, nR) {
  // determine which table to hash
  let dataScan, keyScan, hitScan, idxScan;
  let dataHash, keyHash, hitHash, idxHash;
  let emitScan = emit;
  if (nL >= nR) {
    dataScan = dataL; keyScan = keyL; hitScan = hitL; idxScan = idxL;
    dataHash = dataR; keyHash = keyR; hitHash = hitR; idxHash = idxR;
  } else {
    dataScan = dataR; keyScan = keyR; hitScan = hitR; idxScan = idxR;
    dataHash = dataL; keyHash = keyL; hitHash = hitL; idxHash = idxL;
    emitScan = (i, a, j, b) => emit(j, b, i, a);
  }

  // build lookup table
  const lut = indexLookup(idxHash, dataHash, keyHash);

  // scan other table
  const m = idxScan.length;
  for (let j = 0; j < m; ++j) {
    const rowScan = idxScan[j];
    const list = lut.get(keyScan(rowScan, dataScan));
    if (list) {
      const n = list.length;
      for (let k = 0; k < n; ++k) {
        const i = list[k];
        emitScan(rowScan, dataScan, idxHash[i], dataHash);
        hitHash[i] = 1;
      }
      hitScan[j] = 1;
    }
  }
}

;// ../../node_modules/arquero/src/verbs/lookup.js











function lookup(tableL, tableR, on, ...values) {
  on = inferKeys(tableL, tableR, on);
  values = values.length === 0
    ? [not(tableL.columnNames())]
    : values.flat();
  return _lookup(
    tableL,
    tableR,
    [ parseKey('lookup', tableL, on[0]), parseKey('lookup', tableR, on[1]) ],
    parseValue('lookup', tableR, values)
  );
}

function _lookup(tableL, tableR, [keyL, keyR], { names, exprs, ops = [] }) {
  // instantiate output data
  const cols = columnSet(tableL);
  const total = tableL.totalRows();
  names.forEach(name => cols.add(name, Array(total).fill(NULL)));

  // build lookup table
  const lut = rowLookup(tableR, keyR);

  // generate setter function for lookup match
  const set = unroll(
    ['lr', 'rr', 'data'],
    '{' + concat_concat(names, (_, i) => `_[${i}][lr] = $[${i}](rr, data);`) + '}',
    names.map(name => cols.data[name]),
    aggregateGet(tableR, ops, exprs)
  );

  // find matching rows, set values on match
  const dataR = tableR.data();
  tableL.scan((lrow, data) => {
    const rrow = lut.get(keyL(lrow, data));
    if (rrow >= 0) set(lrow, rrow, dataR);
  });

  return cols.derive(tableL);
}

;// ../../node_modules/arquero/src/expression/compare.js




// generate code to compare a single field
const _compare = (u, v, lt, gt) => `((u = ${u}) < (v = ${v}) || u == null) && v != null ? ${lt} : (u > v || v == null) && u != null ? ${gt} : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${lt} : v !== v && u === u ? ${gt} : `;
const _collate = (u, v, lt, gt, f) => `(v = ${v}, (u = ${u}) == null && v == null) ? 0 : v == null ? ${gt} : u == null ? ${lt} : (u = ${f}(u,v)) ? u : `;

function compare(table, fields) {
  // parse expressions, generate code for both a and b values
  const names = [];
  const exprs = [];
  const fn = [];
  let keys = null, opA = '0', opB = '0';
  if (table.isGrouped()) {
    keys = table.groups().keys;
    opA = 'ka';
    opB = 'kb';
  }
  const { ops } = parse_parse(fields, {
    table,
    value: (name, node) => {
      names.push(name);
      if (node.escape) {
        // if an escaped function, invoke it directly
        const f = i => `fn[${fn.length}](${i}, data)`;
        exprs.push([f('a'), f('b')]);
        fn.push(node.escape);
      } else {
        // generate code to extract values to compare
        exprs.push([
          codegen(node, { index: 'a', op: opA }),
          codegen(node, { index: 'b', op: opB })
        ]);
      }
    },
    window: false
  });

  // calculate aggregate values if needed
  const result = aggregate(table, ops);
  const op = (id, row) => result[id][row];

  // generate comparison code for each field
  const n = names.length;
  let code = 'return (a, b) => {'
    + (op && table.isGrouped() ? 'const ka = keys[a], kb = keys[b];' : '')
    + 'let u, v; return ';
  for (let i = 0; i < n; ++i) {
    const field = fields.get(names[i]);
    const o = field.desc ? -1 : 1;
    const [u, v] = exprs[i];
    if (field.collate) {
      code += _collate(u, v, -o, o, `${o < 0 ? '-' : ''}fn[${fn.length}]`);
      fn.push(field.collate);
    } else {
      code += _compare(u, v, -o, o);
    }
  }
  code += '0;};';

  // instantiate and return comparator function
  return Function('op', 'keys', 'fn', 'data', code)(op, keys, fn, table.data());
}

;// ../../node_modules/arquero/src/verbs/orderby.js








function orderby(table, ...values) {
  return _orderby(table, orderby_parseValues(table, values.flat()));
}

function orderby_parseValues(table, params) {
  let index = -1;
  const exprs = new Map();
  const add = val => exprs.set(++index + '', val);

  params.forEach(param => {
    const expr = param.expr != null ? param.expr : param;

    if (isObject(expr) && !is_function_isFunction(expr)) {
      for (const key in expr) add(expr[key]);
    } else {
      add(
        is_number_isNumber(expr) ? field(param, table.columnName(expr))
          : is_string_isString(expr) ? field(param)
          : is_function_isFunction(expr) ? param
          : error_error(`Invalid orderby field: ${param+''}`)
      );
    }
  });

  return compare(table, exprs);
}

function _orderby(table, comparator) {
  return table.create({ order: comparator });
}

;// ../../node_modules/arquero/src/verbs/pivot.js






// TODO: enforce aggregates only (no output changes) for values
function pivot(table, on, values, options) {
  return _pivot(
    table,
    parseValue('fold', table, on),
    parseValue('fold', table, values, { preparse: pivot_preparse, window: false, aggronly: true }),
    options
  );
}

// map direct field reference to "any" aggregate
function pivot_preparse(map) {
  map.forEach((value, key) =>
    value.field ? map.set(key, any(value + '')) : 0
  );
}

const opt = (value, defaultValue) => value != null ? value : defaultValue;

function _pivot(table, on, values, options = {}) {
  const { keys, keyColumn } = pivotKeys(table, on, options);
  const vsep = opt(options.valueSeparator, '_');
  const namefn = values.names.length > 1
    ? (i, name) => name + vsep + keys[i]
    : i => keys[i];

  // perform separate aggregate operations for each key
  // if keys do not match, emit NaN so aggregate skips it
  // use custom toString method for proper field resolution
  const results = keys.map(
    k => aggregate(table, values.ops.map(op => {
      if (op.name === 'count') { // fix #273
        const fn = r => k === keyColumn[r] ? 1 : NaN;
        fn.toString = () => k + ':1';
        return { ...op, name: 'sum', fields: [fn] };
      }
      const fields = op.fields.map(f => {
        const fn = (r, d) => k === keyColumn[r] ? f(r, d) : NaN;
        fn.toString = () => k + ':' + f;
        return fn;
      });
      return { ...op, fields };
    }))
  );

  return pivot_output(values, namefn, table.groups(), results).new(table);
}

function pivotKeys(table, on, options) {
  const limit = options.limit > 0 ? +options.limit : Infinity;
  const sort = opt(options.sort, true);
  const ksep = opt(options.keySeparator, '_');

  // construct key accessor function
  const get = aggregateGet(table, on.ops, on.exprs);
  const key = get.length === 1
    ? get[0]
    : (row, data) => get.map(fn => fn(row, data)).join(ksep);

  // generate vector of per-row key values
  const kcol = Array(table.totalRows());
  table.scan((row, data) => kcol[row] = key(row, data));

  // collect unique key values
  const uniq = aggregate(
    ungroup_ungroup(table),
    [ {
      id: 0,
      name: 'array_agg_distinct',
      fields: [(row => kcol[row])], params: []
    } ]
  )[0][0];

  // get ordered set of unique key values
  const keys = sort ? uniq.sort() : uniq;

  // return key values
  return {
    keys: Number.isFinite(limit) ? keys.slice(0, limit) : keys,
    keyColumn: kcol
  };
}

function pivot_output({ names, exprs }, namefn, groups, results) {
  const size = groups ? groups.size : 1;
  const cols = columnSet();
  const m = results.length;
  const n = names.length;

  let result;
  const op = (id, row) => result[id][row];

  // write groupby fields to output
  if (groups) groupOutput(cols, groups);

  // write pivot values to output
  for (let i = 0; i < n; ++i) {
    const get = exprs[i];
    if (get.field != null) {
      // if expression is op only, use aggregates directly
      for (let j = 0; j < m; ++j) {
        cols.add(namefn(j, names[i]), results[j][get.field]);
      }
    } else if (size > 1) {
      // if multiple groups, evaluate expression for each
      for (let j = 0; j < m; ++j) {
        result = results[j];
        const col = cols.add(namefn(j, names[i]), Array(size));
        for (let k = 0; k < size; ++k) {
          col[k] = get(k, null, op);
        }
      }
    } else {
      // if only one group, no need to loop
      for (let j = 0; j < m; ++j) {
        result = results[j];
        cols.add(namefn(j, names[i]), [ get(0, null, op) ]);
      }
    }
  }

  return cols;
}

;// ../../node_modules/arquero/src/verbs/reduce.js



function reduce(table, reducer) {
  const cols = columnSet();
  const groups = table.groups();

  // initialize groups
  const { get, names = [], rows, size = 1 } = groups || {};
  const counts = new Uint32Array(size + 1);
  names.forEach(name => cols.add(name, null));

  // compute reduced values
  const cells = groups
    ? reduceGroups(table, reducer, groups)
    : [ reduceFlat(table, reducer) ];

  // initialize output columns
  reducer.outputs().map(name => cols.add(name, []));

  // write reduced values to output columns
  const n = counts.length - 1;
  let len = 0;
  for (let i = 0; i < n; ++i) {
    len += counts[i + 1] = reducer.write(cells[i], cols.data, counts[i]);
  }

  // write group values to output columns
  if (groups) {
    const data = table.data();
    names.forEach((name, index) => {
      const column = cols.data[name] = Array(len);
      const getter = get[index];
      for (let i = 0, j = 0; i < size; ++i) {
        column.fill(getter(rows[i], data), j, j += counts[i + 1]);
      }
    });
  }

  return cols.new(table);
}

;// ../../node_modules/arquero/src/verbs/rename.js



function rename(table, ...columns) {
  const map = new Map();
  table.columnNames(x => (map.set(x, x), 0));
  return _select(table, resolve(table, columns.flat(), map));
}

;// ../../node_modules/arquero/src/util/sample.js




function sample(buffer, replace, index, weight) {
  return (
    replace
      ? (weight ? sampleRW : sampleRU)
      : (weight ? sampleNW : sampleNU)
  )(buffer.length, buffer, index, weight);
}

// uniform sampling with replacement
// uses straightforward uniform sampling
function sampleRU(size, buffer, index) {
  const n = index.length;
  for (let i = 0; i < size; ++i) {
    buffer[i] = index[(n * random()) | 0];
  }
  return buffer;
}

// weighted sampling with replacement
// uses binary search lookup against cumulative weight
function sampleRW(size, buffer, index, weight) {
  const n = index.length;
  const w = new Float64Array(n);

  let sum = 0;
  for (let i = 0; i < n; ++i) {
    w[i] = (sum += weight(index[i]));
  }

  const bisect = bisector(ascending).right;
  for (let i = 0; i < size; ++i) {
    buffer[i] = index[bisect(w, sum * random())];
  }
  return buffer;
}

// uniform sampling without replacement
// uses reservoir sampling to build out the sample
// https://en.wikipedia.org/wiki/Reservoir_sampling
function sampleNU(size, buffer, index) {
  const n = index.length;
  if (size >= n) return index;

  for (let i = 0; i < size; ++i) {
    buffer[i] = index[i];
  }

  for (let i = size; i < n; ++i) {
    const j = i * random();
    if (j < size) {
      buffer[j | 0] = index[i];
    }
  }

  return buffer;
}

// weighted sample without replacement
// uses method of Efraimidis and Spirakis
// TODO: could use min-heap to improve efficiency
function sampleNW(size, buffer, index, weight) {
  const n = index.length;
  if (size >= n) return index;

  const w = new Float32Array(n);
  const k = new Uint32Array(n);
  for (let i = 0; i < n; ++i) {
    k[i] = i;
    w[i] = -Math.log(random()) / weight(index[i]);
  }

  k.sort((a, b) => w[a] - w[b]);
  for (let i = 0; i < size; ++i) {
    buffer[i] = index[k[i]];
  }
  return buffer;
}

;// ../../node_modules/arquero/src/util/shuffle.js


function shuffle_shuffle(array, lo = 0, hi = array.length) {
  let n = hi - (lo = +lo);

  while (n) {
    const i = random() * n-- | 0;
    const v = array[n + lo];
    array[n + lo] = array[i + lo];
    array[i + lo] = v;
  }

  return array;
}

;// ../../node_modules/arquero/src/verbs/sample.js








function sample_sample(table, size, options = {}) {
  return _sample(
    table,
    parseSize(table, size),
    parseWeight(table, options.weight),
    options
  );
}

const sample_get = col => row => col.at(row) || 0;

function parseSize(table, size) {
  return is_number_isNumber(size)
    ? () => size
    : sample_get(_rollup(table, parse_parse({ size }, { table, window: false })).column('size'));
}

function parseWeight(table, w) {
  if (w == null) return null;
  w = is_number_isNumber(w) ? table.columnName(w) : w;
  return sample_get(
    is_string_isString(w)
      ? table.column(w)
      : _derive(table, parse_parse({ w }, { table }), { drop: true }).column('w')
  );
}

function _sample(table, size, weight, options = {}) {
  const { replace, shuffle } = options;
  const parts = table.partitions(false);

  let total = 0;
  size = parts.map((idx, group) => {
    let s = size(group);
    total += (s = (replace ? s : Math.min(idx.length, s)));
    return s;
  });

  const samples = new Uint32Array(total);
  let curr = 0;

  parts.forEach((idx, group) => {
    const sz = size[group];
    const buf = samples.subarray(curr, curr += sz);

    if (!replace && sz === idx.length) {
      // sample size === data size, no replacement
      // no need to sample, just copy indices
      buf.set(idx);
    } else {
      sample(buf, replace, idx, weight);
    }
  });

  if (shuffle !== false && (parts.length > 1 || !replace)) {
    // sampling with replacement methods shuffle, so in
    // that case a single partition is already good to go
    shuffle_shuffle(samples);
  }

  return table.reify(samples);
}

;// ../../node_modules/arquero/src/helpers/slice.js
/**
 * Generate a table expression that filters a table based on ordered row
 * indices from start to end (end not included), where start and end
 * represent per-group ordered row numbers in the table. The resulting
 * string can be used as the input to the filter verb.
 * @param {number} [start] Zero-based index at which to start extraction.
 *  A negative index indicates an offset from the end of the group.
 *  If start is undefined, slice starts from the index 0.
 * @param {number} [end] Zero-based index before which to end extraction.
 *  A negative index indicates an offset from the end of the group.
 *  If end is omitted, slice extracts through the end of the group.
 * @return {string} A table expression string for slicing values.
 * @example slice(1, -1)
 */
function slice_slice(start = 0, end = Infinity) {
  return `${prep(start)} < row_number() && row_number() <= ${prep(end)}`;
}

function prep(index) {
  return index < 0 ? `count() + ${index}` : index;
}

;// ../../node_modules/arquero/src/verbs/slice.js



function verbs_slice_slice(table, start = 0, end = Infinity) {
  if (table.isGrouped()) {
    return filter(table, slice_slice(start, end)).reify();
  }

  // if not grouped, scan table directly
  const indices = [];
  const nrows = table.numRows();
  start = Math.max(0, start + (start < 0 ? nrows : 0));
  end = Math.min(nrows, Math.max(0, end + (end < 0 ? nrows : 0)));
  table.scan(row => indices.push(row), true, end - start, start);
  return table.reify(indices);
}

;// ../../node_modules/arquero/src/verbs/spread.js






function spread_spread(table, values, options) {
  return _spread(table, parseValue('spread', table, values), options);
}

function _spread(table, { names, exprs, ops = [] }, options = {}) {
  if (names.length === 0) return table;

  // ignore 'as' if there are multiple field names
  const as = (names.length === 1 && options.as) || [];
  const drop = options.drop == null ? true : !!options.drop;
  const limit = options.limit == null
    ? as.length || Infinity
    : Math.max(1, +options.limit || 1);

  const get = aggregateGet(table, ops, exprs);
  const cols = columnSet();
  const map = names.reduce((map, name, i) => map.set(name, i), new Map());

  const add = (index, name) => {
    const columns = spreadCols(table, get[index], limit);
    const n = columns.length;
    for (let i = 0; i < n; ++i) {
      cols.add(as[i] || `${name}_${i + 1}`, columns[i]);
    }
  };

  table.columnNames().forEach(name => {
    if (map.has(name)) {
      if (!drop) cols.add(name, table.column(name));
      add(map.get(name), name);
      map.delete(name);
    } else {
      cols.add(name, table.column(name));
    }
  });

  map.forEach(add);

  return cols.derive(table);
}

function spreadCols(table, get, limit) {
  const nrows = table.totalRows();
  const columns = [];

  table.scan((row, data) => {
    const values = toArray(get(row, data));
    const n = Math.min(values.length, limit);
    while (columns.length < n) {
      columns.push(Array(nrows).fill(NULL));
    }
    for (let i = 0; i < n; ++i) {
      columns[i][row] = values[i];
    }
  });

  return columns;
}

;// ../../node_modules/arquero/src/verbs/union.js



function union(table, ...others) {
  return dedupe(verbs_concat_concat(table, others.flat()));
}

;// ../../node_modules/arquero/src/verbs/unorder.js
function unorder(table) {
  return table.isOrdered()
    ? table.create({ order: null })
    : table;
}

;// ../../node_modules/arquero/src/verbs/index.js




























;// ../../node_modules/@uwdata/flechette/src/constants.js
/** Magic bytes 'ARROW1' indicating the Arrow 'file' format. */
const MAGIC = Uint8Array.of(65, 82, 82, 79, 87, 49);

/** Bytes for an 'end of stream' message. */
const EOS = Uint8Array.of(255, 255, 255, 255, 0, 0, 0, 0);

/**
 * Apache Arrow version.
 */
const Version = /** @type {const} */ ({
  /** 0.1.0 (October 2016). */
  V1: 0,
  /** 0.2.0 (February 2017). Non-backwards compatible with V1. */
  V2: 1,
  /** 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2. */
  V3: 2,
  /** >= 0.8.0 (December 2017). Non-backwards compatible with V3. */
  V4: 3,
  /**
   * >= 1.0.0 (July 2020). Backwards compatible with V4 (V5 readers can read V4
   * metadata and IPC messages). Implementations are recommended to provide a
   * V4 compatibility mode with V5 format changes disabled.
   *
   * Incompatible changes between V4 and V5:
   * - Union buffer layout has changed.
   *   In V5, Unions don't have a validity bitmap buffer.
   */
  V5: 4
});

/**
 * Endianness of Arrow-encoded data.
 */
const Endianness = /** @type {const} */ ({
  Little: 0,
  Big: 1
});

/**
 * Message header type codes.
 */
const MessageHeader = /** @type {const} */ ({
  NONE: 0,
  /**
   * A Schema describes the columns in a record batch.
   */
  Schema: 1,
  /**
   * For sending dictionary encoding information. Any Field can be
   * dictionary-encoded, but in this case none of its children may be
   * dictionary-encoded.
   * There is one vector / column per dictionary, but that vector / column
   * may be spread across multiple dictionary batches by using the isDelta
   * flag.
   */
  DictionaryBatch: 2,
  /**
   * A data header describing the shared memory layout of a "record" or "row"
   * batch. Some systems call this a "row batch" internally and others a "record
   * batch".
   */
  RecordBatch: 3,
  /**
   * EXPERIMENTAL: Metadata for n-dimensional arrays, aka "tensors" or
   * "ndarrays". Arrow implementations in general are not required to implement
   * this type.
   *
   * Not currently supported by Flechette.
   */
  Tensor: 4,
  /**
   * EXPERIMENTAL: Metadata for n-dimensional sparse arrays, aka "sparse
   * tensors". Arrow implementations in general are not required to implement
   * this type.
   *
   * Not currently supported by Flechette.
   */
  SparseTensor: 5
});

/**
 * Field data type ids.
 * Only non-negative values ever occur in IPC flatbuffer binary data.
 */
const constants_Type = /** @type {const} */ ({
  /**
   * Dictionary types compress data by using a set of integer indices to
   * lookup potentially repeated vales in a separate dictionary of values.
   *
   * This type entry is provided for API convenience, it does not occur
   * in actual Arrow IPC binary data.
   */
  Dictionary: -1,
  /** No data type. Included for flatbuffer compatibility. */
  NONE: 0,
  /** Null values only. */
  Null: 1,
  /** Integers, either signed or unsigned, with 8, 16, 32, or 64 bit widths. */
  Int: 2,
  /** Floating point numbers with 16, 32, or 64 bit precision. */
  Float: 3,
  /** Opaque binary data. */
  Binary: 4,
  /** Unicode with UTF-8 encoding. */
  Utf8: 5,
  /** Booleans represented as 8 bit bytes. */
  Bool: 6,
  /**
   * Exact decimal value represented as an integer value in two's complement.
   * Currently only 128-bit (16-byte) and 256-bit (32-byte) integers are used.
   * The representation uses the endianness indicated in the schema.
   */
  Decimal: 7,
  /**
   * Date is either a 32-bit or 64-bit signed integer type representing an
   * elapsed time since UNIX epoch (1970-01-01), stored in either of two units:
   * - Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no
   * leap seconds), where the values are evenly divisible by 86400000
   * - Days (32 bits) since the UNIX epoch
   */
  Date: 8,
  /**
   * Time is either a 32-bit or 64-bit signed integer type representing an
   * elapsed time since midnight, stored in either of four units: seconds,
   * milliseconds, microseconds or nanoseconds.
   *
   * The integer `bitWidth` depends on the `unit` and must be one of the following:
   * - SECOND and MILLISECOND: 32 bits
   * - MICROSECOND and NANOSECOND: 64 bits
   *
   * The allowed values are between 0 (inclusive) and 86400 (=24*60*60) seconds
   * (exclusive), adjusted for the time unit (for example, up to 86400000
   * exclusive for the MILLISECOND unit).
   * This definition doesn't allow for leap seconds. Time values from
   * measurements with leap seconds will need to be corrected when ingesting
   * into Arrow (for example by replacing the value 86400 with 86399).
   */
  Time: 9,
  /**
   * Timestamp is a 64-bit signed integer representing an elapsed time since a
   * fixed epoch, stored in either of four units: seconds, milliseconds,
   * microseconds or nanoseconds, and is optionally annotated with a timezone.
   *
   * Timestamp values do not include any leap seconds (in other words, all
   * days are considered 86400 seconds long).
   *
   * The timezone is an optional string for the name of a timezone, one of:
   *
   *  - As used in the Olson timezone database (the "tz database" or
   *    "tzdata"), such as "America/New_York".
   *  - An absolute timezone offset of the form "+XX:XX" or "-XX:XX",
   *    such as "+07:30".
   *
   * Whether a timezone string is present indicates different semantics about
   * the data.
   */
  Timestamp: 10,
  /**
   * A "calendar" interval which models types that don't necessarily
   * have a precise duration without the context of a base timestamp (e.g.
   * days can differ in length during day light savings time transitions).
   * All integers in the units below are stored in the endianness indicated
   * by the schema.
   *
   *  - YEAR_MONTH - Indicates the number of elapsed whole months, stored as
   *    4-byte signed integers.
   *  - DAY_TIME - Indicates the number of elapsed days and milliseconds (no
   *    leap seconds), stored as 2 contiguous 32-bit signed integers (8-bytes
   *    in total). Support of this IntervalUnit is not required for full arrow
   *    compatibility.
   *  - MONTH_DAY_NANO - A triple of the number of elapsed months, days, and
   *    nanoseconds. The values are stored contiguously in 16-byte blocks.
   *    Months and days are encoded as 32-bit signed integers and nanoseconds
   *    is encoded as a 64-bit signed integer. Nanoseconds does not allow for
   *    leap seconds. Each field is independent (e.g. there is no constraint
   *    that nanoseconds have the same sign as days or that the quantity of
   *    nanoseconds represents less than a day's worth of time).
   */
  Interval: 11,
  /**
   * List (vector) data supporting variably-sized lists.
   * A list has a single child data type for list entries.
   */
  List: 12,
  /**
   * A struct consisting of multiple named child data types.
   */
  Struct: 13,
  /**
   * A union is a complex type with parallel child data types. By default ids
   * in the type vector refer to the offsets in the children. Optionally
   * typeIds provides an indirection between the child offset and the type id.
   * For each child `typeIds[offset]` is the id used in the type vector.
   */
  Union: 14,
  /**
   * Binary data where each entry has the same fixed size.
   */
  FixedSizeBinary: 15,
  /**
   * List (vector) data where every list has the same fixed size.
   * A list has a single child data type for list entries.
   */
  FixedSizeList: 16,
  /**
   * A Map is a logical nested type that is represented as
   * List<entries: Struct<key: K, value: V>>
   *
   * In this layout, the keys and values are each respectively contiguous. We do
   * not constrain the key and value types, so the application is responsible
   * for ensuring that the keys are hashable and unique. Whether the keys are sorted
   * may be set in the metadata for this field.
   *
   * In a field with Map type, the field has a child Struct field, which then
   * has two children: key type and the second the value type. The names of the
   * child fields may be respectively "entries", "key", and "value", but this is
   * not enforced.
   *
   * Map
   * ```text
   *   - child[0] entries: Struct
   *   - child[0] key: K
   *   - child[1] value: V
   *  ```
   * Neither the "entries" field nor the "key" field may be nullable.
   *
   * The metadata is structured so that Arrow systems without special handling
   * for Map can make Map an alias for List. The "layout" attribute for the Map
   * field must have the same contents as a List.
   */
  Map: 17,
  /**
   * An absolute length of time unrelated to any calendar artifacts. For the
   * purposes of Arrow implementations, adding this value to a Timestamp
   * ("t1") naively (i.e. simply summing the two numbers) is acceptable even
   * though in some cases the resulting Timestamp (t2) would not account for
   * leap-seconds during the elapsed time between "t1" and "t2". Similarly,
   * representing the difference between two Unix timestamp is acceptable, but
   * would yield a value that is possibly a few seconds off from the true
   * elapsed time.
   *
   * The resolution defaults to millisecond, but can be any of the other
   * supported TimeUnit values as with Timestamp and Time types. This type is
   * always represented as an 8-byte integer.
   */
  Duration: 18,
  /**
   * Same as Binary, but with 64-bit offsets, allowing representation of
   * extremely large data values.
   */
  LargeBinary: 19,
  /**
   * Same as Utf8, but with 64-bit offsets, allowing representation of
   * extremely large data values.
   */
  LargeUtf8: 20,
  /**
   * Same as List, but with 64-bit offsets, allowing representation of
   * extremely large data values.
   */
  LargeList: 21,
  /**
   * Contains two child arrays, run_ends and values. The run_ends child array
   * must be a 16/32/64-bit integer array which encodes the indices at which
   * the run with the value in each corresponding index in the values child
   * array ends. Like list/struct types, the value array can be of any type.
   */
  RunEndEncoded: 22,
  /**
   * Logically the same as Binary, but the internal representation uses a view
   * struct that contains the string length and either the string's entire data
   * inline (for small strings) or an inlined prefix, an index of another buffer,
   * and an offset pointing to a slice in that buffer (for non-small strings).
   *
   * Since it uses a variable number of data buffers, each Field with this type
   * must have a corresponding entry in `variadicBufferCounts`.
   */
  BinaryView: 23,
  /**
   * Logically the same as Utf8, but the internal representation uses a view
   * struct that contains the string length and either the string's entire data
   * inline (for small strings) or an inlined prefix, an index of another buffer,
   * and an offset pointing to a slice in that buffer (for non-small strings).
   *
   * Since it uses a variable number of data buffers, each Field with this type
   * must have a corresponding entry in `variadicBufferCounts`.
   */
  Utf8View: 24,
  /**
   * Represents the same logical types that List can, but contains offsets and
   * sizes allowing for writes in any order and sharing of child values among
   * list values.
   */
  ListView: 25,
  /**
   * Same as ListView, but with 64-bit offsets and sizes, allowing to represent
   * extremely large data values.
   */
  LargeListView: 26
});

/**
 * Floating point number precision.
 */
const constants_Precision = /** @type {const} */ ({
  /** 16-bit floating point number. */
  HALF: 0,
  /** 32-bit floating point number. */
  SINGLE: 1,
  /** 64-bit floating point number. */
  DOUBLE: 2
});

/**
 * Date units.
 */
const constants_DateUnit = /** @type {const} */ ({
  /* Days (as 32 bit int) since the UNIX epoch. */
  DAY: 0,
  /**
   * Milliseconds (as 64 bit int) indicating UNIX time elapsed since the epoch
   * (no leap seconds), with values evenly divisible by 86400000.
   */
  MILLISECOND: 1
});

/**
 * Time units.
 */
const constants_TimeUnit = /** @type {const} */ ({
  /** Seconds. */
  SECOND: 0,
  /** Milliseconds. */
  MILLISECOND: 1,
  /** Microseconds. */
  MICROSECOND: 2,
  /** Nanoseconds. */
  NANOSECOND: 3
});

/**
 * Date/time interval units.
 */
const IntervalUnit = /** @type {const} */ ({
  /**
   * Indicates the number of elapsed whole months, stored as 4-byte signed
   * integers.
   */
  YEAR_MONTH: 0,
  /**
   * Indicates the number of elapsed days and milliseconds (no leap seconds),
   * stored as 2 contiguous 32-bit signed integers (8-bytes in total). Support
   * of this IntervalUnit is not required for full arrow compatibility.
   */
  DAY_TIME: 1,
  /**
   * A triple of the number of elapsed months, days, and nanoseconds.
   * The values are stored contiguously in 16-byte blocks. Months and days are
   * encoded as 32-bit signed integers and nanoseconds is encoded as a 64-bit
   * signed integer. Nanoseconds does not allow for leap seconds. Each field is
   * independent (e.g. there is no constraint that nanoseconds have the same
   * sign as days or that the quantity of nanoseconds represents less than a
   * day's worth of time).
   */
  MONTH_DAY_NANO: 2
});

/**
 * Union type modes.
 */
const UnionMode = /** @type {const} */ ({
  /** Sparse union layout with full arrays for each sub-type. */
  Sparse: 0,
  /** Dense union layout with offsets into value arrays. */
  Dense: 1
});

;// ../../node_modules/@uwdata/flechette/src/util/arrays.js
const uint8Array = Uint8Array;
const uint16Array = Uint16Array;
const uint32Array = Uint32Array;
const uint64Array = BigUint64Array;
const int8Array = Int8Array;
const int16Array = Int16Array;
const int32Array = Int32Array;
const int64Array = BigInt64Array;
const float32Array = Float32Array;
const float64Array = Float64Array;

/**
 * Return the appropriate typed array constructor for the given
 * integer type metadata.
 * @param {number} bitWidth The integer size in bits.
 * @param {boolean} signed Flag indicating if the integer is signed.
 * @returns {import('../types.js').IntArrayConstructor}
 */
function intArrayType(bitWidth, signed) {
  const i = Math.log2(bitWidth) - 3;
  return (
    signed
      ? [int8Array, int16Array, int32Array, int64Array]
      : [uint8Array, uint16Array, uint32Array, uint64Array]
  )[i];
}

/** Shared prototype for typed arrays. */
const arrays_TypedArray = Object.getPrototypeOf(Int8Array);

/**
 * Check if a value is a typed array.
 * @param {*} value The value to check.
 * @returns {value is import('../types.js').TypedArray}
 *  True if value is a typed array, false otherwise.
 */
function arrays_isTypedArray(value) {
  return value instanceof arrays_TypedArray;
}

/**
 * Check if a value is either a standard array or typed array.
 * @param {*} value The value to check.
 * @returns {value is (Array | import('../types.js').TypedArray)}
 *  True if value is an array, false otherwise.
 */
function arrays_isArray(value) {
  return Array.isArray(value) || arrays_isTypedArray(value);
}

/**
 * Check if a value is an array type (constructor) for 64-bit integers,
 * one of BigInt64Array or BigUint64Array.
 * @param {*} value The value to check.
 * @returns {value is import('../types.js').Int64ArrayConstructor}
 *  True if value is a 64-bit array type, false otherwise.
 */
function isInt64ArrayType(value) {
  return value === int64Array || value === uint64Array;
}

/**
 * Determine the correct index into an offset array for a given
 * full column row index. Assumes offset indices can be manipulated
 * as 32-bit signed integers.
 * @param {import('../types.js').IntegerArray} offsets The offsets array.
 * @param {number} index The full column row index.
 */
function arrays_bisect(offsets, index) {
  let a = 0;
  let b = offsets.length;
  if (b <= 2147483648) { // 2 ** 31
    // fast version, use unsigned bit shift
    // array length fits within 32-bit signed integer
    do {
      const mid = (a + b) >>> 1;
      if (offsets[mid] <= index) a = mid + 1;
      else b = mid;
    } while (a < b);
  } else {
    // slow version, use division and truncate
    // array length exceeds 32-bit signed integer
    do {
      const mid = Math.trunc((a + b) / 2);
      if (offsets[mid] <= index) a = mid + 1;
      else b = mid;
    } while (a < b);
  }
  return a;
}

/**
 * Compute a 64-bit aligned buffer size.
 * @param {number} length The starting size.
 * @param {number} bpe Bytes per element.
 * @returns {number} The aligned size.
 */
function align64(length, bpe = 1) {
  return (((length * bpe) + 7) & ~7) / bpe;
}

/**
 * Return a 64-bit aligned version of the array.
 * @template {import('../types.js').TypedArray} T
 * @param {T} array The array.
 * @param {number} length The current array length.
 * @returns {T} The aligned array.
 */
function align(array, length = array.length) {
  const alignedLength = align64(length, array.BYTES_PER_ELEMENT);
  return array.length > alignedLength ? /** @type {T} */ (array.subarray(0, alignedLength))
    : array.length < alignedLength ? resize(array, alignedLength)
    : array;
}

/**
 * Resize a typed array to exactly the specified length.
 * @template {import('../types.js').TypedArray} T
 * @param {T} array The array.
 * @param {number} newLength The new length.
 * @param {number} [offset] The offset at which to copy the old array.
 * @returns {T} The resized array.
 */
function resize(array, newLength, offset = 0) {
  // @ts-ignore
  const newArray = new array.constructor(newLength);
  newArray.set(array, offset);
  return newArray;
}

/**
 * Grow a typed array to accommdate a minimum index. The array size is
 * doubled until it exceeds the minimum index.
 * @template {import('../types.js').TypedArray} T
 * @param {T} array The array.
 * @param {number} index The minimum index.
 * @param {boolean} [shift] Flag to shift copied bytes to back of array.
 * @returns {T} The resized array.
 */
function grow(array, index, shift) {
  while (array.length <= index) {
    array = resize(array, array.length << 1, shift ? array.length : 0);
  }
  return array;
}

;// ../../node_modules/@uwdata/flechette/src/util/objects.js
/**
 * Check if a value is a Date instance
 * @param {*} value The value to check.
 * @returns {value is Date} True if value is a Date, false otherwise.
 */
function objects_isDate(value) {
  return value instanceof Date;
}

/**
 * Check if a value is iterable.
 * @param {*} value The value to check.
 * @returns {value is Iterable} True if value is iterable, false otherwise.
 */
function isIterable(value) {
  return typeof value[Symbol.iterator] === 'function';
}

/**
 * Return the input value if it passes a test.
 * Otherwise throw an error using the given message generator.
 * @template T
 * @param {T} value he value to check.
 * @param {(value: T) => boolean} test The test function.
 * @param {(value: *) => string} message Message generator.
 * @returns {T} The input value.
 * @throws if the value does not pass the test
 */
function check(value, test, message) {
  if (test(value)) return value;
  throw new Error(message(value));
}

/**
 * Return the input value if it exists in the provided set.
 * Otherwise throw an error using the given message generator.
 * @template T
 * @param {T} value The value to check.
 * @param {T[] | Record<string,T>} set The set of valid values.
 * @param {(value: *) => string} [message] Message generator.
 * @returns {T} The input value.
 * @throws if the value is not included in the set
 */
function checkOneOf(value, set, message) {
  set = Array.isArray(set) ? set : Object.values(set);
  return check(
    value,
    (value) => set.includes(value),
    message ?? (() => `${value} must be one of ${set}`)
  );
}

/**
 * Return the first object key that pairs with the given value.
 * @param {Record<string,any>} object The object to search.
 * @param {any} value The value to lookup.
 * @returns {string} The first matching key, or '<Unknown>' if not found.
 */
function keyFor(object, value) {
  for (const [key, val] of Object.entries(object)) {
    if (val === value) return key;
  }
  return '<Unknown>';
}

;// ../../node_modules/@uwdata/flechette/src/data-types.js




/**
 * @typedef {import('./types.js').Field | import('./types.js').DataType} FieldInput
 */

const invalidDataType = (typeId) =>
  `Unsupported data type: "${keyFor(constants_Type, typeId)}" (id ${typeId})`;

/**
 * Return a new field instance for use in a schema or type definition. A field
 * represents a field name, data type, and additional metadata. Fields are used
 * to represent child types within nested types like List, Struct, and Union.
 * @param {string} name The field name.
 * @param {import('./types.js').DataType} type The field data type.
 * @param {boolean} [nullable=true] Flag indicating if the field is nullable
 *  (default `true`).
 * @param {Map<string,string>|null} [metadata=null] Custom field metadata
 *  annotations (default `null`).
 * @returns {import('./types.js').Field} The field instance.
 */
const data_types_field = (name, type, nullable = true, metadata = null) => ({
  name,
  type,
  nullable,
  metadata
});

/**
 * Checks if a value is a field instance.
 * @param {any} value
 * @returns {value is import('./types.js').Field}
 */
function isField(value) {
  return Object.hasOwn(value, 'name') && isDataType(value.type)
}

/**
 * Checks if a value is a data type instance.
 * @param {any} value
 * @returns {value is import('./types.js').DataType}
 */
function isDataType(value) {
  return typeof value?.typeId === 'number';
}

/**
 * Return a field instance from a field or data type input.
 * @param {FieldInput} value
 *  The value to map to a field.
 * @param {string} [defaultName] The default field name.
 * @param {boolean} [defaultNullable=true] The default nullable value.
 * @returns {import('./types.js').Field} The field instance.
 */
function asField(value, defaultName = '', defaultNullable = true) {
  return isField(value)
    ? value
    : data_types_field(
        defaultName,
        check(value, isDataType, () => `Data type expected.`),
        defaultNullable
      );
}

/////

/**
 * Return a basic type with only a type id.
 * @template {typeof Type[keyof typeof Type]} T
 * @param {T} typeId The type id.
 */
const basicType = (typeId) => ({ typeId });

/**
 * Return a Dictionary data type instance.  A dictionary type consists of a
 * dictionary of values (which may be of any type) and corresponding integer
 * indices that reference those values. If values are repeated, a dictionary
 * encoding can provide substantial space savings. In the IPC format,
 * dictionary indices reside alongside other columns in a record batch, while
 * dictionary values are written to special dictionary batches, linked by a
 * unique dictionary *id*.
 * @param {import('./types.js').DataType} type The data type of dictionary
 *  values.
 * @param {import('./types.js').IntType} [indexType] The data type of
 *  dictionary indices. Must be an integer type (default `int32`).
 * @param {boolean} [ordered=false] Indicates if dictionary values are
 *  ordered (default `false`).
 * @param {number} [id=-1] The dictionary id. The default value (-1) indicates
 *  the dictionary applies to a single column only. Provide an explicit id in
 *  order to reuse a dictionary across columns when building, in which case
 *  different dictionaries *must* have different unique ids. All dictionary
 *  ids are later resolved (possibly to new values) upon IPC encoding.
 * @returns {import('./types.js').DictionaryType}
 */
const dictionary = (type, indexType, ordered = false, id = -1) => ({
  typeId: constants_Type.Dictionary,
  id,
  dictionary: type,
  indices: indexType || int32(),
  ordered
});

/**
 * Return a Null data type instance. Null data requires no storage and all
 * extracted values are `null`.
 * @returns {import('./types.js').NullType} The null data type.
 */
const nullType = () => basicType(constants_Type.Null);

/**
 * Return an Int data type instance.
 * @param {import('./types.js').IntBitWidth} [bitWidth=32] The integer bit width.
 *  One of `8`, `16`, `32` (default), or `64`.
 * @param {boolean} [signed=true] Flag for signed or unsigned integers
 *  (default `true`).
 * @returns {import('./types.js').IntType} The integer data type.
 */
const data_types_int = (bitWidth = 32, signed = true) => ({
  typeId: constants_Type.Int,
  bitWidth: checkOneOf(bitWidth, [8, 16, 32, 64]),
  signed,
  values: intArrayType(bitWidth, signed)
});
/**
 * Return an Int data type instance for 8 bit signed integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const int8 = () => data_types_int(8);
/**
 * Return an Int data type instance for 16 bit signed integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const int16 = () => data_types_int(16);
/**
 * Return an Int data type instance for 32 bit signed integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const int32 = () => data_types_int(32);
/**
 * Return an Int data type instance for 64 bit signed integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const int64 = () => data_types_int(64);
/**
 * Return an Int data type instance for 8 bit unsigned integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const uint8 = () => data_types_int(8, false);
/**
 * Return an Int data type instance for 16 bit unsigned integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const uint16 = () => data_types_int(16, false);
/**
 * Return an Int data type instance for 32 bit unsigned integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const uint32 = () => data_types_int(32, false);
/**
 * Return an Int data type instance for 64 bit unsigned integers.
 * @returns {import('./types.js').IntType} The integer data type.
 */
const uint64 = () => data_types_int(64, false);

/**
 * Return a Float data type instance for floating point numbers.
 * @param {import('./types.js').Precision_} [precision=2] The floating point
 *  precision. One of `Precision.HALF` (16-bit), `Precision.SINGLE` (32-bit)
 *  or `Precision.DOUBLE` (64-bit, default).
 * @returns {import('./types.js').FloatType} The floating point data type.
 */
const data_types_float = (precision = 2) => ({
  typeId: constants_Type.Float,
  precision: checkOneOf(precision, constants_Precision),
  values: [uint16Array, float32Array, float64Array][precision]
});
/**
 * Return a Float data type instance for half-precision (16 bit) numbers.
 * @returns {import('./types.js').FloatType} The floating point data type.
 */
const float16 = () => data_types_float(Precision.HALF);
/**
 * Return a Float data type instance for single-precision (32 bit) numbers.
 * @returns {import('./types.js').FloatType} The floating point data type.
 */
const float32 = () => data_types_float(constants_Precision.SINGLE);
/**
 * Return a Float data type instance for double-precision (64 bit) numbers.
 * @returns {import('./types.js').FloatType} The floating point data type.
 */
const float64 = () => data_types_float(constants_Precision.DOUBLE);

/**
 * Return a Binary data type instance for variably-sized opaque binary data
 * with 32-bit offsets.
 * @returns {import('./types.js').BinaryType} The binary data type.
 */
const data_types_binary = () => ({
  typeId: constants_Type.Binary,
  offsets: int32Array
});

/**
 * Return a Utf8 data type instance for Unicode string data.
 * [UTF-8](https://en.wikipedia.org/wiki/UTF-8) code points are stored as
 * binary data.
 * @returns {import('./types.js').Utf8Type} The utf8 data type.
 */
const utf8 = () => ({
  typeId: constants_Type.Utf8,
  offsets: int32Array
});

/**
 * Return a Bool data type instance. Bool values are stored compactly in
 * bitmaps with eight values per byte.
 * @returns {import('./types.js').BoolType} The bool data type.
 */
const bool = () => basicType(constants_Type.Bool);

/**
 * Return a Decimal data type instance. Decimal values are represented as 32,
 * 64, 128, or 256 bit integers in two's complement. Decimals are fixed point
 * numbers with a set *precision* (total number of decimal digits) and *scale*
 * (number of fractional digits). For example, the number `35.42` can be
 * represented as `3542` with *precision* ≥ 4 and *scale* = 2.
 * @param {number} precision The decimal precision: the total number of
 *  decimal digits that can be represented.
 * @param {number} scale The number of fractional digits, beyond the
 *  decimal point.
 * @param {32 | 64 | 128 | 256} [bitWidth] The decimal bit width.
 *  One of 32, 64, 128 (default), or 256.
 * @returns {import('./types.js').DecimalType} The decimal data type.
 */
const decimal = (precision, scale, bitWidth = 128) => ({
  typeId: constants_Type.Decimal,
  precision,
  scale,
  bitWidth: checkOneOf(bitWidth, [32, 64, 128, 256]),
  values: bitWidth === 32 ? int32Array : uint64Array
});
/**
 * Return an Decimal data type instance with a bit width of 32.
 * @param {number} precision The decimal precision: the total number of
 *  decimal digits that can be represented.
 * @param {number} scale The number of fractional digits, beyond the
 *  decimal point.
 * @returns {import('./types.js').DecimalType} The decimal data type.
 */
const decimal32 = (precision, scale) => decimal(precision, scale, 32);
/**
 * Return an Decimal data type instance with a bit width of 64.
 * @param {number} precision The decimal precision: the total number of
 *  decimal digits that can be represented.
 * @param {number} scale The number of fractional digits, beyond the
 *  decimal point.
 * @returns {import('./types.js').DecimalType} The decimal data type.
 */
const decimal64 = (precision, scale) => decimal(precision, scale, 64);
/**
 * Return an Decimal data type instance with a bit width of 128.
 * @param {number} precision The decimal precision: the total number of
 *  decimal digits that can be represented.
 * @param {number} scale The number of fractional digits, beyond the
 *  decimal point.
 * @returns {import('./types.js').DecimalType} The decimal data type.
 */
const decimal128 = (precision, scale) => decimal(precision, scale, 128);
/**
 * Return an Decimal data type instance with a bit width of 256.
 * @param {number} precision The decimal precision: the total number of
 *  decimal digits that can be represented.
 * @param {number} scale The number of fractional digits, beyond the
 *  decimal point.
 * @returns {import('./types.js').DecimalType} The decimal data type.
 */
const decimal256 = (precision, scale) => decimal(precision, scale, 256);

/**
 * Return a Date data type instance. Date values are 32-bit or 64-bit signed
 * integers representing elapsed time since the UNIX epoch (Jan 1, 1970 UTC),
 * either in units of days (32 bits) or milliseconds (64 bits, with values
 * evenly divisible by 86400000).
 * @param {import('./types.js').DateUnit_} unit The date unit.
 *  One of `DateUnit.DAY` or `DateUnit.MILLISECOND`.
 * @returns {import('./types.js').DateType} The date data type.
 */
const data_types_date = (unit) => ({
  typeId: constants_Type.Date,
  unit: checkOneOf(unit, constants_DateUnit),
  values: unit === constants_DateUnit.DAY ? int32Array : int64Array
});
/**
 * Return a Date data type instance with units of days.
 * @returns {import('./types.js').DateType} The date data type.
 */
const dateDay = () => data_types_date(constants_DateUnit.DAY);
/**
 * Return a Date data type instance with units of milliseconds.
 * @returns {import('./types.js').DateType} The date data type.
 */
const dateMillisecond = () => data_types_date(DateUnit.MILLISECOND);

/**
 * Return a Time data type instance, stored in one of four *unit*s: seconds,
 * milliseconds, microseconds or nanoseconds. The integer *bitWidth* depends
 * on the *unit* and must be 32 bits for seconds and milliseconds or 64 bits
 * for microseconds and nanoseconds. The allowed values are between 0
 * (inclusive) and 86400 (=24*60*60) seconds (exclusive), adjusted for the
 * time unit (for example, up to 86400000 exclusive for the
 * `DateUnit.MILLISECOND` unit.
 *
 * This definition doesn't allow for leap seconds. Time values from
 * measurements with leap seconds will need to be corrected when ingesting
 * into Arrow (for example by replacing the value 86400 with 86399).
 * @param {import('./types.js').TimeUnit_} unit The time unit.
 *  One of `TimeUnit.SECOND`, `TimeUnit.MILLISECOND` (default),
 *  `TimeUnit.MICROSECOND`, or `TimeUnit.NANOSECOND`.
 * @param {32 | 64} bitWidth The time bit width. One of `32` (for seconds
 *  and milliseconds) or `64` (for microseconds and nanoseconds).
 * @returns {import('./types.js').TimeType} The time data type.
 */
const time = (unit = constants_TimeUnit.MILLISECOND, bitWidth = 32) => ({
  typeId: constants_Type.Time,
  unit: checkOneOf(unit, constants_TimeUnit),
  bitWidth: checkOneOf(bitWidth, [32, 64]),
  values: bitWidth === 32 ? int32Array : int64Array
});
/**
 * Return a Time data type instance, represented as seconds.
 * @returns {import('./types.js').TimeType} The time data type.
 */
const timeSecond = () => time(TimeUnit.SECOND, 32);
/**
 * Return a Time data type instance, represented as milliseconds.
 * @returns {import('./types.js').TimeType} The time data type.
 */
const timeMillisecond = () => time(TimeUnit.MILLISECOND, 32);
/**
 * Return a Time data type instance, represented as microseconds.
 * @returns {import('./types.js').TimeType} The time data type.
 */
const timeMicrosecond = () => time(TimeUnit.MICROSECOND, 64);
/**
 * Return a Time data type instance, represented as nanoseconds.
 * @returns {import('./types.js').TimeType} The time data type.
 */
const timeNanosecond = () => time(TimeUnit.NANOSECOND, 64);

/**
 * Return a Timestamp data type instance. Timestamp values are 64-bit signed
 * integers representing an elapsed time since a fixed epoch, stored in either
 * of four units: seconds, milliseconds, microseconds or nanoseconds, and are
 * optionally annotated with a timezone. Timestamp values do not include any
 * leap seconds (in other words, all days are considered 86400 seconds long).
 * @param {import('./types.js').TimeUnit_} [unit] The time unit.
 *  One of `TimeUnit.SECOND`, `TimeUnit.MILLISECOND` (default),
 *  `TimeUnit.MICROSECOND`, or `TimeUnit.NANOSECOND`.
 * @param {string|null} [timezone=null] An optional string for the name of a
 *  timezone. If provided, the value should either be a string as used in the
 *  Olson timezone database (the "tz database" or "tzdata"), such as
 *  "America/New_York", or an absolute timezone offset of the form "+XX:XX" or
 *  "-XX:XX", such as "+07:30".Whether a timezone string is present indicates
 *  different semantics about the data.
 * @returns {import('./types.js').TimestampType} The time data type.
 */
const data_types_timestamp = (unit = constants_TimeUnit.MILLISECOND, timezone = null) => ({
  typeId: constants_Type.Timestamp,
  unit: checkOneOf(unit, constants_TimeUnit),
  timezone,
  values: int64Array
});

/**
 * Return an Interval type instance. Values represent calendar intervals stored
 * as integers for each date part. The supported *unit*s are year/moth,
 * day/time, and month/day/nanosecond intervals.
 *
 * `IntervalUnit.YEAR_MONTH` indicates the number of elapsed whole months,
 * stored as 32-bit signed integers.
 *
 * `IntervalUnit.DAY_TIME` indicates the number of elapsed days and
 * milliseconds (no leap seconds), stored as 2 contiguous 32-bit signed
 * integers (8-bytes in total).
 *
 * `IntervalUnit.MONTH_DAY_NANO` is a triple of the number of elapsed months,
 * days, and nanoseconds. The values are stored contiguously in 16-byte blocks.
 * Months and days are encoded as 32-bit signed integers and nanoseconds is
 * encoded as a 64-bit signed integer. Nanoseconds does not allow for leap
 * seconds. Each field is independent (e.g. there is no constraint that
 * nanoseconds have the same sign as days or that the quantity of nanoseconds
 * represents less than a day's worth of time).
 * @param {import('./types.js').IntervalUnit_} unit  The interval unit.
 *  One of `IntervalUnit.YEAR_MONTH`, `IntervalUnit.DAY_TIME`, or
 *  `IntervalUnit.MONTH_DAY_NANO` (default).
 * @returns {import('./types.js').IntervalType} The interval data type.
 */
const interval = (unit = IntervalUnit.MONTH_DAY_NANO) => ({
  typeId: constants_Type.Interval,
  unit: checkOneOf(unit, IntervalUnit),
  values: unit === IntervalUnit.MONTH_DAY_NANO ? undefined : int32Array
});

/**
 * Return a List data type instance, representing variably-sized lists
 * (arrays) with 32-bit offsets. A list has a single child data type for
 * list entries. Lists are represented using integer offsets that indicate
 * list extents within a single child array containing all list values.
 * @param {FieldInput} child The child (list item) field or data type.
 * @returns {import('./types.js').ListType} The list data type.
 */
const data_types_list = (child) => ({
  typeId: constants_Type.List,
  children: [ asField(child) ],
  offsets: int32Array
});

/**
 * Return a Struct data type instance. A struct consists of multiple named
 * child data types. Struct values are stored as parallel child batches, one
 * per child type, and extracted to standard JavaScript objects.
 * @param {import('./types.js').Field[] | Record<string, import('./types.js').DataType>} children
 *  An array of property fields, or an object mapping property names to data
 *  types. If an object, the instantiated fields are assumed to be nullable
 *  and have no metadata.
 * @returns {import('./types.js').StructType} The struct data type.
 */
const struct = (children) => ({
  typeId: constants_Type.Struct,
  children: Array.isArray(children) && isField(children[0])
    ? /** @type {import('./types.js').Field[]} */ (children)
    : Object.entries(children).map(([name, type]) => data_types_field(name, type))
});

/**
 * Return a Union type instance. A union is a complex type with parallel
 * *children* data types. Union values are stored in either a sparse
 * (`UnionMode.Sparse`) or dense (`UnionMode.Dense`) layout *mode*. In a
 * sparse layout, child types are stored in parallel arrays with the same
 * lengths, resulting in many unused, empty values. In a dense layout, child
 * types have variable lengths and an offsets array is used to index the
 * appropriate value.
 *
 * By default, ids in the type vector refer to the index in the children
 * array. Optionally, *typeIds* provide an indirection between the child
 * index and the type id. For each child, `typeIds[index]` is the id used
 * in the type vector. The *typeIdForValue* argument provides a lookup
 * function for mapping input data to the proper child type id, and is
 * required if using builder methods.
 * @param {import('./types.js').UnionMode_} mode The union mode.
 *  One of `UnionMode.Sparse` or `UnionMode.Dense`.
 * @param {FieldInput[]} children The children fields or data types.
 *  Types are mapped to nullable fields with no metadata.
 * @param {number[]} [typeIds]  Children type ids, in the same order as the
 *  children types. Type ids provide a level of indirection over children
 *  types. If not provided, the children indices are used as the type ids.
 * @param {(value: any, index: number) => number} [typeIdForValue]
 *  A function that takes an arbitrary value and a row index and returns a
 *  correponding union type id. Required by builder methods.
 * @returns {import('./types.js').UnionType} The union data type.
 */
const data_types_union = (mode, children, typeIds, typeIdForValue) => {
  typeIds ??= children.map((v, i) => i);
  return {
    typeId: constants_Type.Union,
    mode: checkOneOf(mode, UnionMode),
    typeIds,
    typeMap: typeIds.reduce((m, id, i) => ((m[id] = i), m), {}),
    children: children.map((v, i) => asField(v, `_${i}`)),
    typeIdForValue,
    offsets: int32Array,
  };
};

/**
 * Create a FixedSizeBinary data type instance for opaque binary data where
 * each entry has the same fixed size.
 * @param {number} stride The fixed size in bytes.
 * @returns {import('./types.js').FixedSizeBinaryType} The fixed size binary data type.
 */
const fixedSizeBinary = (stride) => ({
  typeId: constants_Type.FixedSizeBinary,
  stride
});

/**
 * Return a FixedSizeList type instance for list (array) data where every list
 * has the same fixed size. A list has a single child data type for list
 * entries. Fixed size lists are represented as a single child array containing
 * all list values, indexed using the known stride.
 * @param {FieldInput} child The list item data type.
 * @param {number} stride The fixed list size.
 * @returns {import('./types.js').FixedSizeListType} The fixed size list data type.
 */
const fixedSizeList = (child, stride) => ({
  typeId: constants_Type.FixedSizeList,
  stride,
  children: [ asField(child) ]
});

/**
 * Internal method to create a Map type instance.
 * @param {boolean} keysSorted Flag indicating if the map keys are sorted.
 * @param {import('./types.js').Field} child The child fields.
 * @returns {import('./types.js').MapType} The map data type.
 */
const mapType = (keysSorted, child) => ({
  typeId: constants_Type.Map,
  keysSorted,
  children: [child],
  offsets: int32Array
});

/**
 * Return a Map data type instance representing collections of key-value pairs.
 * A Map is a logical nested type that is represented as a list of key-value
 * structs. The key and value types are not constrained, so the application is
 * responsible for ensuring that the keys are hashable and unique, and that
 * keys are properly sorted if *keysSorted* is `true`.
 * @param {FieldInput} keyField The map key field or data type.
 * @param {FieldInput} valueField The map value field or data type.
 * @param {boolean} [keysSorted=false] Flag indicating if the map keys are
 *  sorted (default `false`).
 * @returns {import('./types.js').MapType} The map data type.
 */
const map = (keyField, valueField, keysSorted = false) => mapType(
  keysSorted,
  data_types_field(
    'entries',
    struct([ asField(keyField, 'key', false), asField(valueField, 'value') ]),
    false
  )
);

/**
 * Return a Duration data type instance. Durations represent an absolute length
 * of time unrelated to any calendar artifacts. The resolution defaults to
 * millisecond, but can be any of the other `TimeUnit` values. This type is
 * always represented as a 64-bit integer.
 * @param {import('./types.js').TimeUnit_} unit
 * @returns {import('./types.js').DurationType} The duration data type.
 */
const duration = (unit = constants_TimeUnit.MILLISECOND) => ({
  typeId: constants_Type.Duration,
  unit: checkOneOf(unit, constants_TimeUnit),
  values: int64Array
});

/**
 * Return a LargeBinary data type instance for variably-sized opaque binary
 * data with 64-bit offsets, allowing representation of extremely large data
 * values.
 * @returns {import('./types.js').LargeBinaryType} The large binary data type.
 */
const largeBinary = () => ({
  typeId: constants_Type.LargeBinary,
  offsets: int64Array
});

/**
 * Return a LargeUtf8 data type instance for Unicode string data of variable
 * length with 64-bit offsets, allowing representation of extremely large data
 * values. [UTF-8](https://en.wikipedia.org/wiki/UTF-8) code points are stored
 * as binary data.
 * @returns {import('./types.js').LargeUtf8Type} The large utf8 data type.
 */
const largeUtf8 = () => ({
  typeId: constants_Type.LargeUtf8,
  offsets: int64Array
});

/**
 * Return a LargeList data type instance, representing variably-sized lists
 * (arrays) with 64-bit offsets, allowing representation of extremely large
 * data values. A list has a single child data type for list entries. Lists
 * are represented using integer offsets that indicate list extents within a
 * single child array containing all list values.
 * @param {FieldInput} child The child (list item) field or data type.
 * @returns {import('./types.js').LargeListType} The large list data type.
 */
const largeList = (child) => ({
  typeId: constants_Type.LargeList,
  children: [ asField(child) ],
  offsets: int64Array
});

/**
 * Return a RunEndEncoded data type instance, which compresses data by
 * representing consecutive repeated values as a run. This data type uses two
 * child arrays, `run_ends` and `values`. The `run_ends` child array must be
 * a 16, 32, or 64 bit integer array which encodes the indices at which the
 * run with the value in each corresponding index in the values child array
 * ends. Like list and struct types, the `values` array can be of any type.
 * @param {FieldInput} runsField The run-ends field or data type.
 * @param {FieldInput} valuesField The values field or data type.
 * @returns {import('./types.js').RunEndEncodedType} The large list data type.
 */
const runEndEncoded = (runsField, valuesField) => ({
  typeId: constants_Type.RunEndEncoded,
  children: [
    check(
      asField(runsField, 'run_ends'),
      (field) => field.type.typeId === constants_Type.Int,
      () => 'Run-ends must have an integer type.'
    ),
    asField(valuesField, 'values')
  ]
});

/**
 * Return a BinaryView data type instance. BinaryView data is logically the
 * same as the Binary type, but the internal representation uses a view struct
 * that contains the string length and either the string's entire data inline
 * (for small strings) or an inlined prefix, an index of another buffer, and an
 * offset pointing to a slice in that buffer (for non-small strings).
 *
 * Flechette can encode and decode BinaryView data; however, Flechette does
 * not currently support building BinaryView columns from JavaScript values.
 * @returns {import('./types.js').BinaryViewType} The binary view data type.
 */
const binaryView = () => /** @type{import('./types.js').BinaryViewType} */
  (basicType(Type.BinaryView));

/**
 * Return a Utf8View data type instance. Utf8View data is logically the same as
 * the Utf8 type, but the internal representation uses a view struct that
 * contains the string length and either the string's entire data inline (for
 * small strings) or an inlined prefix, an index of another buffer, and an
 * offset pointing to a slice in that buffer (for non-small strings).
 *
 * Flechette can encode and decode Utf8View data; however, Flechette does
 * not currently support building Utf8View columns from JavaScript values.
 * @returns {import('./types.js').Utf8ViewType} The utf8 view data type.
 */
const utf8View = () => /** @type{import('./types.js').Utf8ViewType} */
  (basicType(Type.Utf8View));

/**
 * Return a ListView data type instance, representing variably-sized lists
 * (arrays) with 32-bit offsets. ListView data represents the same logical
 * types that List can, but contains both offsets and sizes allowing for
 * writes in any order and sharing of child values among list values.
 *
 * Flechette can encode and decode ListView data; however, Flechette does not
 * currently support building ListView columns from JavaScript values.
 * @param {FieldInput} child The child (list item) field or data type.
 * @returns {import('./types.js').ListViewType} The list view data type.
 */
const listView = (child) => ({
  typeId: constants_Type.ListView,
  children: [ asField(child, 'value') ],
  offsets: int32Array
});

/**
 * Return a LargeListView data type instance, representing variably-sized lists
 * (arrays) with 64-bit offsets, allowing representation of extremely large
 * data values. LargeListView data represents the same logical types that
 * LargeList can, but contains both offsets and sizes allowing for writes
 * in any order and sharing of child values among list values.
 *
 * Flechette can encode and decode LargeListView data; however, Flechette does
 * not currently support building LargeListView columns from JavaScript values.
 * @param {FieldInput} child The child (list item) field or data type.
 * @returns {import('./types.js').LargeListViewType} The large list view data type.
 */
const largeListView = (child) => ({
  typeId: constants_Type.LargeListView,
  children: [ asField(child, 'value') ],
  offsets: int64Array
});

;// ../../node_modules/@uwdata/flechette/src/util/numbers.js



// typed arrays over a shared buffer to aid binary conversion
const f64 = new float64Array(2);
const buf = f64.buffer;
const i64 = new int64Array(buf);
const u32 = new uint32Array(buf);
const i32 = new int32Array(buf);
const u8 = new uint8Array(buf);

/**
 * Return a value unchanged.
 * @template T
 * @param {T} value The value.
 * @returns {T} The value.
 */
function numbers_identity(value) {
  return value;
}

/**
 * Return a value coerced to a BigInt.
 * @param {*} value The value.
 * @returns {bigint} The BigInt value.
 */
function toBigInt(value) {
  return BigInt(value);
}

/**
 * Return an offset conversion method for the given data type.
 * @param {{ offsets: import('../types.js').TypedArray}} type The array type.
 */
function toOffset(type) {
  return isInt64ArrayType(type) ? toBigInt : numbers_identity;
}

/**
 * Return the number of days from a millisecond timestamp.
 * @param {number} value The millisecond timestamp.
 * @returns {number} The number of days.
 */
function toDateDay(value) {
  return (value / 864e5) | 0;
}

/**
 * Return a timestamp conversion method for the given time unit.
 * @param {import('../types.js').TimeUnit_} unit The time unit.
 * @returns {(value: number) => bigint} The conversion method.
 */
function toTimestamp(unit) {
  return unit === constants_TimeUnit.SECOND ? value => toBigInt(value / 1e3)
    : unit === constants_TimeUnit.MILLISECOND ? toBigInt
    : unit === constants_TimeUnit.MICROSECOND ? value => toBigInt(value * 1e3)
    : value => toBigInt(value * 1e6);
}

/**
 * Write month/day/nanosecond interval to a byte buffer.
 * @param {Array | Float64Array} interval The interval data.
 * @returns {Uint8Array} A byte buffer with the interval data.
 *  The returned buffer is reused across calls, and so should be
 *  copied to a target buffer immediately.
 */
function toMonthDayNanoBytes([m, d, n]) {
  i32[0] = m;
  i32[1] = d;
  i64[1] = toBigInt(n);
  return u8;
}

/**
 * Coerce a bigint value to a number. Throws an error if the bigint value
 * lies outside the range of what a number can precisely represent.
 * @param {bigint} value The value to check and possibly convert.
 * @returns {number} The converted number value.
 */
function toNumber(value) {
  if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {
    throw Error(`BigInt exceeds integer number representation: ${value}`);
  }
  return Number(value);
}

/**
 * Divide one BigInt value by another, and return the result as a number.
 * The division may involve unsafe integers and a loss of precision.
 * @param {bigint} num The numerator.
 * @param {bigint} div The divisor.
 * @returns {number} The result of the division as a floating point number.
 */
function divide(num, div) {
  return Number(num / div) + Number(num % div) / Number(div);
}

/**
 * Return a 32-bit decimal conversion method for the given decimal scale.
 * @param {number} scale The scale mapping fractional digits to integers.
 * @returns {(value: number|bigint) => number} A conversion method that maps
 *  floating point numbers to 32-bit decimals.
 */
function toDecimal32(scale) {
  return (value) => typeof value === 'bigint'
    ? Number(value)
    : Math.trunc(value * scale);
}

/**
 * Convert a floating point number or bigint to decimal bytes.
 * @param {number|bigint} value The number to encode. If a bigint, we assume
 *  it already represents the decimal in integer form with the correct scale.
 *  Otherwise, we assume a float that requires scaled integer conversion.
 * @param {BigUint64Array} buf The uint64 array to write to.
 * @param {number} offset The starting index offset into the array.
 * @param {number} stride The stride of an encoded decimal, in 64-bit steps.
 * @param {number} scale The scale mapping fractional digits to integers.
 */
function toDecimal(value, buf, offset, stride, scale) {
  const v = typeof value === 'bigint'
    ? value
    : toBigInt(Math.trunc(value * scale));
  // assignment into uint64array performs needed truncation for us
  buf[offset] = v;
  if (stride > 1) {
    buf[offset + 1] = (v >> 64n);
    if (stride > 2) {
      buf[offset + 2] = (v >> 128n);
      buf[offset + 3] = (v >> 192n);
    }
  }
}

// helper method to extract uint64 values from bigints
const asUint64 = v => BigInt.asUintN(64, v);

/**
 * Convert a 64-bit decimal value to a bigint.
 * @param {BigUint64Array} buf The uint64 array containing the decimal bytes.
 * @param {number} offset The starting index offset into the array.
 * @returns {bigint} The converted decimal as a bigint, such that all
 *  fractional digits are scaled up to integers (for example, 1.12 -> 112).
 */
function fromDecimal64(buf, offset) {
  return BigInt.asIntN(64, buf[offset]);
}

/**
 * Convert a 128-bit decimal value to a bigint.
 * @param {BigUint64Array} buf The uint64 array containing the decimal bytes.
 * @param {number} offset The starting index offset into the array.
 * @returns {bigint} The converted decimal as a bigint, such that all
 *  fractional digits are scaled up to integers (for example, 1.12 -> 112).
 */
function fromDecimal128(buf, offset) {
  const i = offset << 1;
  let x;
  if (BigInt.asIntN(64, buf[i + 1]) < 0) {
    x = asUint64(~buf[i]) | (asUint64(~buf[i + 1]) << 64n);
    x = -(x + 1n);
  } else {
    x = buf[i] | (buf[i + 1] << 64n);
  }
  return x;
}

/**
 * Convert a 256-bit decimal value to a bigint.
 * @param {BigUint64Array} buf The uint64 array containing the decimal bytes.
 * @param {number} offset The starting index offset into the array.
 * @returns {bigint} The converted decimal as a bigint, such that all
 *  fractional digits are scaled up to integers (for example, 1.12 -> 112).
 */
function fromDecimal256(buf, offset) {
  const i = offset << 2;
  let x;
  if (BigInt.asIntN(64, buf[i + 3]) < 0) {
    x = asUint64(~buf[i])
      | (asUint64(~buf[i + 1]) << 64n)
      | (asUint64(~buf[i + 2]) << 128n)
      | (asUint64(~buf[i + 3]) << 192n);
    x = -(x + 1n);
  } else {
    x = buf[i]
      | (buf[i + 1] << 64n)
      | (buf[i + 2] << 128n)
      | (buf[i + 3] << 192n);
  }
  return x;
}

/**
 * Convert a 16-bit float from integer bytes to a number.
 * Adapted from https://github.com/apache/arrow/blob/main/js/src/util/math.ts
 * @param {number} value The float as a 16-bit integer.
 * @returns {number} The converted 64-bit floating point number.
 */
function fromFloat16(value) {
  const expo = (value & 0x7C00) >> 10;
  const sigf = (value & 0x03FF) / 1024;
  const sign = (-1) ** ((value & 0x8000) >> 15);
  switch (expo) {
    case 0x1F: return sign * (sigf ? Number.NaN : 1 / 0);
    case 0x00: return sign * (sigf ? 6.103515625e-5 * sigf : 0);
  }
  return sign * (2 ** (expo - 15)) * (1 + sigf);
}

/**
 * Convert a number to a 16-bit float as integer bytes..
 * Inspired by numpy's `npy_double_to_half`:
 * https://github.com/numpy/numpy/blob/5a5987291dc95376bb098be8d8e5391e89e77a2c/numpy/core/src/npymath/halffloat.c#L43
 * Adapted from https://github.com/apache/arrow/blob/main/js/src/util/math.ts
 * @param {number} value The 64-bit floating point number to convert.
 * @returns {number} The converted 16-bit integer.
 */
function toFloat16(value) {
  if (value !== value) return 0x7E00; // NaN
  f64[0] = value;

  // Magic numbers:
  // 0x80000000 = 10000000 00000000 00000000 00000000 -- masks the 32nd bit
  // 0x7ff00000 = 01111111 11110000 00000000 00000000 -- masks the 21st-31st bits
  // 0x000fffff = 00000000 00001111 11111111 11111111 -- masks the 1st-20th bit
  const sign = (u32[1] & 0x80000000) >> 16 & 0xFFFF;
  let expo = (u32[1] & 0x7FF00000), sigf = 0x0000;

  if (expo >= 0x40F00000) {
    //
    // If exponent overflowed, the float16 is either NaN or Infinity.
    // Rules to propagate the sign bit: mantissa > 0 ? NaN : +/-Infinity
    //
    // Magic numbers:
    // 0x40F00000 = 01000000 11110000 00000000 00000000 -- 6-bit exponent overflow
    // 0x7C000000 = 01111100 00000000 00000000 00000000 -- masks the 27th-31st bits
    //
    // returns:
    // qNaN, aka 32256 decimal, 0x7E00 hex, or 01111110 00000000 binary
    // sNaN, aka 32000 decimal, 0x7D00 hex, or 01111101 00000000 binary
    // +inf, aka 31744 decimal, 0x7C00 hex, or 01111100 00000000 binary
    // -inf, aka 64512 decimal, 0xFC00 hex, or 11111100 00000000 binary
    //
    // If mantissa is greater than 23 bits, set to +Infinity like numpy
    if (u32[0] > 0) {
      expo = 0x7C00;
    } else {
      expo = (expo & 0x7C000000) >> 16;
      sigf = (u32[1] & 0x000FFFFF) >> 10;
    }
  } else if (expo <= 0x3F000000) {
    //
    // If exponent underflowed, the float is either signed zero or subnormal.
    //
    // Magic numbers:
    // 0x3F000000 = 00111111 00000000 00000000 00000000 -- 6-bit exponent underflow
    //
    sigf = 0x100000 + (u32[1] & 0x000FFFFF);
    sigf = 0x100000 + (sigf << ((expo >> 20) - 998)) >> 21;
    expo = 0;
  } else {
    //
    // No overflow or underflow, rebase the exponent and round the mantissa
    // Magic numbers:
    // 0x200 = 00000010 00000000 -- masks off the 10th bit
    //
    // Ensure the first mantissa bit (the 10th one) is 1 and round
    expo = (expo - 0x3F000000) >> 10;
    sigf = ((u32[1] & 0x000FFFFF) + 0x200) >> 10;
  }
  return sign | expo | sigf & 0xFFFF;
}

;// ../../node_modules/@uwdata/flechette/src/util/strings.js



const textDecoder = new TextDecoder('utf-8');
const textEncoder = new TextEncoder();

/**
 * Return a UTF-8 string decoded from a byte buffer.
 * @param {Uint8Array} buf The byte buffer.
 * @returns {string} The decoded string.
 */
function decodeUtf8(buf) {
  return textDecoder.decode(buf);
}

/**
 * Return a byte buffer encoded from a UTF-8 string.
 * @param {string } str The string to encode.
 * @returns {Uint8Array} The encoded byte buffer.
 */
function encodeUtf8(str) {
  return textEncoder.encode(str);
}

/**
 * Return a string-coercible key value that uniquely identifies a value.
 * @param {*} value The input value.
 * @returns {string} The key string.
 */
function keyString(value) {
  const val = typeof value !== 'object' || !value ? (value ?? null)
    : objects_isDate(value) ? +value
    // @ts-ignore
    : arrays_isArray(value) ? `[${value.map(keyString)}]`
    : strings_objectKey(value);
  return `${val}`;
}

function strings_objectKey(value) {
  let s = '';
  let i = -1;
  for (const k in value) {
    if (++i > 0) s += ',';
    s += `"${k}":${keyString(value[k])}`;
  }
  return `{${s}}`;
}

;// ../../node_modules/@uwdata/flechette/src/util/read.js



/** The size in bytes of a 32-bit integer. */
const SIZEOF_INT = 4;

/** The size in bytes of a 16-bit integer. */
const SIZEOF_SHORT = 2;

/**
 * Return a boolean for a single bit in a bitmap.
 * @param {Uint8Array} bitmap The bitmap.
 * @param {number} index The bit index to read.
 * @returns {boolean} The boolean bitmap value.
 */
function decodeBit(bitmap, index) {
  return (bitmap[index >> 3] & 1 << (index % 8)) !== 0;
}

/**
 * Lookup helper for flatbuffer object (table) entries.
 * @param {Uint8Array} buf The byte buffer.
 * @param {number} index The base index of the object.
 */
function readObject(buf, index) {
  const pos = index + readInt32(buf, index);
  const vtable = pos - readInt32(buf, pos);
  const size = readInt16(buf, vtable);
  /**
   * Retrieve a value from a flatbuffer table layout.
   * @template T
   * @param {number} index The table entry index.
   * @param {(buf: Uint8Array, offset: number) => T} read Read function to invoke.
   * @param {T} [fallback=null] The default fallback value.
   * @returns {T}
   */
  return (index, read, fallback = null) => {
    if (index < size) {
      const off = readInt16(buf, vtable + index);
      if (off) return read(buf, pos + off);
    }
    return fallback;
  };
}

/**
 * Return a buffer offset value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readOffset(buf, offset) {
  return offset;
}

/**
 * Return a boolean value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {boolean}
 */
function readBoolean(buf, offset) {
  return !!readInt8(buf, offset);
}

/**
 * Return a signed 8-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readInt8(buf, offset) {
  return readUint8(buf, offset) << 24 >> 24;
}

/**
 * Return an unsigned 8-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readUint8(buf, offset) {
  return buf[offset];
}

/**
 * Return a signed 16-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readInt16(buf, offset) {
  return readUint16(buf, offset) << 16 >> 16;
}

/**
 * Return an unsigned 16-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readUint16(buf, offset) {
  return buf[offset] | buf[offset + 1] << 8;
}

/**
 * Return a signed 32-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readInt32(buf, offset) {
  return buf[offset]
    | buf[offset + 1] << 8
    | buf[offset + 2] << 16
    | buf[offset + 3] << 24;
}

/**
 * Return an unsigned 32-bit integer value.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readUint32(buf, offset) {
  return readInt32(buf, offset) >>> 0;
}

/**
 * Return a signed 64-bit integer value coerced to a JS number.
 * Throws an error if the value exceeds what a JS number can represent.
 * @param {Uint8Array} buf
 * @param {number} offset
 * @returns {number}
 */
function readInt64(buf, offset) {
  return toNumber(BigInt.asIntN(
    64,
    BigInt(readUint32(buf, offset)) +
      (BigInt(readUint32(buf, offset + SIZEOF_INT)) << 32n)
  ));
}

/**
 * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer.
 * This allocates a new string and converts to wide chars upon each access.
 * @param {Uint8Array} buf The byte buffer.
 * @param {number} index The index of the string entry.
 * @returns {string} The decoded string.
 */
function readString(buf, index) {
  let offset = index + readInt32(buf, index); // get the string offset
  const length = readInt32(buf, offset);  // get the string length
  offset += SIZEOF_INT; // skip length value
  return decodeUtf8(buf.subarray(offset, offset + length));
}

/**
 * Extract a flatbuffer vector to an array.
 * @template T
 * @param {Uint8Array} buf The byte buffer.
 * @param {number} offset The offset location of the vector.
 * @param {number} stride The stride between vector entries.
 * @param {(buf: Uint8Array, pos: number) => T} extract Vector entry extraction function.
 * @returns {T[]} The extracted vector entries.
 */
function readVector(buf, offset, stride, extract) {
  if (!offset) return [];

  // get base position by adding offset delta
  const base = offset + readInt32(buf, offset);

  // read vector size, extract entries
  return Array.from(
    { length: readInt32(buf, base) },
    (_, i) => extract(buf, base + SIZEOF_INT + i * stride)
  );
}

;// ../../node_modules/@uwdata/flechette/src/util/struct.js
const RowIndex = Symbol('rowIndex');

/**
 * Returns a row proxy object factory. The resulting method takes a
 * batch-level row index as input and returns an object that proxies
 * access to underlying batches.
 * @param {string[]} names The column (property) names
 * @param {import('../batch.js').Batch[]} batches The value batches.
 * @returns {(index: number) => Record<string, any>}
 */
function proxyFactory(names, batches) {
  class RowObject {
    /**
     * Create a new proxy row object representing a struct or table row.
     * @param {number} index The record batch row index.
     */
    constructor(index) {
      this[RowIndex] = index;
    }

    /**
     * Return a JSON-compatible object representation.
     */
    toJSON() {
      return structObject(names, batches, this[RowIndex]);
    }
  };

  // prototype for row proxy objects
  const proto = RowObject.prototype;

  for (let i = 0; i < names.length; ++i) {
    // skip duplicated column names
    if (Object.hasOwn(proto, names[i])) continue;

    // add a getter method for the current batch
    const batch = batches[i];
    Object.defineProperty(proto, names[i], {
      get() { return batch.at(this[RowIndex]); },
      enumerable: true
    });
  }

  return index => new RowObject(index);
}

/**
 * Returns a row object factory. The resulting method takes a
 * batch-level row index as input and returns an object whose property
 * values have been extracted from the batches.
 * @param {string[]} names The column (property) names
 * @param {import('../batch.js').Batch[]} batches The value batches.
 * @returns {(index: number) => Record<string, any>}
 */
function objectFactory(names, batches) {
  return index => structObject(names, batches, index);
}

/**
 * Return a vanilla object representing a struct (row object) type.
 * @param {string[]} names The column (property) names
 * @param {import('../batch.js').Batch[]} batches The value batches.
 * @param {number} index The record batch row index.
 * @returns {Record<string, any>}
 */
function structObject(names, batches, index) {
  const obj = {};
  for (let i = 0; i < names.length; ++i) {
    obj[names[i]] = batches[i].at(index);
  }
  return obj;
}

;// ../../node_modules/@uwdata/flechette/src/batch.js






/**
 * Check if the input is a batch that supports direct access to
 * binary data in the form of typed arrays.
 * @param {Batch<any>?} batch The data batch to check.
 * @returns {boolean} True if a direct batch, false otherwise.
 */
function isDirectBatch(batch) {
  return batch instanceof DirectBatch;
}

/**
 * Column values from a single record batch.
 * A column may contain multiple batches.
 * @template T
 */
class Batch {
  /**
   * The array type to use when extracting data from the batch.
   * A null value indicates that the array type should match
   * the type of the batch's values array.
   * @type {ArrayConstructor | import('./types.js').TypedArrayConstructor | null}
   */
  static ArrayType = null;

  /**
   * Create a new column batch.
   * @param {object} options
   * @param {number} options.length The length of the batch
   * @param {number} options.nullCount The null value count
   * @param {import('./types.js').DataType} options.type The data type.
   * @param {Uint8Array} [options.validity] Validity bitmap buffer
   * @param {import('./types.js').TypedArray} [options.values] Values buffer
   * @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer
   * @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer
   * @param {Batch[]} [options.children] Children batches
   */
  constructor({
    length,
    nullCount,
    type,
    validity,
    values,
    offsets,
    sizes,
    children
  }) {
    this.length = length;
    this.nullCount = nullCount;
    this.type = type;
    this.validity = validity;
    this.values = values;
    this.offsets = offsets;
    this.sizes = sizes;
    this.children = children;

    // optimize access if this batch has no null values
    // some types (like union) may have null values in
    // child batches, but no top-level validity buffer
    if (!nullCount || !this.validity) {
      /** @type {(index: number) => T | null} */
      this.at = index => this.value(index);
    }
  }

  /**
   * Provide an informative object string tag.
   */
  get [Symbol.toStringTag]() {
    return 'Batch';
  }

  /**
   * Return the value at the given index.
   * @param {number} index The value index.
   * @returns {T | null} The value.
   */
  at(index) {
    return this.isValid(index) ? this.value(index) : null;
  }

  /**
   * Check if a value at the given index is valid (non-null).
   * @param {number} index The value index.
   * @returns {boolean} True if valid, false otherwise.
   */
  isValid(index) {
    return decodeBit(this.validity, index);
  }

  /**
   * Return the value at the given index. This method does not check the
   * validity bitmap and is intended primarily for internal use. In most
   * cases, callers should use the `at()` method instead.
   * @param {number} index The value index
   * @returns {T} The value, ignoring the validity bitmap.
   */
  value(index) {
    return /** @type {T} */ (this.values[index]);
  }

  /**
   * Extract an array of values within the given index range. Unlike
   * Array.slice, all arguments are required and may not be negative indices.
   * @param {number} start The starting index, inclusive
   * @param {number} end The ending index, exclusive
   * @returns {import('./types.js').ValueArray<T?>} The slice of values
   */
  slice(start, end) {
    const n = end - start;
    const values = Array(n);
    for (let i = 0; i < n; ++i) {
      values[i] = this.at(start + i);
    }
    return values;
  }

  /**
   * Return an iterator over the values in this batch.
   * @returns {Iterator<T?>}
   */
  *[Symbol.iterator]() {
    for (let i = 0; i < this.length; ++i) {
      yield this.at(i);
    }
  }
}

/**
 * A batch whose value buffer can be used directly, without transformation.
 * @template T
 * @extends {Batch<T>}
 */
class DirectBatch extends Batch {
  /**
   * Create a new column batch with direct value array access.
   * @param {object} options
   * @param {number} options.length The length of the batch
   * @param {number} options.nullCount The null value count
   * @param {import('./types.js').DataType} options.type The data type.
   * @param {Uint8Array} [options.validity] Validity bitmap buffer
   * @param {import('./types.js').TypedArray} options.values Values buffer
   */
  constructor(options) {
    super(options);
    // underlying buffers may be padded, exceeding the logical batch length
    // we trim the values array so we can safely access it directly
    const { length, values } = this;
    this.values = values.subarray(0, length);
  }

  /**
   * Extract an array of values within the given index range. Unlike
   * Array.slice, all arguments are required and may not be negative indices.
   * When feasible, a zero-copy subarray of a typed array is returned.
   * @param {number} start The starting index, inclusive
   * @param {number} end The ending index, exclusive
   * @returns {import('./types.js').ValueArray<T?>} The slice of values
   */
  slice(start, end) {
    // @ts-ignore
    return this.nullCount
      ? super.slice(start, end)
      : this.values.subarray(start, end);
  }

  /**
   * Return an iterator over the values in this batch.
   * @returns {Iterator<T?>}
   */
  [Symbol.iterator]() {
    return this.nullCount
      ? super[Symbol.iterator]()
      : /** @type {Iterator<T?>} */ (this.values[Symbol.iterator]());
  }
}

/**
 * A batch whose values are transformed to 64-bit numbers.
 * @extends {Batch<number>}
 */
class NumberBatch extends Batch {
  static ArrayType = float64Array;
}

/**
 * A batch whose values should be returned in a standard array.
 * @template T
 * @extends {Batch<T>}
 */
class ArrayBatch extends Batch {
  static ArrayType = Array;
}

/**
 * A batch of null values only.
 * @extends {ArrayBatch<null>}
 */
class NullBatch extends ArrayBatch {
  /**
   * @param {number} index The value index
   * @returns {null}
   */
  value(index) { // eslint-disable-line no-unused-vars
    return null;
  }
}

/**
 * A batch that coerces BigInt values to 64-bit numbers.
 * @extends {NumberBatch}
 */
class Int64Batch extends NumberBatch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    return toNumber(/** @type {bigint} */ (this.values[index]));
  }
}

/**
 * A batch of 16-bit floating point numbers, accessed as unsigned
 * 16-bit ints and transformed to 64-bit numbers.
 */
class Float16Batch extends NumberBatch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    const v = /** @type {number} */ (this.values[index]);
    const expo = (v & 0x7C00) >> 10;
    const sigf = (v & 0x03FF) / 1024;
    const sign = (-1) ** ((v & 0x8000) >> 15);
    switch (expo) {
      case 0x1F: return sign * (sigf ? Number.NaN : 1 / 0);
      case 0x00: return sign * (sigf ? 6.103515625e-5 * sigf : 0);
    }
    return sign * (2 ** (expo - 15)) * (1 + sigf);
  }
}

/**
 * A batch of boolean values stored as a bitmap.
 * @extends {ArrayBatch<boolean>}
 */
class BoolBatch extends ArrayBatch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    return decodeBit(/** @type {Uint8Array} */ (this.values), index);
  }
}

/**
 * A batch of 32-bit decimal numbers, returned as converted 64-bit floating
 * point numbers. Number coercion may be lossy if the decimal precision can
 * not be represented in a 64-bit floating point format.
 * @extends {NumberBatch}
 */
class Decimal32NumberBatch extends NumberBatch {
  constructor(options) {
    super(options);
    const { scale } = /** @type {import('./types.js').DecimalType} */ (this.type);
    this.scale = 10 ** scale;
  }
  /**
   * @param {number} index The value index
   */
  value(index) {
    return /** @type {number} */(this.values[index]) / this.scale;
  }
}

/**
 * An abstract class for a batch of 64-, 128- or 256-bit decimal numbers,
 * accessed in strided BigUint64Arrays.
 * @template T
 * @extends {Batch<T>}
 */
class DecimalBatch extends Batch {
  constructor(options) {
    super(options);
    const { bitWidth, scale } = /** @type {import('./types.js').DecimalType} */ (this.type);
    this.decimal = bitWidth === 64 ? fromDecimal64
      : bitWidth === 128 ? fromDecimal128
      : fromDecimal256;
    this.scale = 10n ** BigInt(scale);
  }
}

/**
 * A batch of 64-, 128- or 256-bit decimal numbers, returned as converted
 * 64-bit floating point numbers. Number coercion may be lossy if the decimal
 * precision can not be represented in a 64-bit floating point format.
 * @extends {DecimalBatch<number>}
 */
class DecimalNumberBatch extends DecimalBatch {
  static ArrayType = float64Array;
  /**
   * @param {number} index The value index
   */
  value(index) {
    return divide(
      this.decimal(/** @type {BigUint64Array} */ (this.values), index),
      this.scale
    );
  }
}

/**
 * A batch of 64-, 128- or 256-bit decimal numbers, returned as scaled
 * bigint values, such that all fractional digits have been shifted
 * to integer places by the decimal type scale factor.
 * @extends {DecimalBatch<bigint>}
 */
class DecimalBigIntBatch extends DecimalBatch {
  static ArrayType = Array;
  /**
   * @param {number} index The value index
   */
  value(index) {
    return this.decimal(/** @type {BigUint64Array} */ (this.values), index);
  }
}

/**
 * A batch of date or timestamp values that are coerced to UNIX epoch timestamps
 * and returned as JS Date objects. This batch wraps a source batch that provides
 * timestamp values.
 * @extends {ArrayBatch<Date>}
 */
class DateBatch extends ArrayBatch {
  /**
   * Create a new date batch.
   * @param {Batch<number>} batch A batch of timestamp values.
   */
  constructor(batch) {
    super(batch);
    this.source = batch;
  }

  /**
   * @param {number} index The value index
   */
  value(index) {
    return new Date(this.source.value(index));
  }
}

/**
 * A batch of dates as day counts, coerced to timestamp numbers.
 */
class DateDayBatch extends NumberBatch {
  /**
   * @param {number} index The value index
   * @returns {number}
   */
  value(index) {
    // epoch days to milliseconds
    return 86400000 * /** @type {number} */ (this.values[index]);
  }
}

/**
 * A batch of dates as millisecond timestamps, coerced to numbers.
 */
const DateDayMillisecondBatch = Int64Batch;

/**
 * A batch of timestaps in seconds, coerced to millisecond numbers.
 */
class TimestampSecondBatch extends Int64Batch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    return super.value(index) * 1e3; // seconds to milliseconds
  }
}

/**
 * A batch of timestaps in milliseconds, coerced to numbers.
 */
const TimestampMillisecondBatch = Int64Batch;

/**
 * A batch of timestaps in microseconds, coerced to millisecond numbers.
 */
class TimestampMicrosecondBatch extends Int64Batch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    // microseconds to milliseconds
    return divide(/** @type {bigint} */ (this.values[index]), 1000n);
  }
}

/**
 * A batch of timestaps in nanoseconds, coerced to millisecond numbers.
 */
class TimestampNanosecondBatch extends Int64Batch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    // nanoseconds to milliseconds
    return divide(/** @type {bigint} */ (this.values[index]), 1000000n);
  }
}

/**
 * A batch of day/time intervals, returned as two-element 32-bit int arrays.
 * @extends {ArrayBatch<Int32Array>}
 */
class IntervalDayTimeBatch extends ArrayBatch {
  /**
   * @param {number} index The value index
   * @returns {Int32Array}
   */
  value(index) {
    const values = /** @type {Int32Array} */ (this.values);
    return values.subarray(index << 1, (index + 1) << 1);
  }
}

/**
 * A batch of month/day/nanosecond intervals, returned as three-element arrays.
 * @extends {ArrayBatch<Float64Array>}
 */
class IntervalMonthDayNanoBatch extends ArrayBatch {
  /**
   * @param {number} index The value index
   */
  value(index) {
    const values = /** @type {Uint8Array} */ (this.values);
    const base = index << 4;
    return Float64Array.of(
      readInt32(values, base),
      readInt32(values, base + 4),
      readInt64(values, base + 8)
    );
  }
}

const offset32 = ({values, offsets}, index) => values.subarray(offsets[index], offsets[index + 1]);
const offset64 = ({values, offsets}, index) => values.subarray(toNumber(offsets[index]), toNumber(offsets[index + 1]));

/**
 * A batch of binary blobs with variable offsets, returned as byte buffers of
 * unsigned 8-bit integers. The offsets are 32-bit ints.
 * @extends {ArrayBatch<Uint8Array>}
 */
class BinaryBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {Uint8Array}
   */
  value(index) {
    return offset32(this, index);
  }
}

/**
 * A batch of binary blobs with variable offsets, returned as byte buffers of
 * unsigned 8-bit integers. The offsets are 64-bit ints. Value extraction will
 * fail if an offset exceeds `Number.MAX_SAFE_INTEGER`.
 * @extends {ArrayBatch<Uint8Array>}
 */
class LargeBinaryBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {Uint8Array}
   */
  value(index) {
    return offset64(this, index);
  }
}

/**
 * A batch of UTF-8 strings with variable offsets. The offsets are 32-bit ints.
 * @extends {ArrayBatch<string>}
 */
class Utf8Batch extends ArrayBatch {
  /**
   * @param {number} index
   */
  value(index) {
    return decodeUtf8(offset32(this, index));
  }
}

/**
 * A batch of UTF-8 strings with variable offsets. The offsets are 64-bit ints.
 * Value extraction will fail if an offset exceeds `Number.MAX_SAFE_INTEGER`.
 * @extends {ArrayBatch<string>}
 */
class LargeUtf8Batch extends ArrayBatch {
  /**
   * @param {number} index
   */
  value(index) {
    return decodeUtf8(offset64(this, index));
  }
}

/**
 * A batch of list (array) values of variable length. The list offsets are
 * 32-bit ints.
 * @template V
 * @extends {ArrayBatch<import('./types.js').ValueArray<V>>}
 */
class ListBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {import('./types.js').ValueArray<V>}
   */
  value(index) {
    const offsets = /** @type {Int32Array} */ (this.offsets);
    return this.children[0].slice(offsets[index], offsets[index + 1]);
  }
}

/**
 * A batch of list (array) values of variable length. The list offsets are
 * 64-bit ints. Value extraction will fail if an offset exceeds
 * `Number.MAX_SAFE_INTEGER`.
 * @template V
 * @extends {ArrayBatch<import('./types.js').ValueArray<V>>}
 */
class LargeListBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {import('./types.js').ValueArray<V>}
   */
  value(index) {
    const offsets = /** @type {BigInt64Array} */ (this.offsets);
    return this.children[0].slice(toNumber(offsets[index]), toNumber(offsets[index + 1]));
  }
}

/**
 * A batch of list (array) values of variable length. The list offsets and
 * sizes are 32-bit ints.
 * @template V
 * @extends {ArrayBatch<import('./types.js').ValueArray<V>>}
 */
class ListViewBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {import('./types.js').ValueArray<V>}
   */
  value(index) {
    const a = /** @type {number} */ (this.offsets[index]);
    const b = a + /** @type {number} */ (this.sizes[index]);
    return this.children[0].slice(a, b);
  }
}

/**
 * A batch of list (array) values of variable length. The list offsets and
 * sizes are 64-bit ints. Value extraction will fail if an offset or size
 * exceeds `Number.MAX_SAFE_INTEGER`.
 * @template V
 * @extends {ArrayBatch<import('./types.js').ValueArray<V>>}
 */
class LargeListViewBatch extends ArrayBatch {
  /**
   * @param {number} index
   * @returns {import('./types.js').ValueArray<V>}
   */
  value(index) {
    const a = /** @type {bigint} */ (this.offsets[index]);
    const b = a + /** @type {bigint} */ (this.sizes[index]);
    return this.children[0].slice(toNumber(a), toNumber(b));
  }
}

/**
 * A batch with a fixed stride.
 * @template T
 * @extends {ArrayBatch<T>}
 */
class FixedBatch extends ArrayBatch {
  constructor(options) {
    super(options);
    /** @type {number} */
    // @ts-ignore
    this.stride = this.type.stride;
  }
}

/**
 * A batch of binary blobs of fixed size, returned as byte buffers of unsigned
 * 8-bit integers.
 * @extends {FixedBatch<Uint8Array>}
 */
class FixedBinaryBatch extends FixedBatch {
  /**
   * @param {number} index
   * @returns {Uint8Array}
   */
  value(index) {
    const { stride, values } = this;
    return /** @type {Uint8Array} */ (values)
      .subarray(index * stride, (index + 1) * stride);
  }
}

/**
 * A batch of list (array) values of fixed length.
 * @template V
 * @extends {FixedBatch<import('./types.js').ValueArray<V>>}
 */
class FixedListBatch extends FixedBatch {
  /**
   * @param {number} index
   * @returns {import('./types.js').ValueArray<V>}
   */
  value(index) {
    const { children, stride } = this;
    return children[0].slice(index * stride, (index + 1) * stride);
  }
}

/**
 * Extract Map key-value pairs from parallel child batches.
 */
function pairs({ children, offsets }, index) {
  const [ keys, vals ] = children[0].children;
  const start = offsets[index];
  const end = offsets[index + 1];
  const entries = [];
  for (let i = start; i < end; ++i) {
    entries.push([keys.at(i), vals.at(i)]);
  }
  return entries;
}

/**
 * A batch of map (key, value) values. The map is represented as a list of
 * key-value structs.
 * @template K, V
 * @extends {ArrayBatch<[K, V][]>}
 */
class MapEntryBatch extends ArrayBatch {
  /**
   * Return the value at the given index.
   * @param {number} index The value index.
   * @returns {[K, V][]} The map entries as an array of [key, value] arrays.
   */
  value(index) {
    return /** @type {[K, V][]} */ (pairs(this, index));
  }
}

/**
 * A batch of map (key, value) values. The map is represented as a list of
 * key-value structs.
 * @template K, V
 * @extends {ArrayBatch<Map<K, V>>}
 */
class MapBatch extends ArrayBatch {
  /**
   * Return the value at the given index.
   * @param {number} index The value index.
   * @returns {Map<K, V>} The map value.
   */
  value(index) {
    return new Map(/** @type {[K, V][]} */ (pairs(this, index)));
  }
}

/**
 * A batch of union-type values with a sparse layout, enabling direct
 * lookup from the child value batches.
 * @template T
 * @extends {ArrayBatch<T>}
 */
class SparseUnionBatch extends ArrayBatch {
  /**
   * Create a new column batch.
   * @param {object} options
   * @param {number} options.length The length of the batch
   * @param {number} options.nullCount The null value count
   * @param {import('./types.js').DataType} options.type The data type.
   * @param {Uint8Array} [options.validity] Validity bitmap buffer
   * @param {Int32Array} [options.offsets] Offsets buffer
   * @param {Batch[]} options.children Children batches
   * @param {Int8Array} options.typeIds Union type ids buffer
   * @param {Record<string, number>} options.map A typeId to children index map
   */
  constructor({ typeIds, ...options }) {
    super(options);
    /** @type {Int8Array} */
    this.typeIds = typeIds;
    /** @type {Record<string, number>} */
    // @ts-ignore
    this.typeMap = this.type.typeMap;
  }

  /**
   * @param {number} index The value index.
   */
  value(index, offset = index) {
    const { typeIds, children, typeMap } = this;
    return children[typeMap[typeIds[index]]].at(offset);
  }
}

/**
 * A batch of union-type values with a dense layout, reqiring offset
 * lookups from the child value batches.
 * @template T
 * @extends {SparseUnionBatch<T>}
 */
class DenseUnionBatch extends SparseUnionBatch {
  /**
   * @param {number} index The value index.
   */
  value(index) {
    return super.value(index, /** @type {number} */ (this.offsets[index]));
  }
}

/**
 * A batch of struct values, containing a set of named properties.
 * Struct property values are extracted and returned as JS objects.
 * @extends {ArrayBatch<Record<string, any>>}
 */
class StructBatch extends ArrayBatch {
  constructor(options, factory = objectFactory) {
    super(options);
    /** @type {string[]} */
    // @ts-ignore
    this.names = this.type.children.map(child => child.name);
    this.factory = factory(this.names, this.children);
  }

  /**
   * @param {number} index The value index.
   * @returns {Record<string, any>}
   */
  value(index) {
    return this.factory(index);
  }
}

/**
 * A batch of struct values, containing a set of named properties.
 * Structs are returned as proxy objects that extract data directly
 * from underlying Arrow batches.
 * @extends {StructBatch}
 */
class StructProxyBatch extends StructBatch {
  constructor(options) {
    super(options, proxyFactory);
  }
}

/**
 * A batch of run-end-encoded values.
 * @template T
 * @extends {ArrayBatch<T>}
 */
class RunEndEncodedBatch extends ArrayBatch {
  /**
   * @param {number} index The value index.
   */
  value(index) {
    const [ { values: runs }, vals ] = this.children;
    return vals.at(
      arrays_bisect(/** @type {import('./types.js').IntegerArray} */(runs), index)
    );
  }
}

/**
 * A batch of dictionary-encoded values.
 * @template T
 * @extends {ArrayBatch<T>}
 */
class DictionaryBatch extends ArrayBatch {
  /**
   * Register the backing dictionary. Dictionaries are added
   * after batch creation as the complete dictionary may not
   * be finished across multiple record batches.
   * @param {import('./column.js').Column<T>} dictionary
   * The dictionary of column values.
   */
  setDictionary(dictionary) {
    this.dictionary = dictionary;
    this.cache = dictionary.cache();
    return this;
  }

  /**
   * @param {number} index The value index.
   */
  value(index) {
    return this.cache[this.key(index)];
  }

  /**
   * @param {number} index The value index.
   * @returns {number} The dictionary key
   */
  key(index) {
    return /** @type {number} */ (this.values[index]);
  }
}

/**
 * @template T
 * @extends {ArrayBatch<T>}
 */
class ViewBatch extends ArrayBatch {
  /**
   * Create a new view batch.
   * @param {object} options Batch options.
   * @param {number} options.length The length of the batch
   * @param {number} options.nullCount The null value count
   * @param {import('./types.js').DataType} options.type The data type.
   * @param {Uint8Array} [options.validity] Validity bitmap buffer
   * @param {Uint8Array} options.values Values buffer
   * @param {Uint8Array[]} options.data View data buffers
   */
  constructor({ data, ...options }) {
    super(options);
    this.data = data;
  }

  /**
   * Get the binary data at the provided index.
   * @param {number} index The value index.
   * @returns {Uint8Array}
   */
  view(index) {
    const { values, data } = this;
    const offset = index << 4; // each entry is 16 bytes
    let start = offset + 4;
    let buf = /** @type {Uint8Array} */ (values);
    const length = readInt32(buf, offset);
    if (length > 12) {
      // longer strings are in a data buffer
      start = readInt32(buf, offset + 12);
      buf = data[readInt32(buf, offset + 8)];
    }
    return buf.subarray(start, start + length);
  }
}

/**
 * A batch of binary blobs from variable data buffers, returned as byte
 * buffers of unsigned 8-bit integers.
 * @extends {ViewBatch<Uint8Array>}
 */
class BinaryViewBatch extends ViewBatch {
  /**
   * @param {number} index The value index.
   */
  value(index) {
    return this.view(index);
  }
}

/**
 * A batch of UTF-8 strings from variable data buffers.
 * @extends {ViewBatch<string>}
 */
class Utf8ViewBatch extends ViewBatch {
  /**
   * @param {number} index The value index.
   */
  value(index) {
    return decodeUtf8(this.view(index));
  }
}

;// ../../node_modules/@uwdata/flechette/src/column.js



/**
 * Build up a column from batches.
 */
function columnBuilder(type) {
  let data = [];
  return {
    add(batch) { data.push(batch); return this; },
    clear: () => data = [],
    done: () => new column_Column(data, type)
  };
}

/**
 * A data column. A column provides a view over one or more value batches,
 * each drawn from an Arrow record batch. While this class supports random
 * access to column values by integer index; however, extracting arrays using
 * `toArray()` or iterating over values (`for (const value of column) {...}`)
 * provide more efficient ways for bulk access or scanning.
 * @template T
 */
class column_Column {
  /**
   * Create a new column instance.
   * @param {import('./batch.js').Batch<T>[]} data The value batches.
   * @param {import('./types.js').DataType} [type] The column data type.
   *  If not specified, the type is extracted from the batches.
   */
  constructor(data, type = data[0]?.type) {
    /**
     * The column data type.
     * @type {import('./types.js').DataType}
     * @readonly
     */
    this.type = type;
    /**
     * The column length.
     * @type {number}
     * @readonly
     */
    this.length = data.reduce((m, c) => m + c.length, 0);
    /**
     * The count of null values in the column.
     * @type {number}
     * @readonly
     */
    this.nullCount = data.reduce((m, c) => m + c.nullCount, 0);
    /**
     * An array of column data batches.
     * @type {readonly import('./batch.js').Batch<T>[]}
     * @readonly
     */
    this.data = data;

    const n = data.length;
    const offsets = new Int32Array(n + 1);
    if (n === 1) {
      const [ batch ] = data;
      offsets[1] = batch.length;
      // optimize access to single batch
      this.at = index => batch.at(index);
    } else {
      for (let i = 0, s = 0; i < n; ++i) {
        offsets[i + 1] = (s += data[i].length);
      }
    }

    /**
     * Index offsets for data batches.
     * Used to map a column row index to a batch-specific index.
     * @type {Int32Array}
     * @readonly
     */
    this.offsets = offsets;
  }

  /**
   * Provide an informative object string tag.
   */
  get [Symbol.toStringTag]() {
    return 'Column';
  }

  /**
   * Return an iterator over the values in this column.
   * @returns {Iterator<T?>}
   */
  [Symbol.iterator]() {
    const data = this.data;
    return data.length === 1
      ? data[0][Symbol.iterator]()
      : batchedIterator(data);
  }

  /**
   * Return the column value at the given index. If a column has multiple
   * batches, this method performs binary search over the batch lengths to
   * determine the batch from which to retrieve the value. The search makes
   * lookup less efficient than a standard array access. If making a full
   * scan of a column, consider extracting arrays via `toArray()` or using an
   * iterator (`for (const value of column) {...}`).
   * @param {number} index The row index.
   * @returns {T | null} The value.
   */
  at(index) {
    // NOTE: if there is only one batch, this method is replaced with an
    // optimized version in the Column constructor.
    const { data, offsets } = this;
    const i = arrays_bisect(offsets, index) - 1;
    return data[i]?.at(index - offsets[i]); // undefined if out of range
  }

  /**
   * Return the column value at the given index. This method is the same as
   * `at()` and is provided for better compatibility with Apache Arrow JS.
   * @param {number} index The row index.
   * @returns {T | null} The value.
   */
  get(index) {
    return this.at(index);
  }

  /**
   * Extract column values into a single array instance. When possible,
   * a zero-copy subarray of the input Arrow data is returned.
   * @returns {import('./types.js').ValueArray<T?>}
   */
  toArray() {
    const { length, nullCount, data } = this;
    const copy = !nullCount && isDirectBatch(data[0]);
    const n = data.length;

    if (copy && n === 1) {
      // use batch array directly
      // @ts-ignore
      return data[0].values;
    }

    // determine output array type
    const ArrayType = !n || nullCount > 0 ? Array
      // @ts-ignore
      : (data[0].constructor.ArrayType ?? data[0].values.constructor);

    const array = new ArrayType(length);
    return copy ? copyArray(array, data) : extractArray(array, data);
  }

  /**
   * Return an array of cached column values.
   * Used internally to accelerate dictionary types.
   */
  cache() {
    return this._cache ?? (this._cache = this.toArray());
  }
}

function *batchedIterator(data) {
  for (let i = 0; i < data.length; ++i) {
    const iter = data[i][Symbol.iterator]();
    for (let next = iter.next(); !next.done; next = iter.next()) {
      yield next.value;
    }
  }
}

function copyArray(array, data) {
  for (let i = 0, offset = 0; i < data.length; ++i) {
    const { values } = data[i];
    array.set(values, offset);
    offset += values.length;
  }
  return array;
}

function extractArray(array, data) {
  let index = -1;
  for (let i = 0; i < data.length; ++i) {
    const batch = data[i];
    for (let j = 0; j < batch.length; ++j) {
      array[++index] = batch.at(j);
    }
  }
  return array;
}

;// ../../node_modules/@uwdata/flechette/src/table.js



/**
 * A table consists of a collection of named columns (or 'children').
 * To work with table data directly in JavaScript, use `toColumns()`
 * to extract an object that maps column names to extracted value arrays,
 * or `toArray()` to extract an array of row objects. For random access
 * by row index, use `getChild()` to access data for a specific column.
 */
class table_Table {
  /**
   * Create a new table with the given schema and columns (children).
   * @param {import('./types.js').Schema} schema The table schema.
   * @param {import('./column.js').Column[]} children The table columns.
   * @param {boolean} [useProxy=false] Flag indicating if row proxy
   *  objects should be used to represent table rows (default `false`).
   */
  constructor(schema, children, useProxy = false) {
    const names = schema.fields.map(f => f.name);

    /** @readonly */
    this.schema = schema;
    /** @readonly */
    this.names = names;
    /**
     * @type {import('./column.js').Column[]}
     * @readonly
     */
    this.children = children;
    /**
     * @type {import('./types.js').StructFactory}
     * @readonly
     */
    this.factory = useProxy ? proxyFactory : objectFactory;

    // lazily created row object generators
    const gen = [];

    /**
     * Returns a row object generator for the given batch index.
     * @private
     * @readonly
     * @param {number} b The batch index.
     * @returns {(index: number) => Record<string,any>}
     */
    this.getFactory = b => gen[b]
      ?? (gen[b] = this.factory(names, children.map(c => c.data[b])));
  }

  /**
   * Provide an informative object string tag.
   */
  get [Symbol.toStringTag]() {
    return 'Table';
  }

  /**
   * The number of columns in this table.
   * @return {number} The number of columns.
   */
  get numCols() {
    return this.names.length;
  }

  /**
   * The number of rows in this table.
   * @return {number} The number of rows.
   */
  get numRows() {
    return this.children[0]?.length ?? 0;
  }

  /**
   * Return the child column at the given index position.
   * @param {number} index The column index.
   * @returns {import('./column.js').Column<any>}
   */
  getChildAt(index) {
    return this.children[index];
  }

  /**
   * Return the first child column with the given name.
   * @param {string} name The column name.
   * @returns {import('./column.js').Column<any>}
   */
  getChild(name) {
    const i = this.names.findIndex(x => x === name);
    return i > -1 ? this.children[i] : undefined;
  }

  /**
   * Construct a new table containing only columns at the specified indices.
   * The order of columns in the new table matches the order of input indices.
   * @param {number[]} indices The indices of columns to keep.
   * @param {string[]} [as] Optional new names for selected columns.
   * @returns {Table} A new table with columns at the specified indices.
   */
  selectAt(indices, as = []) {
    const { children, factory, schema } = this;
    const { fields } = schema;
    return new table_Table(
      {
        ...schema,
        fields: indices.map((i, j) => renameField(fields[i], as[j]))
      },
      indices.map(i => children[i]),
      factory === proxyFactory
    );
  }

  /**
   * Construct a new table containing only columns with the specified names.
   * If columns have duplicate names, the first (with lowest index) is used.
   * The order of columns in the new table matches the order of input names.
   * @param {string[]} names Names of columns to keep.
   * @param {string[]} [as] Optional new names for selected columns.
   * @returns {Table} A new table with columns matching the specified names.
   */
  select(names, as) {
    const all = this.names;
    const indices = names.map(name => all.indexOf(name));
    return this.selectAt(indices, as);
  }

  /**
   * Return an object mapping column names to extracted value arrays.
   * @returns {Record<string, import('./types.js').ValueArray<any>>}
   */
  toColumns() {
    const { children, names } = this;
    /** @type {Record<string, import('./types.js').ValueArray<any>>} */
    const cols = {};
    names.forEach((name, i) => cols[name] = children[i]?.toArray() ?? [] );
    return cols;
  }

  /**
   * Return an array of objects representing the rows of this table.
   * @returns {Record<string, any>[]}
   */
  toArray() {
    const { children, getFactory, numRows } = this;
    const data = children[0]?.data ?? [];
    const output = Array(numRows);
    for (let b = 0, row = -1; b < data.length; ++b) {
      const f = getFactory(b);
      for (let i = 0; i < data[b].length; ++i) {
        output[++row] = f(i);
      }
    }
    return output;
  }

  /**
   * Return an iterator over objects representing the rows of this table.
   * @returns {Generator<Record<string, any>, any, null>}
   */
  *[Symbol.iterator]() {
    const { children, getFactory } = this;
    const data = children[0]?.data ?? [];
    for (let b = 0; b < data.length; ++b) {
      const f = getFactory(b);
      for (let i = 0; i < data[b].length; ++i) {
        yield f(i);
      }
    }
  }

  /**
   * Return a row object for the given index.
   * @param {number} index The row index.
   * @returns {Record<string, any>} The row object.
   */
  at(index) {
    const { children, getFactory, numRows } = this;
    if (index < 0 || index >= numRows) return null;
    const [{ offsets }] = children;
    const b = arrays_bisect(offsets, index) - 1;
    return getFactory(b)(index - offsets[b]);
  }

  /**
   * Return a row object for the given index. This method is the same as
   * `at()` and is provided for better compatibility with Apache Arrow JS.
   * @param {number} index The row index.
   * @returns {Record<string, any>} The row object.
   */
  get(index) {
    return this.at(index);
  }
}

function renameField(field, name) {
  return (name != null && name !== field.name)
    ? { ...field, name }
    : field;
}

;// ../../node_modules/@uwdata/flechette/src/batch-type.js




function batchType(type, options = {}) {
  const { typeId, bitWidth, precision, unit } = type;
  const { useBigInt, useDate, useDecimalInt, useMap, useProxy } = options;

  switch (typeId) {
    case constants_Type.Null: return NullBatch;
    case constants_Type.Bool: return BoolBatch;
    case constants_Type.Int:
    case constants_Type.Time:
    case constants_Type.Duration:
      return useBigInt || bitWidth < 64 ? DirectBatch : Int64Batch;
    case constants_Type.Float:
      return precision ? DirectBatch : Float16Batch;
    case constants_Type.Date:
      return batch_type_wrap(
        unit === constants_DateUnit.DAY ? DateDayBatch : DateDayMillisecondBatch,
        useDate && DateBatch
      );
    case constants_Type.Timestamp:
      return batch_type_wrap(
        unit === constants_TimeUnit.SECOND ? TimestampSecondBatch
          : unit === constants_TimeUnit.MILLISECOND ? TimestampMillisecondBatch
          : unit === constants_TimeUnit.MICROSECOND ? TimestampMicrosecondBatch
          : TimestampNanosecondBatch,
        useDate && DateBatch
      );
    case constants_Type.Decimal:
      return bitWidth === 32
        ? (useDecimalInt ? DirectBatch : Decimal32NumberBatch)
        : (useDecimalInt ? DecimalBigIntBatch : DecimalNumberBatch);
    case constants_Type.Interval:
      return unit === IntervalUnit.DAY_TIME ? IntervalDayTimeBatch
        : unit === IntervalUnit.YEAR_MONTH ? DirectBatch
        : IntervalMonthDayNanoBatch;
    case constants_Type.FixedSizeBinary: return FixedBinaryBatch;
    case constants_Type.Utf8: return Utf8Batch;
    case constants_Type.LargeUtf8: return LargeUtf8Batch;
    case constants_Type.Binary: return BinaryBatch;
    case constants_Type.LargeBinary: return LargeBinaryBatch;
    case constants_Type.BinaryView: return BinaryViewBatch;
    case constants_Type.Utf8View: return Utf8ViewBatch;
    case constants_Type.List: return ListBatch;
    case constants_Type.LargeList: return LargeListBatch;
    case constants_Type.Map: return useMap ? MapBatch : MapEntryBatch;
    case constants_Type.ListView: return ListViewBatch;
    case constants_Type.LargeListView: return LargeListViewBatch;
    case constants_Type.FixedSizeList: return FixedListBatch;
    case constants_Type.Struct: return useProxy ? StructProxyBatch : StructBatch;
    case constants_Type.RunEndEncoded: return RunEndEncodedBatch;
    case constants_Type.Dictionary: return DictionaryBatch;
    case constants_Type.Union: return type.mode ? DenseUnionBatch : SparseUnionBatch;
  }
  throw new Error(invalidDataType(typeId));
}

function batch_type_wrap(BaseClass, WrapperClass) {
  return WrapperClass
    ? class WrapBatch extends WrapperClass {
        constructor(options) {
          super(new BaseClass(options));
        }
      }
    : BaseClass;
}

;// ../../node_modules/@uwdata/flechette/src/decode/block.js


/**
 * Decode a block that points to messages within an Arrow 'file' format.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @returns The file block.
 */
function decodeBlock(buf, index) {
  //  0: offset
  //  8: metadataLength
  // 16: bodyLength
  return {
    offset: readInt64(buf, index),
    metadataLength: readInt32(buf, index + 8),
    bodyLength: readInt64(buf, index + 16)
  }
}

/**
 * Decode a vector of blocks.
 * @param {Uint8Array} buf
 * @param {number} index
 * @returns An array of file blocks.
 */
function decodeBlocks(buf, index) {
  return readVector(buf, index, 24, decodeBlock);
}

;// ../../node_modules/@uwdata/flechette/src/decode/record-batch.js



/**
 * Decode a record batch.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @param {import('../types.js').Version_} version Arrow version value
 * @returns {import('../types.js').RecordBatch} The record batch
 */
function decodeRecordBatch(buf, index, version) {
  //  4: length
  //  6: nodes
  //  8: buffers
  // 10: compression (not supported)
  // 12: variadicBuffers (buffer counts for view-typed fields)
  const get = readObject(buf, index);
  if (get(10, readOffset, 0)) {
    throw new Error('Record batch compression not implemented');
  }

  // If an Arrow buffer was written before version 4,
  // advance 8 bytes to skip the now-removed page_id field
  const offset = version < Version.V4 ? 8 : 0;

  return {
    length: get(4, readInt64, 0),
    nodes: readVector(buf, get(6, readOffset), 16, (buf, pos) => ({
      length: readInt64(buf, pos),
      nullCount: readInt64(buf, pos + 8)
    })),
    regions: readVector(buf, get(8, readOffset), 16 + offset, (buf, pos) => ({
      offset: readInt64(buf, pos + offset),
      length: readInt64(buf, pos + offset + 8)
    })),
    variadic: readVector(buf, get(12, readOffset), 8, readInt64)
  };
}

;// ../../node_modules/@uwdata/flechette/src/decode/dictionary-batch.js



/**
 * Decode a dictionary batch.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @param {import('../types.js').Version_} version Arrow version value
 * @returns {import('../types.js').DictionaryBatch} The dictionary batch
 */
function decodeDictionaryBatch(buf, index, version) {
  //  4: id
  //  6: data
  //  8: isDelta
  const get = readObject(buf, index);
  return {
    id: get(4, readInt64, 0),
    data: get(6, (buf, off) => decodeRecordBatch(buf, off, version)),
    /**
     * If isDelta is true the values in the dictionary are to be appended to a
     * dictionary with the indicated id. If isDelta is false this dictionary
     * should replace the existing dictionary.
     */
    isDelta: get(8, readBoolean, false)
  };
}

;// ../../node_modules/@uwdata/flechette/src/decode/data-type.js





/**
 * Decode a data type definition for a field.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data.
 * @param {number} index The starting index in the byte buffer.
 * @param {number} typeId The data type id.
 * @param {import('../types.js').Field[]} [children] A list of parsed child fields.
 * @returns {import('../types.js').DataType} The data type.
 */
function decodeDataType(buf, index, typeId, children) {
  checkOneOf(typeId, constants_Type, invalidDataType);
  const get = readObject(buf, index);

  switch (typeId) {
    // types without flatbuffer objects
    case constants_Type.Binary: return data_types_binary();
    case constants_Type.Utf8: return utf8();
    case constants_Type.LargeBinary: return largeBinary();
    case constants_Type.LargeUtf8: return largeUtf8();
    case constants_Type.List: return data_types_list(children[0]);
    case constants_Type.ListView: return listView(children[0]);
    case constants_Type.LargeList: return largeList(children[0]);
    case constants_Type.LargeListView: return largeListView(children[0]);
    case constants_Type.Struct: return struct(children);
    case constants_Type.RunEndEncoded: return runEndEncoded(children[0], children[1]);

    // types with flatbuffer objects
    case constants_Type.Int: return data_types_int(
      // @ts-ignore
      get(4, readInt32, 0), // bitwidth
      get(6, readBoolean, false) // signed
    );
    case constants_Type.Float: return data_types_float(
      // @ts-ignore
      get(4, readInt16, constants_Precision.HALF) // precision
    );
    case constants_Type.Decimal: return decimal(
      get(4, readInt32, 0), // precision
      get(6, readInt32, 0), // scale
      // @ts-ignore
      get(8, readInt32, 128) // bitwidth
    );
    case constants_Type.Date: return data_types_date(
      // @ts-ignore
      get(4, readInt16, constants_DateUnit.MILLISECOND) // unit
    );
    case constants_Type.Time: return time(
      // @ts-ignore
      get(4, readInt16, constants_TimeUnit.MILLISECOND), // unit
      get(6, readInt32, 32) // bitWidth
    );
    case constants_Type.Timestamp: return data_types_timestamp(
      // @ts-ignore
      get(4, readInt16, constants_TimeUnit.SECOND), // unit
      get(6, readString) // timezone
    );
    case constants_Type.Interval: return interval(
      // @ts-ignore
      get(4, readInt16, IntervalUnit.YEAR_MONTH) // unit
    );
    case constants_Type.Duration: return duration(
      // @ts-ignore
      get(4, readInt16, constants_TimeUnit.MILLISECOND) // unit
    );

    case constants_Type.FixedSizeBinary: return fixedSizeBinary(
      get(4, readInt32, 0) // stride
    );
    case constants_Type.FixedSizeList: return fixedSizeList(
      children[0],
      get(4, readInt32, 0), // stride
    );
    case constants_Type.Map: return mapType(
      get(4, readBoolean, false), // keysSorted
      children[0]
    );

    case constants_Type.Union: return data_types_union(
      // @ts-ignore
      get(4, readInt16, UnionMode.Sparse), // mode
      children,
      readVector(buf, get(6, readOffset), 4, readInt32) // type ids
    );
  }
  // case Type.NONE:
  // case Type.Null:
  // case Type.Bool:
  // case Type.BinaryView:
  // case Type.Utf8View:
  // @ts-ignore
  return { typeId };
}

;// ../../node_modules/@uwdata/flechette/src/decode/metadata.js


/**
 * Decode custom metadata consisting of key-value string pairs.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @returns {import('../types.js').Metadata | null} The custom metadata map
 */
function decodeMetadata(buf, index) {
  const entries = readVector(buf, index, 4, (buf, pos) => {
    const get = readObject(buf, pos);
    return /** @type {[string, string]} */ ([
      get(4, readString), // 4: key (string)
      get(6, readString)  // 6: key (string)
    ]);
  });
  return entries.length ? new Map(entries) : null;
}

;// ../../node_modules/@uwdata/flechette/src/decode/schema.js






/**
 * Decode a table schema describing the fields and their data types.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @param {import('../types.js').Version_} version Arrow version value
 * @returns {import('../types.js').Schema} The schema
 */
function decodeSchema(buf, index, version) {
  //  4: endianness (int16)
  //  6: fields (vector)
  //  8: metadata (vector)
  // 10: features (int64[])
  const get = readObject(buf, index);
  return {
    version,
    endianness: /** @type {import('../types.js').Endianness_} */ (get(4, readInt16, 0)),
    fields: get(6, decodeSchemaFields, []),
    metadata: get(8, decodeMetadata)
  };
}

/**
 * @returns {import('../types.js').Field[] | null}
 */
function decodeSchemaFields(buf, fieldsOffset) {
  return readVector(buf, fieldsOffset, 4, decodeField);
}

/**
 * @returns {import('../types.js').Field}
 */
function decodeField(buf, index) {
  //  4: name (string)
  //  6: nullable (bool)
  //  8: type id (uint8)
  // 10: type (union)
  // 12: dictionary (table)
  // 14: children (vector)
  // 16: metadata (vector)
  const get = readObject(buf, index);
  const typeId = get(8, readUint8, constants_Type.NONE);
  const typeOffset = get(10, readOffset, 0);
  const dict = get(12, decodeDictionary);
  const children = get(14, (buf, off) => decodeFieldChildren(buf, off));

  let type = decodeDataType(buf, typeOffset, typeId, children);
  if (dict) {
    dict.dictionary = type;
    type = dict;
  }

  return {
    name: get(4, readString),
    type,
    nullable: get(6, readBoolean, false),
    metadata: get(16, decodeMetadata)
  };
}

/**
 * @returns {import('../types.js').Field[] | null}
 */
function decodeFieldChildren(buf, fieldOffset) {
  const children = readVector(buf, fieldOffset, 4, decodeField);
  return children.length ? children : null;
}

/**
 * @param {Uint8Array} buf
 * @param {number} index
 * @returns {import('../types.js').DictionaryType}
 */
function decodeDictionary(buf, index) {
  if (!index) return null;
  //  4: id (int64)
  //  6: indexType (Int type)
  //  8: isOrdered (boolean)
  // 10: kind (int16) currently only dense array is supported
  const get = readObject(buf, index);
  return dictionary(
    null, // data type will be populated by caller
    get(6, decodeInt, int32()), // index type
    get(8, readBoolean, false), // ordered
    get(4, readInt64, 0), // id
  );
}

/**
 * Decode an integer data type.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data.
 * @param {number} index The starting index in the byte buffer.
 * @returns {import('../types.js').IntType}
 */
function decodeInt(buf, index) {
  return /** @type {import('../types.js').IntType} */ (
    decodeDataType(buf, index, constants_Type.Int)
  );
}

;// ../../node_modules/@uwdata/flechette/src/decode/message.js







const invalidMessageMetadata = (expected, actual) =>
  `Expected to read ${expected} metadata bytes, but only read ${actual}.`;

const invalidMessageBodyLength = (expected, actual) =>
  `Expected to read ${expected} bytes for message body, but only read ${actual}.`;

const invalidMessageType = (type) =>
  `Unsupported message type: ${type} (${keyFor(MessageHeader, type)})`;

/**
 * A "message" contains a block of Apache Arrow data, such as a schema,
 * record batch, or dictionary batch. This message decodes a single
 * message, returning its associated metadata and content.
 * @param {Uint8Array} buf A byte buffer of binary Arrow IPC data
 * @param {number} index The starting index in the byte buffer
 * @returns {import('../types.js').Message} The decoded message.
 */
function decodeMessage(buf, index) {
  // get message start
  let metadataLength = readInt32(buf, index) || 0;
  index += SIZEOF_INT;

  // ARROW-6313: If the first 4 bytes are continuation indicator (-1), read
  // the next 4 for the 32-bit metadata length. Otherwise, assume this is a
  // pre-v0.15 message, where the first 4 bytes are the metadata length.
  if (metadataLength === -1) {
    metadataLength = readInt32(buf, index) || 0;
    index += SIZEOF_INT;
  }
  if (metadataLength === 0) return null;

  const head = buf.subarray(index, index += metadataLength);
  if (head.byteLength < metadataLength) {
    throw new Error(invalidMessageMetadata(metadataLength, head.byteLength));
  }

  // decode message metadata
  //  4: version
  //  6: headerType
  //  8: headerIndex
  // 10: bodyLength
  const get = readObject(head, 0);
  const version = /** @type {import('../types.js').Version_} */
    (get(4, readInt16, Version.V1));
  const type = /** @type {import('../types.js').MessageHeader_} */
    (get(6, readUint8, MessageHeader.NONE));
  const offset = get(8, readOffset, 0);
  const bodyLength = get(10, readInt64, 0);
  let content;

  if (offset) {
    // decode message header
    const decoder = type === MessageHeader.Schema ? decodeSchema
      : type === MessageHeader.DictionaryBatch ? decodeDictionaryBatch
      : type === MessageHeader.RecordBatch ? decodeRecordBatch
      : null;
    if (!decoder) throw new Error(invalidMessageType(type));
    content = decoder(head, offset, version);

    // extract message body
    if (bodyLength > 0) {
      const body = buf.subarray(index, index += bodyLength);
      if (body.byteLength < bodyLength) {
        throw new Error(invalidMessageBodyLength(bodyLength, body.byteLength));
      }
      // @ts-ignore
      content.body = body;
    }
  }

  return { version, type, index, content };
}

;// ../../node_modules/@uwdata/flechette/src/decode/decode-ipc.js







/**
 * Decode [Apache Arrow IPC data][1] and return parsed schema, record batch,
 * and dictionary batch definitions. The input binary data may be either
 * an `ArrayBuffer` or `Uint8Array`. For Arrow data in the IPC 'stream' format,
 * an array of `Uint8Array` instances is also supported.
 *
 * This method stops short of generating views over field buffers. Use the
 * `createData()` method on the result to enable column data access.
 *
 * [1]: https://arrow.apache.org/docs/format/Columnar.html#serialization-and-interprocess-communication-ipc
 * @param {ArrayBuffer | Uint8Array | Uint8Array[]} data
 *  The source byte buffer, or an array of buffers. If an array, each byte
 *  array may contain one or more self-contained messages. Messages may NOT
 *  span multiple byte arrays.
 * @returns {import('../types.js').ArrowData}
 */
function decodeIPC(data) {
  const source = data instanceof ArrayBuffer
    ? new Uint8Array(data)
    : data;
  return source instanceof Uint8Array && isArrowFileFormat(source)
    ? decodeIPCFile(source)
    : decodeIPCStream(source);
}

/**
 * @param {Uint8Array} buf
 * @returns {boolean}
 */
function isArrowFileFormat(buf) {
  if (!buf || buf.length < 4) return false;
  for (let i = 0; i < 6; ++i) {
    if (MAGIC[i] !== buf[i]) return false;
  }
  return true;
}

/**
 * Decode data in the [Arrow IPC 'stream' format][1].
 *
 * [1]: https://arrow.apache.org/docs/format/Columnar.html#ipc-streaming-format
 * @param {Uint8Array | Uint8Array[]} data The source byte buffer, or an
 *  array of buffers. If an array, each byte array may contain one or more
 *  self-contained messages. Messages may NOT span multiple byte arrays.
 * @returns {import('../types.js').ArrowData}
 */
function decodeIPCStream(data) {
  const stream = [data].flat();

  let schema;
  const records = [];
  const dictionaries = [];

  // consume each message in the stream
  for (const buf of stream) {
    if (!(buf instanceof Uint8Array)) {
      throw new Error(`IPC data batch was not a Uint8Array.`);
    }
    let offset = 0;

    // decode all messages in current buffer
    while (true) {
      const m = decodeMessage(buf, offset);
      if (m === null) break; // end of messages
      offset = m.index;
      if (!m.content) continue;
      switch (m.type) {
        case MessageHeader.Schema:
          // ignore repeated schema messages
          if (!schema) schema = m.content;
          break;
        case MessageHeader.RecordBatch:
          records.push(m.content);
          break;
        case MessageHeader.DictionaryBatch:
          dictionaries.push(m.content);
          break;
      }
    }
  }

  return /** @type {import('../types.js').ArrowData} */ (
    { schema, dictionaries, records, metadata: null }
  );
}

/**
 * Decode data in the [Arrow IPC 'file' format][1].
 *
 * [1]: https://arrow.apache.org/docs/format/Columnar.html#ipc-file-format
 * @param {Uint8Array} data The source byte buffer.
 * @returns {import('../types.js').ArrowData}
 */
function decodeIPCFile(data) {
  // find footer location
  const offset = data.byteLength - (MAGIC.length + 4);
  const length = readInt32(data, offset);

  // decode file footer
  //  4: version
  //  6: schema
  //  8: dictionaries (vector)
  // 10: batches (vector)
  // 12: metadata
  const get = readObject(data, offset - length);
  const version = /** @type {import('../types.js').Version_} */
    (get(4, readInt16, Version.V1));
  const dicts = get(8, decodeBlocks, []);
  const recs = get(10, decodeBlocks, []);

  return /** @type {import('../types.js').ArrowData} */ ({
    schema: get(6, (buf, index) => decodeSchema(buf, index, version)),
    dictionaries: dicts.map(({ offset }) => decodeMessage(data, offset).content),
    records: recs.map(({ offset }) => decodeMessage(data, offset).content),
    metadata: get(12, decodeMetadata)
  });
}

;// ../../node_modules/@uwdata/flechette/src/decode/table-from-ipc.js








/**
 * Decode [Apache Arrow IPC data][1] and return a new Table. The input binary
 * data may be either an `ArrayBuffer` or `Uint8Array`. For Arrow data in the
 * [IPC 'stream' format][2], an array of `Uint8Array` values is also supported.
 *
 * [1]: https://arrow.apache.org/docs/format/Columnar.html#serialization-and-interprocess-communication-ipc
 * [2]: https://arrow.apache.org/docs/format/Columnar.html#ipc-streaming-format
 * @param {ArrayBuffer | Uint8Array | Uint8Array[]} data
 *  The source byte buffer, or an array of buffers. If an array, each byte
 *  array may contain one or more self-contained messages. Messages may NOT
 *  span multiple byte arrays.
 * @param {import('../types.js').ExtractionOptions} [options]
 *  Options for controlling how values are transformed when extracted
 *  from an Arrow binary representation.
 * @returns {Table} A Table instance.
 */
function tableFromIPC(data, options) {
  return createTable(decodeIPC(data), options);
}

/**
 * Create a table from parsed IPC data.
 * @param {import('../types.js').ArrowData} data
 *  The IPC data, as returned by parseIPC.
 * @param {import('../types.js').ExtractionOptions} [options]
 *  Options for controlling how values are transformed when extracted
 *  from am Arrow binary representation.
 * @returns {Table} A Table instance.
 */
function createTable(data, options = {}) {
  const { schema = { fields: [] }, dictionaries, records } = data;
  const { version, fields } = schema;
  const dictionaryMap = new Map;
  const context = contextGenerator(options, version, dictionaryMap);

  // build dictionary type map
  const dictionaryTypes = new Map;
  visitSchemaFields(schema, field => {
    const type = field.type;
    if (type.typeId === constants_Type.Dictionary) {
      dictionaryTypes.set(type.id, type.dictionary);
    }
  });

  // decode dictionaries, build dictionary column map
  const dicts = new Map;
  for (const dict of dictionaries) {
    const { id, data, isDelta, body } = dict;
    const type = dictionaryTypes.get(id);
    const batch = table_from_ipc_visit(type, context({ ...data, body }));
    if (!dicts.has(id)) {
      if (isDelta) {
        throw new Error('Delta update can not be first dictionary batch.');
      }
      dicts.set(id, columnBuilder(type).add(batch));
    } else {
      const dict = dicts.get(id);
      if (!isDelta) dict.clear();
      dict.add(batch);
    }
  }
  dicts.forEach((value, key) => dictionaryMap.set(key, value.done()));

  // decode column fields
  const cols = fields.map(f => columnBuilder(f.type));
  for (const batch of records) {
    const ctx = context(batch);
    fields.forEach((f, i) => cols[i].add(table_from_ipc_visit(f.type, ctx)));
  }

  return new table_Table(schema, cols.map(c => c.done()), options.useProxy);
}

/**
 * Visit all fields within a schema.
 * @param {import('../types.js').Schema} schema
 * @param {(field: import('../types.js').Field) => void} visitor
 */
function visitSchemaFields(schema, visitor) {
  schema.fields.forEach(function visitField(field) {
    visitor(field);
    // @ts-ignore
    field.type.dictionary?.children?.forEach(visitField);
    // @ts-ignore
    field.type.children?.forEach(visitField);
  });
}

/**
 * Context object generator for field visitation and buffer definition.
 */
function contextGenerator(options, version, dictionaryMap) {
  const base = {
    version,
    options,
    dictionary: id => dictionaryMap.get(id),
  };

  /**
   * Return a context generator.
   * @param {import('../types.js').RecordBatch} batch
   */
  return batch => {
    const { length, nodes, regions, variadic, body } = batch;
    let nodeIndex = -1;
    let bufferIndex = -1;
    let variadicIndex = -1;
    return {
      ...base,
      length,
      node: () => nodes[++nodeIndex],
      buffer: (ArrayType) => {
        const { length, offset } = regions[++bufferIndex];
        return ArrayType
          ? new ArrayType(body.buffer, body.byteOffset + offset, length / ArrayType.BYTES_PER_ELEMENT)
          : body.subarray(offset, offset + length)
      },
      variadic: () => variadic[++variadicIndex],
      visit(children) { return children.map(f => table_from_ipc_visit(f.type, this)); }
    };
  };
}

/**
 * Visit a field, instantiating views of buffer regions.
 */
function table_from_ipc_visit(type, ctx) {
  const { typeId } = type;
  const { length, options, node, buffer, variadic, version } = ctx;
  const BatchType = batchType(type, options);

  if (typeId === constants_Type.Null) {
    // no field node, no buffers
    return new BatchType({ length, nullCount: length, type });
  }

  // extract the next { length, nullCount } field node
  const base = { ...node(), type };

  switch (typeId) {
    // validity and data value buffers
    case constants_Type.Bool:
    case constants_Type.Int:
    case constants_Type.Time:
    case constants_Type.Duration:
    case constants_Type.Float:
    case constants_Type.Decimal:
    case constants_Type.Date:
    case constants_Type.Timestamp:
    case constants_Type.Interval:
    case constants_Type.FixedSizeBinary:
      return new BatchType({
        ...base,
        validity: buffer(),
        values: buffer(type.values)
      });

    // validity, offset, and value buffers
    case constants_Type.Utf8:
    case constants_Type.LargeUtf8:
    case constants_Type.Binary:
    case constants_Type.LargeBinary:
      return new BatchType({
        ...base,
        validity: buffer(),
        offsets: buffer(type.offsets),
        values: buffer()
      });

    // views with variadic buffers
    case constants_Type.BinaryView:
    case constants_Type.Utf8View:
      return new BatchType({
        ...base,
        validity: buffer(),
        values: buffer(), // views buffer
        data: Array.from({ length: variadic() }, () => buffer()) // data buffers
      });

    // validity, offset, and list child
    case constants_Type.List:
    case constants_Type.LargeList:
    case constants_Type.Map:
      return new BatchType({
        ...base,
        validity: buffer(),
        offsets: buffer(type.offsets),
        children: ctx.visit(type.children)
      });

    // validity, offset, size, and list child
    case constants_Type.ListView:
    case constants_Type.LargeListView:
      return new BatchType({
        ...base,
        validity: buffer(),
        offsets: buffer(type.offsets),
        sizes: buffer(type.offsets),
        children: ctx.visit(type.children)
      });

    // validity and children
    case constants_Type.FixedSizeList:
    case constants_Type.Struct:
      return new BatchType({
        ...base,
        validity: buffer(),
        children: ctx.visit(type.children)
      });

    // children only
    case constants_Type.RunEndEncoded:
      return new BatchType({
        ...base,
        children: ctx.visit(type.children)
      });

    // dictionary
    case constants_Type.Dictionary: {
      const { id, indices } = type;
      return new BatchType({
        ...base,
        validity: buffer(),
        values: buffer(indices.values),
      }).setDictionary(ctx.dictionary(id));
    }

    // union
    case constants_Type.Union: {
      if (version < Version.V5) {
        buffer(); // skip unused null bitmap
      }
      return new BatchType({
        ...base,
        typeIds: buffer(int8Array),
        offsets: type.mode === UnionMode.Sparse ? null : buffer(type.offsets),
        children: ctx.visit(type.children)
      });
    }

    // unsupported type
    default:
      throw new Error(invalidDataType(typeId));
  }
}

;// ../../node_modules/@uwdata/flechette/src/encode/builder.js




function writeInt32(buf, index, value) {
  buf[index] = value;
  buf[index + 1] = value >> 8;
  buf[index + 2] = value >> 16;
  buf[index + 3] = value >> 24;
}

const INIT_SIZE = 1024;

/** Flatbuffer binary builder. */
class Builder {
  /**
   * Create a new builder instance.
   * @param {import('./sink.js').Sink} sink The byte consumer.
   */
  constructor(sink) {
    /**
     * Sink that consumes built byte buffers;
     * @type {import('./sink.js').Sink}
     */
    this.sink = sink;
    /**
     * Minimum alignment encountered so far.
     * @type {number}
     */
    this.minalign = 1;
    /**
     * Current byte buffer.
     * @type {Uint8Array}
     */
    this.buf = new Uint8Array(INIT_SIZE);
    /**
     * Remaining space in the current buffer.
     * @type {number}
     */
    this.space = INIT_SIZE;
    /**
     * List of offsets of all vtables. Used to find and
     * reuse tables upon duplicated table field schemas.
     * @type {number[]}
     */
    this.vtables = [];
    /**
     * Total bytes written to sink thus far.
     */
    this.outputBytes = 0;
  }

  /**
   * Returns the flatbuffer offset, relative to the end of the current buffer.
   * @returns {number} Offset relative to the end of the buffer.
   */
  offset() {
    return this.buf.length - this.space;
  }

  /**
   * Write a flatbuffer int8 value at the current buffer position
   * and advance the internal cursor.
   * @param {number} value
   */
  writeInt8(value) {
    this.buf[this.space -= 1] = value;
  }

  /**
   * Write a flatbuffer int16 value at the current buffer position
   * and advance the internal cursor.
   * @param {number} value
   */
  writeInt16(value) {
    this.buf[this.space -= 2] = value;
    this.buf[this.space + 1] = value >> 8;
  }

  /**
   * Write a flatbuffer int32 value at the current buffer position
   * and advance the internal cursor.
   * @param {number} value
   */
  writeInt32(value) {
    writeInt32(this.buf, this.space -= 4, value);
  }

  /**
   * Write a flatbuffer int64 value at the current buffer position
   * and advance the internal cursor.
   * @param {number} value
   */
  writeInt64(value) {
    const v = BigInt(value);
    this.writeInt32(Number(BigInt.asIntN(32, v >> BigInt(32))));
    this.writeInt32(Number(BigInt.asIntN(32, v)));
  }

  /**
   * Add a flatbuffer int8 value, properly aligned,
   * @param value The int8 value to add the buffer.
   */
  addInt8(value) {
    builder_prep(this, 1, 0);
    this.writeInt8(value);
  }

  /**
   * Add a flatbuffer int16 value, properly aligned,
   * @param value The int16 value to add the buffer.
   */
  addInt16(value) {
    builder_prep(this, 2, 0);
    this.writeInt16(value);
  }

  /**
   * Add a flatbuffer int32 value, properly aligned,
   * @param value The int32 value to add the buffer.
   */
  addInt32(value) {
    builder_prep(this, 4, 0);
    this.writeInt32(value);
  }

  /**
   * Add a flatbuffer int64 values, properly aligned.
   * @param value The int64 value to add the buffer.
   */
  addInt64(value) {
    builder_prep(this, 8, 0);
    this.writeInt64(value);
  }

  /**
   * Add a flatbuffer offset, relative to where it will be written.
   * @param {number} offset The offset to add.
   */
  addOffset(offset) {
    builder_prep(this, SIZEOF_INT, 0); // Ensure alignment is already done.
    this.writeInt32(this.offset() - offset + SIZEOF_INT);
  }

  /**
   * Add a flatbuffer object (vtable).
   * @param {number} numFields The maximum number of fields
   *  this object may include.
   * @param {(tableBuilder: ReturnType<objectBuilder>) => void} [addFields]
   *  A callback function that writes all fields using an object builder.
   * @returns {number} The object offset.
   */
  addObject(numFields, addFields) {
    const b = builder_objectBuilder(this, numFields);
    addFields?.(b);
    return b.finish();
  }

  /**
   * Add a flatbuffer vector (list).
   * @template T
   * @param {T[]} items An array of items to write.
   * @param {number} itemSize The size in bytes of a serialized item.
   * @param {number} alignment The desired byte alignment value.
   * @param {(builder: this, item: T) => void} writeItem A callback
   *  function that writes a vector item to this builder.
   * @returns {number} The vector offset.
   */
  addVector(items, itemSize, alignment, writeItem) {
    const n = items?.length;
    if (!n) return 0;
    builder_prep(this, SIZEOF_INT, itemSize * n);
    builder_prep(this, alignment, itemSize * n); // Just in case alignment > int.
    for (let i = n; --i >= 0;) {
      writeItem(this, items[i]);
    }
    this.writeInt32(n);
    return this.offset();
  }

  /**
   * Convenience method for writing a vector of byte buffer offsets.
   * @param {number[]} offsets
   * @returns {number} The vector offset.
   */
  addOffsetVector(offsets) {
    return this.addVector(offsets, 4, 4, (b, off) => b.addOffset(off));
  }

  /**
   * Add a flatbuffer UTF-8 string.
   * @param {string} s The string to encode.
   * @return {number} The string offset.
   */
  addString(s) {
    if (s == null) return 0;
    const utf8 = encodeUtf8(s);
    const n = utf8.length;
    this.addInt8(0); // string null terminator
    builder_prep(this, SIZEOF_INT, n);
    this.buf.set(utf8, this.space -= n);
    this.writeInt32(n);
    return this.offset();
  }

  /**
   * Finish the current flatbuffer by adding a root offset.
   * @param {number} rootOffset The root offset.
   */
  finish(rootOffset) {
    builder_prep(this, this.minalign, SIZEOF_INT);
    this.addOffset(rootOffset);
  }

  /**
   * Flush the current flatbuffer byte buffer content to the sink,
   * and reset the flatbuffer builder state.
   */
  flush() {
    const { buf, sink } = this;
    const bytes = buf.subarray(this.space, buf.length);
    sink.write(bytes);
    this.outputBytes += bytes.byteLength;
    this.minalign = 1;
    this.vtables = [];
    this.buf = new Uint8Array(INIT_SIZE);
    this.space = INIT_SIZE;
  }

  /**
   * Add a byte buffer directly to the builder sink. This method bypasses
   * any unflushed flatbuffer state and leaves it unchanged, writing the
   * buffer to the sink *before* the flatbuffer.
   * The buffer will be padded for 64-bit (8-byte) alignment as needed.
   * @param {Uint8Array} buffer The buffer to add.
   * @returns {number} The total byte count of the buffer and padding.
   */
  addBuffer(buffer) {
    const size = buffer.byteLength;
    if (!size) return 0;
    this.sink.write(buffer);
    this.outputBytes += size;
    const pad = ((size + 7) & ~7) - size;
    this.addPadding(pad);
    return size + pad;
  }

  /**
   * Write padding bytes directly to the builder sink. This method bypasses
   * any unflushed flatbuffer state and leaves it unchanged, writing the
   * padding bytes to the sink *before* the flatbuffer.
   * @param {number} byteCount The number of padding bytes.
   */
  addPadding(byteCount) {
    if (byteCount > 0) {
      this.sink.write(new Uint8Array(byteCount));
      this.outputBytes += byteCount;
    }
  }
}

/**
 * Prepare to write an element of `size` after `additionalBytes` have been
 * written, e.g. if we write a string, we need to align such the int length
 * field is aligned to 4 bytes, and the string data follows it directly. If all
 * we need to do is alignment, `additionalBytes` will be 0.
 * @param {Builder} builder The builder to prep.
 * @param {number} size The size of the new element to write.
 * @param {number} additionalBytes Additional padding size.
 */
function builder_prep(builder, size, additionalBytes) {
  let { buf, space, minalign } = builder;

  // track the biggest thing we've ever aligned to
  if (size > minalign) {
    builder.minalign = size;
  }

  // find alignment needed so that `size` aligns after `additionalBytes`
  const bufSize = buf.length;
  const used = bufSize - space + additionalBytes;
  const alignSize = (~used + 1) & (size - 1);

  // reallocate the buffer if needed
  buf = grow(buf, used + alignSize + size - 1, true);
  space += buf.length - bufSize;

  // add padding
  for (let i = 0; i < alignSize; ++i) {
    buf[--space] = 0;
  }

  // update builder state
  builder.buf = buf;
  builder.space = space;
}

/**
 * Returns a builder object for flatbuffer objects (vtables).
 * @param {Builder} builder The underlying flatbuffer builder.
 * @param {number} numFields The expected number of fields, not
 *  including the standard size fields.
 */
function builder_objectBuilder(builder, numFields) {
  /** @type {number[]} */
  const vtable = Array(numFields).fill(0);
  const startOffset = builder.offset();

  function slot(index) {
    vtable[index] = builder.offset();
  }

  return {
    /**
     * Add an int8-valued table field.
     * @param {number} index
     * @param {number} value
     * @param {number} defaultValue
     */
    addInt8(index, value, defaultValue) {
      if (value != defaultValue) {
        builder.addInt8(value);
        slot(index);
      }
    },

    /**
     * Add an int16-valued table field.
     * @param {number} index
     * @param {number} value
     * @param {number} defaultValue
     */
    addInt16(index, value, defaultValue) {
      if (value != defaultValue) {
        builder.addInt16(value);
        slot(index);
      }
    },

    /**
     * Add an int32-valued table field.
     * @param {number} index
     * @param {number} value
     * @param {number} defaultValue
     */
    addInt32(index, value, defaultValue) {
      if (value != defaultValue) {
        builder.addInt32(value);
        slot(index);
      }
    },

    /**
     * Add an int64-valued table field.
     * @param {number} index
     * @param {number} value
     * @param {number} defaultValue
     */
    addInt64(index, value, defaultValue) {
      if (value != defaultValue) {
        builder.addInt64(value);
        slot(index);
      }
    },

    /**
     * Add a buffer offset-valued table field.
     * @param {number} index
     * @param {number} value
     * @param {number} defaultValue
     */
    addOffset(index, value, defaultValue) {
      if (value != defaultValue) {
        builder.addOffset(value);
        slot(index);
      }
    },

    /**
     * Write the vtable to the buffer and return the table offset.
     * @returns {number} The buffer offset to the vtable.
     */
    finish() {
      // add offset entry, will overwrite later with actual offset
      builder.addInt32(0);
      const vtableOffset = builder.offset();

      // trim zero-valued fields (indicating default value)
      let i = numFields;
      while (--i >= 0 && vtable[i] === 0) {} // eslint-disable-line no-empty
      const size = i + 1;

      // Write out the current vtable.
      for (; i >= 0; --i) {
        // Offset relative to the start of the table.
        builder.addInt16(vtable[i] ? (vtableOffset - vtable[i]) : 0);
      }

      const standardFields = 2; // size fields
      builder.addInt16(vtableOffset - startOffset);
      const len = (size + standardFields) * SIZEOF_SHORT;
      builder.addInt16(len);

      // Search for an existing vtable that matches the current one.
      let existingTable = 0;
      const { buf, vtables, space: vt1 } = builder;
    outer_loop:
      for (i = 0; i < vtables.length; ++i) {
        const vt2 = buf.length - vtables[i];
        if (len == readInt16(buf, vt2)) {
          for (let j = SIZEOF_SHORT; j < len; j += SIZEOF_SHORT) {
            if (readInt16(buf, vt1 + j) != readInt16(buf, vt2 + j)) {
              continue outer_loop;
            }
          }
          existingTable = vtables[i];
          break;
        }
      }

      if (existingTable) {
        // Found a match: remove the current vtable.
        // Point table to existing vtable.
        builder.space = buf.length - vtableOffset;
        writeInt32(buf, builder.space, existingTable - vtableOffset);
      } else {
        // No match: add the location of the current vtable to the vtables list.
        // Point table to current vtable.
        const off = builder.offset();
        vtables.push(off);
        writeInt32(buf, buf.length - vtableOffset, off - vtableOffset);
      }

      return vtableOffset;
    }
  }
}

;// ../../node_modules/@uwdata/flechette/src/encode/record-batch.js
/**
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').RecordBatch} batch
 * @returns {number}
 */
function encodeRecordBatch(builder, batch) {
  const { nodes, regions, variadic } = batch;
  const nodeVector = builder.addVector(nodes, 16, 8,
    (builder, node) => {
      builder.writeInt64(node.nullCount);
      builder.writeInt64(node.length);
      return builder.offset();
    }
  );
  const regionVector = builder.addVector(regions, 16, 8,
    (builder, region) => {
      builder.writeInt64(region.length);
      builder.writeInt64(region.offset);
      return builder.offset();
    }
  );
  const variadicVector = builder.addVector(variadic, 8, 8,
    (builder, count) => builder.addInt64(count)
  );
  return builder.addObject(5, b => {
    b.addInt64(0, nodes[0].length, 0);
    b.addOffset(1, nodeVector, 0);
    b.addOffset(2, regionVector, 0);
    // NOT SUPPORTED: 3, compression offset
    b.addOffset(4, variadicVector, 0);
  });
}

;// ../../node_modules/@uwdata/flechette/src/encode/dictionary-batch.js


/**
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').DictionaryBatch} dictionaryBatch
 * @returns {number}
 */
function encodeDictionaryBatch(builder, dictionaryBatch) {
  const dataOffset = encodeRecordBatch(builder, dictionaryBatch.data);
  return builder.addObject(3, b => {
    b.addInt64(0, dictionaryBatch.id, 0);
    b.addOffset(1, dataOffset, 0);
    b.addInt8(2, +dictionaryBatch.isDelta, 0);
  });
}

;// ../../node_modules/@uwdata/flechette/src/encode/metadata.js
/**
 * @param {import('./builder.js').Builder} builder
 * @param {Map<string, string>} metadata
 * @returns {number}
 */
function encodeMetadata(builder, metadata) {
  return metadata?.size > 0
     ? builder.addOffsetVector(Array.from(metadata, ([k, v]) => {
        const key = builder.addString(`${k}`);
        const val = builder.addString(`${v}`);
        return builder.addObject(2, b => {
          b.addOffset(0, key, 0);
          b.addOffset(1, val, 0);
        });
      }))
    : 0;
}

;// ../../node_modules/@uwdata/flechette/src/encode/data-type.js




/**
 * Encode a data type into a flatbuffer.
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').DataType} type
 * @returns {number} The offset at which the data type is written.
 */
function encodeDataType(builder, type) {
  const typeId = checkOneOf(type.typeId, constants_Type, invalidDataType);

  switch (typeId) {
    case constants_Type.Dictionary:
      return encodeDictionary(builder, type);
    case constants_Type.Int:
      return encodeInt(builder, type);
    case constants_Type.Float:
      return encodeFloat(builder, type);
    case constants_Type.Decimal:
      return encodeDecimal(builder, type);
    case constants_Type.Date:
      return encodeDate(builder, type);
    case constants_Type.Time:
      return encodeTime(builder, type);
    case constants_Type.Timestamp:
      return encodeTimestamp(builder, type);
    case constants_Type.Interval:
      return encodeInterval(builder, type);
    case constants_Type.Duration:
      return encodeDuration(builder, type);
    case constants_Type.FixedSizeBinary:
    case constants_Type.FixedSizeList:
      return encodeFixedSize(builder, type);
    case constants_Type.Map:
      return encodeMap(builder, type);
    case constants_Type.Union:
      return encodeUnion(builder, type);
  }
  // case Type.Null:
  // case Type.Binary:
  // case Type.LargeBinary:
  // case Type.BinaryView:
  // case Type.Bool:
  // case Type.Utf8:
  // case Type.Utf8View:
  // case Type.LargeUtf8:
  // case Type.List:
  // case Type.ListView:
  // case Type.LargeList:
  // case Type.LargeListView:
  // case Type.RunEndEncoded:
  // case Type.Struct:
  return builder.addObject(0);
}

function encodeDate(builder, type) {
  return builder.addObject(1, b => {
    b.addInt16(0, type.unit, constants_DateUnit.MILLISECOND);
  });
}

function encodeDecimal(builder, type) {
  return builder.addObject(3, b => {
    b.addInt32(0, type.precision, 0);
    b.addInt32(1, type.scale, 0);
    b.addInt32(2, type.bitWidth, 128);
  });
}

function encodeDuration(builder, type) {
  return builder.addObject(1, b => {
    b.addInt16(0, type.unit, constants_TimeUnit.MILLISECOND);
  });
}

function encodeFixedSize(builder, type) {
  return builder.addObject(1, b => {
    b.addInt32(0, type.stride, 0);
  });
}

function encodeFloat(builder, type) {
  return builder.addObject(1, b => {
    b.addInt16(0, type.precision, constants_Precision.HALF);
  });
}

function encodeInt(builder, type) {
  return builder.addObject(2, b => {
    b.addInt32(0, type.bitWidth, 0);
    b.addInt8(1, +type.signed, 0);
  });
}

function encodeInterval(builder, type) {
  return builder.addObject(1, b => {
    b.addInt16(0, type.unit, IntervalUnit.YEAR_MONTH);
  });
}

function encodeMap(builder, type) {
  return builder.addObject(1, b => {
    b.addInt8(0, +type.keysSorted, 0);
  });
}

function encodeTime(builder, type) {
  return builder.addObject(2, b => {
    b.addInt16(0, type.unit, constants_TimeUnit.MILLISECOND);
    b.addInt32(1, type.bitWidth, 32);
  });
}

function encodeTimestamp(builder, type) {
  const timezoneOffset = builder.addString(type.timezone);
  return builder.addObject(2, b => {
    b.addInt16(0, type.unit, constants_TimeUnit.SECOND);
    b.addOffset(1, timezoneOffset, 0);
  });
}

function encodeUnion(builder, type) {
  const typeIdsOffset = builder.addVector(
    type.typeIds, 4, 4,
    (builder, value) => builder.addInt32(value)
  );
  return builder.addObject(2, b => {
    b.addInt16(0, type.mode, UnionMode.Sparse);
    b.addOffset(1, typeIdsOffset, 0);
  });
}

function encodeDictionary(builder, type) {
  // The Arrow spec uses signed 32-bit integers as the default index type.
  // However, multiple 3rd party tools fail on a null (default) index type,
  // so we always encode the index data type explicitly here.
  return builder.addObject(4, b => {
    b.addInt64(0, type.id, 0);
    b.addOffset(1, encodeDataType(builder, type.indices), 0);
    b.addInt8(2, +type.ordered, 0);
    // NOT SUPPORTED: 3, dictionaryKind (defaults to dense array)
  });
}

;// ../../node_modules/@uwdata/flechette/src/encode/schema.js




const isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;

/**
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').Schema} schema
 * @returns {number}
 */
function encodeSchema(builder, schema) {
  const { fields, metadata } = schema;
  const fieldOffsets = fields.map(f => encodeField(builder, f));
  const fieldsVectorOffset = builder.addOffsetVector(fieldOffsets);
  const metadataOffset = encodeMetadata(builder, metadata);
  return builder.addObject(4, b => {
    b.addInt16(0, +(!isLittleEndian), 0);
    b.addOffset(1, fieldsVectorOffset, 0);
    b.addOffset(2, metadataOffset, 0);
    // NOT SUPPORTED: 3, features
  });
}

/**
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').Field} field
 * @returns {number}
 */
function encodeField(builder, field) {
  const { name, nullable, type, metadata } = field;
  let { typeId } = type;

  // encode field data type
  let typeOffset = 0;
  let dictionaryOffset = 0;
  if (typeId !== constants_Type.Dictionary) {
    typeOffset = encodeDataType(builder, type);
  } else {
    const dict = /** @type {import('../types.js').DictionaryType} */ (type).dictionary;
    typeId = dict.typeId;
    dictionaryOffset = encodeDataType(builder, type);
    typeOffset = encodeDataType(builder, dict);
  }

  // encode children, metadata, name, and field object
  // @ts-ignore
  const childOffsets = (type.children || []).map(f => encodeField(builder, f));
  const childrenVectorOffset = builder.addOffsetVector(childOffsets);
  const metadataOffset = encodeMetadata(builder, metadata);
  const nameOffset = builder.addString(name);
  return builder.addObject(7, b => {
    b.addOffset(0, nameOffset, 0);
    b.addInt8(1, +nullable, +false);
    b.addInt8(2, typeId, constants_Type.NONE);
    b.addOffset(3, typeOffset, 0);
    b.addOffset(4, dictionaryOffset, 0);
    b.addOffset(5, childrenVectorOffset, 0);
    b.addOffset(6, metadataOffset, 0);
  });
}

;// ../../node_modules/@uwdata/flechette/src/encode/footer.js




/**
 * Write a file footer.
 * @param {import('./builder.js').Builder} builder The binary builder.
 * @param {import('../types.js').Schema} schema The table schema.
 * @param {import('../types.js').Block[]} dictBlocks Dictionary batch file blocks.
 * @param {import('../types.js').Block[]} recordBlocks Record batch file blocks.
 * @param {Map<string,string> | null} metadata File-level metadata.
 */
function writeFooter(builder, schema, dictBlocks, recordBlocks, metadata) {
  // encode footer flatbuffer
  const metadataOffset = encodeMetadata(builder, metadata);
  const recsOffset = builder.addVector(recordBlocks, 24, 8, encodeBlock);
  const dictsOffset = builder.addVector(dictBlocks, 24, 8, encodeBlock);
  const schemaOffset = encodeSchema(builder, schema);
  builder.finish(
    builder.addObject(5, b => {
      b.addInt16(0, Version.V5, Version.V1);
      b.addOffset(1, schemaOffset, 0);
      b.addOffset(2, dictsOffset, 0);
      b.addOffset(3, recsOffset, 0);
      b.addOffset(4, metadataOffset, 0);
    })
  );
  const size = builder.offset();

  // add eos with continuation indicator
  builder.addInt32(0);
  builder.addInt32(-1);

  // write builder contents
  builder.flush();

  // write file tail
  builder.sink.write(new Uint8Array(Int32Array.of(size).buffer));
  builder.sink.write(MAGIC);
}

/**
 * Encode a file pointer block.
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').Block} block
 * @returns {number} the current block offset
 */
function encodeBlock(builder, { offset, metadataLength, bodyLength }) {
  builder.writeInt64(bodyLength);
  builder.writeInt32(0);
  builder.writeInt32(metadataLength);
  builder.writeInt64(offset);
  return builder.offset();
}

;// ../../node_modules/@uwdata/flechette/src/encode/message.js


/**
 * Write an IPC message to the builder sink.
 * @param {import('./builder.js').Builder} builder
 * @param {import('../types.js').MessageHeader_} headerType
 * @param {number} headerOffset
 * @param {number} bodyLength
 * @param {import('../types.js').Block[]} [blocks]
 */
function writeMessage(builder, headerType, headerOffset, bodyLength, blocks) {
  builder.finish(
    builder.addObject(5, b => {
      b.addInt16(0, Version.V5, Version.V1);
      b.addInt8(1, headerType, MessageHeader.NONE);
      b.addOffset(2, headerOffset, 0);
      b.addInt64(3, bodyLength, 0);
      // NOT SUPPORTED: 4, message-level metadata
    })
  );

  const prefixSize = 8; // continuation indicator + message size
  const messageSize = builder.offset();
  const alignedSize = (messageSize + prefixSize + 7) & ~7;

  // track blocks for file footer
  blocks?.push({
    offset: builder.outputBytes,
    metadataLength: alignedSize,
    bodyLength
  });

  // write size prefix (including padding)
  builder.addInt32(alignedSize - prefixSize);

  // write the stream continuation indicator
  builder.addInt32(-1);

  // flush the builder content
  builder.flush();

  // add alignment padding as needed
  builder.addPadding(alignedSize - messageSize - prefixSize);
}

;// ../../node_modules/@uwdata/flechette/src/encode/sink.js
class Sink {
  /**
   * Write bytes to this sink.
   * @param {Uint8Array} bytes The byte buffer to write.
   */
  write(bytes) { // eslint-disable-line no-unused-vars
  }

  /**
   * Write padding bytes (zeroes) to this sink.
   * @param {number} byteCount The number of padding bytes.
   */
  pad(byteCount) {
    this.write(new Uint8Array(byteCount));
  }

  /**
   * @returns {Uint8Array | null}
   */
  finish() {
    return null;
  }
}

class MemorySink extends Sink {
  /**
   * A sink that collects bytes in memory.
   */
  constructor() {
    super();
    this.buffers = [];
  }

  /**
   * Write bytes
   * @param {Uint8Array} bytes
   */
  write(bytes) {
    this.buffers.push(bytes);
  }

  /**
   * @returns {Uint8Array}
   */
  finish() {
    const bufs = this.buffers;
    const size = bufs.reduce((sum, b) => sum + b.byteLength, 0);
    const buf = new Uint8Array(size);
    for (let i = 0, off = 0; i < bufs.length; ++i) {
      buf.set(bufs[i], off);
      off += bufs[i].byteLength;
    }
    return buf;
  }
}

;// ../../node_modules/@uwdata/flechette/src/encode/encode-ipc.js









const STREAM = 'stream';
const FILE = 'file';

/**
 * Encode assembled data into Arrow IPC binary format.
 * @param {any} data Assembled table data.
 * @param {object} options Encoding options.
 * @param {import('./sink.js').Sink} [options.sink] IPC byte consumer.
 * @param {'stream' | 'file'} [options.format] Arrow stream or file format.
 * @returns {import('./sink.js').Sink} The sink that was passed in.
 */
function encodeIPC(data, { sink, format = STREAM } = {}) {
  if (format !== STREAM && format !== FILE) {
    throw new Error(`Unrecognized Arrow IPC format: ${format}`);
  }
  const { schema, dictionaries = [], records = [], metadata } = data;
  const builder = new Builder(sink || new MemorySink());
  const file = format === FILE;
  const dictBlocks = [];
  const recordBlocks = [];

  if (file) {
    builder.addBuffer(MAGIC);
  }

  // both stream and file start with the schema
  if (schema) {
    writeMessage(
      builder,
      MessageHeader.Schema,
      encodeSchema(builder, schema),
      0
    );
  }

  // write dictionary messages
  for (const dict of dictionaries) {
    const { data } = dict;
    writeMessage(
      builder,
      MessageHeader.DictionaryBatch,
      encodeDictionaryBatch(builder, dict),
      data.byteLength,
      dictBlocks
    );
    writeBuffers(builder, data.buffers);
  }

  // write record batch messages
  for (const batch of records) {
    writeMessage(
      builder,
      MessageHeader.RecordBatch,
      encodeRecordBatch(builder, batch),
      batch.byteLength,
      recordBlocks
    );
    writeBuffers(builder, batch.buffers);
  }

  // both stream and file include end-of-stream message
  builder.addBuffer(EOS);

  if (file) {
    writeFooter(builder, schema, dictBlocks, recordBlocks, metadata);
  }

  return builder.sink;
}

/**
 * Write byte buffers to the builder sink.
 * Buffers are aligned to 64 bits (8 bytes) as needed.
 * @param {import('./builder.js').Builder} builder
 * @param {Uint8Array[]} buffers
 */
function writeBuffers(builder, buffers) {
  for (let i = 0; i < buffers.length; ++i) {
    builder.addBuffer(buffers[i]); // handles alignment for us
  }
}

;// ../../node_modules/@uwdata/flechette/src/encode/table-to-ipc.js




/**
 * Encode an Arrow table into Arrow IPC binary format.
 * @param {import('../table.js').Table} table The Arrow table to encode.
 * @param {object} options Encoding options.
 * @param {import('./sink.js').Sink} [options.sink] IPC byte consumer.
 * @param {'stream' | 'file'} [options.format] Arrow stream or file format.
 * @returns {Uint8Array | null} The generated bytes (for an in-memory sink)
 *  or null (if using a sink that writes bytes elsewhere).
 */
function tableToIPC(table, options) {
  // accept a format string option for Arrow-JS compatibility
  if (typeof options === 'string') {
    options = { format: options };
  }

  const columns = table.children;
  checkBatchLengths(columns);

  const { dictionaries, idMap } = assembleDictionaryBatches(columns);
  const records = assembleRecordBatches(columns);
  const schema = assembleSchema(table.schema, idMap);
  const data = { schema, dictionaries, records };
  return encodeIPC(data, options).finish();
}

function checkBatchLengths(columns) {
  const n = columns[0]?.data.map(d => d.length);
  columns.forEach(({ data }) => {
    if (data.length !== n.length || data.some((b, i) => b.length !== n[i])) {
      throw new Error('Columns have inconsistent batch sizes.');
    }
  });
}

/**
 * Create a new assembly context.
 */
function assembleContext() {
  let byteLength = 0;
  const nodes = [];
  const regions = [];
  const buffers = [];
  const variadic = [];
  return {
    /**
     * @param {number} length
     * @param {number} nullCount
     */
    node(length, nullCount) {
      nodes.push({ length, nullCount });
    },
    /**
     * @param {import('../types.js').TypedArray} b
     */
    buffer(b) {
      const size = b.byteLength;
      const length = ((size + 7) & ~7);
      regions.push({ offset: byteLength, length });
      byteLength += length;
      buffers.push(new Uint8Array(b.buffer, b.byteOffset, size));
    },
    /**
     * @param {number} length
     */
    variadic(length) {
      variadic.push(length);
    },
    /**
     * @param {import('../types.js').DataType} type
     * @param {import('../batch.js').Batch} batch
     */
    children(type, batch) {
      // @ts-ignore
      type.children.forEach((field, index) => {
        table_to_ipc_visit(field.type, batch.children[index], this);
      });
    },
    /**
     * @returns {import('../types.js').RecordBatch}
     */
    done() {
      return { byteLength, nodes, regions, variadic, buffers };
    }
  };
}

/**
 * Assemble dictionary batches and their unique ids.
 * @param {import('../column.js').Column[]} columns The table columns.
 * @returns {{
 *    dictionaries: import('../types.js').DictionaryBatch[],
 *    idMap: Map<import('../types.js').DataType, number>
 *  }}
 *  The assembled dictionary batches and a map from dictionary column
 *  instances to dictionary ids.
 */
function assembleDictionaryBatches(columns) {
  const dictionaries = [];
  const dictMap = new Map;
  const idMap = new Map;
  let id = -1;

  // track dictionaries, key by dictionary column, assign ids
  const visitor = dictionaryColumn => {
    if (!dictMap.has(dictionaryColumn)) {
      dictMap.set(dictionaryColumn, ++id);
      for (let i = 0; i < dictionaryColumn.data.length; ++i) {
        dictionaries.push({
          id,
          isDelta: i > 0,
          data: assembleRecordBatch([dictionaryColumn], i)
        });
      }
      idMap.set(dictionaryColumn.type, id);
    } else {
      idMap.set(dictionaryColumn.type, dictMap.get(dictionaryColumn));
    }
  };

  // recurse through column batches to find dictionaries
  // it is sufficient to visit the first batch only,
  // as all batches have the same dictionary column
  columns.forEach(col => visitDictionaries(col.data[0], visitor));

  return { dictionaries, idMap };
}

/**
 * Traverse column batches to visit dictionary columns.
 * @param {import('../batch.js').Batch} batch
 * @param {(column: import('../column.js').Column) => void} visitor
 */
function visitDictionaries(batch, visitor) {
  if (batch?.type.typeId === constants_Type.Dictionary) {
    // @ts-ignore - batch has type DictionaryBatch
    const dictionary = batch.dictionary;
    visitor(dictionary);
    visitDictionaries(dictionary.data[0], visitor);
  }
  batch?.children?.forEach(child => visitDictionaries(child, visitor));
}

/**
 * Assemble a schema with resolved dictionary ids.
 * @param {import('../types.js').Schema} schema The schema.
 * @param {Map<import('../types.js').DataType, number>} idMap A map
 *  from dictionary value types to dictionary ids.
 * @returns {import('../types.js').Schema} A new schema with resolved
 *  dictionary ids. If there are no dictionaries, the input schema is
 *  returned unchanged.
 */
function assembleSchema(schema, idMap) {
  // early exit if no dictionaries
  if (!idMap.size) return schema;

  const visit = type => {
    if (type.typeId === constants_Type.Dictionary) {
      type.id = idMap.get(type.dictionary); // lookup and set id
      visitDictType(type);
    }
    if (type.children) {
      (type.children = type.children.slice()).forEach(visitFields);
    }
  };

  // visit a field in a field array
  const visitFields = (field, index, array) => {
    const type = { ...field.type };
    array[index] = { ...field, type };
    visit(type);
  };

  // visit a dictionary values type
  const visitDictType = (parentType) => {
    const type = { ...parentType.dictionary };
    parentType.dictionary = type;
    visit(type);
  };

  schema = { ...schema, fields: schema.fields.slice() };
  schema.fields.forEach(visitFields);
  return schema;
}

/**
 * Assemble record batches with marshalled buffers.
 * @param {import('../column.js').Column[]} columns The table columns.
 * @returns {import('../types.js').RecordBatch[]} The assembled record batches.
 */
function assembleRecordBatches(columns) {
  return (columns[0]?.data || [])
    .map((_, index) => assembleRecordBatch(columns, index));
}

/**
 * Assemble a record batch with marshalled buffers.
 * @param {import('../column.js').Column[]} columns The table columns.
 * @param {number} batchIndex The batch index.
 * @returns {import('../types.js').RecordBatch} The assembled record batch.
 */
function assembleRecordBatch(columns, batchIndex = 0) {
  const ctx = assembleContext();
  columns.forEach(column => {
    table_to_ipc_visit(column.type, column.data[batchIndex], ctx);
  });
  return ctx.done();
}

/**
 * Visit a column batch, assembling buffer data.
 * @param {import('../types.js').DataType} type The data type.
 * @param {import('../batch.js').Batch} batch The column batch.
 * @param {ReturnType<assembleContext>} ctx The assembly context.
 */
function table_to_ipc_visit(type, batch, ctx) {
  const { typeId } = type;

  // no field node, no buffers
  if (typeId === constants_Type.Null) return;

  // record field node info
  ctx.node(batch.length, batch.nullCount);

  switch (typeId) {
    // validity and value buffers
    // backing dictionaries handled elsewhere
    case constants_Type.Bool:
    case constants_Type.Int:
    case constants_Type.Time:
    case constants_Type.Duration:
    case constants_Type.Float:
    case constants_Type.Date:
    case constants_Type.Timestamp:
    case constants_Type.Decimal:
    case constants_Type.Interval:
    case constants_Type.FixedSizeBinary:
    case constants_Type.Dictionary: // dict key values
      ctx.buffer(batch.validity);
      ctx.buffer(batch.values);
      return;

    // validity, offset, and value buffers
    case constants_Type.Utf8:
    case constants_Type.LargeUtf8:
    case constants_Type.Binary:
    case constants_Type.LargeBinary:
      ctx.buffer(batch.validity);
      ctx.buffer(batch.offsets);
      ctx.buffer(batch.values);
      return;

    // views with variadic buffers
    case constants_Type.BinaryView:
    case constants_Type.Utf8View:
      ctx.buffer(batch.validity);
      ctx.buffer(batch.values);
      // @ts-ignore
      ctx.variadic(batch.data.length);
      // @ts-ignore
      batch.data.forEach(b => ctx.buffer(b));
      return;

    // validity, offset, and list child
    case constants_Type.List:
    case constants_Type.LargeList:
    case constants_Type.Map:
      ctx.buffer(batch.validity);
      ctx.buffer(batch.offsets);
      ctx.children(type, batch);
      return;

    // validity, offset, size, and list child
    case constants_Type.ListView:
    case constants_Type.LargeListView:
      ctx.buffer(batch.validity);
      ctx.buffer(batch.offsets);
      ctx.buffer(batch.sizes);
      ctx.children(type, batch);
      return;

    // validity and children
    case constants_Type.FixedSizeList:
    case constants_Type.Struct:
      ctx.buffer(batch.validity);
      ctx.children(type, batch);
      return;

    // children only
    case constants_Type.RunEndEncoded:
      ctx.children(type, batch);
      return;

    // union
    case constants_Type.Union: {
      // @ts-ignore
      ctx.buffer(batch.typeIds);
      if (type.mode === UnionMode.Dense) {
        ctx.buffer(batch.offsets);
      }
      ctx.children(type, batch);
      return;
    }

    // unsupported type
    default:
      throw new Error(invalidDataType(typeId));
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/buffer.js


/**
 * Create a new resizable buffer instance.
 * @param {import('../types.js').TypedArrayConstructor} [arrayType]
 *  The array type.
 * @returns {Buffer} The buffer.
 */
function buffer(arrayType) {
  return new buffer_Buffer(arrayType);
}

/**
 * Resizable byte buffer.
 */
class buffer_Buffer {
  /**
   * Create a new resizable buffer instance.
   * @param {import('../types.js').TypedArrayConstructor} arrayType
   */
  constructor(arrayType = uint8Array) {
    this.buf = new arrayType(512);
  }
  /**
   * Return the underlying data as a 64-bit aligned array of minimum size.
   * @param {number} size The desired minimum array size.
   * @returns {import('../types.js').TypedArray} The 64-bit aligned array.
   */
  array(size) {
    return align(this.buf, size);
  }
  /**
   * Prepare for writes to the given index, resizing as necessary.
   * @param {number} index The array index to prepare to write to.
   */
  prep(index) {
    if (index >= this.buf.length) {
      this.buf = grow(this.buf, index);
    }
  }
  /**
   * Return the value at the given index.
   * @param {number} index The array index.
   */
  get(index) {
    return this.buf[index];
  }
  /**
   * Set a value at the given index.
   * @param {number | bigint} value The value to set.
   * @param {number} index The index to write to.
   */
  set(value, index) {
    this.prep(index);
    this.buf[index] = value;
  }
  /**
   * Write a byte array at the given index. The method should be called
   * only when the underlying buffer is of type Uint8Array.
   * @param {Uint8Array} bytes The byte array.
   * @param {number} index The starting index to write to.
   */
  write(bytes, index) {
    this.prep(index + bytes.length);
    /** @type {Uint8Array} */ (this.buf).set(bytes, index);
  }
}

/**
 * Create a new resizable bitmap instance.
 * @returns {Bitmap} The bitmap buffer.
 */
function bitmap() {
  return new Bitmap();
}

/**
 * Resizable bitmap buffer.
 */
class Bitmap extends buffer_Buffer {
  /**
   * Set a bit to true at the given bitmap index.
   * @param {number} index The index to write to.
   */
  set(index) {
    const i = index >> 3;
    this.prep(i);
    /** @type {Uint8Array} */ (this.buf)[i] |= (1 << (index % 8));
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/batch.js
/**
 * Abstract class for building a column data batch.
 */
class BatchBuilder {
  constructor(type, ctx) {
    this.type = type;
    this.ctx = ctx;
    this.batchClass = ctx.batchType(type);
  }

  /**
   * Initialize the builder state.
   * @returns {this} This builder.
   */
  init() {
    this.index = -1;
    return this;
  }

  /**
   * Write a value to the builder.
   * @param {*} value
   * @param {number} index
   * @returns {boolean | void}
   */
  set(value, index) {
    this.index = index;
    return false;
  }

  /**
   * Returns a batch constructor options object.
   * Used internally to marshal batch data.
   * @returns {Record<string, any>}
   */
  done() {
    return null;
  }

  /**
   * Returns a completed batch and reinitializes the builder state.
   * @returns {import('../../batch.js').Batch}
   */
  batch() {
    const b = new this.batchClass(this.done());
    this.init();
    return b;
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/validity.js




/**
 * Builder for validity bitmaps within batches.
 */
class ValidityBuilder extends BatchBuilder {
  constructor(type, ctx) {
    super(type, ctx);
  }

  init() {
    this.nullCount = 0;
    this.validity = bitmap();
    return super.init();
  }

  /**
   * @param {*} value
   * @param {number} index
   * @returns {boolean | void}
   */
  set(value, index) {
    this.index = index;
    const isValid = value != null;
    if (isValid) {
      this.validity.set(index);
    } else {
      this.nullCount++;
    }
    return isValid;
  }

  done() {
    const { index, nullCount, type, validity } = this;
    return {
      length: index + 1,
      nullCount,
      type,
      validity: nullCount
        ? validity.array((index >> 3) + 1)
        : new uint8Array(0)
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/dictionary.js






/**
 * Create a context object for managing dictionary builders.
 */
function dictionary_dictionaryContext() {
  const idMap = new Map;
  const dicts = new Set;
  return {
    /**
     * Get a dictionary values builder for the given dictionary type.
     * @param {import('../../types.js').DictionaryType} type
     *  The dictionary type.
     * @param {*} ctx The builder context.
     * @returns {ReturnType<dictionaryValues>}
     */
    get(type, ctx) {
      // if a dictionary has a non-negative id, assume it was set
      // intentionally and track it for potential reuse across columns
      // otherwise the dictionary is used for a single column only
      const id = type.id;
      if (id >= 0 && idMap.has(id)) {
        return idMap.get(id);
      } else {
        const dict = dictionaryValues(type, ctx);
        if (id >= 0) idMap.set(id, dict);
        dicts.add(dict);
        return dict;
      }
    },
    /**
     * Finish building dictionary values columns and assign them to
     * their corresponding dictionary batches.
     * @param {import('../../types.js').ExtractionOptions} options
     */
    finish(options) {
      dicts.forEach(dict => dict.finish(options));
    }
  };
}

/**
 * Builder helper for creating dictionary values.
 * @param {import('../../types.js').DictionaryType} type
 *  The dictionary data type.
 * @param {ReturnType<import('../builder.js').builderContext>} ctx
 *  The builder context.
 */
function dictionaryValues(type, ctx) {
  const keys = Object.create(null);
  const values = ctx.builder(type.dictionary);
  const batches = [];

  values.init();
  let index = -1;

  return {
    type,
    values,

    add(batch) {
      batches.push(batch);
      return batch;
    },

    key(value) {
      const v = keyString(value);
      let k = keys[v];
      if (k === undefined) {
        keys[v] = k = ++index;
        values.set(value, k);
      }
      return k;
    },

    finish(options) {
      const valueType = type.dictionary;
      const batch = new (batchType(valueType, options))(values.done());
      const dictionary = new column_Column([batch]);
      batches.forEach(batch => batch.setDictionary(dictionary));
    }
  };
}

/**
 * Builder for dictionary-typed data batches.
 */
class DictionaryBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.dict = ctx.dictionary(type);
  }

  init() {
    this.values = buffer(this.type.indices.values);
    return super.init();
  }

  set(value, index) {
    if (super.set(value, index)) {
      this.values.set(this.dict.key(value), index);
    }
  }

  done() {
    return {
      ...super.done(),
      values: this.values.array(this.index + 1)
    };
  }

  batch() {
    // register batch with dictionary
    // batch will be updated when the dictionary is finished
    return this.dict.add(super.batch());
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/infer-type.js



/**
 * Infer the data type for a given input array.
 * @param {(visitor: (value: any) => void) => void} visit
 *  A function that applies a callback to successive data values.
 * @returns {import('../types.js').DataType} The data type.
 */
function inferType(visit) {
  const profile = profiler();
  visit(value => profile.add(value));
  return profile.type();
}

function profiler() {
  let length = 0;
  let nullCount = 0;
  let boolCount = 0;
  let numberCount = 0;
  let intCount = 0;
  let bigintCount = 0;
  let dateCount = 0;
  let dayCount = 0;
  let stringCount = 0;
  let arrayCount = 0;
  let structCount = 0;
  let min = Infinity;
  let max = -Infinity;
  let minLength = Infinity;
  let maxLength = -Infinity;
  let minBigInt;
  let maxBigInt;
  let arrayProfile;
  let structProfiles = {};

  return {
    add(value) {
      length++;
      if (value == null) {
        nullCount++;
        return;
      }
      switch (typeof value) {
        case 'string':
          stringCount++;
          break;
        case 'number':
          numberCount++;
          if (value < min) min = value;
          if (value > max) max = value;
          if (Number.isInteger(value)) intCount++;
          break;
        case 'bigint':
          bigintCount++;
          if (minBigInt === undefined) {
            minBigInt = maxBigInt = value;
          } else {
            if (value < minBigInt) minBigInt = value;
            if (value > maxBigInt) maxBigInt = value;
          }
          break;
        case 'boolean':
          boolCount++;
          break;
        case 'object':
          if (value instanceof Date) {
            dateCount++;
            // 1 day = 1000ms * 60s * 60min * 24hr = 86400000
            if ((+value % 864e5) === 0) dayCount++;
          } else if (arrays_isArray(value)) {
            arrayCount++;
            const len = value.length;
            if (len < minLength) minLength = len;
            if (len > maxLength) maxLength = len;
            arrayProfile ??= profiler();
            value.forEach(arrayProfile.add);
          } else {
            structCount++;
            for (const key in value) {
              const fieldProfiler = structProfiles[key]
                ?? (structProfiles[key] = profiler());
              fieldProfiler.add(value[key]);
            }
          }
      }
    },
    type() {
      const valid = length - nullCount;
      return valid === 0 ? nullType()
        : intCount === valid ? intType(min, max)
        : numberCount === valid ? float64()
        : bigintCount === valid ? bigintType(minBigInt, maxBigInt)
        : boolCount === valid ? bool()
        : dayCount === valid ? dateDay()
        : dateCount === valid ? data_types_timestamp()
        : stringCount === valid ? dictionary(utf8())
        : arrayCount === valid ? infer_type_arrayType(arrayProfile.type(), minLength, maxLength)
        : structCount === valid ? struct(
            Object.entries(structProfiles).map(_ => data_types_field(_[0], _[1].type()))
          )
        : unionType();
    }
  };
}

/**
 * Return a list or fixed list type.
 * @param {import('../types.js').DataType} type The child data type.
 * @param {number} minLength The minumum list length.
 * @param {number} maxLength The maximum list length.
 * @returns {import('../types.js').DataType} The data type.
 */
function infer_type_arrayType(type, minLength, maxLength) {
  return maxLength === minLength
    ? fixedSizeList(type, minLength)
    : data_types_list(type);
}

/**
 * @param {number} min
 * @param {number} max
 * @returns {import('../types.js').DataType}
 */
function intType(min, max) {
  const v = Math.max(Math.abs(min) - 1, max);
  return v < (1 << 7) ? int8()
    : v < (1 << 15) ? int16()
    : v < (2 ** 31) ? int32()
    : float64();
}

/**
 * @param {bigint} min
 * @param {bigint} max
 * @returns {import('../types.js').IntType}
 */
function bigintType(min, max) {
  const v = -min > max ? -min - 1n : max;
  if (v >= 2 ** 63) {
    throw new Error(`BigInt exceeds 64 bits: ${v}`);
  }
  return int64();
}

/**
 * @returns {import('../types.js').UnionType}
 */
function unionType() {
  throw new Error('Mixed types detected, please define a union type.');
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/binary.js




/**
 * Builder for batches of binary-typed data.
 */
class BinaryBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.toOffset = toOffset(type.offsets);
  }

  init() {
    this.offsets = buffer(this.type.offsets);
    this.values = buffer();
    this.pos = 0;
    return super.init();
  }

  set(value, index) {
    const { offsets, values, toOffset } = this;
    if (super.set(value, index)) {
      values.write(value, this.pos);
      this.pos += value.length;
    }
    offsets.set(toOffset(this.pos), index + 1);
  }

  done() {
    return {
      ...super.done(),
      offsets: this.offsets.array(this.index + 2),
      values: this.values.array(this.pos + 1)
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/bool.js



/**
 * Builder for batches of bool-typed data.
 */
class BoolBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
  }

  init() {
    this.values = bitmap();
    return super.init();
  }

  set(value, index) {
    super.set(value, index);
    if (value) this.values.set(index);
  }

  done() {
    return {
      ...super.done(),
      values: this.values.array((this.index >> 3) + 1)
    }
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/decimal.js




/**
 * Builder for batches of decimal-typed data (64-bits or more).
 */
class DecimalBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.scale = 10 ** type.scale;
    this.stride = type.bitWidth >> 6;
  }

  init() {
    this.values = buffer(this.type.values);
    return super.init();
  }

  set(value, index) {
    const { scale, stride, values } = this;
    if (super.set(value, index)) {
      values.prep((index + 1) * stride);
      // @ts-ignore
      toDecimal(value, values.buf, index * stride, stride, scale);
    }
  }

  done() {
    const { index, stride, values } = this;
    return {
      ...super.done(),
      values: values.array((index + 1) * stride)
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/fixed-size-binary.js



/**
 * Builder for fixed-size-binary-typed data batches.
 */
class FixedSizeBinaryBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.stride = type.stride;
  }

  init() {
    this.values = buffer();
    return super.init();
  }

  set(value, index) {
    if (super.set(value, index)) {
      this.values.write(value, index * this.stride);
    }
  }

  done() {
    const { stride, values } = this;
    return {
      ...super.done(),
      values: values.array(stride * (this.index + 1))
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/fixed-size-list.js


/**
 * Builder for fixed-size-list-typed data batches.
 */
class FixedSizeListBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.child = ctx.builder(this.type.children[0].type);
    this.stride = type.stride;
  }

  init() {
    this.child.init();
    return super.init();
  }

  set(value, index) {
    const { child, stride } = this;
    const base = index * stride;
    if (super.set(value, index)) {
      for (let i = 0; i < stride; ++i) {
        child.set(value[i], base + i);
      }
    } else {
      child.index = base + stride;
    }
  }

  done() {
    const { child } = this;
    return {
      ...super.done(),
      children: [ child.batch() ]
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/interval.js




/**
 * Builder for day/time interval-typed data batches.
 */
class IntervalDayTimeBuilder extends ValidityBuilder {
  init() {
    this.values = buffer(this.type.values);
    return super.init();
  }

  set(value, index) {
    if (super.set(value, index)) {
      const i = index << 1;
      this.values.set(value[0], i);
      this.values.set(value[1], i + 1);
    }
  }

  done() {
    return {
      ...super.done(),
      values: this.values.array((this.index + 1) << 1)
    }
  }
}

/**
 * Builder for month/day/nano interval-typed data batches.
 */
class IntervalMonthDayNanoBuilder extends ValidityBuilder {
  init() {
    this.values = buffer();
    return super.init();
  }

  set(value, index) {
    if (super.set(value, index)) {
      this.values.write(toMonthDayNanoBytes(value), index << 4);
    }
  }

  done() {
    return {
      ...super.done(),
      values: this.values.array((this.index + 1) << 4)
    }
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/list.js




/**
 * Abstract class for building list data batches.
 */
class AbstractListBuilder extends ValidityBuilder {
  constructor(type, ctx, child) {
    super(type, ctx);
    this.child = child;
  }

  init() {
    this.child.init();
    const offsetType = this.type.offsets;
    this.offsets = buffer(offsetType);
    this.toOffset = toOffset(offsetType);
    this.pos = 0;
    return super.init();
  }

  done() {
    return {
      ...super.done(),
      offsets: this.offsets.array(this.index + 2),
      children: [ this.child.batch() ]
    };
  }
}

/**
 * Builder for list-typed data batches.
 */
class ListBuilder extends AbstractListBuilder {
  constructor(type, ctx) {
    super(type, ctx, ctx.builder(type.children[0].type));
  }

  set(value, index) {
    const { child, offsets, toOffset } = this;
    if (super.set(value, index)) {
      value.forEach(v => child.set(v, this.pos++));
    }
    offsets.set(toOffset(this.pos), index + 1);
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/struct.js


/**
 * Abstract class for building list-typed data batches.
 */
class AbstractStructBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.children = type.children.map(c => ctx.builder(c.type));
  }

  init() {
    this.children.forEach(c => c.init());
    return super.init();
  }

  done() {
    const { children } = this;
    children.forEach(c => c.index = this.index);
    return {
      ...super.done(),
      children: children.map(c => c.batch())
    };
  }
}

/**
 * Builder for struct-typed data batches.
 */
class StructBuilder extends AbstractStructBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.setters = this.children.map((child, i) => {
      const name = type.children[i].name;
      return (value, index) => child.set(value?.[name], index);
    });
  }

  set(value, index) {
    super.set(value, index);
    const setters = this.setters;
    for (let i = 0; i < setters.length; ++i) {
      setters[i](value, index);
    }
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/map.js



/**
 * Builder for map-typed data batches.
 */
class MapBuilder extends AbstractListBuilder {
  constructor(type, ctx) {
    super(type, ctx, new MapStructBuilder(type.children[0].type, ctx));
  }

  set(value, index) {
    const { child, offsets, toOffset } = this;
    if (super.set(value, index)) {
      for (const keyValuePair of value) {
        child.set(keyValuePair, this.pos++);
      }
    }
    offsets.set(toOffset(this.pos), index + 1);
  }
}

/**
 * Builder for key-value struct batches within a map.
 */
class MapStructBuilder extends AbstractStructBuilder {
  set(value, index) {
    super.set(value, index);
    const [key, val] = this.children;
    key.set(value[0], index);
    val.set(value[1], index);
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/run-end-encoded.js



const NO_VALUE = {}; // empty object that fails strict equality

/**
 * Builder for run-end-encoded-typed data batches.
 */
class RunEndEncodedBuilder extends BatchBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.children = type.children.map(c => ctx.builder(c.type));
  }

  init() {
    this.pos = 0;
    this.key = null;
    this.value = NO_VALUE;
    this.children.forEach(c => c.init());
    return super.init();
  }

  next() {
    const [runs, vals] = this.children;
    runs.set(this.index + 1, this.pos);
    vals.set(this.value, this.pos++);
  }

  set(value, index) {
    // perform fast strict equality test
    if (value !== this.value) {
      // if no match, fallback to key string test
      const key = keyString(value);
      if (key !== this.key) {
        // if key doesn't match, write prior run and update
        if (this.key) this.next();
        this.key = key;
        this.value = value;
      }
    }
    this.index = index;
  }

  done() {
    this.next();
    const { children, index, type } = this;
    return {
      length: index + 1,
      nullCount: 0,
      type,
      children: children.map(c => c.batch())
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/union.js




/**
 * Abstract class for building union-typed data batches.
 */
class AbstractUnionBuilder extends BatchBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.children = type.children.map(c => ctx.builder(c.type));
    this.typeMap = type.typeMap;
    this.lookup = type.typeIdForValue;
  }

  init() {
    this.nullCount = 0;
    this.typeIds = buffer(int8Array);
    this.children.forEach(c => c.init());
    return super.init();
  }

  set(value, index) {
    const { children, lookup, typeMap, typeIds } = this;
    this.index = index;
    const typeId = lookup(value, index);
    const child = children[typeMap[typeId]];
    typeIds.set(typeId, index);
    if (value == null) ++this.nullCount;
    // @ts-ignore
    this.update(value, index, child);
  }

  done() {
    const { children, nullCount, type, typeIds } = this;
    const length = this.index + 1;
    return {
      length,
      nullCount,
      type,
      typeIds: typeIds.array(length),
      children: children.map(c => c.batch())
    };
  }
}

/**
 * Builder for sparse union-typed data batches.
 */
class SparseUnionBuilder extends AbstractUnionBuilder {
  update(value, index, child) {
    // update selected child with value
    // then set all other children to null
    child.set(value, index);
    this.children.forEach(c => { if (c !== child) c.set(null, index) });
  }
}

/**
 * Builder for dense union-typed data batches.
 */
class DenseUnionBuilder extends AbstractUnionBuilder {
  init() {
    this.offsets = buffer(this.type.offsets);
    return super.init();
  }

  update(value, index, child) {
    const offset = child.index + 1;
    child.set(value, offset);
    this.offsets.set(offset, index);
  }

  done() {
    return {
      ...super.done(),
      offsets: this.offsets.array(this.index + 1)
    };
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/utf8.js



/**
 * Builder for utf8-typed data batches.
 */
class Utf8Builder extends BinaryBuilder {
  set(value, index) {
    super.set(value && encodeUtf8(value), index);
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builders/values.js




/**
 * Builder for data batches that can be accessed directly as typed arrays.
 */
class DirectBuilder extends ValidityBuilder {
  constructor(type, ctx) {
    super(type, ctx);
    this.values = buffer(type.values);
  }

  init() {
    this.values = buffer(this.type.values);
    return super.init();
  }

  /**
   * @param {*} value
   * @param {number} index
   * @returns {boolean | void}
   */
  set(value, index) {
    if (super.set(value, index)) {
      this.values.set(value, index);
    }
  }

  done() {
    return {
      ...super.done(),
      values: this.values.array(this.index + 1)
    };
  }
}

/**
 * Builder for int64/uint64 data batches written as bigints.
 */
class Int64Builder extends DirectBuilder {
  set(value, index) {
    super.set(value == null ? value : toBigInt(value), index);
  }
}

/**
 * Builder for data batches whose values must pass through a transform
 * function prior to be written to a backing buffer.
 */
class TransformBuilder extends DirectBuilder {
  constructor(type, ctx, transform) {
    super(type, ctx);
    this.transform = transform;
  }
  set(value, index) {
    super.set(value == null ? value : this.transform(value), index);
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/builder.js




















/**
 * Create a context object for shared builder state.
 * @param {import('../types.js').ExtractionOptions} [options]
 *  Batch extraction options.
* @param {ReturnType<dictionaryContext>} [dictionaries]
 *  Context object for tracking dictionaries.
 */
function builderContext(
  options = {},
  dictionaries = dictionary_dictionaryContext()
) {
  return {
    batchType: type => batchType(type, options),
    builder(type) { return builder(type, this); },
    dictionary(type) { return dictionaries.get(type, this); },
    finish: () => dictionaries.finish(options)
  };
}

/**
 * Returns a batch builder for the given type and builder context.
 * @param {import('../types.js').DataType} type A data type.
 * @param {ReturnType<builderContext>} [ctx] A builder context.
 * @returns {import('./builders/batch.js').BatchBuilder}
 */
function builder(type, ctx = builderContext()) {
  const { typeId } = type;
  switch (typeId) {
    case constants_Type.Int:
    case constants_Type.Time:
    case constants_Type.Duration:
      return isInt64ArrayType(type.values)
        ? new Int64Builder(type, ctx)
        : new DirectBuilder(type, ctx);
    case constants_Type.Float:
      return type.precision
        ? new DirectBuilder(type, ctx)
        : new TransformBuilder(type, ctx, toFloat16)
    case constants_Type.Binary:
    case constants_Type.LargeBinary:
      return new BinaryBuilder(type, ctx);
    case constants_Type.Utf8:
    case constants_Type.LargeUtf8:
      return new Utf8Builder(type, ctx);
    case constants_Type.Bool:
      return new BoolBuilder(type, ctx);
    case constants_Type.Decimal:
      return type.bitWidth === 32
        ? new TransformBuilder(type, ctx, toDecimal32(type.scale))
        : new DecimalBuilder(type, ctx);
    case constants_Type.Date:
      return new TransformBuilder(type, ctx, type.unit ? toBigInt : toDateDay);
    case constants_Type.Timestamp:
      return new TransformBuilder(type, ctx, toTimestamp(type.unit));
    case constants_Type.Interval:
      switch (type.unit) {
        case IntervalUnit.DAY_TIME:
          return new IntervalDayTimeBuilder(type, ctx);
        case IntervalUnit.MONTH_DAY_NANO:
          return new IntervalMonthDayNanoBuilder(type, ctx);
      }
      // case IntervalUnit.YEAR_MONTH:
      return new DirectBuilder(type, ctx);
    case constants_Type.List:
    case constants_Type.LargeList:
      return new ListBuilder(type, ctx);
    case constants_Type.Struct:
      return new StructBuilder(type, ctx);
    case constants_Type.Union:
      return type.mode
        ? new DenseUnionBuilder(type, ctx)
        : new SparseUnionBuilder(type, ctx);
    case constants_Type.FixedSizeBinary:
      return new FixedSizeBinaryBuilder(type, ctx);
    case constants_Type.FixedSizeList:
      return new FixedSizeListBuilder(type, ctx);
    case constants_Type.Map:
      return new MapBuilder(type, ctx);
    case constants_Type.RunEndEncoded:
      return new RunEndEncodedBuilder(type, ctx);

    case constants_Type.Dictionary:
      return new DictionaryBuilder(type, ctx);
  }
  // case Type.BinaryView:
  // case Type.Utf8View:
  // case Type.ListView:
  // case Type.LargeListView:
  throw new Error(invalidDataType(typeId));
}

;// ../../node_modules/@uwdata/flechette/src/build/column-from-values.js







/**
 * Create a new column by iterating over provided values.
 * @template T
 * @param {Iterable | ((callback: (value: any) => void) => void)} values
 *  Either an iterable object or a visitor function that applies a callback
 *  to successive data values (akin to Array.forEach).
 * @param {import('../types.js').DataType} [type] The data type.
 * @param {import('../types.js').ColumnBuilderOptions} [options]
 *  Builder options for the generated column.
 * @param {ReturnType<
 *    import('./builders/dictionary.js').dictionaryContext
 *  >} [dicts] Dictionary context object, for internal use only.
 * @returns {Column<T>} The generated column.
 */
function columnFromValues(values, type, options = {}, dicts) {
  const visit = isIterable(values)
    ? callback => { for (const value of values) callback(value); }
    : values;

  type ??= inferType(visit);
  const { maxBatchRows = Infinity, ...opt } = options;
  let data;

  if (type.typeId === constants_Type.Null) {
    let length = 0;
    visit(() => ++length);
    data = nullBatches(type, length, maxBatchRows);
  } else {
    const ctx = builderContext(opt, dicts);
    const b = builder(type, ctx).init();
    const next = b => data.push(b.batch());
    data = [];

    let row = 0;
    visit(value => {
      b.set(value, row++);
      if (row >= maxBatchRows) {
        next(b);
        row = 0;
      }
    });
    if (row) next(b);

    // resolve dictionaries
    ctx.finish();
  }

  return new column_Column(data, type);
}

/**
 * Create null batches with the given batch size limit.
 * @param {import('../types.js').NullType} type The null data type.
 * @param {number} length The total column length.
 * @param {number} limit The maximum batch size.
 * @returns {import('../batch.js').NullBatch[]} The null batches.
 */
function nullBatches(type, length, limit) {
  const data = [];
  const batch = length => new NullBatch({ length, nullCount: length, type });
  const numBatches = Math.floor(length / limit);
  for (let i = 0; i < numBatches; ++i) {
    data.push(batch(limit));
  }
  const rem = length % limit;
  if (rem) data.push(batch(rem));
  return data;
}

;// ../../node_modules/@uwdata/flechette/src/build/column-from-array.js






/**
 * Create a new column from a provided data array.
 * @template T
 * @param {Array | import('../types.js').TypedArray} array The input data.
 * @param {import('../types.js').DataType} [type] The data type.
 *  If not specified, type inference is attempted.
 * @param {import('../types.js').ColumnBuilderOptions} [options]
 *  Builder options for the generated column.
 * @param {ReturnType<import('./builders/dictionary.js').dictionaryContext>} [dicts]
 *  Builder context object, for internal use only.
 * @returns {Column<T>} The generated column.
 */
function column_from_array_columnFromArray(array, type, options = {}, dicts) {
  return !type && arrays_isTypedArray(array)
    ? columnFromTypedArray(array, options)
    : columnFromValues(v => array.forEach(v), type, options, dicts);
}

/**
 * Create a new column from a typed array input.
 * @template T
 * @param {import('../types.js').TypedArray} values The input data.
 * @param {import('../types.js').ColumnBuilderOptions} options
 *  Builder options for the generated column.
 * @returns {Column<T>} The generated column.
 */
function columnFromTypedArray(values, { maxBatchRows, useBigInt }) {
  const arrayType = /** @type {import('../types.js').TypedArrayConstructor} */ (
    values.constructor
  );
  const type = typeForTypedArray(arrayType);
  const length = values.length;
  const limit = Math.min(maxBatchRows || Infinity, length);
  const numBatches = Math.floor(length / limit);

  const batches = [];
  const batchType = isInt64ArrayType(arrayType) && !useBigInt ? Int64Batch : DirectBatch;
  const add = (start, end) => batches.push(new batchType({
    length: end - start,
    nullCount: 0,
    type,
    validity: new uint8Array(0),
    values: values.subarray(start, end)
  }));

  let idx = 0;
  for (let i = 0; i < numBatches; ++i) add(idx, idx += limit);
  if (idx < length) add(idx, length);

  return new column_Column(batches);
}

/**
 * Return an Arrow data type for a given typed array type.
 * @param {import('../types.js').TypedArrayConstructor} arrayType
 *  The typed array type.
 * @returns {import('../types.js').DataType} The data type.
 */
function typeForTypedArray(arrayType) {
  switch (arrayType) {
    case float32Array: return float32();
    case float64Array: return float64();
    case int8Array: return int8();
    case int16Array: return int16();
    case int32Array: return int32();
    case int64Array: return int64();
    case uint8Array: return uint8();
    case uint16Array: return uint16();
    case uint32Array: return uint32();
    case uint64Array: return uint64();
  }
}

;// ../../node_modules/@uwdata/flechette/src/build/table-from-columns.js




/**
 * Create a new table from a collection of columns. Columns are assumed
 * to have the same record batch sizes.
 * @param {[string, import('../column.js').Column][]
 *  | Record<string, import('../column.js').Column>} data The columns,
 *  as an object with name keys, or an array of [name, column] pairs.
 * @param {boolean} [useProxy] Flag indicating if row proxy
 *  objects should be used to represent table rows (default `false`).
 * @returns {Table} The new table.
 */
function table_from_columns_tableFromColumns(data, useProxy) {
  const fields = [];
  const entries = Array.isArray(data) ? data : Object.entries(data);
  const length = entries[0]?.[1].length;

  const columns = entries.map(([name, col]) => {
    if (col.length !== length) {
      throw new Error('All columns must have the same length.');
    }
    fields.push(data_types_field(name, col.type));
    return col;
  });

  const schema = {
    version: Version.V5,
    endianness: Endianness.Little,
    fields,
    metadata: null
  };

  return new table_Table(schema, columns, useProxy);
}

;// ../../node_modules/@uwdata/flechette/src/build/table-from-arrays.js




/**
 * Create a new table from the provided arrays.
 * @param {[string, Array | import('../types.js').TypedArray][]
 *  | Record<string, Array | import('../types.js').TypedArray>} data
 *  The input data as a collection of named arrays.
 * @param {import('../types.js').TableBuilderOptions} options
 *  Table builder options, including an optional type map.
 * @returns {import('../table.js').Table} The new table.
 */
function tableFromArrays(data, options = {}) {
  const { types = {}, ...opt } = options;
  const dicts = dictionaryContext();
  const entries = Array.isArray(data) ? data : Object.entries(data);
  const columns = entries.map(([name, array]) =>
    /** @type {[string, import('../column.js').Column]} */ (
    [ name, columnFromArray(array, types[name], opt, dicts)]
  ));
  return tableFromColumns(columns, options.useProxy);
}

;// ../../node_modules/@uwdata/flechette/src/index.js
















;// ../../node_modules/arquero/src/format/util/columns.js


/**
 * Return a potentially filtered list of column names.
 * @param {import('../../table/Table.js').Table} table A data table.
 * @param {import('../types.js').ColumnSelectOptions} names The column names to select.
 * @returns {string[]} The selected column names.
 */
function columns_columns(table, names) {
  // @ts-ignore
  return is_function_isFunction(names) ? names(table)
    : names || table.columnNames();
}

;// ../../node_modules/arquero/src/format/to-arrow.js





/**
 * Create an Apache Arrow table for an input table.
 * @param {import('../table/Table.js').Table} table
 *  An input Arquero table to convert to Arrow format.
 * @param {import('./types.js').ArrowFormatOptions} [options]
 *  Encoding options, including column data types.
 * @return {import('@uwdata/flechette').Table} An Arrow Table instance.
 */
function toArrow(table, options = {}) {
  const { columns, limit = Infinity, offset = 0, types = {}, ...opt } = options;
  const names = columns_columns(table, columns);
  const data = table.data();

  // make a full table scan with no indirection?
  const fullScan = offset === 0
    && table.numRows() <= limit
    && !table.isFiltered()
    && !table.isOrdered();

  return table_from_columns_tableFromColumns(names.map(name => {
    const values = data[name];
    const type = types[name];
    const isArray = isArrayType(values);
    let col;
    if (fullScan && (isArray || is_function_isFunction(values.toArray))) {
      // @ts-ignore - use faster path, takes advantange of typed arrays
      col = column_from_array_columnFromArray(isArray ? values : values.toArray(), type, opt);
    } else {
      // use table scan method to visit column values
      const get = isArray
        ? row => values[row]
        : row => values.at(row);
      col = columnFromValues(
        visit => table.scan(row => visit(get(row)), true, limit, offset),
        type,
        opt
      );
    }
    return [name, col];
  }));
}

;// ../../node_modules/arquero/src/format/to-arrow-ipc.js



/**
 * Format a table as binary data in the Apache Arrow IPC format.
 * @param {import('../table/Table.js').Table} data The table data
 * @param {import('./types.js').ArrowIPCFormatOptions} [options]
 *  The Arrow IPC formatting options. Set the *format* option to `'stream'`
 *  or `'file'` to specify the IPC format.
 * @return {Uint8Array} A new Uint8Array of Arrow-encoded binary data.
 */
function toArrowIPC(data, options = {}) {
  const { format = 'stream', ...toArrowOptions } = options;
  return tableToIPC(toArrow(data, toArrowOptions), { format });
}

;// ../../node_modules/arquero/src/util/identity.js
function identity_identity(x) {
  return x;
}

;// ../../node_modules/arquero/src/format/util/scan.js


function scan(table, names, limit = 100, offset, ctx) {
  const { start = identity_identity, cell, end = identity_identity } = ctx;
  const data = table.data();
  const n = names.length;
  table.scan(row => {
    start(row);
    for (let i = 0; i < n; ++i) {
      const name = names[i];
      cell(data[name].at(row), name, i);
    }
    end(row);
  }, true, limit, offset);
}

;// ../../node_modules/arquero/src/format/to-csv.js





/**
 * Options for CSV formatting.
 * @typedef {object} CSVFormatOptions
 * @property {string} [delimiter=','] The delimiter between values.
 * @property {boolean} [header=true] Flag to specify presence of header row.
 *  If true, includes a header row with column names.
 *  If false, the header is omitted.
 * @property {number} [limit=Infinity] The maximum number of rows to print.
 * @property {number} [offset=0] The row offset indicating how many initial rows to skip.
 * @property {import('./types.js').ColumnSelectOptions} [columns] Ordered list
 *  of column names to include. If function-valued, the function should
 *  accept a table as input and return an array of column name strings.
 * @property {Object.<string, (value: any) => any>} [format] Object of column
 *  format options. The object keys should be column names. The object values
 *  should be formatting functions to invoke to transform column values prior
 *  to output. If specified, these override automatically inferred options.
 */

/**
 * Format a table as a comma-separated values (CSV) string. Other
 * delimiters, such as tabs or pipes ('|'), can be specified using
 * the options argument.
 * @param {import('../table/Table.js').Table} table The table to format.
 * @param {CSVFormatOptions} options The formatting options.
 * @return {string} A delimited-value format string.
 */
function toCSV(table, options = {}) {
  const names = columns_columns(table, options.columns);
  const format = options.format || {};
  const delim = options.delimiter || ',';
  const header = options.header ?? true;
  const reFormat = new RegExp(`["${delim}\n\r]`);

  const formatValue = value => value == null ? ''
    : isDate(value) ? formatUTCDate(value, true)
    : reFormat.test(value += '') ? '"' + value.replace(/"/g, '""') + '"'
    : value;

  const vals = names.map(formatValue);
  let text = header ? (vals.join(delim) + '\n') : '';

  scan(table, names, options.limit || Infinity, options.offset, {
    cell(value, name, index) {
      vals[index] = formatValue(format[name] ? format[name](value) : value);
    },
    end() {
      text += vals.join(delim) + '\n';
    }
  });

  return text;
}

;// ../../node_modules/arquero/src/util/map-object.js
function mapObject(obj, fn, output = {}) {
  for (const key in obj) {
    output[key] = fn(obj[key], key);
  }
  return output;
}

;// ../../node_modules/arquero/src/format/util/infer.js


function isExactDateUTC(d) {
  return d.getUTCHours() === 0
    && d.getUTCMinutes() === 0
    && d.getUTCSeconds() === 0
    && d.getUTCMilliseconds() === 0;
}

function inferFormat(scan, options = {}) {
  let count = 0;
  let nulls = 0;
  let dates = 0;
  let dutcs = 0;
  let nums = 0;
  let digits = 0;

  scan(value => {
    ++count;
    if (value == null) {
      ++nulls;
      return;
    }

    const type = typeof value;
    if (type === 'object' && isDate(value)) {
      ++dates;
      if (isExactDateUTC(value)) ++dutcs;
    } else if (type === 'number') {
      ++nums;
      if (value === value &&  (value | 0) !== value) {
        const s = value + '';
        const p = s.indexOf('.');
        if (p >= 0) {
          const e = s.indexOf('e');
          const l = e > 0 ? e : s.length;
          digits = Math.max(digits, l - p - 1);
        }
      }
    }
  });

  return {
    align:  (nulls + nums + dates) / count > 0.5 ? 'r' : 'l',
    format: {
      utc:    dates === dutcs,
      digits: Math.min(digits, options.maxdigits || 6)
    }
  };
}

;// ../../node_modules/arquero/src/format/util/formats.js


function formats(table, names, options) {
  const formatOpt = options.format || {};
  const alignOpt = options.align || {};
  const format = {};
  const align = {};

  names.forEach(name => {
    const auto = inferFormat(formats_values(table, name), options);
    align[name] = alignOpt[name] || auto.align;
    format[name] = formatOpt[name] || auto.format;
  });

  return { align, format };
}

function formats_values(table, columnName) {
  const column = table.column(columnName);
  return fn => table.scan(row => fn(column.at(row)));
}

;// ../../node_modules/arquero/src/format/util/format-value.js





/**
 * Format a value as a string.
 * @param {*} v The value to format.
 * @param {import('../types.js').ValueFormatOptions} options Formatting options.
 * @return {string} The formatted string.
 */
function formatValue(v, options = {}) {
  if (is_function_isFunction(options)) {
    // @ts-ignore
    return options(v) + '';
  }

  const type = typeof v;

  if (type === 'object') {
    if (isDate(v)) {
      // @ts-ignore
      return options.utc ? formatUTCDate(v) : formatDate(v);
    } else {
      const s = JSON.stringify(
        v,
        // @ts-ignore
        (k, v) => isTypedArray(v) ? Array.from(v) : v
      );
      // @ts-ignore
      const maxlen = options.maxlen || 30;
      return s.length > maxlen
        ? s.slice(0, 28) + '\u2026' + (s[0] === '[' ? ']' : '}')
        : s;
    }
  } else if (type === 'number') {
    // @ts-ignore
    const digits = options.digits || 0;
    let a;
    return v !== 0 && ((a = Math.abs(v)) >= 1e18 || a < Math.pow(10, -digits))
      ? v.toExponential(digits)
      : v.toFixed(digits);
  } else {
    return v + '';
  }
}

;// ../../node_modules/arquero/src/format/to-html.js







/**
 * Null format function.
 * @callback NullFormat
 * @param {null|undefined} [value] The value to format.
 * @return {string} The formatted HTML string.
 */

/**
 * CSS style function.
 * @callback StyleFunction
 * @param {string} name The column name.
 * @param {number} row The table row index.
 * @return {string} A CSS style string.
 */

/**
 * CSS style options.
 * @typedef {Object.<string, string | StyleFunction>} StyleOptions
 */

/**
 * Options for HTML formatting.
 * @typedef {object} HTMLFormatOptions
 * @property {number} [limit=Infinity] The maximum number of rows to print.
 * @property {number} [offset=0] The row offset indicating how many initial rows to skip.
 * @property {import('./types.js').ColumnSelectOptions} [columns] Ordered list
 *  of column names to include. If function-valued, the function should
 *  accept a table as input and return an array of column name strings.
 * @property {import('./types.js').ColumnAlignOptions} [align] Object of column
 *  alignment options. The object keys should be column names. The object
 *  values should be aligment strings, one of 'l' (left), 'c' (center), or
 *  'r' (right). If specified, these override automatically inferred options.
 * @property {import('./types.js').ColumnFormatOptions} [format] Object of column
 *  format options. The object keys should be column names. The object values
 *  should be formatting functions or specification objects. If specified,
 *  these override automatically inferred options.
 * @property {NullFormat} [null] Format function for null or undefined values.
 *  If specified, this function will be invoked with the null or undefined
 *  value as the sole input, and the return value will be used as the HTML
 *  output for the value.
 * @property {StyleOptions} [style] CSS styles to include in HTML output.
 *  The object keys should be HTML table tag names: 'table', 'thead',
 *  'tbody', 'tr', 'th', or 'td'. The object values should be strings of
 *  valid CSS style directives (such as "font-weight: bold;") or functions
 *  that take a column name and row as inputs and return a CSS string.
 * @property {number} [maxdigits=6] The maximum number of fractional digits
 *  to include when formatting numbers. This option is passed to the format
 *  inference method and is overridden by any explicit format options.
 */

/**
 * Format a table as an HTML table string.
 * @param {import('../table/Table.js').Table} table The table to format.
 * @param {HTMLFormatOptions} options The formatting options.
 * @return {string} An HTML table string.
 */
function toHTML(table, options = {}) {
  const names = columns_columns(table, options.columns);
  const { align, format } = formats(table, names, options);
  const style = styles(options);
  const nullish = options.null;

  const alignValue = a => a === 'c' ? 'center' : a === 'r' ? 'right' : 'left';
  const escape = s => s.replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
  const baseFormat = (value, opt) => escape(formatValue(value, opt));
  const formatter = nullish
    ? (value, opt) => value == null ? nullish(value) : baseFormat(value, opt)
    : baseFormat;

  let r = -1;
  let idx = -1;

  const tag = (tag, name, shouldAlign) => {
    const a = shouldAlign ? alignValue(align[name]) : '';
    const s = style[tag] ? (style[tag](name, idx, r) || '') : '';
    const css = (a ? (`text-align: ${a};` + (s ? ' ' : '')) : '') + s;
    return `<${tag}${css ? ` style="${css}"` : ''}>`;
  };

  let text = tag('table')
    + tag('thead')
    + tag('tr', r)
    + names.map(name => `${tag('th', name, 1)}${name}</th>`).join('')
    + '</tr></thead>'
    + tag('tbody');

  scan(table, names, options.limit, options.offset, {
    start(row) {
      r = row;
      ++idx;
      text += tag('tr');
    },
    cell(value, name) {
      text += tag('td', name, 1)
        + formatter(value, format[name])
        + '</td>';
    },
    end() {
      text += '</tr>';
    }
  });

  return text + '</tbody></table>';
}

function styles(options) {
  return mapObject(
    options.style,
    value => is_function_isFunction(value) ? value : () => value
  );
}

;// ../../node_modules/arquero/src/format/stream/constants.js
const constants_EOL = {};
const constants_BREAK = {};
const constants_QUOTE = 34;
const constants_NEWLINE = 10;
const constants_RETURN = 13;

const constants_COLUMNS = 'columns';
const constants_NDJSON = 'ndjson';
const ROWS = 'rows';

;// ../../node_modules/arquero/src/format/to-json.js






/**
 * Options for JSON formatting.
 * @typedef {object} JSONFormatOptions
 * @property {'columns' | 'rows' | 'ndjson' | null} [type] The format type.
 *  One of `'columns'` (for an object with named column arrays)`, 'rows'` (for
 *  an array for row objects), or `'ndjson'` for [newline-delimited JSON][1]
 *  rows. For `'ndjson'`, each line of text will contain a JSON row object
 *  (with no trailing comma) and string properties will be stripped of any
 *  newline characters. If no format type is specified, defaults to `'rows'`.
 *
 *  [1]: https://github.com/ndjson/ndjson-spec
 * @property {number} [limit=Infinity] The maximum number of rows to print.
 * @property {number} [offset=0] The row offset indicating how many initial
 *  rows to skip.
 * @property {import('./types.js').ColumnSelectOptions} [columns] Ordered list
 *  of column names to include. If function-valued, the function should
 *  accept a table as input and return an array of column name strings.
 * @property {Object.<string, (value: any) => any>} [format] Object of column
 *  format options. The object keys should be column names. The object values
 *  should be formatting functions to invoke to transform column values prior
 *  to output. If specified, these override automatically inferred options.
 */

const defaultFormatter = value => isDate(value)
  ? formatUTCDate(value, true)
  : value;

/**
 * Format a table as a JavaScript Object Notation (JSON) string.
 * @param {import('../table/Table.js').Table} table The table to format.
 * @param {JSONFormatOptions} options The formatting options.
 * @return {string} A JSON string.
 */
function toJSON(table, {
  type,
  columns: cols,
  format = {},
  limit,
  offset
} = {}) {
  const names = columns_columns(table, cols);
  const fmt = names.map(name => format[name] || defaultFormatter);
  const scan = fn => table.scan(fn, true, limit, offset);

  return type === constants_COLUMNS
    ? toColumns(table, names, fmt, scan)
    : toRows(table, names, fmt, scan, type === constants_NDJSON);
}

function toColumns(table, names, format, scan) {
  let text = '{';

  names.forEach((name, i) => {
    text += (i ? ',' : '') + JSON.stringify(name) + ':[';

    const column = table.column(name);
    const formatter = format[i];
    let r = -1;
    scan(row => {
      const value = column.at(row);
      text += (++r ? ',' : '') + JSON.stringify(formatter(value));
    });

    text += ']';
  });

  return text + '}';
}

function toRows(table, names, format, scan, nd = false) {
  const n = names.length;
  const keys = names.map(name => `"${name}":`);
  const cols = names.map(name => table.column(name));

  const finish = nd ? o => o.replaceAll('\n', '') : identity_identity;
  const sep = nd ? '\n' : ',';
  let text = nd ? '' : '[';

  let r = -1;
  scan(row => {
    const props = [];
    for (let i = 0; i < n; ++i) {
      props.push(keys[i] + JSON.stringify(format[i](cols[i].at(row))));
    }
    text += (++r ? sep : '') + finish(`{${props.join(',')}}`);
  });

  return text + (nd ? '' : ']');
}

;// ../../node_modules/arquero/src/format/to-markdown.js





/**
 * Options for Markdown formatting.
 * @typedef {object} MarkdownFormatOptions
 * @property {number} [limit=Infinity] The maximum number of rows to print.
 * @property {number} [offset=0] The row offset indicating how many initial
 *  rows to skip.
 * @property {import('./types.js').ColumnSelectOptions} [columns] Ordered list
 *  of column names to include. If function-valued, the function should
 *  accept a table as input and return an array of column name strings.
 * @property {import('./types.js').ColumnAlignOptions} [align] Object of column
 *  alignment options. The object keys should be column names. The object
 *  values should be aligment strings, one of 'l' (left), 'c' (center), or
 *  'r' (right). If specified, these override automatically inferred options.
 * @property {import('./types.js').ColumnFormatOptions} [format] Object of column
 *  format options. The object keys should be column names. The object values
 *  should be formatting functions or specification objects. If specified,
 *  these override automatically inferred options.
 * @property {number} [maxdigits=6] The maximum number of fractional digits
 *  to include when formatting numbers. This option is passed to the format
 *  inference method and is overridden by any explicit format options.
 */

/**
 * Format a table as a GitHub-Flavored Markdown table string.
 * @param {import('../table/Table.js').Table} table The table to format.
 * @param {MarkdownFormatOptions} options The formatting options.
 * @return {string} A GitHub-Flavored Markdown table string.
 */
function toMarkdown(table, options = {}) {
  const names = columns_columns(table, options.columns);
  const { align, format } = formats(table, names, options);

  const alignValue = a => a === 'c' ? ':-:' : a === 'r' ? '-:' : ':-';
  const escape = s => s.replace(/\|/g, '\\|');

  let text = '|'
    + names.map(escape).join('|')
    + '|\n|'
    + names.map(name => alignValue(align[name])).join('|')
    + '|\n';

  scan(table, names, options.limit, options.offset, {
    start() {
      text += '|';
    },
    cell(value, name) {
      text += escape(formatValue(value, format[name])) + '|';
    },
    end() {
      text += '\n';
    }
  });

  return text;
}

;// ../../node_modules/arquero/src/table/ColumnTable.js











/**
 * A data table with transformation verbs.
 */
class ColumnTable_ColumnTable extends Table {
  /**
   * Create a new table with additional columns drawn from one or more input
   * tables. All tables must have the same numer of rows and are reified
   * prior to assignment. In the case of repeated column names, input table
   * columns overwrite existing columns.
   * @param {...(Table|import('./types.js').ColumnData)} tables
   *  The tables to merge with this table.
   * @return {this} A new table with merged columns.
   * @example table.assign(table1, table2)
   */
  assign(...tables) {
    return verbs_assign_assign(this, ...tables);
  }

  /**
   * Count the number of values in a group. This method is a shorthand
   * for *rollup* with a count aggregate function.
   * @param {import('./types.js').CountOptions} [options]
   *  Options for the count.
   * @return {this} A new table with groupby and count columns.
   * @example table.groupby('colA').count()
   * @example table.groupby('colA').count({ as: 'num' })
   */
  count(options = {}) {
    const { as = 'count' } = options;
    return rollup_rollup(this, { [as]: count() });
  }

  /**
   * Derive new column values based on the provided expressions. By default,
   * new columns are added after (higher indices than) existing columns. Use
   * the before or after options to place new columns elsewhere.
   * @param {import('./types.js').ExprObject} values
   *  Object of name-value pairs defining the columns to derive. The input
   *  object should have output column names for keys and table expressions
   *  for values.
   * @param {import('./types.js').DeriveOptions} [options]
   *  Options for dropping or relocating derived columns. Use either a before
   *  or after property to indicate where to place derived columns. Specifying
   *  both before and after is an error. Unlike the *relocate* verb, this
   *  option affects only new columns; updated columns with existing names
   *  are excluded from relocation.
   * @return {this} A new table with derived columns added.
   * @example table.derive({ sumXY: d => d.x + d.y })
   * @example table.derive({ z: d => d.x * d.y }, { before: 'x' })
   */
  derive(values, options) {
    return derive(this, values, options);
  }

  /**
   * Filter a table to a subset of rows based on the input criteria.
   * The resulting table provides a filtered view over the original data; no
   * data copy is made. To create a table that copies only filtered data to
   * new data structures, call *reify* on the output table.
   * @param {import('./types.js').TableExpr} criteria
   *  Filter criteria as a table expression. Both aggregate and window
   *  functions are permitted, taking into account *groupby* or *orderby*
   *  settings.
   * @return {this} A new table with filtered rows.
   * @example table.filter(d => abs(d.value) < 5)
   */
  filter(criteria) {
    return filter(this, criteria);
  }

  /**
   * Extract rows with indices from start to end (end not included), where
   * start and end represent per-group ordered row numbers in the table.
   * @param {number} [start] Zero-based index at which to start extraction.
   *  A negative index indicates an offset from the end of the group.
   *  If start is undefined, slice starts from the index 0.
   * @param {number} [end] Zero-based index before which to end extraction.
   *  A negative index indicates an offset from the end of the group.
   *  If end is omitted, slice extracts through the end of the group.
   * @return {this} A new table with sliced rows.
   * @example table.slice(1, -1)
   */
  slice(start, end) {
    return verbs_slice_slice(this, start, end);
  }

  /**
   * Group table rows based on a set of column values.
   * Subsequent operations that are sensitive to grouping (such as
   * aggregate functions) will operate over the grouped rows.
   * To undo grouping, use *ungroup*.
   * @param  {...import('./types.js').ExprList} keys
   *  Key column values to group by. The keys may be specified using column
   *  name strings, column index numbers, value objects with output column
   *  names for keys and table expressions for values, or selection helper
   *  functions.
   * @return {this} A new table with grouped rows.
   * @example table.groupby('colA', 'colB')
   * @example table.groupby({ key: d => d.colA + d.colB })
   */
  groupby(...keys) {
    return groupby(this, ...keys);
  }

  /**
   * Order table rows based on a set of column values. Subsequent operations
   * sensitive to ordering (such as window functions) will operate over sorted
   * values. The resulting table provides an view over the original data,
   * without any copying. To create a table with sorted data copied to new
   * data strucures, call *reify* on the result of this method. To undo
   * ordering, use *unorder*.
   * @param  {...import('./types.js').OrderKeys} keys
   *  Key values to sort by, in precedence order.
   *  By default, sorting is done in ascending order.
   *  To sort in descending order, wrap values using *desc*.
   *  If a string, order by the column with that name.
   *  If a number, order by the column with that index.
   *  If a function, must be a valid table expression; aggregate functions
   *  are permitted, but window functions are not.
   *  If an object, object values must be valid values parameters
   *  with output column names for keys and table expressions
   *  for values (the output names will be ignored).
   *  If an array, array values must be valid key parameters.
   * @return {this} A new ordered table.
   * @example table.orderby('a', desc('b'))
   * @example table.orderby({ a: 'a', b: desc('b') )})
   * @example table.orderby(desc(d => d.a))
   */
  orderby(...keys) {
    return orderby(this, ...keys);
  }

  /**
   * Relocate a subset of columns to change their positions, also
   * potentially renaming them.
   * @param {import('./types.js').Select} columns
   *  An ordered selection of columns to relocate.
   *  The input may consist of column name strings, column integer indices,
   *  rename objects with current column names as keys and new column names
   *  as values, or functions that take a table as input and returns a valid
   *  selection parameter (typically the output of selection helper functions
   *  such as *all*, *not*, or *range*).
   * @param {import('./types.js').RelocateOptions} options
   *  Options for relocating. Must include either the before or after property
   *  to indicate where to place the relocated columns. Specifying both before
   *  and after is an error.
   * @return {this} A new table with relocated columns.
   * @example table.relocate(['colY', 'colZ'], { after: 'colX' })
   * @example table.relocate(not('colB', 'colC'), { before: 'colA' })
   * @example table.relocate({ colA: 'newA', colB: 'newB' }, { after: 'colC' })
   */
  relocate(columns, options) {
    return relocate(this, toArray(columns), options);
  }

  /**
   * Rename one or more columns, preserving column order.
   * @param {...import('./types.js').Select} columns
   *  One or more rename objects with current column names as keys and new
   *  column names as values.
   * @return {this} A new table with renamed columns.
   * @example table.rename({ oldName: 'newName' })
   * @example table.rename({ a: 'a2', b: 'b2' })
   */
  rename(...columns) {
    return rename(this, ...columns);
  }

  /**
   * Reduce a table, processing all rows to produce a new table.
   * To produce standard aggregate summaries, use the rollup verb.
   * This method allows the use of custom reducer implementations,
   * for example to produce multiple rows for an aggregate.
   * @param {import('../verbs/reduce/reducer.js').Reducer} reducer
   *  The reducer to apply.
   * @return {this} A new table of reducer outputs.
   */
  reduce(reducer) {
    return reduce(this, reducer);
  }

  /**
   * Rollup a table to produce an aggregate summary.
   * Often used in conjunction with *groupby*.
   * To produce counts only, *count* is a shortcut.
   * @param {import('./types.js').ExprObject} [values]
   *  Object of name-value pairs defining aggregate output columns. The input
   *  object should have output column names for keys and table expressions
   *  for values. The expressions must be valid aggregate expressions: window
   *  functions are not allowed and column references must be arguments to
   *  aggregate functions.
   * @return {this} A new table of aggregate summary values.
   * @example table.groupby('colA').rollup({ mean: d => mean(d.colB) })
   * @example table.groupby('colA').rollup({ mean: op.median('colB') })
   */
  rollup(values) {
    return rollup_rollup(this, values);
  }

  /**
   * Generate a table from a random sample of rows.
   * If the table is grouped, performs a stratified sample by
   * sampling from each group separately.
   * @param {number | import('./types.js').TableExpr} size
   *  The number of samples to draw per group.
   *  If number-valued, the same sample size is used for each group.
   *  If function-valued, the input should be an aggregate table
   *  expression compatible with *rollup*.
   * @param {import('./types.js').SampleOptions} [options]
   *  Options for sampling.
   * @return {this} A new table with sampled rows.
   * @example table.sample(50)
   * @example table.sample(100, { replace: true })
   * @example table.groupby('colA').sample(() => op.floor(0.5 * op.count()))
   */
  sample(size, options) {
    return sample_sample(this, size, options);
  }

  /**
   * Select a subset of columns into a new table, potentially renaming them.
   * @param {...import('./types.js').Select} columns
   *  An ordered selection of columns.
   *  The input may consist of column name strings, column integer indices,
   *  rename objects with current column names as keys and new column names
   *  as values, or functions that take a table as input and returns a valid
   *  selection parameter (typically the output of selection helper functions
   *  such as *all*, *not*, or *range*.).
   * @return {this} A new table of selected columns.
   * @example table.select('colA', 'colB')
   * @example table.select(not('colB', 'colC'))
   * @example table.select({ colA: 'newA', colB: 'newB' })
   */
  select(...columns) {
    return select_select(this, ...columns);
  }

  /**
   * Ungroup a table, removing any grouping criteria.
   * Undoes the effects of *groupby*.
   * @return {this} A new ungrouped table, or this table if not grouped.
   * @example table.ungroup()
   */
  ungroup() {
    return ungroup_ungroup(this);
  }

  /**
   * Unorder a table, removing any sorting criteria.
   * Undoes the effects of *orderby*.
   * @return {this} A new unordered table, or this table if not ordered.
   * @example table.unorder()
   */
  unorder() {
    return unorder(this);
  }

  // -- Cleaning Verbs ------------------------------------------------------

  /**
   * De-duplicate table rows by removing repeated row values.
   * @param {...import('./types.js').ExprList} keys
   *  Key columns to check for duplicates.
   *  Two rows are considered duplicates if they have matching values for
   *  all keys. If keys are unspecified, all columns are used.
   *  The keys may be specified using column name strings, column index
   *  numbers, value objects with output column names for keys and table
   *  expressions for values, or selection helper functions.
   * @return {this} A new de-duplicated table.
   * @example table.dedupe()
   * @example table.dedupe('a', 'b')
   * @example table.dedupe({ abs: d => op.abs(d.a) })
   */
  dedupe(...keys) {
    return dedupe(this, ...keys);
  }

  /**
   * Impute missing values or rows. Accepts a set of column-expression pairs
   * and evaluates the expressions to replace any missing (null, undefined,
   * or NaN) values in the original column.
   * If the expand option is specified, imputes new rows for missing
   * combinations of values. All combinations of key values (a full cross
   * product) are considered for each level of grouping (specified by
   * *groupby*). New rows will be added for any combination
   * of key and groupby values not already contained in the table. For all
   * non-key and non-group columns the new rows are populated with imputation
   * values (first argument) if specified, otherwise undefined.
   * If the expand option is specified, any filter or orderby settings are
   * removed from the output table, but groupby settings persist.
   * @param {import('./types.js').ExprObject} values
   *  Object of name-value pairs for the column values to impute. The input
   *  object should have existing column names for keys and table expressions
   *  for values. The expressions will be evaluated to determine replacements
   *  for any missing values.
   * @param {import('./types.js').ImputeOptions} [options] Imputation options.
   *  The expand property specifies a set of column values to consider for
   *  imputing missing rows. All combinations of expanded values are
   *  considered, and new rows are added for each combination that does not
   *  appear in the input table.
   * @return {this} A new table with imputed values and/or rows.
   * @example table.impute({ v: () => 0 })
   * @example table.impute({ v: d => op.mean(d.v) })
   * @example table.impute({ v: () => 0 }, { expand: ['x', 'y'] })
   */
  impute(values, options) {
    return impute(this, values, options);
  }

  // -- Reshaping Verbs -----------------------------------------------------

  /**
   * Fold one or more columns into two key-value pair columns.
   * The fold transform is an inverse of the *pivot* transform.
   * The resulting table has two new columns, one containing the column
   * names (named "key") and the other the column values (named "value").
   * The number of output rows equals the original row count multiplied
   * by the number of folded columns.
   * @param {import('./types.js').ExprList} values The columns to fold.
   *  The columns may be specified using column name strings, column index
   *  numbers, value objects with output column names for keys and table
   *  expressions for values, or selection helper functions.
   * @param {import('./types.js').FoldOptions} [options] Options for folding.
   * @return {this} A new folded table.
   * @example table.fold('colA')
   * @example table.fold(['colA', 'colB'])
   * @example table.fold(range(5, 8))
   */
  fold(values, options) {
    return fold(this, values, options);
  }

  /**
   * Pivot columns into a cross-tabulation.
   * The pivot transform is an inverse of the *fold* transform.
   * The resulting table has new columns for each unique combination
   * of the provided *keys*, populated with the provided *values*.
   * The provided *values* must be aggregates, as a single set of keys may
   * include more than one row. If string-valued, the *any* aggregate is used.
   * If only one *values* column is defined, the new pivoted columns will
   * be named using key values directly. Otherwise, input value column names
   * will be included as a component of the output column names.
   * @param {import('./types.js').ExprList} keys
   *  Key values to map to new column names. The keys may be specified using
   *  column name strings, column index numbers, value objects with output
   *  column names for keys and table expressions for values, or selection
   *  helper functions.
   * @param {import('./types.js').ExprList} values Output values for pivoted
   *  columns. Column references will be wrapped in an *any* aggregate. If
   *  object-valued, the input object should have output value names for keys
   *  and aggregate table expressions for values.
   * @param {import('./types.js').PivotOptions} [options]
   *  Options for pivoting.
   * @return {this} A new pivoted table.
   * @example table.pivot('key', 'value')
   * @example table.pivot(['keyA', 'keyB'], ['valueA', 'valueB'])
   * @example table.pivot({ key: d => d.key }, { value: d => op.sum(d.value) })
   */
  pivot(keys, values, options) {
    return pivot(this, keys, values, options);
  }

  /**
   * Spread array elements into a set of new columns.
   * Output columns are named based on the value key and array index.
   * @param {import('./types.js').ExprList} values
   *  The column values to spread. The values may be specified using column
   *  name strings, column index numbers, value objects with output column
   *  names for keys and table expressions for values, or selection helper
   *  functions.
   * @param {import('./types.js').SpreadOptions } [options]
   *  Options for spreading.
   * @return {this} A new table with the spread columns added.
   * @example table.spread({ a: d => op.split(d.text, '') })
   * @example table.spread('arrayCol', { limit: 100 })
   */
  spread(values, options) {
    return spread_spread(this, values, options);
  }

  /**
   * Unroll one or more array-valued columns into new rows.
   * If more than one array value is used, the number of new rows
   * is the smaller of the limit and the largest length.
   * Values for all other columns are copied over.
   * @param {import('./types.js').ExprList} values
   *  The column values to unroll. The values may be specified using column
   *  name strings, column index numbers, value objects with output column
   *  names for keys and table expressions for values, or selection helper
   *  functions.
   * @param {import('./types.js').UnrollOptions} [options]
   *  Options for unrolling.
   * @return {this} A new unrolled table.
   * @example table.unroll('colA', { limit: 1000 })
   */
  unroll(values, options) {
    return unroll_unroll(this, values, options);
  }

  // -- Joins ---------------------------------------------------------------

  /**
   * Lookup values from a secondary table and add them as new columns.
   * A lookup occurs upon matching key values for rows in both tables.
   * If the secondary table has multiple rows with the same key, only
   * the last observed instance will be considered in the lookup.
   * Lookup is similar to *join_left*, but with a simpler
   * syntax and the added constraint of allowing at most one match only.
   * @param {import('./types.js').TableRef} other
   *  The secondary table to look up values from.
   * @param {import('./types.js').JoinKeys} [on]
   *  Lookup keys (column name strings or table expressions) for this table
   *  and the secondary table, respectively. If unspecified, the values of
   *  all columns with matching names are compared.
   * @param {...import('./types.js').ExprList} [values]
   *  The column values to add from the secondary table. Can be column name
   *  strings or objects with column names as keys and table expressions as
   *  values. If unspecified, includes all columns from the secondary table
   *  whose names do no match any column in the primary table.
   * @return {this} A new table with lookup values added.
   * @example table.lookup(other, ['key1', 'key2'], 'value1', 'value2')
   */
  lookup(other, on, ...values) {
    return lookup(this, other, on, ...values);
  }

  /**
   * Join two tables, extending the columns of one table with
   * values from the other table. The current table is considered
   * the "left" table in the join, and the new table input is
   * considered the "right" table in the join. By default an inner
   * join is performed, removing all rows that do not match the
   * join criteria. To perform left, right, or full outer joins, use
   * the *join_left*, *join_right*, or *join_full* methods, or provide
   * an options argument.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows. If unspecified, the values of
   *  all columns with matching names are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @param {import('./types.js').JoinValues} [values]
   *  The columns to include in the join output.
   *  If unspecified, all columns from both tables are included; paired
   *  join keys sharing the same column name are included only once.
   *  If array-valued, a two element array should be provided, containing
   *  the columns to include for the left and right tables, respectively.
   *  Array input may consist of column name strings, objects with output
   *  names as keys and single-table table expressions as values, or the
   *  selection helper functions *all*, *not*, or *range*.
   *  If object-valued, specifies the key-value pairs for each output,
   *  defined using two-table table expressions.
   * @param {import('./types.js').JoinOptions} [options]
   *  Options for the join.
   * @return {this} A new joined table.
   * @example table.join(other, ['keyL', 'keyR'])
   * @example table.join(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  join(other, on, values, options) {
    return join_join(this, other, on, values, options);
  }

  /**
   * Perform a left outer join on two tables. Rows in the left table
   * that do not match a row in the right table will be preserved.
   * This is a convenience method with fixed options for *join*.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows.
   *  If unspecified, the values of all columns with matching names
   *  are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @param {import('./types.js').JoinValues} [values]
   *  he columns to include in the join output.
   *  If unspecified, all columns from both tables are included; paired
   *  join keys sharing the same column name are included only once.
   *  If array-valued, a two element array should be provided, containing
   *  the columns to include for the left and right tables, respectively.
   *  Array input may consist of column name strings, objects with output
   *  names as keys and single-table table expressions as values, or the
   *  selection helper functions *all*, *not*, or *range*.
   *  If object-valued, specifies the key-value pairs for each output,
   *  defined using two-table table expressions.
   * @param {import('./types.js').JoinOptions} [options]
   *  Options for the join. With this method, any options will be
   *  overridden with `{left: true, right: false}`.
   * @return {this} A new joined table.
   * @example table.join_left(other, ['keyL', 'keyR'])
   * @example table.join_left(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  join_left(other, on, values, options) {
    const opt = { ...options, left: true, right: false };
    return join_join(this, other, on, values, opt);
  }

  /**
   * Perform a right outer join on two tables. Rows in the right table
   * that do not match a row in the left table will be preserved.
   * This is a convenience method with fixed options for *join*.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows.
   *  If unspecified, the values of all columns with matching names
   *  are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @param {import('./types.js').JoinValues} [values]
   *  The columns to include in the join output.
   *  If unspecified, all columns from both tables are included; paired
   *  join keys sharing the same column name are included only once.
   *  If array-valued, a two element array should be provided, containing
   *  the columns to include for the left and right tables, respectively.
   *  Array input may consist of column name strings, objects with output
   *  names as keys and single-table table expressions as values, or the
   *  selection helper functions *all*, *not*, or *range*.
   *  If object-valued, specifies the key-value pairs for each output,
   *  defined using two-table table expressions.
   * @param {import('./types.js').JoinOptions} [options]
   *  Options for the join. With this method, any options will be overridden
   *  with `{left: false, right: true}`.
   * @return {this} A new joined table.
   * @example table.join_right(other, ['keyL', 'keyR'])
   * @example table.join_right(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  join_right(other, on, values, options) {
    const opt = { ...options, left: false, right: true };
    return join_join(this, other, on, values, opt);
  }

  /**
   * Perform a full outer join on two tables. Rows in either the left or
   * right table that do not match a row in the other will be preserved.
   * This is a convenience method with fixed options for *join*.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows.
   *  If unspecified, the values of all columns with matching names
   *  are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @param {import('./types.js').JoinValues} [values]
   *  The columns to include in the join output.
   *  If unspecified, all columns from both tables are included; paired
   *  join keys sharing the same column name are included only once.
   *  If array-valued, a two element array should be provided, containing
   *  the columns to include for the left and right tables, respectively.
   *  Array input may consist of column name strings, objects with output
   *  names as keys and single-table table expressions as values, or the
   *  selection helper functions *all*, *not*, or *range*.
   *  If object-valued, specifies the key-value pairs for each output,
   *  defined using two-table table expressions.
   * @param {import('./types.js').JoinOptions} [options]
   *  Options for the join. With this method, any options will be overridden
   *  with `{left: true, right: true}`.
   * @return {this} A new joined table.
   * @example table.join_full(other, ['keyL', 'keyR'])
   * @example table.join_full(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  join_full(other, on, values, options) {
    const opt = { ...options, left: true, right: true };
    return join_join(this, other, on, values, opt);
  }

  /**
   * Produce the Cartesian cross product of two tables. The output table
   * has one row for every pair of input table rows. Beware that outputs
   * may be quite large, as the number of output rows is the product of
   * the input row counts.
   * This is a convenience method for *join* in which the
   * join criteria is always true.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinValues} [values]
   *  The columns to include in the output.
   *  If unspecified, all columns from both tables are included.
   *  If array-valued, a two element array should be provided, containing
   *  the columns to include for the left and right tables, respectively.
   *  Array input may consist of column name strings, objects with output
   *  names as keys and single-table table expressions as values, or the
   *  selection helper functions *all*, *not*, or *range*.
   *  If object-valued, specifies the key-value pairs for each output,
   *  defined using two-table table expressions.
   * @param {import('./types.js').JoinOptions} [options]
   *  Options for the join.
   * @return {this} A new joined table.
   * @example table.cross(other)
   * @example table.cross(other, [['leftKey', 'leftVal'], ['rightVal']])
   */
  cross(other, values, options) {
    return cross(this, other, values, options);
  }

  /**
   * Perform a semi-join, filtering the left table to only rows that
   * match a row in the right table.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows.
   *  If unspecified, the values of all columns with matching names
   *  are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @return {this} A new filtered table.
   * @example table.semijoin(other)
   * @example table.semijoin(other, ['keyL', 'keyR'])
   * @example table.semijoin(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  semijoin(other, on) {
    return semijoin(this, other, on);
  }

  /**
   * Perform an anti-join, filtering the left table to only rows that
   * do *not* match a row in the right table.
   * @param {import('./types.js').TableRef} other
   *  The other (right) table to join with.
   * @param {import('./types.js').JoinPredicate} [on]
   *  The join criteria for matching table rows.
   *  If unspecified, the values of all columns with matching names
   *  are compared.
   *  If array-valued, a two-element array should be provided, containing
   *  the columns to compare for the left and right tables, respectively.
   *  If a one-element array or a string value is provided, the same
   *  column names will be drawn from both tables.
   *  If function-valued, should be a two-table table expression that
   *  returns a boolean value. When providing a custom predicate, note that
   *  join key values can be arrays or objects, and that normal join
   *  semantics do not consider null or undefined values to be equal (that is,
   *  null !== null). Use the op.equal function to handle these cases.
   * @return {this} A new filtered table.
   * @example table.antijoin(other)
   * @example table.antijoin(other, ['keyL', 'keyR'])
   * @example table.antijoin(other, (a, b) => op.equal(a.keyL, b.keyR))
   */
  antijoin(other, on) {
    return antijoin(this, other, on);
  }

  // -- Set Operations ------------------------------------------------------

  /**
   * Concatenate multiple tables into a single table, preserving all rows.
   * This transformation mirrors the UNION_ALL operation in SQL.
   * Only named columns in this table are included in the output.
   * @param  {...import('./types.js').TableRefList} tables
   *  A list of tables to concatenate.
   * @return {this} A new concatenated table.
   * @example table.concat(other)
   * @example table.concat(other1, other2)
   * @example table.concat([other1, other2])
   */
  concat(...tables) {
    return verbs_concat_concat(this, ...tables);
  }

  /**
   * Union multiple tables into a single table, deduplicating all rows.
   * This transformation mirrors the UNION operation in SQL. It is
   * similar to *concat* but suppresses duplicate rows with
   * values identical to another row.
   * Only named columns in this table are included in the output.
   * @param  {...import('./types.js').TableRefList} tables
   *  A list of tables to union.
   * @return {this} A new unioned table.
   * @example table.union(other)
   * @example table.union(other1, other2)
   * @example table.union([other1, other2])
   */
  union(...tables) {
    return union(this, ...tables);
  }

  /**
   * Intersect multiple tables, keeping only rows whose with identical
   * values for all columns in all tables, and deduplicates the rows.
   * This transformation is similar to a series of *semijoin*.
   * calls, but additionally suppresses duplicate rows.
   * @param  {...import('./types.js').TableRefList} tables
   *  A list of tables to intersect.
   * @return {this} A new filtered table.
   * @example table.intersect(other)
   * @example table.intersect(other1, other2)
   * @example table.intersect([other1, other2])
   */
  intersect(...tables) {
    return intersect_intersect(this, ...tables);
  }

  /**
   * Compute the set difference with multiple tables, keeping only rows in
   * this table that whose values do not occur in the other tables.
   * This transformation is similar to a series of *anitjoin*
   * calls, but additionally suppresses duplicate rows.
   * @param  {...import('./types.js').TableRefList} tables
   *  A list of tables to difference.
   * @return {this} A new filtered table.
   * @example table.except(other)
   * @example table.except(other1, other2)
   * @example table.except([other1, other2])
   */
  except(...tables) {
    return except(this, ...tables);
  }

  // -- Table Output Formats ------------------------------------------------

  /**
   * Format this table as a Flechette Arrow table.
   * @param {import('../format/types.js').ArrowFormatOptions} [options]
   *  The Arrow formatting options.
   * @return {import('@uwdata/flechette').Table} A Flechette Arrow table.
   */
  toArrow(options) {
    return toArrow(this, options);
  }

  /**
   * Format this table as binary data in the Apache Arrow IPC format.
   * @param {import('../format/types.js').ArrowIPCFormatOptions} [options]
   *  The Arrow IPC formatting options.
   * @return {Uint8Array} A new Uint8Array of Arrow-encoded binary data.
   */
  toArrowIPC(options) {
    return toArrowIPC(this, options);
  }

  /**
   * Format this table as a comma-separated values (CSV) string. Other
   * delimiters, such as tabs or pipes ('|'), can be specified using
   * the options argument.
   * @param {import('../format/to-csv.js').CSVFormatOptions} [options]
   *   The CSV formatting options.
   * @return {string} A delimited value string.
   */
  toCSV(options) {
    return toCSV(this, options);
  }

  /**
   * Format this table as an HTML table string.
   * @param {import('../format/to-html.js').HTMLFormatOptions} [options]
   *  The HTML formatting options.
   * @return {string} An HTML table string.
   */
  toHTML(options) {
    return toHTML(this, options);
  }

  /**
   * Format this table as a JavaScript Object Notation (JSON) string.
   * @param {import('../format/to-json.js').JSONFormatOptions} [options]
   *  The JSON formatting options.
   * @return {string} A JSON string.
   */
  toJSON(options) {
    return toJSON(this, options);
  }

  /**
   * Format this table as a GitHub-Flavored Markdown table string.
   * @param {import('../format/to-markdown.js').MarkdownFormatOptions} [options]
   *  The Markdown formatting options.
   * @return {string} A GitHub-Flavored Markdown table string.
   */
  toMarkdown(options) {
    return toMarkdown(this, options);
  }
}

;// ../../node_modules/arquero/src/format/from-arrow.js








/**
 * Create a new table backed by an Apache Arrow table instance.
 * @param {import('./types.js').ArrowInput} input
 *  An Apache Arrow data table or Arrow IPC byte buffer.
 * @param {import('./types.js').ArrowOptions} [options]
 *  Options for Arrow import.
 * @return {ColumnTable} A new table containing the imported values.
 */
function fromArrow(input, options) {
  const { columns = selection_all(), ...rest } = options || {};
  const arrow = input instanceof ArrayBuffer || input instanceof Uint8Array
    ? tableFromIPC(input, { useDate: true, ...rest })
    : input;

  const { fields } = arrow.schema;

  // resolve column selection
  const names = fields.map(f => f.name);
  const sel = resolve({
    columnNames: test => test ? names.filter(test) : names.slice(),
    columnIndex: name => names.indexOf(name)
  }, columns);

  // build Arquero columns for backing Arrow columns
  const cols = columnSet();
  sel.forEach((name, key) => {
    const col = /** @type {import('./types.js').ArrowColumn} */ (arrow.getChild(key));
    cols.add(name, col.type.typeId === -1 ? from_arrow_dictionary(col) : col);
  });

  return new ColumnTable_ColumnTable(cols.data, cols.names);
}

/**
 * Parse Arrow data and return a Promise for an Arquero table.
 * @param {ReadableStream<Uint8Array>} stream
 *  An input byte stream, Apache Arrow data table, or Arrow IPC byte buffer.
 * @param {import('./types.js').ArrowOptions} [options]
 *  Options for Arrow import.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 */
async function fromArrowStream(stream, options) {
  return fromArrow(await collectBytes(stream), options);
}

/**
 * Load an Arrow file from a URL and return a Promise for an Arquero table.
 * @param {string} path The URL or file path to load.
 * @param {import('./types.js').LoadOptions
 *  & import('./types.js').ArrowOptions} [options] Arrow parse options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 * @example aq.loadArrow('data/table.arrow')
 */
async function loadArrow(path, options) {
  return fromArrowStream(await byteStream(path, options), options);
}

function from_arrow_dictionary(column) {
  const { data, length, nullCount } = column;
  const batch = data[data.length - 1];
  // support both flechette and arrow-js
  const cache = batch.cache ?? batch.dictionary.toArray();
  const size = cache.length;
  const keys = dictKeys(data, length, nullCount, size);

  const get = nullCount
    ? (k => k === size ? null : cache[k])
    : (k => cache[k]);

  return {
    length,
    nullCount,
    at: row => get(keys[row]),
    key: row => keys[row],
    keyFor(value) {
      if (value === null) return nullCount ? size : -1;
      for (let i = 0; i < size; ++i) {
        if (cache[i] === value) return i;
      }
      return -1;
    },
    groups(names) {
      const s = size + (nullCount ? 1 : 0);
      return {
        keys,
        get: [get],
        names,
        rows: sequence(0, s),
        size: s
      };
    },
    [Symbol.iterator]: () => column[Symbol.iterator](),
    toArray: () => column.toArray()
  };
}

/**
 * Generate a dictionary key array.
 * @param {readonly any[]} data Arrow column batches
 * @param {number} length The length of the Arrow column
 * @param {number} nulls The count of column null values
 * @param {number} size The backing dictionary size
 */
function dictKeys(data, length, nulls, size) {
  const v = data.length > 1 || nulls
    ? flatten(data, length)
    : data[0].values;
  return nulls ? nullKeys(data, v, size) : v;
}

/**
 * Flatten Arrow column chunks into a single array.
 */
function flatten(data, length) {
  const type = data[0].values.constructor;
  const array = new type(length);
  const n = data.length;
  for (let i = 0, idx = 0, len; i < n; ++i) {
    len = data[i].length;
    array.set(data[i].values.subarray(0, len), idx);
    idx += len;
  }
  return array;
}

/**
 * Encode null values as an additional dictionary key.
 * Returns a new key array with null values added.
 * TODO: safeguard against integer overflow?
 */
function nullKeys(data, keys, key) {
  // iterate over null bitmaps, encode null values as key
  const n = data.length;
  for (let i = 0, idx = 0, byte; i < n; ++i) {
    const batch = data[i];
    const { length } = batch;
    // support both flechette and arrow-js
    const validity = batch.validity ?? batch.nullBitmap;
    const m = length >> 3;
    if (validity && validity.length) {
      for (let j = 0; j <= m; ++j) {
        if ((byte = validity[j]) !== 255) {
          const base = idx + (j << 3);
          if ((byte & (1 << 0)) === 0) keys[base + 0] = key;
          if ((byte & (1 << 1)) === 0) keys[base + 1] = key;
          if ((byte & (1 << 2)) === 0) keys[base + 2] = key;
          if ((byte & (1 << 3)) === 0) keys[base + 3] = key;
          if ((byte & (1 << 4)) === 0) keys[base + 4] = key;
          if ((byte & (1 << 5)) === 0) keys[base + 5] = key;
          if ((byte & (1 << 6)) === 0) keys[base + 6] = key;
          if ((byte & (1 << 7)) === 0) keys[base + 7] = key;
        }
      }
    }
    idx += length;
  }
  return keys;
}

;// ../../node_modules/arquero/src/format/stream/delimited-text-stream.js



function unquote(str) {
  return str.slice(1, -1).replace(/""/g, '"');
}

/**
 * Returns a new delimited text stream transformer.
 * @param {string} [delimiter=','] The column delimiter string.
 *  The value should be a single character.
 * @returns {Transformer<string, string[][]>}
 */
function delimited_text_stream_delimitedTextTransformer(delimiter = ',') {
  if (delimiter.length !== 1) {
    error(`Text delimiter should be a single character, found "${delimiter}"`);
  }
  const delimCode = delimiter.charCodeAt(0);

  let I = 0; // current chunk character index
  let N = 0; // length of current text chunk
  let qc = 0; // consecutive quote char count
  let eol = false; // current token followed by EOL?
  let skipNewline = false; // skip newline after carriage return?
  let inQuote = false; // chunk boundary within quoted text?
  let chunk = null; // current text chunk
  let fragment = null; // text fragment leftover from prior chunk
  let row = []; // current row of delimited text values

  function addFragment(str) {
    fragment = fragment ? (fragment + str) : str;
  }

  function token() {
    if (eol) return eol = false, EOL;
    const j = I;
    const jq = chunk.charCodeAt(j) === QUOTE;

    // handle quotes, unescape nested double quotes
    if (inQuote || jq) {
      let q = qc && !jq; // indicate completion of quote
      if (inQuote && !q) {
        --I; // back up if cross-chunk quote
      } else if (jq) {
        ++qc; // increment consecutive quote chars
      }
      inQuote = true;

      // process characters within quote
      if (!q) {
        while (++I < N) {
          if (chunk.charCodeAt(I) === QUOTE) {
            if (++qc === 3) {
              // consume escaped quote char ("")
              qc = 1;
            } else if (++I < N && chunk.charCodeAt(I) !== QUOTE) {
              qc = 0; // reset quote char count
              q = true; // reached end of quote
              break;
            }
          }
        }
        if (!q) {
          // end of chunk and still in quote
          // break off intra-quote fragment
          addFragment(chunk.slice(j, N));
          return BREAK;
        }
      }

      // extract and unescape quoted text
      const quoted = unquote((fragment ?? '') + chunk.slice(j, I));
      qc = 0;
      inQuote = false;
      fragment = null;

      // if a quote stops at end of chunk, treat as normal fragment
      if (I >= N) {
        fragment = quoted;
        return BREAK;
      }

      // check for end of line
      const c = chunk.charCodeAt(I++);
      if (c === NEWLINE) eol = true;
      else if (c === RETURN) {
        eol = true;
        if (I >= N) skipNewline = true;
        else if (chunk.charCodeAt(I) === NEWLINE) ++I;
      }
      return quoted;
    }

    // find next delimiter or newline
    let i;
    while (I < N) {
      const c = chunk.charCodeAt(i = I++);
      if (c === NEWLINE) eol = true;
      else if (c === RETURN) {
        eol = true;
        if (I >= N) skipNewline = true;
        else if (chunk.charCodeAt(I) === NEWLINE) ++I;
      }
      else if (c !== delimCode) continue;
      return chunk.slice(j, i);
    }

    // current token straddles chunks, save fragment
    addFragment(chunk.slice(j, N));
    return BREAK;
  }

  return {
    start() {},

    transform(next, controller) {
      chunk = next;
      N = chunk.length;
      I = 0;
      const batch = [];
      let t;

      if (skipNewline) {
        if (chunk.charCodeAt(I) === NEWLINE) ++I;
        skipNewline = false;
      }

      if (fragment != null) {
        if ((t = token()) === BREAK) {
          controller.enqueue(batch);
          return;
        }
        else {
          row.push((fragment ?? '') + t);
          fragment = null;
        }
      }

      while (true) {
        if ((t = token()) === BREAK) {
          controller.enqueue(batch);
          return;
        }
        else if (t === EOL) (batch.push(row), row = []);
        else row.push(t);
      }
    },

    flush(controller) {
      if (row.length || fragment) {
        if (fragment != null) row.push(fragment);
        controller.enqueue([row]);
      }
    }
  };
}

;// ../../node_modules/arquero/src/util/parse-values.js



const parseBoolean = [ // boolean
  v => (v === 'true') || (v === 'false'),
  v => v === 'false' ? false : true
];

const parseNumber = [ // number
  v => v === 'NaN' || (v = +v) === v,
  v => +v
];

const parseDate = [ // iso date
  is_iso_date_string_isISODateString,
  v => new Date(Date.parse(v))
];

function numberParser(decimal) {
  return decimal && decimal !== '.'
    ? parseNumber.map(f => s => f(s && s.replace(decimal, '.')))
    : parseNumber;
}

function parse_values_parseValues(values, options) {
  const { decimal, limit = values.length } = options;
  const types = [parseBoolean, numberParser(decimal), parseDate];
  const n = types.length;
  for (let i = 0; i < n; ++i) {
    const [test, parser] = types[i];
    if (parse_values_check(values, test, limit)) {
      return parser;
    }
  }
  return identity;
}

function parse_values_check(values, test, n) {
  for (let i = 0; i < n; ++i) {
    const v = values[i];
    if (v != null && !test(v)) {
      return false;
    }
  }
  return true;
}

;// ../../node_modules/arquero/src/format/stream/parse-text-rows.js








/**
 * Create a table from column names and value arrays.
 * @param {string[]} names Column names
 * @param {any[]} values Column value arrays
 * @returns {ColumnTable}
 */
function toTable(names, values) {
  /** @type {import('../../table/types.js').ColumnData} */
  const columns = {};
  names.forEach((name, i) => columns[name] = values[i]);
  return new ColumnTable(columns, names);
}

/**
 * Create a table from delimited text rows.
 * @param {string} input
 * @param {Transformer[]} transformers
 * @param {*} [options]
 * @returns {ColumnTable}
 */
function parse_text_rows_parseTextRowsSync(input, transformers, options = {}) {
  /** @type {string[][]} */
  const rows = pipelineSync(input, transformers);
  const { names, values } = parseTextRowBatches([rows], options);
  return toTable(names, values);
}

/**
 * Create a table from a stream of delimited text rows.
 * @param {ReadableStream<string>} input
 * @param {*} [options]
 * @returns {Promise<ColumnTable>}
 */
async function parse_text_rows_parseTextRowsStream(input, transformers, options = {}) {
  const stream = pipelineStream(input, transformers);

  // pull batches from stream to meet type inference needs
  const automax = +options.autoMax || 1000;
  const iter = streamIterator(stream);
  const init = [];
  let size = 0;
  while (size < automax) {
    const next = await iter.next();
    const batch = next.value;
    if (batch?.length > 0) {
      init.push(batch);
      size += batch.length;
    }
    if (next.done) break;
  }

  // parse initial batches, retrieve type parser functions
  const { names, values, parsers } = parseTextRowBatches(init, options);
  const n = names.length;

  // parse remainder of stream
  for await (const batch of iter) {
    for (let r = 0; r < batch.length; ++r) {
      const row = batch[r];
      for (let i = 0; i < n; ++i) {
        values[i].push(row[i] ? parsers[i](row[i]) : null);
      }
    }
  }

  return toTable(names, values);
}

/**
 * Create column value arrays for batches of text rows.
 * @param {string[][][]} batches
 * @param {*} options
 * @returns {{ names: string[], values: any[], parsers: ReturnType<getParsers> }}
 */
function parseTextRowBatches(batches, options) {
  const [batch] = batches;
  const n = batch[0].length;
  const automax = +options.autoMax || 1000;
  const values = repeat(n, () => []);
  let names = options.header !== false ? batch.shift() : options.names;
  names = names
    ? names.length < n ? [...names, defaultNames(n, names.length)] : names
    : defaultNames(n);

  // transpose text rows into column arrays
  for (const batch of batches) {
    for (let r = 0; r < batch.length; ++r) {
      const row = batch[r];
      for (let i = 0; i < n; ++i) {
        values[i].push(row[i] === '' ? null : row[i]);
      }
    }
  }

  // initialize parsers
  const parsers = getParsers(names, values, { ...options, limit: automax });

  // apply parsers to column arrays
  parsers.forEach((parse, i) => {
    if (parse === identity) return;
    const v = values[i];
    for (let r = 0; r < v.length; ++r) {
      if (v[r] != null) v[r] = parse(v[r]);
    }
  });

  return { names, values, parsers };
}

function defaultNames(n, off = 0) {
  return repeat(n - off, i => `col${i + off + 1}`);
}

function getParsers(names, values, options) {
  const { parse = {} } = options;
  const noParse = options.autoType === false;

  return names.map(
    (name, i) => isFunction(parse[name]) ? parse[name]
      : noParse ? identity
      : parseValues(values[i], options)
  );
}

;// ../../node_modules/arquero/src/format/from-csv.js
 // eslint-disable-line no-unused-vars





/**
 * Options for CSV parsing.
 * @typedef {object} CSVParseOptions
 * @property {string} [delimiter=','] Single-character delimiter between values.
 * @property {string} [decimal='.'] Single-character numeric decimal separator.
 * @property {boolean} [header=true] Flag to specify presence of header row.
 *  If true, assumes the CSV contains a header row with column names. If false,
 *  indicates the CSV does not contain a header row; columns are given the
 *  names 'col1', 'col2', etc unless the *names* option is specified.
 * @property {string[]} [names] An array of column names to use for header-less
 *  CSV files. This option is ignored if the header option is true.
 * @property {number} [skip=0] The number of lines to skip before reading data.
 * @property {string} [comment] A string used to identify comment lines. Any
 *  lines that start with the comment pattern are skipped.
 * @property {boolean} [autoType=true] Flag for automatic type inference.
 * @property {number} [autoMax=1000] Maximum number of initial values to use
 *  for type inference.
 * @property {Record<string, (value: string) => any>} [parse] Object of
 *  column parsing options. The object keys should be column names. The object
 *  values should be parsing functions that transform values upon input.
 */

/**
 * Parse a comma-separated values (CSV) string into a table. Other
 * delimiters, such as tabs or pipes ('|'), can be specified using
 * the options argument. By default, automatic type inference is performed
 * for input values; string values that match the ISO standard
 * date format are parsed into JavaScript Date objects. To disable this
 * behavior, set the autoType option to false. To perform custom parsing
 * of input column values, use the parse option.
 * @param {string} input The input text.
 * @param {CSVParseOptions} [options] The formatting options.
 * @return {ColumnTable} An Arquero table.
 */
function fromCSV(input, options) {
  return parseTextRowsSync(input, transforms(options), options);
}

/**
 * Parse a comma-separated values (CSV) string into a table. Other
 * delimiters, such as tabs or pipes ('|'), can be specified using
 * the options argument. By default, automatic type inference is performed
 * for input values; string values that match the ISO standard
 * date format are parsed into JavaScript Date objects. To disable this
 * behavior, set the autoType option to false. To perform custom parsing
 * of input column values, use the parse option.
 * @param {ReadableStream<string>} stream The input stream.
 * @param {CSVParseOptions} [options] The formatting options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 */
async function fromCSVStream(stream, options) {
  return parseTextRowsStream(stream, transforms(options), options);
}

/**
 * Load a CSV file from a URL and return a Promise for an Arquero table.
 * @param {string} path The URL or file path to load.
 * @param {import('./types.js').LoadOptions & CSVParseOptions} [options]
 *  CSV parse options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 * @example aq.loadCSV('data/table.csv')
 * @example aq.loadTSV('data/table.tsv', { delimiter: '\t' })
 */
async function loadCSV(path, options) {
  return fromCSVStream(await textStream(path, options), options);
}

function transforms({
  delimiter = ',',
  skip = 0,
  comment = undefined
} = {}) {
  return [
    delimitedTextTransformer(delimiter),
    lineFilterTransformer(skip, comment, row => row[0])
  ];
}

;// ../../node_modules/arquero/src/format/stream/text-line-stream.js


/**
 * Returns a new text line stream transformer.
 * @returns {Transformer<string, string[]>}
 */
function text_line_stream_textLineTransformer() {
  let I = 0; // current chunk character index
  let skipNewline = false; // skip newline after carriage return
  let fragment = ''; // remaining fragment from previous chunk

  function parseLine(text) {
    const N = text.length;
    const j = I;

    // find next newline
    while (I < N) {
      const c = text.charCodeAt(I);
      const i = ++I;
      if (c === RETURN) {
        if (I >= N) skipNewline = true;
        else if (text.charCodeAt(I) === NEWLINE) ++I;
      } else if (c !== NEWLINE) {
        continue;
      }
      return text.slice(j, i);
    }

    // current line straddles chunks
    fragment += text.slice(j, N);
    return BREAK;
  }

  return {
    start() {},
    transform(chunk, controller) {
      I = 0;
      let line;
      const lines = [];
      if (skipNewline) {
        if (chunk.charCodeAt(I) === NEWLINE) ++I;
        skipNewline = false;
      }
      if (fragment) {
        line = parseLine(chunk);
        if (line === BREAK) {
          controller.enqueue(lines);
          return;
        }
        else (lines.push(fragment + line), fragment = '');
      }
      while ((line = parseLine(chunk)) !== BREAK) {
        lines.push(line);
      }
      controller.enqueue(lines);
    },
    flush(controller) {
      if (fragment) controller.enqueue([fragment]);
    }
  };
}

;// ../../node_modules/arquero/src/format/from-fixed.js
 // eslint-disable-line no-unused-vars







/**
 * Options for fixed width file parsing.
 * @typedef {object} FixedParseOptions
 * @property {[number, number][]} [positions] Array of start, end indices for
 *  fixed-width columns. Specifying extact positions supports extraction of
 *  a selected subset of columns.
 * @property {number[]} [widths] Array of fixed column widths. This option is
 *  ignored if the positions property is specified.
 * @property {string[]} [names] An array of column names. The array length
 *  should match the length of the positions array. If not specified or
 *  shorter than the positions array, default column names are generated.
 * @property {string} [decimal='.'] Single-character numeric decimal separator.
 * @property {number} [skip=0] The number of lines to skip before reading data.
 * @property {string} [comment] A string used to identify comment lines. Any
 *  lines that start with the comment pattern are skipped.
 * @property {boolean} [autoType=true] Flag for automatic type inference.
 * @property {number} [autoMax=1000] Maximum number of initial values to use
 *  for type inference.
 * @property {Record<string, (value: string) => any>} [parse] Object of
 *  column parsing options. The object keys should be column names. The object
 *  values should be parsing functions that transform values upon input.
 */

/**
 * Parse a fixed-width file (FWF) string into a table. By default, automatic
 * type inference is performed for input values; string values that match the
 * ISO standard date format are parsed into JavaScript Date objects. To
 * disable this behavior, set the autoType option to false. To perform custom
 * parsing of input column values, use the parse option.
 * @param {string} input The input text.
 * @param {FixedParseOptions} [options] The formatting options.
 * @return {ColumnTable} An Arquero table.
 */
function fromFixed(input, options) {
  return parseTextRowsSync(
    input,
    from_fixed_transforms(options),
    { ...options, header: false }
  );
}

/**
 * Parse a fixed-width file (FWF) stream into a table. By default, automatic
 * type inference is performed for input values; string values that match the
 * ISO standard date format are parsed into JavaScript Date objects. To
 * disable this behavior, set the autoType option to false. To perform custom
 * parsing of input column values, use the parse option.
 * @param {ReadableStream<string>} stream The input stream.
 * @param {FixedParseOptions} [options] The formatting options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 */
async function fromFixedStream(stream, options) {
  return parseTextRowsStream(
    stream,
    from_fixed_transforms(options),
    { ...options, header: false }
  );
}

/**
 * Load a fixed width file from a URL and return a Promise for an Arquero table.
 * @param {string} path The URL or file path to load.
 * @param {import('./types.js').LoadOptions & FixedParseOptions} [options]
 * Fixed width parse options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 * @example aq.loadFixedWidth('data/table.txt', { names: ['name', 'city', state'], widths: [10, 20, 2] })
 */
async function loadFixed(path, options) {
  return fromFixedStream(await textStream(path, options), options);
}

function from_fixed_transforms({
  skip = 0,
  comment = undefined,
  positions = undefined,
  widths = undefined
} = {}) {
  if (!positions && !widths) {
    error('Fixed width files require a "positions" or "widths" option.');
  }
  let p = 0;
  const breaks = positions || widths.map(w => [p, p += w]);
  return [
    textLineTransformer(),
    lineFilterTransformer(skip, comment, row => row[0]),
    fixedTextTransformer(breaks)
  ];
}

;// ../../node_modules/arquero/src/format/from-json.js












/**
 * Options for JSON parsing.
 * @typedef {object} JSONParseOptions
 * @property {'columns' | 'rows' | 'ndjson' | null} [type] The format type.
 *  One of `'columns'` (for an object with named column arrays)`, 'rows'` (for
 *  an array for row objects), or `'ndjson'` for [newline-delimited JSON][1]
 *  rows. For `'ndjson'`, each line of text must contain a JSON row object
 *  (with no trailing comma) and string properties must not contain any
 *  newline characters. If no format type is specified, one of `'rows'` or
 *  `'columns'` is inferred from the structure of the parsed JSON.
 *
 *  [1]: https://github.com/ndjson/ndjson-spec
 * @property {boolean} [autoType=true] Flag controlling automatic type
 *  inference for column values. If false, date parsing for input JSON
 *  strings is disabled.
 * @property {Record<string, (value: any) => any>} [parse] Object of column
 *  parsing options. The object keys should be column names. The object values
 *  should be parsing functions that transform values upon input.
 * @property {string[]} [columns] An array of column names to include. JSON
 *  properties missing from this list are not included in the table.
 * @property {number} [skip=0] The number of lines to skip before reading data.
 *  Applicable to newline-delimited (NDJSON) data only.
 * @property {string} [comment] A string used to identify comment lines. Any
 *  lines that start with the comment pattern are skipped. Applicable to
 *   newline-delimited (NDJSON)  data only.
 */

/**
 * Parse JavaScript Object Notation (JSON) data into a table.
 * By default, automatic type inference is performed
 * for input values; string values that match the ISO standard
 * date format are parsed into JavaScript Date objects. To disable this
 * behavior, set the autoType option to false. To perform custom parsing
 * of input column values, use the parse option.
 * @param {string} input The input text or stream.
 * @param {JSONParseOptions} options The JSON parse options.
 * @return {ColumnTable} A new table containing the parsed values.
 */
function fromJSON(input, options = {}) {
  const { columns = undefined, type = undefined } = options;
  let data;
  if (type === NDJSON) {
    data = parseJSONSync(input, columns, from_json_transforms(options));
  } else {
    const json = isString(input) ? JSON.parse(input) : input;
    data = (type === COLUMNS || (!type && !isArray(json)))
      ? parseJSONColumns(json, columns)
      : parseJSONRows(json, columns);
  }
  return postprocessJSON(data, options);
}

/**
 * Parse a JavaScript Object Notation (JSON) stream into a table.
 * By default, automatic type inference is performed
 * for input values; string values that match the ISO standard
 * date format are parsed into JavaScript Date objects. To disable this
 * behavior, set the autoType option to false. To perform custom parsing
 * of input column values, use the parse option.
 * @param {ReadableStream<string>} input The input text or stream.
 * @param {JSONParseOptions} options The JSON parse options.
 * @return {Promise<ColumnTable>} A Promise to a new table containing the
 *  parsed values.
 */
async function fromJSONStream(input, options = {}) {
  return options.type === NDJSON
    ? postprocessJSON(
        await parseJSONStream(input, options.columns, from_json_transforms(options)),
        options
      )
    : fromJSON(await collectJSON(input), options);
}

/**
 * Load a JSON file from a URL and return a Promise for an Arquero table.
 * If the loaded JSON is array-valued, an array-of-objects format is assumed
 * and the aq.from method is used to construct the table. Otherwise, a
 * column object format is assumed and aq.fromJSON is applied.
 * @param {string} path The URL or file path to load.
 * @param {import('./types.js').LoadOptions & JSONParseOptions} [options]
 *  JSON parse options.
 * @return {Promise<ColumnTable>} A Promise to an Arquero table.
 * @example aq.loadJSON('data/table.json')
 */
async function loadJSON(path, options) {
  const input = await textStream(path, options);
  if (!options?.type &&
    path.slice(-NDJSON.length-1).toLowerCase() === `.${NDJSON}`) {
    options = { ...options, type: NDJSON };
  }
  return fromJSONStream(input, options);
}

function from_json_transforms({
  comment = undefined,
  skip = 0
} = {}) {
  return [
    textLineTransformer(),
    lineFilterTransformer(skip, comment)
  ];
}

/**
 * @param {import('../table/types.js').ColumnData} data Initial column data.
 * @param {string[]} [names] The column names to use.
 * @return {{
 *   columns: import('../table/types.js').ColumnData,
 *   names: string[]
 * }}
 */
function parseJSONColumns(data, names) {
  /** @type {import('../table/types.js').ColumnData} */
  let columns = data;
  if (names) {
    columns = names.reduce((c, name) => (c[name] = data[name], c), {});
  } else {
    names = Object.keys(columns);
  }
  return { columns, names };
}

/**
 * @param {object[]} data The input row objects.
 * @param {string[]} [names] The column names to use.
 * @return {{
 *   columns: import('../table/types.js').ColumnData,
 *   names: string[]
 * }}
 */
function parseJSONRows(data, names) {
  names ??= Object.keys(data[0]);
  const cols = names.map(() => []);

  const n = data.length;
  const m = names.length;
  for (let i = 0; i < n; ++i) {
    const obj = data[i];
    for (let j = 0; j < m; ++j) {
      cols[j].push(obj[names[j]]);
    }
  }

  /** @type {import('../table/types.js').ColumnData} */
  const columns = {};
  names.forEach((name, i) => columns[name] = cols[i]);
  return { columns, names };
}

/**
 * Post-process JavaScript Object Notation (JSON) data, performing type
 * inference as needed and returning a table instance.
 * @param {{
 *  columns: import('../table/types.js').ColumnData,
 *  names: string[]
 * }} data The column data.
 * @param {JSONParseOptions} [options] The JSON parse options.
 * @return {ColumnTable} A new table containing the parsed values.
 */
function postprocessJSON({ columns, names }, {
  autoType = true,
  parse = undefined
} = {}) {
  // parse values as necessary
  if (autoType || parse) {
    const parsers = parse || {};
    for (const name in columns) {
      const col = columns[name];
      const len = col.length;
      if (parsers[name]) {
        // apply custom parser
        for (let i = 0; i < len; ++i) {
          col[i] = parsers[name](col[i]);
        }
      } else if (autoType) {
        // apply autoType parser
        for (let i = 0; i < len; ++i) {
          const val = col[i];
          if (isString(val) && isISODateString(val) && !isDigitString(val)) {
            col[i] = new Date(val);
          }
        }
      }
    }
  }

  return new ColumnTable(columns, names);
}

;// ../../node_modules/arquero/src/helpers/bin.js
/**
 * Options for binning number values.
 * @typedef {object} BinOptions
 * @property {number} [maxbins] The maximum number of bins.
 * @property {number} [minstep] The minimum step size between bins.
 * @property {number} [step] The exact step size to use between bins.
 *  If specified, the maxbins and minstep options are ignored.
 * @property {boolean} [nice=true] Flag indicating if bins should
 *  snap to "nice" human-friendly values such as multiples of ten.
 * @property {number} [offset=0] Step offset for bin boundaries.
 *  The default floors to the lower bin boundary. A value of 1 snaps
 *  one step higher to the upper bin boundary, and so on.
 */

/**
 * Generate a table expression that performs uniform binning of
 * number values. The resulting string can be used as part of the
 * input to table transformation verbs.
 * @param {string} name The name of the column to bin.
 * @param {BinOptions} [options] Binning scheme options.
 * @return {string} A table expression string for binned values.
 * @example bin('colA', { maxbins: 20 })
 */
function bin_bin(name, options = {}) {
  const field = `d[${JSON.stringify(name)}]`;
  const { maxbins, nice, minstep, step, offset } = options;
  const args = [maxbins, nice, minstep, step];

  let n = args.length;
  while (n && args[--n] == null) args.pop();
  const a = args.length ? ', ' + args.map(a => a + '').join(', ') : '';

  return `d => op.bin(${field}, ...op.bins(${field}${a}), ${offset || 0})`;
}

;// ../../node_modules/arquero/src/verbs/helpers/agg.js



/**
 * Convenience function for computing a single aggregate value for
 * a table. Equivalent to ungrouping a table, applying a rollup verb
 * for a single aggregate, and extracting the resulting value.
 * @param {import('../../table/Table.js').Table} table A table instance.
 * @param {import('../../table/types.js').TableExpr} expr An
 *   aggregate table expression to evaluate.
 * @return {import('../../table/types.js').DataValue} The aggregate value.
 * @example agg(table, op.max('colA'))
 * @example agg(table, d => [op.min('colA'), op.max('colA')])
 */
function agg(table, expr) {
  return rollup(ungroup(table), { _: expr }).get('_');
}

;// ../../node_modules/arquero/src/op/register.js








const onIllegal = (name, type) =>
  error(`Illegal ${type} name: ${toString(name)}`);

const onDefined = (name, type) =>
  error(`The ${type} ${toString(name)} is already defined. Use override option?`);

const onReserve = (name, type) =>
  error(`The ${type} name ${toString(name)} is reserved and can not be overridden.`);

function register_check(name, options, obj = opApi, type = 'function') {
  if (!name) onIllegal(name, type);
  if (!options.override && Object.hasOwn(obj, name)) onDefined(name, type);
}

function verifyFunction(name, def, object, options) {
  return object[name] === def || register_check(name, options);
}

/**
 * Register an aggregate or window operation.
 * @param {string} name The name of the operation
 * @param {AggregateDef|WindowDef} def The operation definition.
 * @param {object} object The registry object to add the definition to.
 * @param {RegisterOptions} [options] Registration options.
 */
function addOp(name, def, object, options = {}) {
  if (verifyFunction(name, def, object, options)) return;
  const [nf = 0, np = 0] = def.param; // num fields, num params
  object[name] = def;
  opApi[name] = (...params) => op(
    name,
    params.slice(0, nf),
    params.slice(nf, nf + np)
  );
}

/**
 * Register a custom aggregate function.
 * @param {string} name The name to use for the aggregate function.
 * @param {AggregateDef} def The aggregate operator definition.
 * @param {RegisterOptions} [options] Function registration options.
 * @throws If a function with the same name is already registered and
 *  the override option is not specified.
 */
function addAggregateFunction(name, def, options) {
  addOp(name, def, aggregateFunctions, options);
}

/**
 * Register a custom window function.
 * @param {string} name The name to use for the window function.
 * @param {WindowDef} def The window operator definition.
 * @param {RegisterOptions} [options] Function registration options.
 * @throws If a function with the same name is already registered and
 *  the override option is not specified.
 */
function addWindowFunction(name, def, options) {
  addOp(name, def, windowFunctions, options);
}

/**
 * Register a function for use within table expressions.
 * If only a single argument is provided, it will be assumed to be a
 * function and the system will try to extract its name.
 * @param {string} name The name to use for the function.
 * @param {Function} fn A standard JavaScript function.
 * @param {RegisterOptions} [options] Function registration options.
 * @throws If a function with the same name is already registered and
 *  the override option is not specified, or if no name is provided
 *  and the input function is anonymous.
 */
function addFunction(name, fn, options = {}) {
  if (arguments.length === 1) {
    // @ts-ignore
    fn = name;
    name = fn.name;
    if (name === '' || name === 'anonymous') {
      error('Anonymous function provided, please include a name argument.');
    } else if (name === ROW_OBJECT) {
      onReserve(ROW_OBJECT, 'function');
    }
  }
  if (verifyFunction(name, fn, functions, options)) return;
  functions[name] = fn;
  opApi[name] = fn;
}

/**
 * Aggregate function definition.
 * @typedef {import('./aggregate-functions.js').AggregateDef} AggregateDef
 */

/**
 * Window function definition.
 * @typedef {import('./window-functions.js').WindowDef} WindowDef
 */

/**
 * Options for registering new functions.
 * @typedef {object} RegisterOptions
 * @property {boolean} [override=false] Flag indicating if the added
 *  function can override an existing function with the same name.
 */

;// ../../node_modules/arquero/src/table/index.js




/**
 * Create a new table for a set of named columns.
 * @param {object|Map} columns
 *  The set of named column arrays. Keys are column names.
 *  The enumeration order of the keys determines the column indices,
 *  unless the names parameter is specified.
 *  Values must be arrays (or array-like values) of identical length.
 * @param {string[]} [names] Ordered list of column names. If specified,
 *  this array determines the column indices. If not specified, the
 *  key enumeration order of the columns object is used.
 * @return {ColumnTable} the instantiated table
 * @example table({ colA: ['a', 'b', 'c'], colB: [3, 4, 5] })
 */
function table(columns, names) {
  if (columns instanceof ColumnTable) return columns;
  /** @type {import('./types.js').ColumnData} */
  const data = {};
  const keys = [];
  for (const [key, value] of entries(columns)) {
    data[key] = value;
    keys.push(key);
  }
  return new ColumnTable(data, names || keys);
}

/**
 * Create a new table from an existing object, such as an array of
 * objects or a set of key-value pairs.
 * @param {object|Array|Map} values Data values to populate the table.
 *  If array-valued or iterable, imports rows for each non-null value,
 *  using the provided column names as keys for each row object. If no
 *  names are provided, the first non-null object's own keys are used.
 *  If object- or Map-valued, create columns for the keys and values.
 * @param {string[]} [names] Column names to include.
 *  For object or Map values, specifies the key and value column names.
 *  Otherwise, specifies the keys to look up on each row object.
 * @return {ColumnTable} the instantiated table.
 * @example from([ { colA: 1, colB: 2 }, { colA: 3, colB: 4 } ])
 */
function from(values, names) {
  return new ColumnTable(columnsFrom(values, names), names);
}

;// ../../node_modules/arquero/src/index.js
// export internal class and method definitions







// public API

























;// ../../node_modules/svelte/src/runtime/store/index.js


const subscriber_queue = [];

/**
 * Creates a `Readable` store that allows reading by subscription.
 *
 * https://svelte.dev/docs/svelte-store#readable
 * @template T
 * @param {T} [value] initial value
 * @param {import('./public.js').StartStopNotifier<T>} [start]
 * @returns {import('./public.js').Readable<T>}
 */
function readable(value, start) {
	return {
		subscribe: writable(value, start).subscribe
	};
}

/**
 * Create a `Writable` store that allows both updating and reading by subscription.
 *
 * https://svelte.dev/docs/svelte-store#writable
 * @template T
 * @param {T} [value] initial value
 * @param {import('./public.js').StartStopNotifier<T>} [start]
 * @returns {import('./public.js').Writable<T>}
 */
function writable(value, start = utils_noop) {
	/** @type {import('./public.js').Unsubscriber} */
	let stop;
	/** @type {Set<import('./private.js').SubscribeInvalidateTuple<T>>} */
	const subscribers = new Set();
	/** @param {T} new_value
	 * @returns {void}
	 */
	function set(new_value) {
		if (safe_not_equal(value, new_value)) {
			value = new_value;
			if (stop) {
				// store is ready
				const run_queue = !subscriber_queue.length;
				for (const subscriber of subscribers) {
					subscriber[1]();
					subscriber_queue.push(subscriber, value);
				}
				if (run_queue) {
					for (let i = 0; i < subscriber_queue.length; i += 2) {
						subscriber_queue[i][0](subscriber_queue[i + 1]);
					}
					subscriber_queue.length = 0;
				}
			}
		}
	}

	/**
	 * @param {import('./public.js').Updater<T>} fn
	 * @returns {void}
	 */
	function update(fn) {
		set(fn(value));
	}

	/**
	 * @param {import('./public.js').Subscriber<T>} run
	 * @param {import('./private.js').Invalidator<T>} [invalidate]
	 * @returns {import('./public.js').Unsubscriber}
	 */
	function subscribe(run, invalidate = utils_noop) {
		/** @type {import('./private.js').SubscribeInvalidateTuple<T>} */
		const subscriber = [run, invalidate];
		subscribers.add(subscriber);
		if (subscribers.size === 1) {
			stop = start(set, update) || utils_noop;
		}
		run(value);
		return () => {
			subscribers.delete(subscriber);
			if (subscribers.size === 0 && stop) {
				stop();
				stop = null;
			}
		};
	}
	return { set, update, subscribe };
}

/**
 * Derived value store by synchronizing one or more readable stores and
 * applying an aggregation function over its input values.
 *
 * https://svelte.dev/docs/svelte-store#derived
 * @template {import('./private.js').Stores} S
 * @template T
 * @overload
 * @param {S} stores - input stores
 * @param {(values: import('./private.js').StoresValues<S>, set: (value: T) => void, update: (fn: import('./public.js').Updater<T>) => void) => import('./public.js').Unsubscriber | void} fn - function callback that aggregates the values
 * @param {T} [initial_value] - initial value
 * @returns {import('./public.js').Readable<T>}
 */

/**
 * Derived value store by synchronizing one or more readable stores and
 * applying an aggregation function over its input values.
 *
 * https://svelte.dev/docs/svelte-store#derived
 * @template {import('./private.js').Stores} S
 * @template T
 * @overload
 * @param {S} stores - input stores
 * @param {(values: import('./private.js').StoresValues<S>) => T} fn - function callback that aggregates the values
 * @param {T} [initial_value] - initial value
 * @returns {import('./public.js').Readable<T>}
 */

/**
 * @template {import('./private.js').Stores} S
 * @template T
 * @param {S} stores
 * @param {Function} fn
 * @param {T} [initial_value]
 * @returns {import('./public.js').Readable<T>}
 */
function derived(stores, fn, initial_value) {
	const single = !Array.isArray(stores);
	/** @type {Array<import('./public.js').Readable<any>>} */
	const stores_array = single ? [stores] : stores;
	if (!stores_array.every(Boolean)) {
		throw new Error('derived() expects stores as input, got a falsy value');
	}
	const auto = fn.length < 2;
	return readable(initial_value, (set, update) => {
		let started = false;
		const values = [];
		let pending = 0;
		let cleanup = utils_noop;
		const sync = () => {
			if (pending) {
				return;
			}
			cleanup();
			const result = fn(single ? values[0] : values, set, update);
			if (auto) {
				set(result);
			} else {
				cleanup = utils_is_function(result) ? result : utils_noop;
			}
		};
		const unsubscribers = stores_array.map((store, i) =>
			subscribe(
				store,
				(value) => {
					values[i] = value;
					pending &= ~(1 << i);
					if (started) {
						sync();
					}
				},
				() => {
					pending |= 1 << i;
				}
			)
		);
		started = true;
		sync();
		return function stop() {
			utils_run_all(unsubscribers);
			cleanup();
			// We need to set this to false because callbacks can still happen despite having unsubscribed:
			// Callbacks might already be placed in the queue which doesn't know it should no longer
			// invoke this derived store.
			started = false;
		};
	});
}

/**
 * Takes a store and returns a new one derived from the old one that is readable.
 *
 * https://svelte.dev/docs/svelte-store#readonly
 * @template T
 * @param {import('./public.js').Readable<T>} store  - store to make readonly
 * @returns {import('./public.js').Readable<T>}
 */
function readonly(store) {
	return {
		subscribe: store.subscribe.bind(store)
	};
}



;// ../../canvas_viz/dist/helpers/table.js
const UNIQUE_COLS_PCTG = 0.1;
function getColumnType(table, columnName) {
    // Check if column exists
    if (!table.column(columnName)) {
        return undefined;
    }
    // Get the first value using array() method
    const columnValues = table.array(columnName);
    const firstValue = columnValues[0];
    // Handle special case for SignedBigNum (often used for large numbers in Arquero)
    if ((firstValue === null || firstValue === void 0 ? void 0 : firstValue.constructor.name) === "SignedBigNum") {
        return "number";
    }
    if (typeof firstValue === "object") {
        const objectClass = firstValue.constructor.name;
        if (objectClass.includes("Array")) {
            return "array";
        }
    }
    return typeof firstValue;
}
function getBinnableStringColumns(table) {
    if (!table) {
        console.warn("[table] getBinnableStringColumns: Table is null or undefined");
        return [];
    }
    try {
        const colNames = table.columnNames();
        const binnnableStringColumns = [];
        // Process in batches for large tables to avoid UI freezing
        const processColumns = (startIdx, batchSize) => {
            const endIdx = Math.min(startIdx + batchSize, colNames.length);
            for (let i = startIdx; i < endIdx; i++) {
                const colName = colNames[i];
                try {
                    const columnType = getColumnType(table, colName);
                    if (columnType === "string") {
                        try {
                            if (isStringColumnBinnable(colName, table)) {
                                binnnableStringColumns.push(colName);
                            }
                        }
                        catch (error) {
                            console.warn(`[table] Error checking if column ${colName} is binnable:`, error);
                        }
                    }
                }
                catch (error) {
                    console.warn(`[table] Error processing column ${colName}:`, error);
                }
            }
            // If there are more columns to process, schedule the next batch
            if (endIdx < colNames.length) {
                setTimeout(() => processColumns(endIdx, batchSize), 0);
            }
        };
        // For smaller tables, process all at once
        if (colNames.length <= 20) {
            processColumns(0, colNames.length);
        }
        else {
            // For larger tables, process in smaller batches
            processColumns(0, 20);
        }
        return binnnableStringColumns;
    }
    catch (error) {
        console.error("[table] getBinnableStringColumns: Error processing table:", error);
        return [];
    }
}
function isStringColumnBinnable(columnName, table) {
    var _a;
    /** If more than UNIQUE_COLS_PCTG percent of the column are unique strings, likely an ID, don't bin. */
    const threshold = Math.ceil(UNIQUE_COLS_PCTG * table.numRows());
    // Early optimization: if we have fewer rows than threshold, we can use the original approach
    if (table.numRows() <= threshold) {
        const unique = table.groupby(columnName).count().numRows();
        return unique < threshold;
    }
    // More memory-efficient approach for larger tables
    const uniqueValues = new Set();
    const column = table.array(columnName);
    // Only need to check until we exceed threshold
    for (let i = 0; i < column.length; i++) {
        const value = ((_a = column[i]) === null || _a === void 0 ? void 0 : _a.toString()) || '';
        uniqueValues.add(value);
        // If we've already found more unique values than our threshold,
        // we can stop early and return false
        if (uniqueValues.size >= threshold) {
            return false;
        }
    }
    return true;
}
const cartesian = (...a) => a.reduce((a, b) => a.flatMap((d) => b.map((e) => [d, e].reduce((acc, val) => acc.concat(val), []))));

;// ../../canvas_viz/dist/stores.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



/**
 * Adapted from https://github.com/cabreraalex/widget-svelte-cookiecutter
 *
 * @param name_ Name of the variable in the model. This is the same as the
 *              name of the corresponding Python variable in widget.py
 * @param value_ Default value
 * @param model backbone model containing state synced between Python and JS
 * @returns Svelte store that is synced with the model.
 */
function createSyncedWidget(name_, value_, model) {
    const name = name_;
    const internalWritable = writable(value_);
    const modelValue = model.get(name);
    if (modelValue !== undefined && modelValue !== null) {
        internalWritable.set(modelValue);
    }
    // when the model changes, update the store
    model.on('change:' + name, () => internalWritable.set(model.get(name)), null);
    return {
        // when the store changes, update the model
        set: (v) => {
            internalWritable.set(v);
            if (model) {
                model.set(name, v);
                model.save_changes();
            }
        },
        subscribe: internalWritable.subscribe,
        update: (func) => {
            internalWritable.update((v) => {
                const output = func(v);
                if (model) {
                    model.set(name, output);
                    model.save_changes();
                }
                return output;
            });
        },
    };
}
let canvasSpec;
let widgetSpecs;
let dataTable;
let selected;
let groupColumns;
let stores_filter;
let filterError;
let tooltip;
let stores_table;
let filteredTable;
let groupNames;
let groupedTables;
/**
 * https://github.com/NicolaZucchia/WorkingVisLabTool/blob/main/src/stores.ts
 * Note that when the cell containing the widget is re-run, a new model is
 * created. We don't want the former model to hang around. We don't want state
 * to carry over when the widget is re-run. That's why all of the stores are
 * initialized in this function, which is called when the widget's cell is run.
 * @param model backbone model that contains state synced between Python and JS
 */
function initializeStores(model) {
    canvasSpec = createSyncedWidget("canvas_spec", {}, model);
    widgetSpecs = createSyncedWidget("widgetSpecs", {}, model);
    dataTable = createSyncedWidget("table", new DataView(new ArrayBuffer(0)), model);
    selected = createSyncedWidget("selected", [], model);
    groupColumns = createSyncedWidget("group_columns", [], model);
    stores_filter = createSyncedWidget("filter", "", model);
    filterError = createSyncedWidget("filter_error", "", model);
    tooltip = createSyncedWidget("data_sample_tooltip", {
        hover: false,
        mousePos: { x: 0, y: 0 },
        fetchPrefix: "",
        instance: undefined,
        number: 0,
    }, model);
    stores_table = derived(dataTable, (d) => fromArrow(d.buffer));
    filteredTable = derived([stores_table, stores_filter], ([table, filter]) => {
        filterError.set("");
        let filteredTable = table;
        if (filter) {
            try {
                filteredTable = filteredTable.filter(filter);
            }
            catch (err) {
                filterError.set(err);
            }
        }
        return filteredTable;
    });
    groupNames = derived([filteredTable, groupColumns], ([filteredTable, groupColumns]) => {
        if (groupColumns.length > 0) {
            const uniqueColumnValues = groupColumns.map((col) => filteredTable
                .rollup({ col: op_api_opApi.array_agg_distinct(col) })
                .object().col);
            // If just one column, don't do cartesian product and make it a 2D array.
            if (uniqueColumnValues.length === 1) {
                return uniqueColumnValues[0].map((group) => [group]);
            }
            return cartesian(...uniqueColumnValues);
        }
        else
            return [];
    });
    groupedTables = derived([filteredTable, groupColumns, groupNames, canvasSpec], ([filteredTable, groupColumns, groupNames, canvasSpec]) => {
        if (groupColumns !== undefined &&
            filteredTable !== undefined &&
            groupNames !== undefined &&
            groupColumns.length > 0 &&
            groupNames.length > 0) {
            let groupedTable = filteredTable.groupby(...groupColumns);
            let partitions = groupedTable.partitions();
            let groupedTables = partitions.map((partition) => filteredTable.reify(Array.from(partition)));
            return groupedTables;
        }
        else {
            return [];
        }
    });
}

;// ../../node_modules/svelte-fa/dist/utils.js
function setCustomFontSize(element, size) {
    if (size && size !== "lg" && size !== "sm" && size !== "xs") {
        element.style.fontSize = size.replace("x", "em");
    }
    else {
        element.style.fontSize = "";
    }
}
function getTransform(scale, translateX, translateY, rotate, flip, translateTimes = 1, translateUnit = "", rotateUnit = "") {
    let flipX = 1;
    let flipY = 1;
    if (flip) {
        if (flip == "horizontal") {
            flipX = -1;
        }
        else if (flip == "vertical") {
            flipY = -1;
        }
        else {
            flipX = flipY = -1;
        }
    }
    if (typeof scale === "string") {
        scale = parseFloat(scale);
    }
    if (typeof translateX === "string") {
        translateX = parseFloat(translateX);
    }
    if (typeof translateY === "string") {
        translateY = parseFloat(translateY);
    }
    const x = `${translateX * translateTimes}${translateUnit}`;
    const y = `${translateY * translateTimes}${translateUnit}`;
    let output = `translate(${x},${y}) scale(${flipX * scale},${flipY * scale})`;
    if (rotate) {
        output += ` rotate(${rotate}${rotateUnit})`;
    }
    return output;
}

;// ../../node_modules/svelte-fa/dist/fa.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-fa/dist/fa.svelte generated by Svelte v4.2.19 */





function add_css(target) {
	append_styles(target, "svelte-16y1fc9", ".svelte-fa-base{height:1em;overflow:visible;transform-origin:center;vertical-align:-0.125em}.svelte-fa-fw{text-align:center;width:1.25em}.svelte-fa-pull-left.svelte-16y1fc9{float:left}.svelte-fa-pull-right.svelte-16y1fc9{float:right}.svelte-fa-size-lg.svelte-16y1fc9{font-size:1.33333em;line-height:0.75em;vertical-align:-0.225em}.svelte-fa-size-sm.svelte-16y1fc9{font-size:0.875em}.svelte-fa-size-xs.svelte-16y1fc9{font-size:0.75em}.spin.svelte-16y1fc9{animation:svelte-16y1fc9-spin 2s 0s infinite linear}.pulse.svelte-16y1fc9{animation:svelte-16y1fc9-spin 1s infinite steps(8)}@keyframes svelte-16y1fc9-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}");
}

// (35:0) {#if i[4]}
function create_if_block(ctx) {
	let svg;
	let g1;
	let g0;
	let g1_transform_value;
	let g1_transform_origin_value;
	let svg_class_value;
	let svg_viewBox_value;
	let svg_aria_hidden_value;
	let if_block0 = /*title*/ ctx[3] && create_if_block_2(ctx);

	function select_block_type(ctx, dirty) {
		if (typeof /*i*/ ctx[17][4] == "string") return create_if_block_1;
		return create_else_block;
	}

	let current_block_type = select_block_type(ctx, -1);
	let if_block1 = current_block_type(ctx);

	return {
		c() {
			svg = svg_element("svg");
			if (if_block0) if_block0.c();
			g1 = svg_element("g");
			g0 = svg_element("g");
			if_block1.c();
			dom_attr(g0, "transform", /*transform*/ ctx[16]);
			dom_attr(g1, "transform", g1_transform_value = "translate(" + /*i*/ ctx[17][0] / 2 + " " + /*i*/ ctx[17][1] / 2 + ")");
			dom_attr(g1, "transform-origin", g1_transform_origin_value = "" + (/*i*/ ctx[17][0] / 4 + " 0"));
			dom_attr(svg, "id", /*id*/ ctx[1]);
			dom_attr(svg, "class", svg_class_value = "svelte-fa svelte-fa-base " + /*clazz*/ ctx[0] + " svelte-16y1fc9");
			dom_attr(svg, "style", /*style*/ ctx[2]);
			dom_attr(svg, "viewBox", svg_viewBox_value = "0 0 " + /*i*/ ctx[17][0] + " " + /*i*/ ctx[17][1]);
			dom_attr(svg, "aria-hidden", svg_aria_hidden_value = /*title*/ ctx[3] === undefined);
			dom_attr(svg, "role", "img");
			dom_attr(svg, "xmlns", "http://www.w3.org/2000/svg");
			toggle_class(svg, "pulse", /*pulse*/ ctx[9]);
			toggle_class(svg, "svelte-fa-size-lg", /*size*/ ctx[4] === "lg");
			toggle_class(svg, "svelte-fa-size-sm", /*size*/ ctx[4] === "sm");
			toggle_class(svg, "svelte-fa-size-xs", /*size*/ ctx[4] === "xs");
			toggle_class(svg, "svelte-fa-fw", /*fw*/ ctx[6]);
			toggle_class(svg, "svelte-fa-pull-left", /*pull*/ ctx[7] === "left");
			toggle_class(svg, "svelte-fa-pull-right", /*pull*/ ctx[7] === "right");
			toggle_class(svg, "spin", /*spin*/ ctx[8]);
		},
		m(target, anchor) {
			dom_insert(target, svg, anchor);
			if (if_block0) if_block0.m(svg, null);
			dom_append(svg, g1);
			dom_append(g1, g0);
			if_block1.m(g0, null);
			/*svg_binding*/ ctx[24](svg);
		},
		p(ctx, dirty) {
			if (/*title*/ ctx[3]) {
				if (if_block0) {
					if_block0.p(ctx, dirty);
				} else {
					if_block0 = create_if_block_2(ctx);
					if_block0.c();
					if_block0.m(svg, g1);
				}
			} else if (if_block0) {
				if_block0.d(1);
				if_block0 = null;
			}

			if (current_block_type === (current_block_type = select_block_type(ctx, dirty)) && if_block1) {
				if_block1.p(ctx, dirty);
			} else {
				if_block1.d(1);
				if_block1 = current_block_type(ctx);

				if (if_block1) {
					if_block1.c();
					if_block1.m(g0, null);
				}
			}

			if (dirty & /*transform*/ 65536) {
				dom_attr(g0, "transform", /*transform*/ ctx[16]);
			}

			if (dirty & /*i*/ 131072 && g1_transform_value !== (g1_transform_value = "translate(" + /*i*/ ctx[17][0] / 2 + " " + /*i*/ ctx[17][1] / 2 + ")")) {
				dom_attr(g1, "transform", g1_transform_value);
			}

			if (dirty & /*i*/ 131072 && g1_transform_origin_value !== (g1_transform_origin_value = "" + (/*i*/ ctx[17][0] / 4 + " 0"))) {
				dom_attr(g1, "transform-origin", g1_transform_origin_value);
			}

			if (dirty & /*id*/ 2) {
				dom_attr(svg, "id", /*id*/ ctx[1]);
			}

			if (dirty & /*clazz*/ 1 && svg_class_value !== (svg_class_value = "svelte-fa svelte-fa-base " + /*clazz*/ ctx[0] + " svelte-16y1fc9")) {
				dom_attr(svg, "class", svg_class_value);
			}

			if (dirty & /*style*/ 4) {
				dom_attr(svg, "style", /*style*/ ctx[2]);
			}

			if (dirty & /*i*/ 131072 && svg_viewBox_value !== (svg_viewBox_value = "0 0 " + /*i*/ ctx[17][0] + " " + /*i*/ ctx[17][1])) {
				dom_attr(svg, "viewBox", svg_viewBox_value);
			}

			if (dirty & /*title*/ 8 && svg_aria_hidden_value !== (svg_aria_hidden_value = /*title*/ ctx[3] === undefined)) {
				dom_attr(svg, "aria-hidden", svg_aria_hidden_value);
			}

			if (dirty & /*clazz, pulse*/ 513) {
				toggle_class(svg, "pulse", /*pulse*/ ctx[9]);
			}

			if (dirty & /*clazz, size*/ 17) {
				toggle_class(svg, "svelte-fa-size-lg", /*size*/ ctx[4] === "lg");
			}

			if (dirty & /*clazz, size*/ 17) {
				toggle_class(svg, "svelte-fa-size-sm", /*size*/ ctx[4] === "sm");
			}

			if (dirty & /*clazz, size*/ 17) {
				toggle_class(svg, "svelte-fa-size-xs", /*size*/ ctx[4] === "xs");
			}

			if (dirty & /*clazz, fw*/ 65) {
				toggle_class(svg, "svelte-fa-fw", /*fw*/ ctx[6]);
			}

			if (dirty & /*clazz, pull*/ 129) {
				toggle_class(svg, "svelte-fa-pull-left", /*pull*/ ctx[7] === "left");
			}

			if (dirty & /*clazz, pull*/ 129) {
				toggle_class(svg, "svelte-fa-pull-right", /*pull*/ ctx[7] === "right");
			}

			if (dirty & /*clazz, spin*/ 257) {
				toggle_class(svg, "spin", /*spin*/ ctx[8]);
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(svg);
			}

			if (if_block0) if_block0.d();
			if_block1.d();
			/*svg_binding*/ ctx[24](null);
		}
	};
}

// (56:4) {#if title}
function create_if_block_2(ctx) {
	let title_1;
	let t;

	return {
		c() {
			title_1 = svg_element("title");
			t = dom_text(/*title*/ ctx[3]);
		},
		m(target, anchor) {
			dom_insert(target, title_1, anchor);
			dom_append(title_1, t);
		},
		p(ctx, dirty) {
			if (dirty & /*title*/ 8) set_data(t, /*title*/ ctx[3]);
		},
		d(detaching) {
			if (detaching) {
				dom_detach(title_1);
			}
		}
	};
}

// (67:8) {:else}
function create_else_block(ctx) {
	let path0;
	let path0_d_value;
	let path0_fill_value;
	let path0_fill_opacity_value;
	let path0_transform_value;
	let path1;
	let path1_d_value;
	let path1_fill_value;
	let path1_fill_opacity_value;
	let path1_transform_value;

	return {
		c() {
			path0 = svg_element("path");
			path1 = svg_element("path");
			dom_attr(path0, "d", path0_d_value = /*i*/ ctx[17][4][0]);
			dom_attr(path0, "fill", path0_fill_value = /*secondaryColor*/ ctx[11] || /*color*/ ctx[5] || "currentColor");

			dom_attr(path0, "fill-opacity", path0_fill_opacity_value = /*swapOpacity*/ ctx[14] != false
			? /*primaryOpacity*/ ctx[12]
			: /*secondaryOpacity*/ ctx[13]);

			dom_attr(path0, "transform", path0_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")");
			dom_attr(path1, "d", path1_d_value = /*i*/ ctx[17][4][1]);
			dom_attr(path1, "fill", path1_fill_value = /*primaryColor*/ ctx[10] || /*color*/ ctx[5] || "currentColor");

			dom_attr(path1, "fill-opacity", path1_fill_opacity_value = /*swapOpacity*/ ctx[14] != false
			? /*secondaryOpacity*/ ctx[13]
			: /*primaryOpacity*/ ctx[12]);

			dom_attr(path1, "transform", path1_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")");
		},
		m(target, anchor) {
			dom_insert(target, path0, anchor);
			dom_insert(target, path1, anchor);
		},
		p(ctx, dirty) {
			if (dirty & /*i*/ 131072 && path0_d_value !== (path0_d_value = /*i*/ ctx[17][4][0])) {
				dom_attr(path0, "d", path0_d_value);
			}

			if (dirty & /*secondaryColor, color*/ 2080 && path0_fill_value !== (path0_fill_value = /*secondaryColor*/ ctx[11] || /*color*/ ctx[5] || "currentColor")) {
				dom_attr(path0, "fill", path0_fill_value);
			}

			if (dirty & /*swapOpacity, primaryOpacity, secondaryOpacity*/ 28672 && path0_fill_opacity_value !== (path0_fill_opacity_value = /*swapOpacity*/ ctx[14] != false
			? /*primaryOpacity*/ ctx[12]
			: /*secondaryOpacity*/ ctx[13])) {
				dom_attr(path0, "fill-opacity", path0_fill_opacity_value);
			}

			if (dirty & /*i*/ 131072 && path0_transform_value !== (path0_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")")) {
				dom_attr(path0, "transform", path0_transform_value);
			}

			if (dirty & /*i*/ 131072 && path1_d_value !== (path1_d_value = /*i*/ ctx[17][4][1])) {
				dom_attr(path1, "d", path1_d_value);
			}

			if (dirty & /*primaryColor, color*/ 1056 && path1_fill_value !== (path1_fill_value = /*primaryColor*/ ctx[10] || /*color*/ ctx[5] || "currentColor")) {
				dom_attr(path1, "fill", path1_fill_value);
			}

			if (dirty & /*swapOpacity, secondaryOpacity, primaryOpacity*/ 28672 && path1_fill_opacity_value !== (path1_fill_opacity_value = /*swapOpacity*/ ctx[14] != false
			? /*secondaryOpacity*/ ctx[13]
			: /*primaryOpacity*/ ctx[12])) {
				dom_attr(path1, "fill-opacity", path1_fill_opacity_value);
			}

			if (dirty & /*i*/ 131072 && path1_transform_value !== (path1_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")")) {
				dom_attr(path1, "transform", path1_transform_value);
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(path0);
				dom_detach(path1);
			}
		}
	};
}

// (61:8) {#if typeof i[4] == "string"}
function create_if_block_1(ctx) {
	let path;
	let path_d_value;
	let path_fill_value;
	let path_transform_value;

	return {
		c() {
			path = svg_element("path");
			dom_attr(path, "d", path_d_value = /*i*/ ctx[17][4]);
			dom_attr(path, "fill", path_fill_value = /*color*/ ctx[5] || /*primaryColor*/ ctx[10] || "currentColor");
			dom_attr(path, "transform", path_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")");
		},
		m(target, anchor) {
			dom_insert(target, path, anchor);
		},
		p(ctx, dirty) {
			if (dirty & /*i*/ 131072 && path_d_value !== (path_d_value = /*i*/ ctx[17][4])) {
				dom_attr(path, "d", path_d_value);
			}

			if (dirty & /*color, primaryColor*/ 1056 && path_fill_value !== (path_fill_value = /*color*/ ctx[5] || /*primaryColor*/ ctx[10] || "currentColor")) {
				dom_attr(path, "fill", path_fill_value);
			}

			if (dirty & /*i*/ 131072 && path_transform_value !== (path_transform_value = "translate(" + /*i*/ ctx[17][0] / -2 + " " + /*i*/ ctx[17][1] / -2 + ")")) {
				dom_attr(path, "transform", path_transform_value);
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(path);
			}
		}
	};
}

function create_fragment(ctx) {
	let if_block_anchor;
	let if_block = /*i*/ ctx[17][4] && create_if_block(ctx);

	return {
		c() {
			if (if_block) if_block.c();
			if_block_anchor = empty();
		},
		m(target, anchor) {
			if (if_block) if_block.m(target, anchor);
			dom_insert(target, if_block_anchor, anchor);
		},
		p(ctx, [dirty]) {
			if (/*i*/ ctx[17][4]) {
				if (if_block) {
					if_block.p(ctx, dirty);
				} else {
					if_block = create_if_block(ctx);
					if_block.c();
					if_block.m(if_block_anchor.parentNode, if_block_anchor);
				}
			} else if (if_block) {
				if_block.d(1);
				if_block = null;
			}
		},
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(if_block_anchor);
			}

			if (if_block) if_block.d(detaching);
		}
	};
}

function instance($$self, $$props, $$invalidate) {
	let i;
	let transform;
	let { class: clazz = void 0 } = $$props;
	let { id = void 0 } = $$props;
	let { style = void 0 } = $$props;
	let { icon } = $$props;
	let { title = void 0 } = $$props;
	let { size = void 0 } = $$props;
	let { color = void 0 } = $$props;
	let { fw = false } = $$props;
	let { pull = void 0 } = $$props;
	let { scale = 1 } = $$props;
	let { translateX = 0 } = $$props;
	let { translateY = 0 } = $$props;
	let { rotate = void 0 } = $$props;
	let { flip = void 0 } = $$props;
	let { spin = false } = $$props;
	let { pulse = false } = $$props;
	let { primaryColor = "" } = $$props;
	let { secondaryColor = "" } = $$props;
	let { primaryOpacity = 1 } = $$props;
	let { secondaryOpacity = 0.4 } = $$props;
	let { swapOpacity = false } = $$props;
	let svgElement;

	function svg_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			svgElement = $$value;
			$$invalidate(15, svgElement);
		});
	}

	$$self.$$set = $$props => {
		if ('class' in $$props) $$invalidate(0, clazz = $$props.class);
		if ('id' in $$props) $$invalidate(1, id = $$props.id);
		if ('style' in $$props) $$invalidate(2, style = $$props.style);
		if ('icon' in $$props) $$invalidate(18, icon = $$props.icon);
		if ('title' in $$props) $$invalidate(3, title = $$props.title);
		if ('size' in $$props) $$invalidate(4, size = $$props.size);
		if ('color' in $$props) $$invalidate(5, color = $$props.color);
		if ('fw' in $$props) $$invalidate(6, fw = $$props.fw);
		if ('pull' in $$props) $$invalidate(7, pull = $$props.pull);
		if ('scale' in $$props) $$invalidate(19, scale = $$props.scale);
		if ('translateX' in $$props) $$invalidate(20, translateX = $$props.translateX);
		if ('translateY' in $$props) $$invalidate(21, translateY = $$props.translateY);
		if ('rotate' in $$props) $$invalidate(22, rotate = $$props.rotate);
		if ('flip' in $$props) $$invalidate(23, flip = $$props.flip);
		if ('spin' in $$props) $$invalidate(8, spin = $$props.spin);
		if ('pulse' in $$props) $$invalidate(9, pulse = $$props.pulse);
		if ('primaryColor' in $$props) $$invalidate(10, primaryColor = $$props.primaryColor);
		if ('secondaryColor' in $$props) $$invalidate(11, secondaryColor = $$props.secondaryColor);
		if ('primaryOpacity' in $$props) $$invalidate(12, primaryOpacity = $$props.primaryOpacity);
		if ('secondaryOpacity' in $$props) $$invalidate(13, secondaryOpacity = $$props.secondaryOpacity);
		if ('swapOpacity' in $$props) $$invalidate(14, swapOpacity = $$props.swapOpacity);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*svgElement, size*/ 32784) {
			$: if (svgElement && size) {
				setCustomFontSize(svgElement, size);
			}
		}

		if ($$self.$$.dirty & /*icon*/ 262144) {
			$: $$invalidate(17, i = icon && icon.icon || [0, 0, "", [], ""]);
		}

		if ($$self.$$.dirty & /*scale, translateX, translateY, rotate, flip*/ 16252928) {
			$: $$invalidate(16, transform = getTransform(scale, translateX, translateY, rotate, flip, 512));
		}
	};

	return [
		clazz,
		id,
		style,
		title,
		size,
		color,
		fw,
		pull,
		spin,
		pulse,
		primaryColor,
		secondaryColor,
		primaryOpacity,
		secondaryOpacity,
		swapOpacity,
		svgElement,
		transform,
		i,
		icon,
		scale,
		translateX,
		translateY,
		rotate,
		flip,
		svg_binding
	];
}

class Fa extends SvelteComponent {
	constructor(options) {
		super();

		init(
			this,
			options,
			instance,
			create_fragment,
			safe_not_equal,
			{
				class: 0,
				id: 1,
				style: 2,
				icon: 18,
				title: 3,
				size: 4,
				color: 5,
				fw: 6,
				pull: 7,
				scale: 19,
				translateX: 20,
				translateY: 21,
				rotate: 22,
				flip: 23,
				spin: 8,
				pulse: 9,
				primaryColor: 10,
				secondaryColor: 11,
				primaryOpacity: 12,
				secondaryOpacity: 13,
				swapOpacity: 14
			},
			add_css
		);
	}
}

/* harmony default export */ const fa_svelte = (Fa);
;// ../../node_modules/svelte-fa/dist/fa-layers.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-fa/dist/fa-layers.svelte generated by Svelte v4.2.19 */





function fa_layers_svelte_add_css(target) {
	append_styles(target, "svelte-duy4ya", ".svelte-fa-layers.svelte-duy4ya{display:inline-block;position:relative}.svelte-fa-layers.svelte-duy4ya .svelte-fa{position:absolute;bottom:0;left:0;right:0;top:0;margin:auto;text-align:center}.svelte-fa-layers.svelte-duy4ya .svelte-fa-layers-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%)}.svelte-fa-layers.svelte-duy4ya .svelte-fa-layers-text span{display:inline-block}.svelte-fa-pull-left.svelte-duy4ya{float:left}.svelte-fa-pull-right.svelte-duy4ya{float:right}.svelte-fa-size-lg.svelte-duy4ya{font-size:1.33333em;line-height:0.75em;vertical-align:-0.225em}.svelte-fa-size-sm.svelte-duy4ya{font-size:0.875em}.svelte-fa-size-xs.svelte-duy4ya{font-size:0.75em}");
}

function fa_layers_svelte_create_fragment(ctx) {
	let span;
	let span_class_value;
	let current;
	const default_slot_template = /*#slots*/ ctx[7].default;
	const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[6], null);

	return {
		c() {
			span = dom_element("span");
			if (default_slot) default_slot.c();
			dom_attr(span, "id", /*id*/ ctx[1]);
			dom_attr(span, "class", span_class_value = "svelte-fa-layers svelte-fa-base svelte-fa-fw " + /*clazz*/ ctx[0] + " svelte-duy4ya");
			dom_attr(span, "style", /*style*/ ctx[2]);
			toggle_class(span, "svelte-fa-pull-left", /*pull*/ ctx[4] === "left");
			toggle_class(span, "svelte-fa-pull-right", /*pull*/ ctx[4] === "right");
			toggle_class(span, "svelte-fa-size-lg", /*size*/ ctx[3] === "lg");
			toggle_class(span, "svelte-fa-size-sm", /*size*/ ctx[3] === "sm");
			toggle_class(span, "svelte-fa-size-xs", /*size*/ ctx[3] === "xs");
		},
		m(target, anchor) {
			dom_insert(target, span, anchor);

			if (default_slot) {
				default_slot.m(span, null);
			}

			/*span_binding*/ ctx[8](span);
			current = true;
		},
		p(ctx, [dirty]) {
			if (default_slot) {
				if (default_slot.p && (!current || dirty & /*$$scope*/ 64)) {
					update_slot_base(
						default_slot,
						default_slot_template,
						ctx,
						/*$$scope*/ ctx[6],
						!current
						? get_all_dirty_from_scope(/*$$scope*/ ctx[6])
						: get_slot_changes(default_slot_template, /*$$scope*/ ctx[6], dirty, null),
						null
					);
				}
			}

			if (!current || dirty & /*id*/ 2) {
				dom_attr(span, "id", /*id*/ ctx[1]);
			}

			if (!current || dirty & /*clazz*/ 1 && span_class_value !== (span_class_value = "svelte-fa-layers svelte-fa-base svelte-fa-fw " + /*clazz*/ ctx[0] + " svelte-duy4ya")) {
				dom_attr(span, "class", span_class_value);
			}

			if (!current || dirty & /*style*/ 4) {
				dom_attr(span, "style", /*style*/ ctx[2]);
			}

			if (!current || dirty & /*clazz, pull*/ 17) {
				toggle_class(span, "svelte-fa-pull-left", /*pull*/ ctx[4] === "left");
			}

			if (!current || dirty & /*clazz, pull*/ 17) {
				toggle_class(span, "svelte-fa-pull-right", /*pull*/ ctx[4] === "right");
			}

			if (!current || dirty & /*clazz, size*/ 9) {
				toggle_class(span, "svelte-fa-size-lg", /*size*/ ctx[3] === "lg");
			}

			if (!current || dirty & /*clazz, size*/ 9) {
				toggle_class(span, "svelte-fa-size-sm", /*size*/ ctx[3] === "sm");
			}

			if (!current || dirty & /*clazz, size*/ 9) {
				toggle_class(span, "svelte-fa-size-xs", /*size*/ ctx[3] === "xs");
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(default_slot, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(default_slot, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(span);
			}

			if (default_slot) default_slot.d(detaching);
			/*span_binding*/ ctx[8](null);
		}
	};
}

function fa_layers_svelte_instance($$self, $$props, $$invalidate) {
	let { $$slots: slots = {}, $$scope } = $$props;
	let { class: clazz = void 0 } = $$props;
	let { id = void 0 } = $$props;
	let { style = void 0 } = $$props;
	let { size = void 0 } = $$props;
	let { pull = void 0 } = $$props;
	let containerElement;

	function span_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			containerElement = $$value;
			$$invalidate(5, containerElement);
		});
	}

	$$self.$$set = $$props => {
		if ('class' in $$props) $$invalidate(0, clazz = $$props.class);
		if ('id' in $$props) $$invalidate(1, id = $$props.id);
		if ('style' in $$props) $$invalidate(2, style = $$props.style);
		if ('size' in $$props) $$invalidate(3, size = $$props.size);
		if ('pull' in $$props) $$invalidate(4, pull = $$props.pull);
		if ('$$scope' in $$props) $$invalidate(6, $$scope = $$props.$$scope);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*containerElement, size*/ 40) {
			$: if (containerElement && size) {
				setCustomFontSize(containerElement, size);
			}
		}
	};

	return [clazz, id, style, size, pull, containerElement, $$scope, slots, span_binding];
}

class Fa_layers extends SvelteComponent {
	constructor(options) {
		super();

		init(
			this,
			options,
			fa_layers_svelte_instance,
			fa_layers_svelte_create_fragment,
			safe_not_equal,
			{
				class: 0,
				id: 1,
				style: 2,
				size: 3,
				pull: 4
			},
			fa_layers_svelte_add_css
		);
	}
}

/* harmony default export */ const fa_layers_svelte = ((/* unused pure expression or super */ null && (Fa_layers)));
;// ../../node_modules/svelte-fa/dist/fa-layers-text.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-fa/dist/fa-layers-text.svelte generated by Svelte v4.2.19 */





function fa_layers_text_svelte_add_css(target) {
	append_styles(target, "svelte-h566x7", ".container.svelte-h566x7{display:inline-block;height:auto}.svelte-fa-size-lg.svelte-h566x7{font-size:1.33333em;line-height:0.75em;vertical-align:-0.225em}.svelte-fa-size-sm.svelte-h566x7{font-size:0.875em}.svelte-fa-size-xs.svelte-h566x7{font-size:0.75em}");
}

function fa_layers_text_svelte_create_fragment(ctx) {
	let span1;
	let span0;
	let span1_class_value;
	let current;
	const default_slot_template = /*#slots*/ ctx[13].default;
	const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[12], null);

	return {
		c() {
			span1 = dom_element("span");
			span0 = dom_element("span");
			if (default_slot) default_slot.c();
			dom_attr(span0, "class", "svelte-fa-base container svelte-h566x7");
			dom_attr(span0, "style", /*style*/ ctx[2]);
			toggle_class(span0, "svelte-fa-size-lg", /*size*/ ctx[3] === "lg");
			toggle_class(span0, "svelte-fa-size-sm", /*size*/ ctx[3] === "sm");
			toggle_class(span0, "svelte-fa-size-xs", /*size*/ ctx[3] === "xs");
			dom_attr(span1, "id", /*id*/ ctx[1]);
			dom_attr(span1, "class", span1_class_value = "svelte-fa-layers-text " + /*clazz*/ ctx[0] + " svelte-h566x7");
		},
		m(target, anchor) {
			dom_insert(target, span1, anchor);
			dom_append(span1, span0);

			if (default_slot) {
				default_slot.m(span0, null);
			}

			/*span0_binding*/ ctx[14](span0);
			current = true;
		},
		p(ctx, [dirty]) {
			if (default_slot) {
				if (default_slot.p && (!current || dirty & /*$$scope*/ 4096)) {
					update_slot_base(
						default_slot,
						default_slot_template,
						ctx,
						/*$$scope*/ ctx[12],
						!current
						? get_all_dirty_from_scope(/*$$scope*/ ctx[12])
						: get_slot_changes(default_slot_template, /*$$scope*/ ctx[12], dirty, null),
						null
					);
				}
			}

			if (!current || dirty & /*style*/ 4) {
				dom_attr(span0, "style", /*style*/ ctx[2]);
			}

			if (!current || dirty & /*size*/ 8) {
				toggle_class(span0, "svelte-fa-size-lg", /*size*/ ctx[3] === "lg");
			}

			if (!current || dirty & /*size*/ 8) {
				toggle_class(span0, "svelte-fa-size-sm", /*size*/ ctx[3] === "sm");
			}

			if (!current || dirty & /*size*/ 8) {
				toggle_class(span0, "svelte-fa-size-xs", /*size*/ ctx[3] === "xs");
			}

			if (!current || dirty & /*id*/ 2) {
				dom_attr(span1, "id", /*id*/ ctx[1]);
			}

			if (!current || dirty & /*clazz*/ 1 && span1_class_value !== (span1_class_value = "svelte-fa-layers-text " + /*clazz*/ ctx[0] + " svelte-h566x7")) {
				dom_attr(span1, "class", span1_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(default_slot, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(default_slot, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(span1);
			}

			if (default_slot) default_slot.d(detaching);
			/*span0_binding*/ ctx[14](null);
		}
	};
}

function fa_layers_text_svelte_instance($$self, $$props, $$invalidate) {
	let transform;
	let { $$slots: slots = {}, $$scope } = $$props;
	let { class: clazz = void 0 } = $$props;
	let { id = void 0 } = $$props;
	let { style = void 0 } = $$props;
	let { size = void 0 } = $$props;
	let { color = "" } = $$props;
	let { scale = 1 } = $$props;
	let { translateX = 0 } = $$props;
	let { translateY = 0 } = $$props;
	let { rotate = void 0 } = $$props;
	let { flip = void 0 } = $$props;
	let containerElement;

	function span0_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			containerElement = $$value;
			((((((($$invalidate(4, containerElement), $$invalidate(11, transform)), $$invalidate(5, color)), $$invalidate(6, scale)), $$invalidate(7, translateX)), $$invalidate(8, translateY)), $$invalidate(9, rotate)), $$invalidate(10, flip));
		});
	}

	$$self.$$set = $$props => {
		if ('class' in $$props) $$invalidate(0, clazz = $$props.class);
		if ('id' in $$props) $$invalidate(1, id = $$props.id);
		if ('style' in $$props) $$invalidate(2, style = $$props.style);
		if ('size' in $$props) $$invalidate(3, size = $$props.size);
		if ('color' in $$props) $$invalidate(5, color = $$props.color);
		if ('scale' in $$props) $$invalidate(6, scale = $$props.scale);
		if ('translateX' in $$props) $$invalidate(7, translateX = $$props.translateX);
		if ('translateY' in $$props) $$invalidate(8, translateY = $$props.translateY);
		if ('rotate' in $$props) $$invalidate(9, rotate = $$props.rotate);
		if ('flip' in $$props) $$invalidate(10, flip = $$props.flip);
		if ('$$scope' in $$props) $$invalidate(12, $$scope = $$props.$$scope);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*scale, translateX, translateY, rotate, flip*/ 1984) {
			$: $$invalidate(11, transform = getTransform(scale, translateX, translateY, rotate, flip, 1, "em", "deg"));
		}

		if ($$self.$$.dirty & /*containerElement, transform*/ 2064) {
			$: if (containerElement) {
				$$invalidate(4, containerElement.style.transform = transform, containerElement);
			}
		}

		if ($$self.$$.dirty & /*containerElement, color*/ 48) {
			$: if (containerElement && color) {
				$$invalidate(4, containerElement.style.color = color, containerElement);
			}
		}

		if ($$self.$$.dirty & /*containerElement, size*/ 24) {
			$: if (containerElement && size) {
				setCustomFontSize(containerElement, size);
			}
		}
	};

	return [
		clazz,
		id,
		style,
		size,
		containerElement,
		color,
		scale,
		translateX,
		translateY,
		rotate,
		flip,
		transform,
		$$scope,
		slots,
		span0_binding
	];
}

class Fa_layers_text extends SvelteComponent {
	constructor(options) {
		super();

		init(
			this,
			options,
			fa_layers_text_svelte_instance,
			fa_layers_text_svelte_create_fragment,
			safe_not_equal,
			{
				class: 0,
				id: 1,
				style: 2,
				size: 3,
				color: 5,
				scale: 6,
				translateX: 7,
				translateY: 8,
				rotate: 9,
				flip: 10
			},
			fa_layers_text_svelte_add_css
		);
	}
}

/* harmony default export */ const fa_layers_text_svelte = ((/* unused pure expression or super */ null && (Fa_layers_text)));
;// ../../node_modules/svelte-fa/dist/index.js



/* harmony default export */ const dist = (fa_svelte);



;// ../../node_modules/svelte/src/runtime/easing/index.js
/*
Adapted from https://github.com/mattdesl
Distributed under MIT License https://github.com/mattdesl/eases/blob/master/LICENSE.md
*/


/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function backInOut(t) {
	const s = 1.70158 * 1.525;
	if ((t *= 2) < 1) return 0.5 * (t * t * ((s + 1) * t - s));
	return 0.5 * ((t -= 2) * t * ((s + 1) * t + s) + 2);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function backIn(t) {
	const s = 1.70158;
	return t * t * ((s + 1) * t - s);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function backOut(t) {
	const s = 1.70158;
	return --t * t * ((s + 1) * t + s) + 1;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function bounceOut(t) {
	const a = 4.0 / 11.0;
	const b = 8.0 / 11.0;
	const c = 9.0 / 10.0;
	const ca = 4356.0 / 361.0;
	const cb = 35442.0 / 1805.0;
	const cc = 16061.0 / 1805.0;
	const t2 = t * t;
	return t < a
		? 7.5625 * t2
		: t < b
		? 9.075 * t2 - 9.9 * t + 3.4
		: t < c
		? ca * t2 - cb * t + cc
		: 10.8 * t * t - 20.52 * t + 10.72;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function bounceInOut(t) {
	return t < 0.5 ? 0.5 * (1.0 - bounceOut(1.0 - t * 2.0)) : 0.5 * bounceOut(t * 2.0 - 1.0) + 0.5;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function bounceIn(t) {
	return 1.0 - bounceOut(1.0 - t);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function circInOut(t) {
	if ((t *= 2) < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1);
	return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function circIn(t) {
	return 1.0 - Math.sqrt(1.0 - t * t);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function circOut(t) {
	return Math.sqrt(1 - --t * t);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function easing_cubicInOut(t) {
	return t < 0.5 ? 4.0 * t * t * t : 0.5 * Math.pow(2.0 * t - 2.0, 3.0) + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function cubicIn(t) {
	return t * t * t;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function easing_cubicOut(t) {
	const f = t - 1.0;
	return f * f * f + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function elasticInOut(t) {
	return t < 0.5
		? 0.5 * Math.sin(((+13.0 * Math.PI) / 2) * 2.0 * t) * Math.pow(2.0, 10.0 * (2.0 * t - 1.0))
		: 0.5 *
				Math.sin(((-13.0 * Math.PI) / 2) * (2.0 * t - 1.0 + 1.0)) *
				Math.pow(2.0, -10.0 * (2.0 * t - 1.0)) +
				1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function elasticIn(t) {
	return Math.sin((13.0 * t * Math.PI) / 2) * Math.pow(2.0, 10.0 * (t - 1.0));
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function elasticOut(t) {
	return Math.sin((-13.0 * (t + 1.0) * Math.PI) / 2) * Math.pow(2.0, -10.0 * t) + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function expoInOut(t) {
	return t === 0.0 || t === 1.0
		? t
		: t < 0.5
		? +0.5 * Math.pow(2.0, 20.0 * t - 10.0)
		: -0.5 * Math.pow(2.0, 10.0 - t * 20.0) + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function expoIn(t) {
	return t === 0.0 ? t : Math.pow(2.0, 10.0 * (t - 1.0));
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function expoOut(t) {
	return t === 1.0 ? t : 1.0 - Math.pow(2.0, -10.0 * t);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quadInOut(t) {
	t /= 0.5;
	if (t < 1) return 0.5 * t * t;
	t--;
	return -0.5 * (t * (t - 2) - 1);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quadIn(t) {
	return t * t;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quadOut(t) {
	return -t * (t - 2.0);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quartInOut(t) {
	return t < 0.5 ? +8.0 * Math.pow(t, 4.0) : -8.0 * Math.pow(t - 1.0, 4.0) + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quartIn(t) {
	return Math.pow(t, 4.0);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quartOut(t) {
	return Math.pow(t - 1.0, 3.0) * (1.0 - t) + 1.0;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quintInOut(t) {
	if ((t *= 2) < 1) return 0.5 * t * t * t * t * t;
	return 0.5 * ((t -= 2) * t * t * t * t + 2);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quintIn(t) {
	return t * t * t * t * t;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function quintOut(t) {
	return --t * t * t * t * t + 1;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function sineInOut(t) {
	return -0.5 * (Math.cos(Math.PI * t) - 1);
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function sineIn(t) {
	const v = Math.cos(t * Math.PI * 0.5);
	if (Math.abs(v) < 1e-14) return 1;
	else return 1 - v;
}

/**
 * https://svelte.dev/docs/svelte-easing
 * @param {number} t
 * @returns {number}
 */
function sineOut(t) {
	return Math.sin((t * Math.PI) / 2);
}

;// ../../node_modules/svelte/src/runtime/transition/index.js



/**
 * Animates a `blur` filter alongside an element's opacity.
 *
 * https://svelte.dev/docs/svelte-transition#blur
 * @param {Element} node
 * @param {import('./public').BlurParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function transition_blur(
	node,
	{ delay = 0, duration = 400, easing = cubicInOut, amount = 5, opacity = 0 } = {}
) {
	const style = getComputedStyle(node);
	const target_opacity = +style.opacity;
	const f = style.filter === 'none' ? '' : style.filter;
	const od = target_opacity * (1 - opacity);
	const [value, unit] = split_css_unit(amount);
	return {
		delay,
		duration,
		easing,
		css: (_t, u) => `opacity: ${target_opacity - od * u}; filter: ${f} blur(${u * value}${unit});`
	};
}

/**
 * Animates the opacity of an element from 0 to the current opacity for `in` transitions and from the current opacity to 0 for `out` transitions.
 *
 * https://svelte.dev/docs/svelte-transition#fade
 * @param {Element} node
 * @param {import('./public').FadeParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function fade(node, { delay = 0, duration = 400, easing = utils_identity } = {}) {
	const o = +getComputedStyle(node).opacity;
	return {
		delay,
		duration,
		easing,
		css: (t) => `opacity: ${t * o}`
	};
}

/**
 * Animates the x and y positions and the opacity of an element. `in` transitions animate from the provided values, passed as parameters to the element's default values. `out` transitions animate from the element's default values to the provided values.
 *
 * https://svelte.dev/docs/svelte-transition#fly
 * @param {Element} node
 * @param {import('./public').FlyParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function fly(
	node,
	{ delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 } = {}
) {
	const style = getComputedStyle(node);
	const target_opacity = +style.opacity;
	const transform = style.transform === 'none' ? '' : style.transform;
	const od = target_opacity * (1 - opacity);
	const [xValue, xUnit] = split_css_unit(x);
	const [yValue, yUnit] = split_css_unit(y);
	return {
		delay,
		duration,
		easing,
		css: (t, u) => `
			transform: ${transform} translate(${(1 - t) * xValue}${xUnit}, ${(1 - t) * yValue}${yUnit});
			opacity: ${target_opacity - od * u}`
	};
}

/**
 * Slides an element in and out.
 *
 * https://svelte.dev/docs/svelte-transition#slide
 * @param {Element} node
 * @param {import('./public').SlideParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function slide(node, { delay = 0, duration = 400, easing = easing_cubicOut, axis = 'y' } = {}) {
	const style = getComputedStyle(node);
	const opacity = +style.opacity;
	const primary_property = axis === 'y' ? 'height' : 'width';
	const primary_property_value = parseFloat(style[primary_property]);
	const secondary_properties = axis === 'y' ? ['top', 'bottom'] : ['left', 'right'];
	const capitalized_secondary_properties = secondary_properties.map(
		(e) => `${e[0].toUpperCase()}${e.slice(1)}`
	);
	const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`]);
	const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`]);
	const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`]);
	const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`]);
	const border_width_start_value = parseFloat(
		style[`border${capitalized_secondary_properties[0]}Width`]
	);
	const border_width_end_value = parseFloat(
		style[`border${capitalized_secondary_properties[1]}Width`]
	);
	return {
		delay,
		duration,
		easing,
		css: (t) =>
			'overflow: hidden;' +
			`opacity: ${Math.min(t * 20, 1) * opacity};` +
			`${primary_property}: ${t * primary_property_value}px;` +
			`padding-${secondary_properties[0]}: ${t * padding_start_value}px;` +
			`padding-${secondary_properties[1]}: ${t * padding_end_value}px;` +
			`margin-${secondary_properties[0]}: ${t * margin_start_value}px;` +
			`margin-${secondary_properties[1]}: ${t * margin_end_value}px;` +
			`border-${secondary_properties[0]}-width: ${t * border_width_start_value}px;` +
			`border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;`
	};
}

/**
 * Animates the opacity and scale of an element. `in` transitions animate from an element's current (default) values to the provided values, passed as parameters. `out` transitions animate from the provided values to an element's default values.
 *
 * https://svelte.dev/docs/svelte-transition#scale
 * @param {Element} node
 * @param {import('./public').ScaleParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function transition_scale(
	node,
	{ delay = 0, duration = 400, easing = cubicOut, start = 0, opacity = 0 } = {}
) {
	const style = getComputedStyle(node);
	const target_opacity = +style.opacity;
	const transform = style.transform === 'none' ? '' : style.transform;
	const sd = 1 - start;
	const od = target_opacity * (1 - opacity);
	return {
		delay,
		duration,
		easing,
		css: (_t, u) => `
			transform: ${transform} scale(${1 - sd * u});
			opacity: ${target_opacity - od * u}
		`
	};
}

/**
 * Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `<path>` and `<polyline>`.
 *
 * https://svelte.dev/docs/svelte-transition#draw
 * @param {SVGElement & { getTotalLength(): number }} node
 * @param {import('./public').DrawParams} [params]
 * @returns {import('./public').TransitionConfig}
 */
function draw(node, { delay = 0, speed, duration, easing = cubicInOut } = {}) {
	let len = node.getTotalLength();
	const style = getComputedStyle(node);
	if (style.strokeLinecap !== 'butt') {
		len += parseInt(style.strokeWidth);
	}
	if (duration === undefined) {
		if (speed === undefined) {
			duration = 800;
		} else {
			duration = len / speed;
		}
	} else if (typeof duration === 'function') {
		duration = duration(len);
	}
	return {
		delay,
		duration,
		easing,
		css: (_, u) => `
			stroke-dasharray: ${len};
			stroke-dashoffset: ${u * len};
		`
	};
}

/**
 * The `crossfade` function creates a pair of [transitions](https://svelte.dev/docs#template-syntax-element-directives-transition-fn) called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used.
 *
 * https://svelte.dev/docs/svelte-transition#crossfade
 * @param {import('./public').CrossfadeParams & {
 * 	fallback?: (node: Element, params: import('./public').CrossfadeParams, intro: boolean) => import('./public').TransitionConfig;
 * }} params
 * @returns {[(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig, (node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig]}
 */
function crossfade({ fallback, ...defaults }) {
	/** @type {Map<any, Element>} */
	const to_receive = new Map();
	/** @type {Map<any, Element>} */
	const to_send = new Map();
	/**
	 * @param {Element} from_node
	 * @param {Element} node
	 * @param {import('./public').CrossfadeParams} params
	 * @returns {import('./public').TransitionConfig}
	 */
	function crossfade(from_node, node, params) {
		const {
			delay = 0,
			duration = (d) => Math.sqrt(d) * 30,
			easing = cubicOut
		} = assign(assign({}, defaults), params);
		const from = from_node.getBoundingClientRect();
		const to = node.getBoundingClientRect();
		const dx = from.left - to.left;
		const dy = from.top - to.top;
		const dw = from.width / to.width;
		const dh = from.height / to.height;
		const d = Math.sqrt(dx * dx + dy * dy);
		const style = getComputedStyle(node);
		const transform = style.transform === 'none' ? '' : style.transform;
		const opacity = +style.opacity;
		return {
			delay,
			duration: is_function(duration) ? duration(d) : duration,
			easing,
			css: (t, u) => `
				opacity: ${t * opacity};
				transform-origin: top left;
				transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${
				t + (1 - t) * dh
			});
			`
		};
	}

	/**
	 * @param {Map<any, Element>} items
	 * @param {Map<any, Element>} counterparts
	 * @param {boolean} intro
	 * @returns {(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig}
	 */
	function transition(items, counterparts, intro) {
		return (node, params) => {
			items.set(params.key, node);
			return () => {
				if (counterparts.has(params.key)) {
					const other_node = counterparts.get(params.key);
					counterparts.delete(params.key);
					return crossfade(other_node, node, params);
				}
				// if the node is disappearing altogether
				// (i.e. wasn't claimed by the other list)
				// then we need to supply an outro
				items.delete(params.key);
				return fallback && fallback(node, params, intro);
			};
		};
	}
	return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)];
}

// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faChartBar.js
var faChartBar = __webpack_require__(4383);
;// ../../canvas_viz/dist/types.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var CanvasDataType;
(function (CanvasDataType) {
    CanvasDataType[CanvasDataType["TABULAR"] = 1] = "TABULAR";
    CanvasDataType[CanvasDataType["IMAGE"] = 2] = "IMAGE";
    CanvasDataType[CanvasDataType["AUDIO"] = 3] = "AUDIO";
})(CanvasDataType || (CanvasDataType = {}));
var ResolverType;
(function (ResolverType) {
    ResolverType[ResolverType["BINNED_STRING"] = 0] = "BINNED_STRING";
    ResolverType[ResolverType["NUMBER"] = 1] = "NUMBER";
})(ResolverType || (ResolverType = {}));

;// ../../node_modules/@fireflysemantics/join/fesm2015/fireflysemantics-join.js
/**
MIT License

Copyright (c) Firefly Semantics Corporation
Copyright (c) 2020 Ole K. Ersoy
Copyright (c) 2015 José F. Romaniello

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
/**
 * @param args The components of the URL
 * @throws TypeError if the args URL components are not all of type string
 * @return The URL string
 */
function fireflysemantics_join_join(...args) {
    let components = [];
    /**
     * If an empty array is received then
     * the URL is just ''.
     */
    if (args.length === 0) {
        return '';
    }
    /** The args values must be of type string */
    args.forEach(component => {
        if (typeof component !== 'string') {
            throw new TypeError(`Url components must be of type string. 
                    The ${component} component is of type ${typeof component}`);
        }
    });
    /**
     * If the protocol is specified by itself,
     * then the protocol is combined with the
     * subsequent array value.
     */
    const protocol = args[0];
    if (protocol.match(/^[^/:]+:\/*$/) && args.length > 1) {
        var first = args.shift();
        args[0] = first + args[0];
    }
    /**
     * The file protocol should have two or three slashes.
     * Other protocols should have 2.
     */
    if (args[0].match(/^file:\/\/\//)) {
        args[0] = args[0].replace(/^([^/:]+):\/*/, '$1:///');
    }
    else {
        args[0] = args[0].replace(/^([^/:]+):\/*/, '$1://');
    }
    /** The args values must be of type string */
    args.forEach((component, i) => {
        if (component === '') {
            return;
        }
        /**
         * Remove starting slashes for all but the first component
         */
        if (i > 0) {
            component = component.replace(/^[\/]+/, '');
        }
        /**
         * Remove the ending slashes for each component but the last.
         */
        if (i < args.length - 1) {
            component = component.replace(/[\/]+$/, '');
        }
        else {
            // For the last combine multiple slashes into one.
            component = component.replace(/[\/]+$/, '/');
        }
        components.push(component);
    });
    /**
     * Separate all the components by a single /
     */
    let url = components.join('/');
    // remove trailing slash before parameters or hash
    url = url.replace(/\/(\?|&|#[^!])/g, '$1');
    // replace ? in parameters with &
    var parts = url.split('?');
    url = parts.shift() + (parts.length > 0 ? '?' : '') + parts.join('&');
    return url;
}

/*
 * Public API Surface of join
 */

/**
 * Generated bundle index. Do not edit.
 */


//# sourceMappingURL=fireflysemantics-join.js.map

// EXTERNAL MODULE: ../../node_modules/@jupyterlab/services/lib/index.js
var lib = __webpack_require__(7883);
;// ../../canvas_viz/dist/helpers/contentservice.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Singleton contentsService class for managing file operations
 */
class ContentsService {
    constructor() {
        var _a;
        const contentsManager = new lib.ContentsManager();
        this.contentsManager = contentsManager;
        // Get the server root from the contents manager settings
        this.baseServerPath = ((_a = contentsManager.serverSettings) === null || _a === void 0 ? void 0 : _a.baseUrl) || process.env.JUPYTER_SERVER_ROOT || '';
    }
    static getInstance() {
        if (!this.instance) {
            this.instance = new ContentsService();
        }
        return this.instance;
    }
    /**
     * Create a file/directory if it does not exist. Otherwise, save the change in a file/directory in the given path
     * @param path path to a file/directory
     * @param options options that specify if it's a file or directory and additial information
     * Usage: save('snippets', { type: 'directory' }) to create/save a directory
     *        save('snippets/test.json', {type: 'file', format: 'text', content: 'Lorem ipsum dolor sit amet'})
     */
    async save(path, options) {
        try {
            const changedModel = await this.contentsManager.save(path, options);
            return changedModel;
        }
        catch (error) {
            console.error('Error saving file/directory:', error);
            throw error; // Re-throw the error instead of returning it
        }
    }
    async readContent(path) {
        try {
            const getFileResult = await this.contentsManager.get(path);
            if (typeof getFileResult.content !== 'string') {
                throw new Error('Unable to read the image');
            }
            return `data:${getFileResult.mimetype};${getFileResult.format},${getFileResult.content}`;
        }
        catch (error) {
            console.error('Error reading file/directory:', error);
            throw error; // Re-throw the error instead of returning it
        }
    }
    async readAudioContent(path) {
        try {
            const getFileResult = await this.contentsManager.get(path);
            if (typeof getFileResult.content !== 'string') {
                throw new Error('Unable to read the Audio data');
            }
            return `${getFileResult.content}`;
        }
        catch (error) {
            console.error('Error reading file/directory:', error);
            throw error; // Re-throw the error instead of returning it
        }
    }
    /**
     * Convert a server path to a local filesystem path
     * @param path - Server path (e.g., '/notebooks/example.ipynb')
     * @returns Local filesystem path (e.g., '/home/user/notebooks/example.ipynb')
     *
     * Usage:
     * ```typescript
     * const serverPath = '/notebooks/example.ipynb';
     * const localPath = contentsService.getLocalPath(serverPath);
     * console.log(localPath); // '/home/user/notebooks/example.ipynb'
     * ```
     */
    getLocalPath(path) {
        const relativePath = this.contentsManager.localPath(path);
        if (!this.baseServerPath) {
            console.warn('Base server path not available, returning relative path');
            return relativePath;
        }
        return `${this.baseServerPath}/${relativePath}`.replace(/\/+/g, '/'); // Clean up any double slashes
    }
    /**
     * Convert a local filesystem path to a server path
     * @param localPath - Local filesystem path (e.g., '/home/user/notebooks/example.ipynb')
     * @returns Server path (e.g., '/notebooks/example.ipynb')
     *
     * Usage:
     * ```typescript
     * const localPath = '/home/user/notebooks/example.ipynb';
     * const serverPath = contentsService.getServerPath(localPath);
     * console.log(serverPath); // '/notebooks/example.ipynb'
     * ```
     */
    getServerPath(localPath) {
        return this.contentsManager.normalize(localPath);
    }
    /**
     * Resolve a relative path against a parent directory
     * @param relativePath - Relative path to resolve (e.g., '../data/file.csv')
     * @param parent - Parent directory to resolve against (e.g., '/notebooks/project')
     * @returns Resolved absolute server path
     *
     * Usage:
     * ```typescript
     * // When in /notebooks/project/analysis
     * const relativePath = '../data/file.csv';
     * const parent = '/notebooks/project/analysis';
     * const resolved = contentsService.resolvePath(relativePath, parent);
     * console.log(resolved); // '/notebooks/project/data/file.csv'
     *
     * // Handle special cases
     * contentsService.resolvePath('.', '/home');        // Returns '/home'
     * contentsService.resolvePath('..', '/home/user');  // Returns '/home'
     * contentsService.resolvePath('file.txt', '/dir');  // Returns '/dir/file.txt'
     * ```
     */
    resolvePath(relativePath, parent) {
        return this.contentsManager.resolvePath(relativePath, parent);
    }
}

;// ../../canvas_viz/dist/elements/ImageSample.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/ImageSample.svelte generated by Svelte v4.2.19 */






function create_catch_block(ctx) {
	let p;
	let t_value = /*error*/ ctx[9].message + "";
	let t;

	return {
		c() {
			p = dom_element("p");
			t = dom_text(t_value);
			dom_attr(p, "class", "error");
		},
		m(target, anchor) {
			dom_insert(target, p, anchor);
			dom_append(p, t);
		},
		p(ctx, dirty) {
			if (dirty & /*imagePromise*/ 8 && t_value !== (t_value = /*error*/ ctx[9].message + "")) set_data(t, t_value);
		},
		d(detaching) {
			if (detaching) {
				dom_detach(p);
			}
		}
	};
}

// (53:2) {:then src}
function create_then_block(ctx) {
	let img;
	let img_src_value;
	let img_alt_value;
	let img_class_value;
	let img_style_value;
	let mounted;
	let dispose;

	return {
		c() {
			img = dom_element("img");
			dom_attr(img, "id", "imageSample");
			if (!src_url_equal(img.src, img_src_value = /*src*/ ctx[8])) dom_attr(img, "src", img_src_value);
			dom_attr(img, "alt", img_alt_value = "Image with title: " + /*id*/ ctx[0]);
			dom_attr(img, "class", img_class_value = /*large*/ ctx[2] ? "mx-1" : "w-12 m-1");
			dom_attr(img, "style", img_style_value = `background: black; max-width: ${/*large*/ ctx[2] ? '256px' : '128px'}`);
		},
		m(target, anchor) {
			dom_insert(target, img, anchor);

			if (!mounted) {
				dispose = dom_listen(img, "error", handleImageError);
				mounted = true;
			}
		},
		p(ctx, dirty) {
			if (dirty & /*imagePromise*/ 8 && !src_url_equal(img.src, img_src_value = /*src*/ ctx[8])) {
				dom_attr(img, "src", img_src_value);
			}

			if (dirty & /*id*/ 1 && img_alt_value !== (img_alt_value = "Image with title: " + /*id*/ ctx[0])) {
				dom_attr(img, "alt", img_alt_value);
			}

			if (dirty & /*large*/ 4 && img_class_value !== (img_class_value = /*large*/ ctx[2] ? "mx-1" : "w-12 m-1")) {
				dom_attr(img, "class", img_class_value);
			}

			if (dirty & /*large*/ 4 && img_style_value !== (img_style_value = `background: black; max-width: ${/*large*/ ctx[2] ? '256px' : '128px'}`)) {
				dom_attr(img, "style", img_style_value);
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(img);
			}

			mounted = false;
			dispose();
		}
	};
}

// (51:23)      <p class="loading">Loading...</p>   {:then src}
function create_pending_block(ctx) {
	let p;

	return {
		c() {
			p = dom_element("p");
			p.textContent = "Loading...";
			dom_attr(p, "class", "loading");
		},
		m(target, anchor) {
			dom_insert(target, p, anchor);
		},
		p: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(p);
			}
		}
	};
}

function ImageSample_svelte_create_fragment(ctx) {
	let div;
	let promise;

	let info = {
		ctx,
		current: null,
		token: null,
		hasCatch: true,
		pending: create_pending_block,
		then: create_then_block,
		catch: create_catch_block,
		value: 8,
		error: 9
	};

	handle_promise(promise = /*imagePromise*/ ctx[3], info);

	return {
		c() {
			div = dom_element("div");
			info.block.c();
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			info.block.m(div, info.anchor = null);
			info.mount = () => div;
			info.anchor = null;
		},
		p(new_ctx, [dirty]) {
			ctx = new_ctx;
			info.ctx = ctx;

			if (dirty & /*imagePromise*/ 8 && promise !== (promise = /*imagePromise*/ ctx[3]) && handle_promise(promise, info)) {
				
			} else {
				update_await_block_branch(info, ctx, dirty);
			}
		},
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			info.block.d();
			info.token = null;
			info = null;
		}
	};
}

function handleImageError(event) {
	console.error("Error loading image:", event);
	const target = event.target;
	target.alt = 'Image failed to load';
}

function ImageSample_svelte_instance($$self, $$props, $$invalidate) {
	let $canvasSpec,
		$$unsubscribe_canvasSpec = utils_noop,
		$$subscribe_canvasSpec = () => ($$unsubscribe_canvasSpec(), $$unsubscribe_canvasSpec = subscribe(canvasSpec, $$value => $$invalidate(5, $canvasSpec = $$value)), canvasSpec);

	$$self.$$.on_destroy.push(() => $$unsubscribe_canvasSpec());
	let { id } = $$props;
	let { canvasSpec } = $$props;
	$$subscribe_canvasSpec();
	let { large = false } = $$props;
	let { storybook = false } = $$props;
	let imagePromise;
	const contentsManager = ContentsService.getInstance();

	async function loadImage(filesPath, imageId) {
		if (storybook) {
			return fireflysemantics_join_join(filesPath, imageId);
		} else {
			try {
				const filePath = fireflysemantics_join_join(filesPath, imageId);
				const result = await contentsManager.readContent(filePath);

				if (typeof result !== 'string') {
					throw new Error('Unexpected content type');
				}

				return result;
			} catch(error) {
				console.error('Error reading image file:', error);
				throw new Error(`Failed to load image: ${imageId}`);
			}
		}
	}

	$$self.$$set = $$props => {
		if ('id' in $$props) $$invalidate(0, id = $$props.id);
		if ('canvasSpec' in $$props) $$subscribe_canvasSpec($$invalidate(1, canvasSpec = $$props.canvasSpec));
		if ('large' in $$props) $$invalidate(2, large = $$props.large);
		if ('storybook' in $$props) $$invalidate(4, storybook = $$props.storybook);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*$canvasSpec, id*/ 33) {
			$: $$invalidate(3, imagePromise = loadImage($canvasSpec.filesPath, id));
		}
	};

	return [id, canvasSpec, large, imagePromise, storybook, $canvasSpec];
}

class ImageSample extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, ImageSample_svelte_instance, ImageSample_svelte_create_fragment, safe_not_equal, {
			id: 0,
			canvasSpec: 1,
			large: 2,
			storybook: 4
		});
	}
}

/* harmony default export */ const ImageSample_svelte = (ImageSample);
;// ../../node_modules/svelte/src/runtime/index.js


// EXTERNAL MODULE: ../../node_modules/wavesurfer.js/dist/wavesurfer.js
var dist_wavesurfer = __webpack_require__(7290);
var wavesurfer_default = /*#__PURE__*/__webpack_require__.n(dist_wavesurfer);
;// ../../canvas_viz/dist/elements/IconButton.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/IconButton.svelte generated by Svelte v4.2.19 */



const get_text_slot_changes = dirty => ({});
const get_text_slot_context = ctx => ({});
const get_icon_slot_changes = dirty => ({});
const get_icon_slot_context = ctx => ({});

// (26:4) {#if $$slots.icon}
function IconButton_svelte_create_if_block(ctx) {
	let div;
	let div_class_value;
	let current;
	const icon_slot_template = /*#slots*/ ctx[3].icon;
	const icon_slot = create_slot(icon_slot_template, ctx, /*$$scope*/ ctx[2], get_icon_slot_context);

	return {
		c() {
			div = dom_element("div");
			if (icon_slot) icon_slot.c();
			dom_attr(div, "class", div_class_value = /*$$slots*/ ctx[1].text ? "pr-2 flex" : "flex");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);

			if (icon_slot) {
				icon_slot.m(div, null);
			}

			current = true;
		},
		p(ctx, dirty) {
			if (icon_slot) {
				if (icon_slot.p && (!current || dirty & /*$$scope*/ 4)) {
					update_slot_base(
						icon_slot,
						icon_slot_template,
						ctx,
						/*$$scope*/ ctx[2],
						!current
						? get_all_dirty_from_scope(/*$$scope*/ ctx[2])
						: get_slot_changes(icon_slot_template, /*$$scope*/ ctx[2], dirty, get_icon_slot_changes),
						get_icon_slot_context
					);
				}
			}

			if (!current || dirty & /*$$slots*/ 2 && div_class_value !== (div_class_value = /*$$slots*/ ctx[1].text ? "pr-2 flex" : "flex")) {
				dom_attr(div, "class", div_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(icon_slot, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(icon_slot, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			if (icon_slot) icon_slot.d(detaching);
		}
	};
}

function IconButton_svelte_create_fragment(ctx) {
	let button;
	let div;
	let t;
	let button_class_value;
	let current;
	let mounted;
	let dispose;
	let if_block = /*$$slots*/ ctx[1].icon && IconButton_svelte_create_if_block(ctx);
	const text_slot_template = /*#slots*/ ctx[3].text;
	const text_slot = create_slot(text_slot_template, ctx, /*$$scope*/ ctx[2], get_text_slot_context);

	return {
		c() {
			button = dom_element("button");
			div = dom_element("div");
			if (if_block) if_block.c();
			t = space();
			if (text_slot) text_slot.c();
			dom_attr(div, "class", "flex items-center");

			dom_attr(button, "class", button_class_value = "" + ((/*filled*/ ctx[0]
			? 'bg-button hover:bg-button_hover text-text-dark'
			: 'bg-white text-button border border-button hover:bg-button hover:text-white') + " rounded-md py-1 px-2 transition"));
		},
		m(target, anchor) {
			dom_insert(target, button, anchor);
			dom_append(button, div);
			if (if_block) if_block.m(div, null);
			dom_append(div, t);

			if (text_slot) {
				text_slot.m(div, null);
			}

			current = true;

			if (!mounted) {
				dispose = [
					dom_listen(button, "click", /*click_handler*/ ctx[4]),
					dom_listen(button, "mouseleave", /*mouseleave_handler*/ ctx[5])
				];

				mounted = true;
			}
		},
		p(ctx, [dirty]) {
			if (/*$$slots*/ ctx[1].icon) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*$$slots*/ 2) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = IconButton_svelte_create_if_block(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}

			if (text_slot) {
				if (text_slot.p && (!current || dirty & /*$$scope*/ 4)) {
					update_slot_base(
						text_slot,
						text_slot_template,
						ctx,
						/*$$scope*/ ctx[2],
						!current
						? get_all_dirty_from_scope(/*$$scope*/ ctx[2])
						: get_slot_changes(text_slot_template, /*$$scope*/ ctx[2], dirty, get_text_slot_changes),
						get_text_slot_context
					);
				}
			}

			if (!current || dirty & /*filled*/ 1 && button_class_value !== (button_class_value = "" + ((/*filled*/ ctx[0]
			? 'bg-button hover:bg-button_hover text-text-dark'
			: 'bg-white text-button border border-button hover:bg-button hover:text-white') + " rounded-md py-1 px-2 transition"))) {
				dom_attr(button, "class", button_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			transitions_transition_in(text_slot, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			transitions_transition_out(text_slot, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(button);
			}

			if (if_block) if_block.d();
			if (text_slot) text_slot.d(detaching);
			mounted = false;
			utils_run_all(dispose);
		}
	};
}

function IconButton_svelte_instance($$self, $$props, $$invalidate) {
	let { $$slots: slots = {}, $$scope } = $$props;
	const $$slots = compute_slots(slots);
	let { filled = false } = $$props;

	function click_handler(event) {
		bubble.call(this, $$self, event);
	}

	function mouseleave_handler(event) {
		bubble.call(this, $$self, event);
	}

	$$self.$$set = $$props => {
		if ('filled' in $$props) $$invalidate(0, filled = $$props.filled);
		if ('$$scope' in $$props) $$invalidate(2, $$scope = $$props.$$scope);
	};

	return [filled, $$slots, $$scope, slots, click_handler, mouseleave_handler];
}

class IconButton extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, IconButton_svelte_instance, IconButton_svelte_create_fragment, safe_not_equal, { filled: 0 });
	}
}

/* harmony default export */ const IconButton_svelte = (IconButton);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faPlay.js
var faPlay = __webpack_require__(3852);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faPause.js
var faPause = __webpack_require__(2162);
;// ../../canvas_viz/dist/elements/AudioSample.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/AudioSample.svelte generated by Svelte v4.2.19 */












function create_icon_slot(ctx) {
	let fa;
	let current;

	fa = new dist({
			props: {
				icon: /*playing*/ ctx[3] ? faPause/* faPause */.G1 : faPlay/* faPlay */.ij,
				slot: "icon"
			}
		});

	return {
		c() {
			create_component(fa.$$.fragment);
		},
		m(target, anchor) {
			mount_component(fa, target, anchor);
			current = true;
		},
		p(ctx, dirty) {
			const fa_changes = {};
			if (dirty & /*playing*/ 8) fa_changes.icon = /*playing*/ ctx[3] ? faPause/* faPause */.G1 : faPlay/* faPlay */.ij;
			fa.$set(fa_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(fa, detaching);
		}
	};
}

function AudioSample_svelte_create_fragment(ctx) {
	let div1;
	let button;
	let t;
	let div0;
	let iconbutton;
	let div1_class_value;
	let current;
	let mounted;
	let dispose;

	iconbutton = new IconButton_svelte({
			props: {
				$$slots: { icon: [create_icon_slot] },
				$$scope: { ctx }
			}
		});

	iconbutton.$on("click", /*changePlayStatus*/ ctx[4]);

	return {
		c() {
			div1 = dom_element("div");
			button = dom_element("button");
			t = space();
			div0 = dom_element("div");
			create_component(iconbutton.$$.fragment);
			dom_attr(button, "type", "button");
			dom_attr(button, "class", "p-0 border-0 bg-transparent");
			dom_attr(div1, "class", div1_class_value = "flex flex-col " + (/*large*/ ctx[1] ? 'w-48 mx-1' : 'w-24 m-1'));
		},
		m(target, anchor) {
			dom_insert(target, div1, anchor);
			dom_append(div1, button);
			/*button_binding*/ ctx[11](button);
			dom_append(div1, t);
			dom_append(div1, div0);
			mount_component(iconbutton, div0, null);
			current = true;

			if (!mounted) {
				dispose = dom_listen(button, "click", /*click_handler*/ ctx[10]);
				mounted = true;
			}
		},
		p(ctx, [dirty]) {
			const iconbutton_changes = {};

			if (dirty & /*$$scope, playing*/ 8200) {
				iconbutton_changes.$$scope = { dirty, ctx };
			}

			iconbutton.$set(iconbutton_changes);

			if (!current || dirty & /*large*/ 2 && div1_class_value !== (div1_class_value = "flex flex-col " + (/*large*/ ctx[1] ? 'w-48 mx-1' : 'w-24 m-1'))) {
				dom_attr(div1, "class", div1_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(iconbutton.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(iconbutton.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div1);
			}

			/*button_binding*/ ctx[11](null);
			destroy_component(iconbutton);
			mounted = false;
			dispose();
		}
	};
}

function base64ToArrayBuffer(base64) {
	try {
		const trimmedBase64 = base64.trim();
		const binaryString = atob(trimmedBase64);
		const bytes = new Uint8Array(binaryString.length);

		for (let i = 0; i < binaryString.length; i++) {
			bytes[i] = binaryString.charCodeAt(i);
		}

		return bytes.buffer;
	} catch(error) {
		console.error("Failed to decode base64 string:", error);
		console.log("Problematic base64 string:", base64);
		throw error;
	}
}

function AudioSample_svelte_instance($$self, $$props, $$invalidate) {
	let $canvasSpec,
		$$unsubscribe_canvasSpec = utils_noop,
		$$subscribe_canvasSpec = () => ($$unsubscribe_canvasSpec(), $$unsubscribe_canvasSpec = subscribe(canvasSpec, $$value => $$invalidate(9, $canvasSpec = $$value)), canvasSpec);

	$$self.$$.on_destroy.push(() => $$unsubscribe_canvasSpec());
	let { id } = $$props;
	let { canvasSpec } = $$props;
	$$subscribe_canvasSpec();
	let { large = false } = $$props;
	let { storybook = false } = $$props;
	const contentsManager = ContentsService.getInstance();
	let container;
	let wavesurfer;
	let playing = false;
	let oldId = "";

	function changePlayStatus() {
		if (playing) {
			wavesurfer.pause();
			$$invalidate(3, playing = false);
		} else {
			wavesurfer.play();
			$$invalidate(3, playing = true);
		}
	}

	onDestroy(() => {
		if (wavesurfer) {
			wavesurfer.destroy();
		}
	});

	function click_handler(event) {
		bubble.call(this, $$self, event);
	}

	function button_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			container = $$value;
			((((($$invalidate(2, container), $$invalidate(5, id)), $$invalidate(8, oldId)), $$invalidate(7, wavesurfer)), $$invalidate(9, $canvasSpec)), $$invalidate(6, storybook));
		});
	}

	$$self.$$set = $$props => {
		if ('id' in $$props) $$invalidate(5, id = $$props.id);
		if ('canvasSpec' in $$props) $$subscribe_canvasSpec($$invalidate(0, canvasSpec = $$props.canvasSpec));
		if ('large' in $$props) $$invalidate(1, large = $$props.large);
		if ('storybook' in $$props) $$invalidate(6, storybook = $$props.storybook);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*container, id, oldId, wavesurfer, $canvasSpec, storybook*/ 996) {
			$: if (container !== undefined && id !== oldId) {
				if (wavesurfer !== undefined) wavesurfer.destroy();
				$$invalidate(2, container.innerHTML = "", container);

				$$invalidate(7, wavesurfer = wavesurfer_default().create({
					container,
					waveColor: "#cfcfcf",
					progressColor: "#0071e3"
				}));

				const filePath = fireflysemantics_join_join($canvasSpec.filesPath, id);

				if (storybook) {
					wavesurfer.load(filePath);
				} else {
					contentsManager.readAudioContent(filePath).then(result => {
						const arrayBuffer = base64ToArrayBuffer(result);
						wavesurfer.loadArrayBuffer(arrayBuffer);
					}).catch(error => {
						console.error("Unable to load the audio data", error);
					});
				}

				$$invalidate(3, playing = false);
				$$invalidate(8, oldId = id);
			}
		}
	};

	return [
		canvasSpec,
		large,
		container,
		playing,
		changePlayStatus,
		id,
		storybook,
		wavesurfer,
		oldId,
		$canvasSpec,
		click_handler,
		button_binding
	];
}

class AudioSample extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, AudioSample_svelte_instance, AudioSample_svelte_create_fragment, safe_not_equal, {
			id: 5,
			canvasSpec: 0,
			large: 1,
			storybook: 6
		});
	}
}

/* harmony default export */ const AudioSample_svelte = (AudioSample);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faTable.js
var faTable = __webpack_require__(7184);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faSort.js
var faSort = __webpack_require__(4584);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faSortUp.js
var faSortUp = __webpack_require__(8079);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faSortDown.js
var faSortDown = __webpack_require__(8958);
;// ../../canvas_viz/dist/elements/TabularSample.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/TabularSample.svelte generated by Svelte v4.2.19 */









function TabularSample_svelte_add_css(target) {
	append_styles(target, "svelte-1m3mj5f", "table.svelte-1m3mj5f{border-collapse:collapse;width:100%}th.svelte-1m3mj5f,td.svelte-1m3mj5f{border-color:#d1d5db}thead.svelte-1m3mj5f{border-bottom:2px solid #d1d5db}.header-bg.svelte-1m3mj5f{background-color:#1e3a8a}.hover-header.svelte-1m3mj5f:hover{background-color:#1e40af}.even-row.svelte-1m3mj5f{background-color:#e6f3ff}.odd-row.svelte-1m3mj5f{background-color:#f0f7ff}tr.svelte-1m3mj5f:hover{background-color:#cce4ff !important}");
}

function get_each_context(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[9] = list[i];
	child_ctx[11] = i;
	return child_ctx;
}

function get_each_context_1(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[12] = list[i];
	return child_ctx;
}

function get_each_context_2(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[12] = list[i];
	return child_ctx;
}

// (58:0) {:else}
function TabularSample_svelte_create_else_block(ctx) {
	let div;
	let table;
	let thead;
	let tr;
	let t;
	let tbody;
	let current;
	let each_value_2 = each_ensure_array_like(/*columns*/ ctx[2]);
	let each_blocks_1 = [];

	for (let i = 0; i < each_value_2.length; i += 1) {
		each_blocks_1[i] = create_each_block_2(get_each_context_2(ctx, each_value_2, i));
	}

	const out = i => transitions_transition_out(each_blocks_1[i], 1, 1, () => {
		each_blocks_1[i] = null;
	});

	let each_value = each_ensure_array_like(/*sortedData*/ ctx[1]);
	let each_blocks = [];

	for (let i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
	}

	return {
		c() {
			div = dom_element("div");
			table = dom_element("table");
			thead = dom_element("thead");
			tr = dom_element("tr");

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				each_blocks_1[i].c();
			}

			t = space();
			tbody = dom_element("tbody");

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			dom_attr(tr, "class", "svelte-1m3mj5f");
			dom_attr(thead, "class", "header-bg svelte-1m3mj5f");
			dom_attr(tbody, "class", "divide-y divide-gray-300");
			dom_attr(table, "class", "min-w-full divide-y divide-gray-300 svelte-1m3mj5f");
			dom_attr(div, "class", "overflow-x-auto border rounded-lg shadow-sm");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			dom_append(div, table);
			dom_append(table, thead);
			dom_append(thead, tr);

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				if (each_blocks_1[i]) {
					each_blocks_1[i].m(tr, null);
				}
			}

			dom_append(table, t);
			dom_append(table, tbody);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(tbody, null);
				}
			}

			current = true;
		},
		p(ctx, dirty) {
			if (dirty & /*toggleSort, columns, getSortIcon*/ 28) {
				each_value_2 = each_ensure_array_like(/*columns*/ ctx[2]);
				let i;

				for (i = 0; i < each_value_2.length; i += 1) {
					const child_ctx = get_each_context_2(ctx, each_value_2, i);

					if (each_blocks_1[i]) {
						each_blocks_1[i].p(child_ctx, dirty);
						transitions_transition_in(each_blocks_1[i], 1);
					} else {
						each_blocks_1[i] = create_each_block_2(child_ctx);
						each_blocks_1[i].c();
						transitions_transition_in(each_blocks_1[i], 1);
						each_blocks_1[i].m(tr, null);
					}
				}

				group_outros();

				for (i = each_value_2.length; i < each_blocks_1.length; i += 1) {
					out(i);
				}

				check_outros();
			}

			if (dirty & /*columns, sortedData*/ 6) {
				each_value = each_ensure_array_like(/*sortedData*/ ctx[1]);
				let i;

				for (i = 0; i < each_value.length; i += 1) {
					const child_ctx = get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
					} else {
						each_blocks[i] = create_each_block(child_ctx);
						each_blocks[i].c();
						each_blocks[i].m(tbody, null);
					}
				}

				for (; i < each_blocks.length; i += 1) {
					each_blocks[i].d(1);
				}

				each_blocks.length = each_value.length;
			}
		},
		i(local) {
			if (current) return;

			for (let i = 0; i < each_value_2.length; i += 1) {
				transitions_transition_in(each_blocks_1[i]);
			}

			current = true;
		},
		o(local) {
			each_blocks_1 = each_blocks_1.filter(Boolean);

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				transitions_transition_out(each_blocks_1[i]);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_each(each_blocks_1, detaching);
			destroy_each(each_blocks, detaching);
		}
	};
}

// (53:0) {#if data.length === 0}
function TabularSample_svelte_create_if_block(ctx) {
	let div;
	let fa;
	let t0;
	let span;
	let current;
	fa = new dist({ props: { icon: faTable/* faTable */.w9 } });

	return {
		c() {
			div = dom_element("div");
			create_component(fa.$$.fragment);
			t0 = space();
			span = dom_element("span");
			span.textContent = "No data available";
			dom_attr(span, "class", "ml-2");
			dom_attr(div, "class", "p-2 text-gray-500 flex items-center justify-center border rounded-lg");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(fa, div, null);
			dom_append(div, t0);
			dom_append(div, span);
			current = true;
		},
		p: utils_noop,
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(fa);
		}
	};
}

// (63:10) {#each columns as column}
function create_each_block_2(ctx) {
	let th;
	let div;
	let t0_value = /*column*/ ctx[12] + "";
	let t0;
	let t1;
	let span;
	let fa;
	let t2;
	let current;
	let mounted;
	let dispose;

	fa = new dist({
			props: {
				icon: /*getSortIcon*/ ctx[4](/*column*/ ctx[12]),
				size: "sm"
			}
		});

	function click_handler() {
		return /*click_handler*/ ctx[8](/*column*/ ctx[12]);
	}

	return {
		c() {
			th = dom_element("th");
			div = dom_element("div");
			t0 = dom_text(t0_value);
			t1 = space();
			span = dom_element("span");
			create_component(fa.$$.fragment);
			t2 = space();
			dom_attr(span, "class", "ml-2");
			dom_attr(div, "class", "flex items-center");
			dom_attr(th, "class", "px-6 py-3 text-left text-xs font-bold text-white uppercase tracking-wider cursor-pointer hover-header border-r last:border-r-0 svelte-1m3mj5f");
		},
		m(target, anchor) {
			dom_insert(target, th, anchor);
			dom_append(th, div);
			dom_append(div, t0);
			dom_append(div, t1);
			dom_append(div, span);
			mount_component(fa, span, null);
			dom_append(th, t2);
			current = true;

			if (!mounted) {
				dispose = dom_listen(th, "click", click_handler);
				mounted = true;
			}
		},
		p(new_ctx, dirty) {
			ctx = new_ctx;
			if ((!current || dirty & /*columns*/ 4) && t0_value !== (t0_value = /*column*/ ctx[12] + "")) set_data(t0, t0_value);
			const fa_changes = {};
			if (dirty & /*columns*/ 4) fa_changes.icon = /*getSortIcon*/ ctx[4](/*column*/ ctx[12]);
			fa.$set(fa_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(th);
			}

			destroy_component(fa);
			mounted = false;
			dispose();
		}
	};
}

// (81:12) {#each columns as column}
function create_each_block_1(ctx) {
	let td;
	let t_value = /*row*/ ctx[9][/*column*/ ctx[12]] + "";
	let t;

	return {
		c() {
			td = dom_element("td");
			t = dom_text(t_value);
			dom_attr(td, "class", "px-6 py-4 whitespace-nowrap text-sm text-gray-900 border-r last:border-r-0 svelte-1m3mj5f");
		},
		m(target, anchor) {
			dom_insert(target, td, anchor);
			dom_append(td, t);
		},
		p(ctx, dirty) {
			if (dirty & /*sortedData, columns*/ 6 && t_value !== (t_value = /*row*/ ctx[9][/*column*/ ctx[12]] + "")) set_data(t, t_value);
		},
		d(detaching) {
			if (detaching) {
				dom_detach(td);
			}
		}
	};
}

// (79:8) {#each sortedData as row, i}
function create_each_block(ctx) {
	let tr;
	let t;
	let tr_class_value;
	let each_value_1 = each_ensure_array_like(/*columns*/ ctx[2]);
	let each_blocks = [];

	for (let i = 0; i < each_value_1.length; i += 1) {
		each_blocks[i] = create_each_block_1(get_each_context_1(ctx, each_value_1, i));
	}

	return {
		c() {
			tr = dom_element("tr");

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			t = space();
			dom_attr(tr, "class", tr_class_value = "" + (null_to_empty(/*i*/ ctx[11] % 2 === 0 ? 'even-row' : 'odd-row') + " svelte-1m3mj5f"));
		},
		m(target, anchor) {
			dom_insert(target, tr, anchor);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(tr, null);
				}
			}

			dom_append(tr, t);
		},
		p(ctx, dirty) {
			if (dirty & /*sortedData, columns*/ 6) {
				each_value_1 = each_ensure_array_like(/*columns*/ ctx[2]);
				let i;

				for (i = 0; i < each_value_1.length; i += 1) {
					const child_ctx = get_each_context_1(ctx, each_value_1, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
					} else {
						each_blocks[i] = create_each_block_1(child_ctx);
						each_blocks[i].c();
						each_blocks[i].m(tr, t);
					}
				}

				for (; i < each_blocks.length; i += 1) {
					each_blocks[i].d(1);
				}

				each_blocks.length = each_value_1.length;
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(tr);
			}

			destroy_each(each_blocks, detaching);
		}
	};
}

function TabularSample_svelte_create_fragment(ctx) {
	let current_block_type_index;
	let if_block;
	let if_block_anchor;
	let current;
	const if_block_creators = [TabularSample_svelte_create_if_block, TabularSample_svelte_create_else_block];
	const if_blocks = [];

	function select_block_type(ctx, dirty) {
		if (/*data*/ ctx[0].length === 0) return 0;
		return 1;
	}

	current_block_type_index = select_block_type(ctx, -1);
	if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);

	return {
		c() {
			if_block.c();
			if_block_anchor = empty();
		},
		m(target, anchor) {
			if_blocks[current_block_type_index].m(target, anchor);
			dom_insert(target, if_block_anchor, anchor);
			current = true;
		},
		p(ctx, [dirty]) {
			let previous_block_index = current_block_type_index;
			current_block_type_index = select_block_type(ctx, dirty);

			if (current_block_type_index === previous_block_index) {
				if_blocks[current_block_type_index].p(ctx, dirty);
			} else {
				group_outros();

				transitions_transition_out(if_blocks[previous_block_index], 1, 1, () => {
					if_blocks[previous_block_index] = null;
				});

				check_outros();
				if_block = if_blocks[current_block_type_index];

				if (!if_block) {
					if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
					if_block.c();
				} else {
					if_block.p(ctx, dirty);
				}

				transitions_transition_in(if_block, 1);
				if_block.m(if_block_anchor.parentNode, if_block_anchor);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(if_block_anchor);
			}

			if_blocks[current_block_type_index].d(detaching);
		}
	};
}

function TabularSample_svelte_instance($$self, $$props, $$invalidate) {
	let columns;
	let sortedData;
	let { data = [] } = $$props;
	let { maxRows = 10 } = $$props;
	let sortField = null;
	let sortDirection = 'asc';

	function toggleSort(column) {
		if (sortField === column) {
			$$invalidate(7, sortDirection = sortDirection === 'asc' ? 'desc' : 'asc');
		} else {
			$$invalidate(6, sortField = column);
			$$invalidate(7, sortDirection = 'asc');
		}
	}

	function getSortIcon(column) {
		if (sortField !== column) return faSort/* faSort */.OM;
		return sortDirection === 'asc' ? faSortUp/* faSortUp */.Dv : faSortDown/* faSortDown */.Yn;
	}

	const click_handler = column => toggleSort(column);

	$$self.$$set = $$props => {
		if ('data' in $$props) $$invalidate(0, data = $$props.data);
		if ('maxRows' in $$props) $$invalidate(5, maxRows = $$props.maxRows);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*data*/ 1) {
			$: $$invalidate(2, columns = data.length > 0 ? Object.keys(data[0]) : []);
		}

		if ($$self.$$.dirty & /*data, sortField, sortDirection, maxRows*/ 225) {
			$: $$invalidate(1, sortedData = [...data].sort((a, b) => {
				if (!sortField) return 0;
				const aVal = a[sortField];
				const bVal = b[sortField];
				const direction = sortDirection === 'asc' ? 1 : -1;
				if (aVal < bVal) return -1 * direction;
				if (aVal > bVal) return 1 * direction;
				return 0;
			}).slice(0, maxRows));
		}
	};

	return [
		data,
		sortedData,
		columns,
		toggleSort,
		getSortIcon,
		maxRows,
		sortField,
		sortDirection,
		click_handler
	];
}

class TabularSample extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, TabularSample_svelte_instance, TabularSample_svelte_create_fragment, safe_not_equal, { data: 0, maxRows: 5 }, TabularSample_svelte_add_css);
	}
}

/* harmony default export */ const TabularSample_svelte = (TabularSample);
;// ../../canvas_viz/dist/helpers/filetype.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */




function getComponentForType(type) {
    switch (type) {
        case CanvasDataType.AUDIO:
            return AudioSample_svelte;
        case CanvasDataType.IMAGE:
            return ImageSample_svelte;
        default:
            return TabularSample_svelte;
    }
}

;// ../../canvas_viz/dist/elements/DataSampleDetail.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/DataSampleDetail.svelte generated by Svelte v4.2.19 */








function DataSampleDetail_svelte_get_each_context(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[16] = list[i][0];
	child_ctx[17] = list[i][1];
	return child_ctx;
}

// (50:0) {#if $tooltip.hover && $tooltip.instance !== undefined}
function DataSampleDetail_svelte_create_if_block(ctx) {
	let div3;
	let div0;
	let switch_instance;
	let t0;
	let div2;
	let div1;
	let t1_value = /*$tooltip*/ ctx[7].instance[/*$canvasSpec*/ ctx[9].idColumn] + "";
	let t1;
	let t2;
	let t3;
	let div3_resize_listener;
	let div3_transition;
	let current;
	var switch_value = getComponentForType(/*$canvasSpec*/ ctx[9].dataType);

	function switch_props(ctx, dirty) {
		return {
			props: {
				id: /*$tooltip*/ ctx[7].instance[/*$canvasSpec*/ ctx[9].idColumn],
				canvasSpec: /*canvasSpec*/ ctx[0],
				storybook: /*storybook*/ ctx[2],
				large: true
			}
		};
	}

	if (switch_value) {
		switch_instance = construct_svelte_component(switch_value, switch_props(ctx));
	}

	let if_block = /*$tooltip*/ ctx[7].number !== undefined && DataSampleDetail_svelte_create_if_block_2(ctx);
	let each_value = each_ensure_array_like(Object.entries(/*$tooltip*/ ctx[7].instance));
	let each_blocks = [];

	for (let i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = DataSampleDetail_svelte_create_each_block(DataSampleDetail_svelte_get_each_context(ctx, each_value, i));
	}

	return {
		c() {
			div3 = dom_element("div");
			div0 = dom_element("div");
			if (switch_instance) create_component(switch_instance.$$.fragment);
			t0 = space();
			div2 = dom_element("div");
			div1 = dom_element("div");
			t1 = dom_text(t1_value);
			t2 = space();
			if (if_block) if_block.c();
			t3 = space();

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			dom_attr(div0, "class", "flex flex-shrink-0");
			dom_attr(div1, "class", "flex font-bold");
			dom_attr(div2, "class", "flex flex-col pl-2 pr-4 m-2 mt-0 break-all");
			dom_attr(div3, "class", "text-sm fixed p-1 rounded text-text-dark shadow z-10 flex mt-4 mb-4");
			dom_attr(div3, "style", /*style*/ ctx[8]);
			scheduler_add_render_callback(() => /*div3_elementresize_handler*/ ctx[15].call(div3));
		},
		m(target, anchor) {
			dom_insert(target, div3, anchor);
			dom_append(div3, div0);
			if (switch_instance) mount_component(switch_instance, div0, null);
			dom_append(div3, t0);
			dom_append(div3, div2);
			dom_append(div2, div1);
			dom_append(div1, t1);
			dom_append(div2, t2);
			if (if_block) if_block.m(div2, null);
			dom_append(div2, t3);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(div2, null);
				}
			}

			div3_resize_listener = add_iframe_resize_listener(div3, /*div3_elementresize_handler*/ ctx[15].bind(div3));
			current = true;
		},
		p(ctx, dirty) {
			if (dirty & /*$canvasSpec*/ 512 && switch_value !== (switch_value = getComponentForType(/*$canvasSpec*/ ctx[9].dataType))) {
				if (switch_instance) {
					group_outros();
					const old_component = switch_instance;

					transitions_transition_out(old_component.$$.fragment, 1, 0, () => {
						destroy_component(old_component, 1);
					});

					check_outros();
				}

				if (switch_value) {
					switch_instance = construct_svelte_component(switch_value, switch_props(ctx, dirty));
					create_component(switch_instance.$$.fragment);
					transitions_transition_in(switch_instance.$$.fragment, 1);
					mount_component(switch_instance, div0, null);
				} else {
					switch_instance = null;
				}
			} else if (switch_value) {
				const switch_instance_changes = {};
				if (dirty & /*$tooltip, $canvasSpec*/ 640) switch_instance_changes.id = /*$tooltip*/ ctx[7].instance[/*$canvasSpec*/ ctx[9].idColumn];
				if (dirty & /*canvasSpec*/ 1) switch_instance_changes.canvasSpec = /*canvasSpec*/ ctx[0];
				if (dirty & /*storybook*/ 4) switch_instance_changes.storybook = /*storybook*/ ctx[2];
				switch_instance.$set(switch_instance_changes);
			}

			if ((!current || dirty & /*$tooltip, $canvasSpec*/ 640) && t1_value !== (t1_value = /*$tooltip*/ ctx[7].instance[/*$canvasSpec*/ ctx[9].idColumn] + "")) set_data(t1, t1_value);

			if (/*$tooltip*/ ctx[7].number !== undefined) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*$tooltip*/ 128) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = DataSampleDetail_svelte_create_if_block_2(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div2, t3);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}

			if (dirty & /*formatValue, Object, $tooltip, $canvasSpec*/ 1664) {
				each_value = each_ensure_array_like(Object.entries(/*$tooltip*/ ctx[7].instance));
				let i;

				for (i = 0; i < each_value.length; i += 1) {
					const child_ctx = DataSampleDetail_svelte_get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
					} else {
						each_blocks[i] = DataSampleDetail_svelte_create_each_block(child_ctx);
						each_blocks[i].c();
						each_blocks[i].m(div2, null);
					}
				}

				for (; i < each_blocks.length; i += 1) {
					each_blocks[i].d(1);
				}

				each_blocks.length = each_value.length;
			}

			if (!current || dirty & /*style*/ 256) {
				dom_attr(div3, "style", /*style*/ ctx[8]);
			}
		},
		i(local) {
			if (current) return;
			if (switch_instance) transitions_transition_in(switch_instance.$$.fragment, local);
			transitions_transition_in(if_block);

			if (local) {
				scheduler_add_render_callback(() => {
					if (!current) return;
					if (!div3_transition) div3_transition = create_bidirectional_transition(div3, fade, {}, true);
					div3_transition.run(1);
				});
			}

			current = true;
		},
		o(local) {
			if (switch_instance) transitions_transition_out(switch_instance.$$.fragment, local);
			transitions_transition_out(if_block);

			if (local) {
				if (!div3_transition) div3_transition = create_bidirectional_transition(div3, fade, {}, false);
				div3_transition.run(0);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div3);
			}

			if (switch_instance) destroy_component(switch_instance);
			if (if_block) if_block.d();
			destroy_each(each_blocks, detaching);
			div3_resize_listener();
			if (detaching && div3_transition) div3_transition.end();
		}
	};
}

// (71:6) {#if $tooltip.number !== undefined}
function DataSampleDetail_svelte_create_if_block_2(ctx) {
	let div;
	let fa;
	let t0;
	let span;
	let t1_value = /*$tooltip*/ ctx[7].number + "";
	let t1;
	let current;
	fa = new dist({ props: { icon: faChartBar/* faChartBar */.$F } });

	return {
		c() {
			div = dom_element("div");
			create_component(fa.$$.fragment);
			t0 = space();
			span = dom_element("span");
			t1 = dom_text(t1_value);
			dom_attr(span, "class", "ml-2");
			dom_attr(div, "class", "flex flex-nowrap");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(fa, div, null);
			dom_append(div, t0);
			dom_append(div, span);
			dom_append(span, t1);
			current = true;
		},
		p(ctx, dirty) {
			if ((!current || dirty & /*$tooltip*/ 128) && t1_value !== (t1_value = /*$tooltip*/ ctx[7].number + "")) set_data(t1, t1_value);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(fa);
		}
	};
}

// (78:8) {#if key !== $canvasSpec.idColumn && !key.startsWith("familiarity_") && !key.startsWith("duplicates_") && !key.startsWith("projection_") && !key.startsWith("splitFamiliarity")}
function DataSampleDetail_svelte_create_if_block_1(ctx) {
	let div;
	let span0;
	let t0_value = /*key*/ ctx[16] + "";
	let t0;
	let t1;
	let t2;
	let span1;
	let t3_value = /*formatValue*/ ctx[10](/*val*/ ctx[17]) + "";
	let t3;
	let t4;

	return {
		c() {
			div = dom_element("div");
			span0 = dom_element("span");
			t0 = dom_text(t0_value);
			t1 = dom_text(":");
			t2 = space();
			span1 = dom_element("span");
			t3 = dom_text(t3_value);
			t4 = space();
			dom_attr(span0, "class", "font-bold");
			dom_attr(span1, "class", "ml-2");
			dom_attr(div, "class", "flex flex-nowrap");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			dom_append(div, span0);
			dom_append(span0, t0);
			dom_append(span0, t1);
			dom_append(div, t2);
			dom_append(div, span1);
			dom_append(span1, t3);
			dom_append(div, t4);
		},
		p(ctx, dirty) {
			if (dirty & /*$tooltip*/ 128 && t0_value !== (t0_value = /*key*/ ctx[16] + "")) set_data(t0, t0_value);
			if (dirty & /*$tooltip*/ 128 && t3_value !== (t3_value = /*formatValue*/ ctx[10](/*val*/ ctx[17]) + "")) set_data(t3, t3_value);
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}
		}
	};
}

// (77:6) {#each Object.entries($tooltip.instance) as [key, val]}
function DataSampleDetail_svelte_create_each_block(ctx) {
	let show_if = /*key*/ ctx[16] !== /*$canvasSpec*/ ctx[9].idColumn && !/*key*/ ctx[16].startsWith("familiarity_") && !/*key*/ ctx[16].startsWith("duplicates_") && !/*key*/ ctx[16].startsWith("projection_") && !/*key*/ ctx[16].startsWith("splitFamiliarity");
	let if_block_anchor;
	let if_block = show_if && DataSampleDetail_svelte_create_if_block_1(ctx);

	return {
		c() {
			if (if_block) if_block.c();
			if_block_anchor = empty();
		},
		m(target, anchor) {
			if (if_block) if_block.m(target, anchor);
			dom_insert(target, if_block_anchor, anchor);
		},
		p(ctx, dirty) {
			if (dirty & /*$tooltip, $canvasSpec*/ 640) show_if = /*key*/ ctx[16] !== /*$canvasSpec*/ ctx[9].idColumn && !/*key*/ ctx[16].startsWith("familiarity_") && !/*key*/ ctx[16].startsWith("duplicates_") && !/*key*/ ctx[16].startsWith("projection_") && !/*key*/ ctx[16].startsWith("splitFamiliarity");

			if (show_if) {
				if (if_block) {
					if_block.p(ctx, dirty);
				} else {
					if_block = DataSampleDetail_svelte_create_if_block_1(ctx);
					if_block.c();
					if_block.m(if_block_anchor.parentNode, if_block_anchor);
				}
			} else if (if_block) {
				if_block.d(1);
				if_block = null;
			}
		},
		d(detaching) {
			if (detaching) {
				dom_detach(if_block_anchor);
			}

			if (if_block) if_block.d(detaching);
		}
	};
}

function DataSampleDetail_svelte_create_fragment(ctx) {
	let if_block_anchor;
	let current;
	let mounted;
	let dispose;
	scheduler_add_render_callback(/*onwindowresize*/ ctx[14]);
	let if_block = /*$tooltip*/ ctx[7].hover && /*$tooltip*/ ctx[7].instance !== undefined && DataSampleDetail_svelte_create_if_block(ctx);

	return {
		c() {
			if (if_block) if_block.c();
			if_block_anchor = empty();
		},
		m(target, anchor) {
			if (if_block) if_block.m(target, anchor);
			dom_insert(target, if_block_anchor, anchor);
			current = true;

			if (!mounted) {
				dispose = dom_listen(window, "resize", /*onwindowresize*/ ctx[14]);
				mounted = true;
			}
		},
		p(ctx, [dirty]) {
			if (/*$tooltip*/ ctx[7].hover && /*$tooltip*/ ctx[7].instance !== undefined) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*$tooltip*/ 128) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = DataSampleDetail_svelte_create_if_block(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(if_block_anchor.parentNode, if_block_anchor);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(if_block_anchor);
			}

			if (if_block) if_block.d(detaching);
			mounted = false;
			dispose();
		}
	};
}

function DataSampleDetail_svelte_instance($$self, $$props, $$invalidate) {
	let yPos;
	let xStyle;
	let style;

	let $tooltip,
		$$unsubscribe_tooltip = utils_noop,
		$$subscribe_tooltip = () => ($$unsubscribe_tooltip(), $$unsubscribe_tooltip = subscribe(tooltip, $$value => $$invalidate(7, $tooltip = $$value)), tooltip);

	let $canvasSpec,
		$$unsubscribe_canvasSpec = utils_noop,
		$$subscribe_canvasSpec = () => ($$unsubscribe_canvasSpec(), $$unsubscribe_canvasSpec = subscribe(canvasSpec, $$value => $$invalidate(9, $canvasSpec = $$value)), canvasSpec);

	$$self.$$.on_destroy.push(() => $$unsubscribe_tooltip());
	$$self.$$.on_destroy.push(() => $$unsubscribe_canvasSpec());

	const formatValue = val => {
		if (Array.isArray(val)) return val.toString();
		if (typeof val === 'number') return val.toFixed(2);
		return val;
	};

	let { canvasSpec } = $$props;
	$$subscribe_canvasSpec();
	let { tooltip } = $$props;
	$$subscribe_tooltip();
	let { storybook = false } = $$props;
	let windowWidth = 0;
	let windowHeight = 0;
	let tooltipWidth = 0;
	let tooltipHeight = 0;
	let maxTooltipWidth = 0;

	function onwindowresize() {
		$$invalidate(3, windowWidth = window.innerWidth)
		$$invalidate(4, windowHeight = window.innerHeight)
	}

	function div3_elementresize_handler() {
		tooltipWidth = this.offsetWidth;
		tooltipHeight = this.offsetHeight;
		$$invalidate(5, tooltipWidth);
		$$invalidate(6, tooltipHeight);
	}

	$$self.$$set = $$props => {
		if ('canvasSpec' in $$props) $$subscribe_canvasSpec($$invalidate(0, canvasSpec = $$props.canvasSpec));
		if ('tooltip' in $$props) $$subscribe_tooltip($$invalidate(1, tooltip = $$props.tooltip));
		if ('storybook' in $$props) $$invalidate(2, storybook = $$props.storybook);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*tooltipWidth, maxTooltipWidth*/ 2080) {
			$: $$invalidate(11, maxTooltipWidth = tooltipWidth > maxTooltipWidth
			? tooltipWidth
			: maxTooltipWidth);
		}

		if ($$self.$$.dirty & /*windowHeight, $tooltip, tooltipHeight*/ 208) {
			$: $$invalidate(13, yPos = windowHeight > $tooltip.mousePos.y + tooltipHeight
			? $tooltip.mousePos.y
			: $tooltip.mousePos.y - tooltipHeight - 20);
		}

		if ($$self.$$.dirty & /*windowWidth, $tooltip, maxTooltipWidth*/ 2184) {
			// TODO: The offset is necessary because the sidebar of jupyter lab messes up the
			// tooltip position. This messes up the stories. Need to fix this
			$: $$invalidate(12, xStyle = windowWidth > $tooltip.mousePos.x + maxTooltipWidth + 100
			? `left: ${$tooltip.mousePos.x - 250}px;`
			: `right: 10px;`);
		}

		if ($$self.$$.dirty & /*yPos, xStyle*/ 12288) {
			$: $$invalidate(8, style = `top: ${yPos}px; ${xStyle}; background: black`);
		}
	};

	return [
		canvasSpec,
		tooltip,
		storybook,
		windowWidth,
		windowHeight,
		tooltipWidth,
		tooltipHeight,
		$tooltip,
		style,
		$canvasSpec,
		formatValue,
		maxTooltipWidth,
		xStyle,
		yPos,
		onwindowresize,
		div3_elementresize_handler
	];
}

class DataSampleDetail extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, DataSampleDetail_svelte_instance, DataSampleDetail_svelte_create_fragment, safe_not_equal, { canvasSpec: 0, tooltip: 1, storybook: 2 });
	}
}

/* harmony default export */ const DataSampleDetail_svelte = (DataSampleDetail);
;// ../../canvas_viz/dist/JupyterWidget.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/JupyterWidget.svelte generated by Svelte v4.2.19 */








function JupyterWidget_svelte_create_else_block(ctx) {
	let t;

	return {
		c() {
			t = dom_text("No data to show.");
		},
		m(target, anchor) {
			dom_insert(target, t, anchor);
		},
		p: utils_noop,
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(t);
			}
		}
	};
}

// (26:0) {#if $table && $widgetSpec}
function JupyterWidget_svelte_create_if_block(ctx) {
	let div;
	let switch_instance;
	let div_class_value;
	let current;
	var switch_value = /*widget*/ ctx[0];

	function switch_props(ctx, dirty) {
		return {
			props: {
				widgetSpec: /*$widgetSpec*/ ctx[2],
				selected: selected,
				filter: stores_filter,
				groupColumns: groupColumns,
				groupNames: groupNames,
				canvasSpec: canvasSpec,
				dataTable: dataTable,
				filterError: filterError,
				tooltip: tooltip,
				table: stores_table,
				filteredTable: filteredTable,
				groupedTables: groupedTables,
				notebook: true
			}
		};
	}

	if (switch_value) {
		switch_instance = construct_svelte_component(switch_value, switch_props(ctx));
		switch_instance.$on("specChanged", /*handleSpecChanged*/ ctx[4]);
	}

	return {
		c() {
			div = dom_element("div");
			if (switch_instance) create_component(switch_instance.$$.fragment);

			dom_attr(div, "class", div_class_value = "" + ((/*$widgetSpec*/ ctx[2].name === 'toolbar'
			? 'border-midgrey border-2'
			: '') + " mt-2 h-full"));

			set_style(div, "min-height", "350px");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			if (switch_instance) mount_component(switch_instance, div, null);
			current = true;
		},
		p(ctx, dirty) {
			if (dirty & /*widget*/ 1 && switch_value !== (switch_value = /*widget*/ ctx[0])) {
				if (switch_instance) {
					group_outros();
					const old_component = switch_instance;

					transitions_transition_out(old_component.$$.fragment, 1, 0, () => {
						destroy_component(old_component, 1);
					});

					check_outros();
				}

				if (switch_value) {
					switch_instance = construct_svelte_component(switch_value, switch_props(ctx, dirty));
					switch_instance.$on("specChanged", /*handleSpecChanged*/ ctx[4]);
					create_component(switch_instance.$$.fragment);
					transitions_transition_in(switch_instance.$$.fragment, 1);
					mount_component(switch_instance, div, null);
				} else {
					switch_instance = null;
				}
			} else if (switch_value) {
				const switch_instance_changes = {};
				if (dirty & /*$widgetSpec*/ 4) switch_instance_changes.widgetSpec = /*$widgetSpec*/ ctx[2];
				switch_instance.$set(switch_instance_changes);
			}

			if (!current || dirty & /*$widgetSpec*/ 4 && div_class_value !== (div_class_value = "" + ((/*$widgetSpec*/ ctx[2].name === 'toolbar'
			? 'border-midgrey border-2'
			: '') + " mt-2 h-full"))) {
				dom_attr(div, "class", div_class_value);
			}
		},
		i(local) {
			if (current) return;
			if (switch_instance) transitions_transition_in(switch_instance.$$.fragment, local);
			current = true;
		},
		o(local) {
			if (switch_instance) transitions_transition_out(switch_instance.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			if (switch_instance) destroy_component(switch_instance);
		}
	};
}

function JupyterWidget_svelte_create_fragment(ctx) {
	let current_block_type_index;
	let if_block;
	let t;
	let datasampledetail;
	let current;
	const if_block_creators = [JupyterWidget_svelte_create_if_block, JupyterWidget_svelte_create_else_block];
	const if_blocks = [];

	function select_block_type(ctx, dirty) {
		if (/*$table*/ ctx[1] && /*$widgetSpec*/ ctx[2]) return 0;
		return 1;
	}

	current_block_type_index = select_block_type(ctx, -1);
	if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
	datasampledetail = new DataSampleDetail_svelte({ props: { tooltip: tooltip, canvasSpec: canvasSpec } });

	return {
		c() {
			if_block.c();
			t = space();
			create_component(datasampledetail.$$.fragment);
		},
		m(target, anchor) {
			if_blocks[current_block_type_index].m(target, anchor);
			dom_insert(target, t, anchor);
			mount_component(datasampledetail, target, anchor);
			current = true;
		},
		p(ctx, [dirty]) {
			let previous_block_index = current_block_type_index;
			current_block_type_index = select_block_type(ctx, dirty);

			if (current_block_type_index === previous_block_index) {
				if_blocks[current_block_type_index].p(ctx, dirty);
			} else {
				group_outros();

				transitions_transition_out(if_blocks[previous_block_index], 1, 1, () => {
					if_blocks[previous_block_index] = null;
				});

				check_outros();
				if_block = if_blocks[current_block_type_index];

				if (!if_block) {
					if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
					if_block.c();
				} else {
					if_block.p(ctx, dirty);
				}

				transitions_transition_in(if_block, 1);
				if_block.m(t.parentNode, t);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			transitions_transition_in(datasampledetail.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			transitions_transition_out(datasampledetail.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(t);
			}

			if_blocks[current_block_type_index].d(detaching);
			destroy_component(datasampledetail, detaching);
		}
	};
}

function JupyterWidget_svelte_instance($$self, $$props, $$invalidate) {
	let $table;
	let $widgetSpec;
	component_subscribe($$self, stores_table, $$value => $$invalidate(1, $table = $$value));
	let { model } = $$props;
	let { widget } = $$props;
	let widgetSpec = createSyncedWidget("widget_spec", model.attributes.widget_spec, model);
	component_subscribe($$self, widgetSpec, value => $$invalidate(2, $widgetSpec = value));

	function handleSpecChanged(event) {
		widgetSpec.set(event.detail.spec);
	}

	$$self.$$set = $$props => {
		if ('model' in $$props) $$invalidate(5, model = $$props.model);
		if ('widget' in $$props) $$invalidate(0, widget = $$props.widget);
	};

	return [widget, $table, $widgetSpec, widgetSpec, handleSpecChanged, model];
}

class JupyterWidget extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, JupyterWidget_svelte_instance, JupyterWidget_svelte_create_fragment, safe_not_equal, { model: 5, widget: 0 });
	}
}

/* harmony default export */ const JupyterWidget_svelte = (JupyterWidget);
;// ../../canvas_viz/dist/canvasbasewidget.js



class CanvasBaseDomWidgetView extends base_.DOMWidgetView {
    setupWidget(model, canvasWidget) {
        initializeStores(model);
        new JupyterWidget_svelte({
            target: this.el,
            props: {
                model: model,
                widget: canvasWidget,
            },
        });
    }
    render() {
        throw new Error('render() must be implemented by Canvas Widget');
    }
}

// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faEdit.js
var faEdit = __webpack_require__(2174);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faCheck.js
var faCheck = __webpack_require__(2888);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faTimes.js
var faTimes = __webpack_require__(7882);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faQuestionCircle.js
var faQuestionCircle = __webpack_require__(3430);
;// ../../canvas_viz/dist/elements/Tooltip.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/Tooltip.svelte generated by Svelte v4.2.19 */







function Tooltip_svelte_add_css(target) {
	append_styles(target, "svelte-49ae0e", "[data-tooltip].svelte-49ae0e{position:relative;z-index:2;display:block}[data-tooltip].svelte-49ae0e:before,[data-tooltip].svelte-49ae0e:after{visibility:hidden;opacity:0;pointer-events:none;transition:0.2s ease-out;transform:translate(-50%, 5px)}[data-tooltip].svelte-49ae0e:before{position:absolute;top:100%;left:50%;margin-bottom:5px;padding:7px;width:100%;min-width:300px;max-width:400px;border-radius:3px;background-color:#000;background-color:hsla(0, 0%, 20%, 0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.2;transition:0.2s ease-out}[data-tooltip].svelte-49ae0e:hover:before,[data-tooltip].svelte-49ae0e:hover:after{visibility:visible;opacity:1;transform:translate(-50%, 0)}[data-tooltip=\"false\"].svelte-49ae0e:hover:before,[data-tooltip=\"false\"].svelte-49ae0e:hover:after{visibility:hidden;opacity:0}");
}

function Tooltip_svelte_create_fragment(ctx) {
	let div;
	let fa;
	let current;
	fa = new dist({ props: { icon: faQuestionCircle/* faQuestionCircle */.wR } });

	return {
		c() {
			div = dom_element("div");
			create_component(fa.$$.fragment);
			dom_attr(div, "class", "w-max svelte-49ae0e");
			dom_attr(div, "data-tooltip", /*text*/ ctx[0]);
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(fa, div, null);
			current = true;
		},
		p(ctx, [dirty]) {
			if (!current || dirty & /*text*/ 1) {
				dom_attr(div, "data-tooltip", /*text*/ ctx[0]);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(fa);
		}
	};
}

function Tooltip_svelte_instance($$self, $$props, $$invalidate) {
	let { text } = $$props;

	$$self.$$set = $$props => {
		if ('text' in $$props) $$invalidate(0, text = $$props.text);
	};

	return [text];
}

class Tooltip extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, Tooltip_svelte_instance, Tooltip_svelte_create_fragment, safe_not_equal, { text: 0 }, Tooltip_svelte_add_css);
	}
}

/* harmony default export */ const Tooltip_svelte = (Tooltip);
;// ../../canvas_viz/dist/elements/Heading.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/Heading.svelte generated by Svelte v4.2.19 */





function Heading_svelte_create_fragment(ctx) {
	let div1;
	let div0;
	let h2;
	let t0;
	let t1;
	let tooltip;
	let current;
	tooltip = new Tooltip_svelte({ props: { text: /*description*/ ctx[1] } });

	return {
		c() {
			div1 = dom_element("div");
			div0 = dom_element("div");
			h2 = dom_element("h2");
			t0 = dom_text(/*heading*/ ctx[0]);
			t1 = space();
			create_component(tooltip.$$.fragment);
			dom_attr(h2, "class", "text-2xl font-bold leading-7 text-gray-900 pr-2");
			dom_attr(div0, "class", "flex items-center");
			dom_attr(div1, "class", "flex items-center justify-between pb-3 pr-4");
		},
		m(target, anchor) {
			dom_insert(target, div1, anchor);
			dom_append(div1, div0);
			dom_append(div0, h2);
			dom_append(h2, t0);
			dom_append(div0, t1);
			mount_component(tooltip, div0, null);
			current = true;
		},
		p(ctx, [dirty]) {
			if (!current || dirty & /*heading*/ 1) set_data(t0, /*heading*/ ctx[0]);
			const tooltip_changes = {};
			if (dirty & /*description*/ 2) tooltip_changes.text = /*description*/ ctx[1];
			tooltip.$set(tooltip_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(tooltip.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(tooltip.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div1);
			}

			destroy_component(tooltip);
		}
	};
}

let hover = false;
let offsetX = 0;

function Heading_svelte_instance($$self, $$props, $$invalidate) {
	let { heading } = $$props;
	let { description } = $$props;

	$$self.$$set = $$props => {
		if ('heading' in $$props) $$invalidate(0, heading = $$props.heading);
		if ('description' in $$props) $$invalidate(1, description = $$props.description);
	};

	return [heading, description];
}

class Heading extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, Heading_svelte_instance, Heading_svelte_create_fragment, safe_not_equal, { heading: 0, description: 1 });
	}
}

/* harmony default export */ const Heading_svelte = (Heading);
// EXTERNAL MODULE: ../../node_modules/html2canvas/dist/html2canvas.js
var html2canvas = __webpack_require__(8317);
var html2canvas_default = /*#__PURE__*/__webpack_require__.n(html2canvas);
;// ../../canvas_viz/dist/helpers/export.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function exportView(container, name) {
    html2canvas_default()(container).then((canvas) => {
        const a = document.createElement("a");
        a.href = canvas
            .toDataURL("image/jpeg")
            .replace("image/jpeg", "image/octet-stream");
        a.download = `${name}.jpg`;
        a.click();
    });
}

// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faImage.js
var faImage = __webpack_require__(6705);
;// ../../canvas_viz/dist/elements/ComponentHeader.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/ComponentHeader.svelte generated by Svelte v4.2.19 */









function ComponentHeader_svelte_create_icon_slot(ctx) {
	let fa;
	let current;
	fa = new dist({ props: { icon: faImage/* faImage */.jb, slot: "icon" } });

	return {
		c() {
			create_component(fa.$$.fragment);
		},
		m(target, anchor) {
			mount_component(fa, target, anchor);
			current = true;
		},
		p: utils_noop,
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(fa, detaching);
		}
	};
}

// (35:6) 
function create_text_slot(ctx) {
	let span;

	return {
		c() {
			span = dom_element("span");
			span.textContent = "Download";
			dom_attr(span, "slot", "text");
		},
		m(target, anchor) {
			dom_insert(target, span, anchor);
		},
		p: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(span);
			}
		}
	};
}

function ComponentHeader_svelte_create_fragment(ctx) {
	let div3;
	let div1;
	let heading;
	let t0;
	let div0;
	let t1;
	let div2;
	let iconbutton;
	let current;

	heading = new Heading_svelte({
			props: {
				heading: /*title*/ ctx[0],
				description: /*description*/ ctx[1]
			}
		});

	const default_slot_template = /*#slots*/ ctx[3].default;
	const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[5], null);

	iconbutton = new IconButton_svelte({
			props: {
				$$slots: {
					text: [create_text_slot],
					icon: [ComponentHeader_svelte_create_icon_slot]
				},
				$$scope: { ctx }
			}
		});

	iconbutton.$on("click", /*click_handler*/ ctx[4]);

	return {
		c() {
			div3 = dom_element("div");
			div1 = dom_element("div");
			create_component(heading.$$.fragment);
			t0 = space();
			div0 = dom_element("div");
			if (default_slot) default_slot.c();
			t1 = space();
			div2 = dom_element("div");
			create_component(iconbutton.$$.fragment);
			dom_attr(div0, "class", "flex flex-wrap");
			dom_attr(div1, "class", "flex flex-wrap");
			dom_attr(div2, "class", "pb-3 pl-3");
			dom_attr(div3, "class", "flex items-top justify-between");
		},
		m(target, anchor) {
			dom_insert(target, div3, anchor);
			dom_append(div3, div1);
			mount_component(heading, div1, null);
			dom_append(div1, t0);
			dom_append(div1, div0);

			if (default_slot) {
				default_slot.m(div0, null);
			}

			dom_append(div3, t1);
			dom_append(div3, div2);
			mount_component(iconbutton, div2, null);
			current = true;
		},
		p(ctx, [dirty]) {
			const heading_changes = {};
			if (dirty & /*title*/ 1) heading_changes.heading = /*title*/ ctx[0];
			if (dirty & /*description*/ 2) heading_changes.description = /*description*/ ctx[1];
			heading.$set(heading_changes);

			if (default_slot) {
				if (default_slot.p && (!current || dirty & /*$$scope*/ 32)) {
					update_slot_base(
						default_slot,
						default_slot_template,
						ctx,
						/*$$scope*/ ctx[5],
						!current
						? get_all_dirty_from_scope(/*$$scope*/ ctx[5])
						: get_slot_changes(default_slot_template, /*$$scope*/ ctx[5], dirty, null),
						null
					);
				}
			}

			const iconbutton_changes = {};

			if (dirty & /*$$scope*/ 32) {
				iconbutton_changes.$$scope = { dirty, ctx };
			}

			iconbutton.$set(iconbutton_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(heading.$$.fragment, local);
			transitions_transition_in(default_slot, local);
			transitions_transition_in(iconbutton.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(heading.$$.fragment, local);
			transitions_transition_out(default_slot, local);
			transitions_transition_out(iconbutton.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div3);
			}

			destroy_component(heading);
			if (default_slot) default_slot.d(detaching);
			destroy_component(iconbutton);
		}
	};
}

function ComponentHeader_svelte_instance($$self, $$props, $$invalidate) {
	let { $$slots: slots = {}, $$scope } = $$props;
	let { title } = $$props;
	let { description } = $$props;
	let { container } = $$props;
	const click_handler = () => exportView(container, "Scatterplot");

	$$self.$$set = $$props => {
		if ('title' in $$props) $$invalidate(0, title = $$props.title);
		if ('description' in $$props) $$invalidate(1, description = $$props.description);
		if ('container' in $$props) $$invalidate(2, container = $$props.container);
		if ('$$scope' in $$props) $$invalidate(5, $$scope = $$props.$$scope);
	};

	return [title, description, container, slots, click_handler, $$scope];
}

class ComponentHeader extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, ComponentHeader_svelte_instance, ComponentHeader_svelte_create_fragment, safe_not_equal, { title: 0, description: 1, container: 2 });
	}
}

/* harmony default export */ const ComponentHeader_svelte = (ComponentHeader);
;// ../../canvas_viz/dist/helpers/dimensions.js
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
function mapWidth(width) {
    switch (width) {
        case 'XS':
            return 'col-span-1';
        case 'S':
            return 'col-span-2';
        case 'M':
            return 'col-span-3';
        case 'L':
            return 'col-span-4';
        case 'XL':
            return 'col-span-5';
        case 'XXL':
            return 'col-span-6';
        default:
            return 'col-span-2';
    }
}
function mapHeight(height, grid = false) {
    switch (height) {
        case 'XS':
            return grid ? 'row-span-1' : 'max-h-XS';
        case 'S':
            return grid ? 'row-span-2' : 'max-h-S';
        case 'M':
            return grid ? 'row-span-3' : 'max-h-M';
        case 'L':
            return grid ? 'row-span-4' : 'max-h-L';
        case 'XL':
            return grid ? 'row-span-5' : 'max-h-XL';
        case 'XXL':
            return grid ? 'row-span-6' : 'max-h-XXL';
        default:
            return grid ? 'row-span-2' : 'max-h-S';
    }
}
function mapHeightFixed(height, grid = false) {
    switch (height) {
        case 'XS':
            return grid ? 'row-span-1' : 'h-XS';
        case 'S':
            return grid ? 'row-span-2' : 'h-S';
        case 'M':
            return grid ? 'row-span-3' : 'h-M';
        case 'L':
            return grid ? 'row-span-4' : 'h-L';
        case 'XL':
            return grid ? 'row-span-5' : 'h-XL';
        case 'XXL':
            return grid ? 'row-span-6' : 'h-XXL';
        default:
            return grid ? 'row-span-2' : 'h-S';
    }
}

// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faAlignJustify.js
var faAlignJustify = __webpack_require__(4733);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faListOl.js
var faListOl = __webpack_require__(3801);
// EXTERNAL MODULE: ../../node_modules/@fortawesome/free-solid-svg-icons/faLayerGroup.js
var faLayerGroup = __webpack_require__(9718);
;// ./src/summarySpecs.ts
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */






function extractColumnElements(table) {
    const summaryElements = [];
    summaryElements.push({
        name: '# of Instances',
        data: table.numRows(),
    });
    const colNames = table.columnNames();
    for (const colName of colNames) {
        const columnType = getColumnType(table, colName);
        if (columnType === 'number') {
            if (colName.startsWith('duplicates_')) {
                summaryElements.push(getTotalNonNegativeElements(colName, table));
            }
            else if (!colName.startsWith('projection_')) {
                summaryElements.push({
                    name: colName,
                    data: {
                        spec: getNumberColumnSpec(colName),
                        data: { values: 'arrow_table' },
                        resolver: {
                            type: ResolverType.NUMBER,
                            columnName: colName,
                        },
                    },
                });
            }
        }
        else if (columnType === 'string') {
            if (isStringColumnBinnable(colName, table)) {
                summaryElements.unshift({
                    name: colName,
                    data: {
                        spec: getBinnedStringColumnSpec(colName),
                        data: { values: 'arrow_table' },
                        resolver: {
                            type: ResolverType.BINNED_STRING,
                            columnName: colName,
                        },
                    },
                });
            }
        }
    }
    return summaryElements;
}
function getQueryTree(table) {
    return {
        name: 'init',
        next: [tableQueryElement, ...getQueryElementsFromTable(table)],
    };
}
function getNumberColumnSpec(columnName) {
    return {
        $schema: 'https://vega.github.io/schema/vega-lite/v5.json',
        title: `${columnName} binned`,
        data: { values: 'values' },
        mark: { type: 'bar', tooltip: true },
        encoding: {
            x: {
                field: 'bin_0',
                title: 'value',
            },
            y: { field: 'count', type: 'quantitative', title: 'instances' },
        },
    };
}
function getBinnedStringColumnSpec(columnName) {
    return {
        $schema: 'https://vega.github.io/schema/vega-lite/v5.json',
        title: `${columnName} distribution`,
        data: { name: 'values' },
        mark: { type: 'bar', tooltip: true, cursor: 'pointer' },
        encoding: {
            y: { field: columnName, type: 'nominal', sort: '-x' },
            x: {
                field: 'count',
                type: 'quantitative',
                title: 'instances',
            },
        },
    };
}
function getQueryElementsFromTable(table) {
    const elements = [];
    for (const columnName of table.columnNames()) {
        const type = getColumnType(table, columnName);
        switch (type) {
            case 'number':
                elements.push(getNumberQueryElement(table, columnName));
                break;
            case 'string':
                if (isStringColumnBinnable(columnName, table)) {
                    elements.push(getStringQueryElement(table, columnName));
                }
                break;
            case 'array':
                if (getBinnableStringColumns(table).length > 0) {
                    elements.push(getArrayQueryElement(table, columnName));
                }
                break;
            default:
                break;
        }
    }
    return elements;
}
const tableQueryElement = {
    name: 'table',
    icon: faTable/* faTable */.w9,
    next: [
        {
            name: 'numRows',
            next: (names, table) => {
                return { name: '# of Instances', data: table.numRows() };
            },
        },
    ],
};
function getNumberQueryElement(table, columnName) {
    return {
        name: columnName,
        icon: faListOl/* faListOl */.Ts,
        next: [
            {
                name: 'histogram',
                next: (names, table) => {
                    return {
                        name: columnName,
                        data: {
                            spec: getNumberColumnSpec(columnName),
                            data: { values: 'arrow_table' },
                            resolver: {
                                type: ResolverType.NUMBER,
                                columnName: columnName,
                            },
                        },
                    };
                },
            },
            {
                name: 'non-negative',
                next: getNonNegativeNumberQueryElements(table),
            },
        ],
    };
}
function getNonNegativeNumberQueryElements(table) {
    const elements = [];
    elements.push({
        name: 'total',
        next: (names, table) => getTotalNonNegativeElements(names[0], table),
    });
    for (const column of getBinnableStringColumns(table)) {
        elements.push({
            name: `by ${column}`,
            next: (names, table) => {
                return {
                    name: 'Nonempty List',
                    data: {
                        spec: {
                            $schema: 'https://vega.github.io/schema/vega-lite/v5.json',
                            title: `${names[0]} per ${column}`,
                            description: `Bar chart visualizing the distribution of ${names[0]} per ${column}.`,
                            transform: [
                                {
                                    filter: `datum.${names[0]} >= 0`,
                                },
                            ],
                            data: { name: 'values' },
                            mark: { type: 'bar', tooltip: true },
                            encoding: {
                                y: { field: column, type: 'nominal', title: column },
                                x: {
                                    aggregate: 'count',
                                    type: 'quantitative',
                                    title: names[0],
                                },
                            },
                        },
                        data: {
                            values: 'arrow_table',
                        },
                    },
                };
            },
        });
    }
    return elements;
}
function getTotalNonNegativeElements(columnName, table) {
    const column = table.array(columnName);
    let nonNegativeElements = 0;
    column.forEach((element) => {
        if (element >= 0) {
            nonNegativeElements++;
        }
    });
    return {
        name: columnName,
        data: nonNegativeElements,
    };
}
function getStringQueryElement(table, columnName) {
    return {
        name: columnName,
        icon: faAlignJustify/* faAlignJustify */.Ti,
        next: [
            {
                name: 'histogram',
                next: (names, table) => {
                    return {
                        name: columnName,
                        data: {
                            spec: getBinnedStringColumnSpec(columnName),
                            data: { values: 'arrow_table' },
                            resolver: {
                                type: ResolverType.BINNED_STRING,
                                columnName: columnName,
                            },
                        },
                    };
                },
            },
        ],
    };
}
function getArrayQueryElement(table, columnName) {
    return {
        name: columnName,
        icon: faLayerGroup/* faLayerGroup */.qI,
        next: [
            {
                name: 'not empty',
                next: getArrayBinQueryElements(table),
            },
        ],
    };
}
function getArrayBinQueryElements(table) {
    const elements = [];
    for (const column of getBinnableStringColumns(table)) {
        elements.push({
            name: `bin by ${column}`,
            next: (names, table) => {
                return {
                    name: 'Nonempty List',
                    data: {
                        spec: {
                            $schema: 'https://vega.github.io/schema/vega-lite/v5.json',
                            title: `${names[0]} per ${column}`,
                            description: `Bar chart visualizing the distribution of ${names[0]} per ${column}.`,
                            transform: [
                                {
                                    filter: `length(datum.${names[0]}) > 0`,
                                },
                            ],
                            data: { name: 'values' },
                            mark: { type: 'bar', tooltip: true },
                            encoding: {
                                y: { field: column, type: 'nominal', title: column },
                                x: {
                                    aggregate: 'count',
                                    type: 'quantitative',
                                    title: names[0],
                                },
                            },
                        },
                        data: {
                            values: 'arrow_table',
                        },
                    },
                };
            },
        });
    }
    return elements;
}

;// ../../canvas_viz/dist/elements/TextField.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/TextField.svelte generated by Svelte v4.2.19 */




function TextField_svelte_create_fragment(ctx) {
	let input;
	let mounted;
	let dispose;

	return {
		c() {
			input = dom_element("input");
			dom_attr(input, "class", "border border-midgrey rounded w-full");
			dom_attr(input, "type", "text");
			dom_attr(input, "placeholder", /*placeholder*/ ctx[1]);
		},
		m(target, anchor) {
			dom_insert(target, input, anchor);
			set_input_value(input, /*value*/ ctx[0]);

			if (!mounted) {
				dispose = dom_listen(input, "input", /*input_input_handler*/ ctx[2]);
				mounted = true;
			}
		},
		p(ctx, [dirty]) {
			if (dirty & /*placeholder*/ 2) {
				dom_attr(input, "placeholder", /*placeholder*/ ctx[1]);
			}

			if (dirty & /*value*/ 1 && input.value !== /*value*/ ctx[0]) {
				set_input_value(input, /*value*/ ctx[0]);
			}
		},
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(input);
			}

			mounted = false;
			dispose();
		}
	};
}

function TextField_svelte_instance($$self, $$props, $$invalidate) {
	let { value } = $$props;
	let { placeholder = "" } = $$props;

	function input_input_handler() {
		value = this.value;
		$$invalidate(0, value);
	}

	$$self.$$set = $$props => {
		if ('value' in $$props) $$invalidate(0, value = $$props.value);
		if ('placeholder' in $$props) $$invalidate(1, placeholder = $$props.placeholder);
	};

	return [value, placeholder, input_input_handler];
}

class TextField extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, TextField_svelte_instance, TextField_svelte_create_fragment, safe_not_equal, { value: 0, placeholder: 1 });
	}
}

/* harmony default export */ const TextField_svelte = (TextField);
;// ../../node_modules/json-stringify-pretty-compact/index.js
// Note: This regex matches even invalid JSON strings, but since we’re
// working on the output of `JSON.stringify` we know that only valid strings
// are present (unless the user supplied a weird `options.indent` but in
// that case we don’t care since the output would be invalid anyway).
const stringOrChar = /("(?:[^\\"]|\\.)*")|[:,]/g;

function stringify(passedObj, options = {}) {
  const indent = JSON.stringify(
    [1],
    undefined,
    options.indent === undefined ? 2 : options.indent
  ).slice(2, -3);

  const maxLength =
    indent === ""
      ? Infinity
      : options.maxLength === undefined
      ? 80
      : options.maxLength;

  let { replacer } = options;

  return (function _stringify(obj, currentIndent, reserved) {
    if (obj && typeof obj.toJSON === "function") {
      obj = obj.toJSON();
    }

    const string = JSON.stringify(obj, replacer);

    if (string === undefined) {
      return string;
    }

    const length = maxLength - currentIndent.length - reserved;

    if (string.length <= length) {
      const prettified = string.replace(
        stringOrChar,
        (match, stringLiteral) => {
          return stringLiteral || `${match} `;
        }
      );
      if (prettified.length <= length) {
        return prettified;
      }
    }

    if (replacer != null) {
      obj = JSON.parse(string);
      replacer = undefined;
    }

    if (typeof obj === "object" && obj !== null) {
      const nextIndent = currentIndent + indent;
      const items = [];
      let index = 0;
      let start;
      let end;

      if (Array.isArray(obj)) {
        start = "[";
        end = "]";
        const { length } = obj;
        for (; index < length; index++) {
          items.push(
            _stringify(obj[index], nextIndent, index === length - 1 ? 0 : 1) ||
              "null"
          );
        }
      } else {
        start = "{";
        end = "}";
        const keys = Object.keys(obj);
        const { length } = keys;
        for (; index < length; index++) {
          const key = keys[index];
          const keyPart = `${JSON.stringify(key)}: `;
          const value = _stringify(
            obj[key],
            nextIndent,
            keyPart.length + (index === length - 1 ? 0 : 1)
          );
          if (value !== undefined) {
            items.push(keyPart + value);
          }
        }
      }

      if (items.length > 0) {
        return [start, indent + items.join(`,\n${nextIndent}`), end].join(
          `\n${currentIndent}`
        );
      }
    }

    return string;
  })(passedObj, "", 0);
}

;// ../../node_modules/vega-util/build/vega-util.module.js
function accessor (fn, fields, name) {
  fn.fields = fields || [];
  fn.fname = name;
  return fn;
}
function accessorName(fn) {
  return fn == null ? null : fn.fname;
}
function accessorFields(fn) {
  return fn == null ? null : fn.fields;
}

function getter (path) {
  return path.length === 1 ? get1(path[0]) : getN(path);
}
const get1 = field => function (obj) {
  return obj[field];
};
const getN = path => {
  const len = path.length;
  return function (obj) {
    for (let i = 0; i < len; ++i) {
      obj = obj[path[i]];
    }
    return obj;
  };
};

function vega_util_module_error (message) {
  throw Error(message);
}

function splitAccessPath (p) {
  const path = [],
    n = p.length;
  let q = null,
    b = 0,
    s = '',
    i,
    j,
    c;
  p = p + '';
  function push() {
    path.push(s + p.substring(i, j));
    s = '';
    i = j + 1;
  }
  for (i = j = 0; j < n; ++j) {
    c = p[j];
    if (c === '\\') {
      s += p.substring(i, j++);
      i = j;
    } else if (c === q) {
      push();
      q = null;
      b = -1;
    } else if (q) {
      continue;
    } else if (i === b && c === '"') {
      i = j + 1;
      q = c;
    } else if (i === b && c === "'") {
      i = j + 1;
      q = c;
    } else if (c === '.' && !b) {
      if (j > i) {
        push();
      } else {
        i = j + 1;
      }
    } else if (c === '[') {
      if (j > i) push();
      b = i = j + 1;
    } else if (c === ']') {
      if (!b) vega_util_module_error('Access path missing open bracket: ' + p);
      if (b > 0) push();
      b = 0;
      i = j + 1;
    }
  }
  if (b) vega_util_module_error('Access path missing closing bracket: ' + p);
  if (q) vega_util_module_error('Access path missing closing quote: ' + p);
  if (j > i) {
    j++;
    push();
  }
  return path;
}

function vega_util_module_field (field, name, opt) {
  const path = splitAccessPath(field);
  field = path.length === 1 ? path[0] : field;
  return accessor((opt && opt.get || getter)(path), [field], name || field);
}

const id = vega_util_module_field('id');
const vega_util_module_identity = accessor(_ => _, [], 'identity');
const zero = accessor(() => 0, [], 'zero');
const one = accessor(() => 1, [], 'one');
const truthy = accessor(() => true, [], 'true');
const falsy = accessor(() => false, [], 'false');

function log$1(method, level, input) {
  const args = [level].concat([].slice.call(input));
  console[method].apply(console, args); // eslint-disable-line no-console
}
const None = 0;
const Error$1 = 1;
const vega_util_module_Warn = 2;
const vega_util_module_Info = 3;
const vega_util_module_Debug = 4;
function logger (_, method) {
  let handler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : log$1;
  let level = _ || None;
  return {
    level(_) {
      if (arguments.length) {
        level = +_;
        return this;
      } else {
        return level;
      }
    },
    error() {
      if (level >= Error$1) handler(method || 'error', 'ERROR', arguments);
      return this;
    },
    warn() {
      if (level >= vega_util_module_Warn) handler(method || 'warn', 'WARN', arguments);
      return this;
    },
    info() {
      if (level >= vega_util_module_Info) handler(method || 'log', 'INFO', arguments);
      return this;
    },
    debug() {
      if (level >= vega_util_module_Debug) handler(method || 'log', 'DEBUG', arguments);
      return this;
    }
  };
}

var vega_util_module_isArray = Array.isArray;

function vega_util_module_isObject (_) {
  return _ === Object(_);
}

const isLegalKey = key => key !== '__proto__';
function mergeConfig() {
  for (var _len = arguments.length, configs = new Array(_len), _key = 0; _key < _len; _key++) {
    configs[_key] = arguments[_key];
  }
  return configs.reduce((out, source) => {
    for (const key in source) {
      if (key === 'signals') {
        // for signals, we merge the signals arrays
        // source signals take precedence over
        // existing signals with the same name
        out.signals = mergeNamed(out.signals, source.signals);
      } else {
        // otherwise, merge objects subject to recursion constraints
        // for legend block, recurse for the layout entry only
        // for style block, recurse for all properties
        // otherwise, no recursion: objects overwrite, no merging
        const r = key === 'legend' ? {
          layout: 1
        } : key === 'style' ? true : null;
        writeConfig(out, key, source[key], r);
      }
    }
    return out;
  }, {});
}
function writeConfig(output, key, value, recurse) {
  if (!isLegalKey(key)) return;
  let k, o;
  if (vega_util_module_isObject(value) && !vega_util_module_isArray(value)) {
    o = vega_util_module_isObject(output[key]) ? output[key] : output[key] = {};
    for (k in value) {
      if (recurse && (recurse === true || recurse[k])) {
        writeConfig(o, k, value[k]);
      } else if (isLegalKey(k)) {
        o[k] = value[k];
      }
    }
  } else {
    output[key] = value;
  }
}
function mergeNamed(a, b) {
  if (a == null) return b;
  const map = {},
    out = [];
  function add(_) {
    if (!map[_.name]) {
      map[_.name] = 1;
      out.push(_);
    }
  }
  b.forEach(add);
  a.forEach(add);
  return out;
}

function peek (array) {
  return array[array.length - 1];
}

function vega_util_module_toNumber (_) {
  return _ == null || _ === '' ? null : +_;
}

const vega_util_module_exp = sign => x => sign * Math.exp(x);
const vega_util_module_log = sign => x => Math.log(sign * x);
const symlog = c => x => Math.sign(x) * Math.log1p(Math.abs(x / c));
const symexp = c => x => Math.sign(x) * Math.expm1(Math.abs(x)) * c;
const vega_util_module_pow = exponent => x => x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
function pan(domain, delta, lift, ground) {
  const d0 = lift(domain[0]),
    d1 = lift(peek(domain)),
    dd = (d1 - d0) * delta;
  return [ground(d0 - dd), ground(d1 - dd)];
}
function panLinear(domain, delta) {
  return pan(domain, delta, vega_util_module_toNumber, vega_util_module_identity);
}
function panLog(domain, delta) {
  var sign = Math.sign(domain[0]);
  return pan(domain, delta, vega_util_module_log(sign), vega_util_module_exp(sign));
}
function panPow(domain, delta, exponent) {
  return pan(domain, delta, vega_util_module_pow(exponent), vega_util_module_pow(1 / exponent));
}
function panSymlog(domain, delta, constant) {
  return pan(domain, delta, symlog(constant), symexp(constant));
}
function zoom(domain, anchor, scale, lift, ground) {
  const d0 = lift(domain[0]),
    d1 = lift(peek(domain)),
    da = anchor != null ? lift(anchor) : (d0 + d1) / 2;
  return [ground(da + (d0 - da) * scale), ground(da + (d1 - da) * scale)];
}
function zoomLinear(domain, anchor, scale) {
  return zoom(domain, anchor, scale, vega_util_module_toNumber, vega_util_module_identity);
}
function zoomLog(domain, anchor, scale) {
  const sign = Math.sign(domain[0]);
  return zoom(domain, anchor, scale, vega_util_module_log(sign), vega_util_module_exp(sign));
}
function zoomPow(domain, anchor, scale, exponent) {
  return zoom(domain, anchor, scale, vega_util_module_pow(exponent), vega_util_module_pow(1 / exponent));
}
function zoomSymlog(domain, anchor, scale, constant) {
  return zoom(domain, anchor, scale, symlog(constant), symexp(constant));
}

function vega_util_module_quarter(date) {
  return 1 + ~~(new Date(date).getMonth() / 3);
}
function vega_util_module_utcquarter(date) {
  return 1 + ~~(new Date(date).getUTCMonth() / 3);
}

function vega_util_module_array (_) {
  return _ != null ? vega_util_module_isArray(_) ? _ : [_] : [];
}

/**
 * Span-preserving range clamp. If the span of the input range is less
 * than (max - min) and an endpoint exceeds either the min or max value,
 * the range is translated such that the span is preserved and one
 * endpoint touches the boundary of the min/max range.
 * If the span exceeds (max - min), the range [min, max] is returned.
 */
function clampRange (range, min, max) {
  let lo = range[0],
    hi = range[1],
    span;
  if (hi < lo) {
    span = hi;
    hi = lo;
    lo = span;
  }
  span = hi - lo;
  return span >= max - min ? [min, max] : [lo = Math.min(Math.max(lo, min), max - span), lo + span];
}

function vega_util_module_isFunction (_) {
  return typeof _ === 'function';
}

const DESCENDING = 'descending';
function vega_util_module_compare (fields, orders, opt) {
  opt = opt || {};
  orders = vega_util_module_array(orders) || [];
  const ord = [],
    get = [],
    fmap = {},
    gen = opt.comparator || comparator;
  vega_util_module_array(fields).forEach((f, i) => {
    if (f == null) return;
    ord.push(orders[i] === DESCENDING ? -1 : 1);
    get.push(f = vega_util_module_isFunction(f) ? f : vega_util_module_field(f, null, opt));
    (accessorFields(f) || []).forEach(_ => fmap[_] = 1);
  });
  return get.length === 0 ? null : accessor(gen(get, ord), Object.keys(fmap));
}
const vega_util_module_ascending = (u, v) => (u < v || u == null) && v != null ? -1 : (u > v || v == null) && u != null ? 1 : (v = v instanceof Date ? +v : v, u = u instanceof Date ? +u : u) !== u && v === v ? -1 : v !== v && u === u ? 1 : 0;
const comparator = (fields, orders) => fields.length === 1 ? compare1(fields[0], orders[0]) : compareN(fields, orders, fields.length);
const compare1 = (field, order) => function (a, b) {
  return vega_util_module_ascending(field(a), field(b)) * order;
};
const compareN = (fields, orders, n) => {
  orders.push(0); // pad zero for convenient lookup
  return function (a, b) {
    let f,
      c = 0,
      i = -1;
    while (c === 0 && ++i < n) {
      f = fields[i];
      c = vega_util_module_ascending(f(a), f(b));
    }
    return c * orders[i];
  };
};

function vega_util_module_constant (_) {
  return vega_util_module_isFunction(_) ? _ : () => _;
}

function debounce (delay, handler) {
  let tid;
  return e => {
    if (tid) clearTimeout(tid);
    tid = setTimeout(() => (handler(e), tid = null), delay);
  };
}

function extend (_) {
  for (let x, k, i = 1, len = arguments.length; i < len; ++i) {
    x = arguments[i];
    for (k in x) {
      _[k] = x[k];
    }
  }
  return _;
}

/**
 * Return an array with minimum and maximum values, in the
 * form [min, max]. Ignores null, undefined, and NaN values.
 */
function extent (array, f) {
  let i = 0,
    n,
    v,
    min,
    max;
  if (array && (n = array.length)) {
    if (f == null) {
      // find first valid value
      for (v = array[i]; i < n && (v == null || v !== v); v = array[++i]);
      min = max = v;

      // visit all other values
      for (; i < n; ++i) {
        v = array[i];
        // skip null/undefined; NaN will fail all comparisons
        if (v != null) {
          if (v < min) min = v;
          if (v > max) max = v;
        }
      }
    } else {
      // find first valid value
      for (v = f(array[i]); i < n && (v == null || v !== v); v = f(array[++i]));
      min = max = v;

      // visit all other values
      for (; i < n; ++i) {
        v = f(array[i]);
        // skip null/undefined; NaN will fail all comparisons
        if (v != null) {
          if (v < min) min = v;
          if (v > max) max = v;
        }
      }
    }
  }
  return [min, max];
}

function extentIndex (array, f) {
  const n = array.length;
  let i = -1,
    a,
    b,
    c,
    u,
    v;
  if (f == null) {
    while (++i < n) {
      b = array[i];
      if (b != null && b >= b) {
        a = c = b;
        break;
      }
    }
    if (i === n) return [-1, -1];
    u = v = i;
    while (++i < n) {
      b = array[i];
      if (b != null) {
        if (a > b) {
          a = b;
          u = i;
        }
        if (c < b) {
          c = b;
          v = i;
        }
      }
    }
  } else {
    while (++i < n) {
      b = f(array[i], i, array);
      if (b != null && b >= b) {
        a = c = b;
        break;
      }
    }
    if (i === n) return [-1, -1];
    u = v = i;
    while (++i < n) {
      b = f(array[i], i, array);
      if (b != null) {
        if (a > b) {
          a = b;
          u = i;
        }
        if (c < b) {
          c = b;
          v = i;
        }
      }
    }
  }
  return [u, v];
}

function vega_util_module_has (object, property) {
  return Object.hasOwn(object, property);
}

const vega_util_module_NULL = {};
function fastmap (input) {
  let obj = {},
    test;
  function has$1(key) {
    return vega_util_module_has(obj, key) && obj[key] !== vega_util_module_NULL;
  }
  const map = {
    size: 0,
    empty: 0,
    object: obj,
    has: has$1,
    get(key) {
      return has$1(key) ? obj[key] : undefined;
    },
    set(key, value) {
      if (!has$1(key)) {
        ++map.size;
        if (obj[key] === vega_util_module_NULL) --map.empty;
      }
      obj[key] = value;
      return this;
    },
    delete(key) {
      if (has$1(key)) {
        --map.size;
        ++map.empty;
        obj[key] = vega_util_module_NULL;
      }
      return this;
    },
    clear() {
      map.size = map.empty = 0;
      map.object = obj = {};
    },
    test(_) {
      if (arguments.length) {
        test = _;
        return map;
      } else {
        return test;
      }
    },
    clean() {
      const next = {};
      let size = 0;
      for (const key in obj) {
        const value = obj[key];
        if (value !== vega_util_module_NULL && (!test || !test(value))) {
          next[key] = value;
          ++size;
        }
      }
      map.size = size;
      map.empty = 0;
      map.object = obj = next;
    }
  };
  if (input) Object.keys(input).forEach(key => {
    map.set(key, input[key]);
  });
  return map;
}

function vega_util_module_flush (range, value, threshold, left, right, center) {
  if (!threshold && threshold !== 0) return center;
  const t = +threshold;
  let a = range[0],
    b = peek(range),
    l;

  // swap endpoints if range is reversed
  if (b < a) {
    l = a;
    a = b;
    b = l;
  }

  // compare value to endpoints
  l = Math.abs(value - a);
  const r = Math.abs(b - value);

  // adjust if value is within threshold distance of endpoint
  return l < r && l <= t ? left : r <= t ? right : center;
}

function inherits (child, parent, members) {
  const proto = child.prototype = Object.create(parent.prototype);
  Object.defineProperty(proto, 'constructor', {
    value: child,
    writable: true,
    enumerable: true,
    configurable: true
  });
  return extend(proto, members);
}

/**
 * Predicate that returns true if the value lies within the span
 * of the given range. The left and right flags control the use
 * of inclusive (true) or exclusive (false) comparisons.
 */
function inrange (value, range, left, right) {
  let r0 = range[0],
    r1 = range[range.length - 1],
    t;
  if (r0 > r1) {
    t = r0;
    r0 = r1;
    r1 = t;
  }
  left = left === undefined || left;
  right = right === undefined || right;
  return (left ? r0 <= value : r0 < value) && (right ? value <= r1 : value < r1);
}

function isBoolean (_) {
  return typeof _ === 'boolean';
}

function vega_util_module_isDate (_) {
  return Object.prototype.toString.call(_) === '[object Date]';
}

function vega_util_module_isIterable (_) {
  return _ && vega_util_module_isFunction(_[Symbol.iterator]);
}

function vega_util_module_isNumber (_) {
  return typeof _ === 'number';
}

function vega_util_module_isRegExp (_) {
  return Object.prototype.toString.call(_) === '[object RegExp]';
}

function vega_util_module_isString (_) {
  return typeof _ === 'string';
}

function vega_util_module_key (fields, flat, opt) {
  if (fields) {
    fields = flat ? vega_util_module_array(fields).map(f => f.replace(/\\(.)/g, '$1')) : vega_util_module_array(fields);
  }
  const len = fields && fields.length,
    gen = opt && opt.get || getter,
    map = f => gen(flat ? [f] : splitAccessPath(f));
  let fn;
  if (!len) {
    fn = function () {
      return '';
    };
  } else if (len === 1) {
    const get = map(fields[0]);
    fn = function (_) {
      return '' + get(_);
    };
  } else {
    const get = fields.map(map);
    fn = function (_) {
      let s = '' + get[0](_),
        i = 0;
      while (++i < len) s += '|' + get[i](_);
      return s;
    };
  }
  return accessor(fn, fields, 'key');
}

function lerp (array, frac) {
  const lo = array[0],
    hi = peek(array),
    f = +frac;
  return !f ? lo : f === 1 ? hi : lo + f * (hi - lo);
}

const DEFAULT_MAX_SIZE = 10000;

// adapted from https://github.com/dominictarr/hashlru/ (MIT License)
function lruCache (maxsize) {
  maxsize = +maxsize || DEFAULT_MAX_SIZE;
  let curr, prev, size;
  const clear = () => {
    curr = {};
    prev = {};
    size = 0;
  };
  const update = (key, value) => {
    if (++size > maxsize) {
      prev = curr;
      curr = {};
      size = 1;
    }
    return curr[key] = value;
  };
  clear();
  return {
    clear,
    has: key => vega_util_module_has(curr, key) || vega_util_module_has(prev, key),
    get: key => vega_util_module_has(curr, key) ? curr[key] : vega_util_module_has(prev, key) ? update(key, prev[key]) : undefined,
    set: (key, value) => vega_util_module_has(curr, key) ? curr[key] = value : update(key, value)
  };
}

function merge (compare, array0, array1, output) {
  const n0 = array0.length,
    n1 = array1.length;
  if (!n1) return array0;
  if (!n0) return array1;
  const merged = output || new array0.constructor(n0 + n1);
  let i0 = 0,
    i1 = 0,
    i = 0;
  for (; i0 < n0 && i1 < n1; ++i) {
    merged[i] = compare(array0[i0], array1[i1]) > 0 ? array1[i1++] : array0[i0++];
  }
  for (; i0 < n0; ++i0, ++i) {
    merged[i] = array0[i0];
  }
  for (; i1 < n1; ++i1, ++i) {
    merged[i] = array1[i1];
  }
  return merged;
}

function vega_util_module_repeat (str, reps) {
  let s = '';
  while (--reps >= 0) s += str;
  return s;
}

function vega_util_module_pad (str, length, padchar, align) {
  const c = padchar || ' ',
    s = str + '',
    n = length - s.length;
  return n <= 0 ? s : align === 'left' ? vega_util_module_repeat(c, n) + s : align === 'center' ? vega_util_module_repeat(c, ~~(n / 2)) + s + vega_util_module_repeat(c, Math.ceil(n / 2)) : s + vega_util_module_repeat(c, n);
}

/**
 * Return the numerical span of an array: the difference between
 * the last and first values.
 */
function span (array) {
  return array && peek(array) - array[0] || 0;
}

function $(x) {
  return vega_util_module_isArray(x) ? '[' + x.map($) + ']' : vega_util_module_isObject(x) || vega_util_module_isString(x) ?
  // Output valid JSON and JS source strings.
  // See http://timelessrepo.com/json-isnt-a-javascript-subset
  JSON.stringify(x).replace('\u2028', '\\u2028').replace('\u2029', '\\u2029') : x;
}

function toBoolean (_) {
  return _ == null || _ === '' ? null : !_ || _ === 'false' || _ === '0' ? false : !!_;
}

const defaultParser = _ => vega_util_module_isNumber(_) ? _ : vega_util_module_isDate(_) ? _ : Date.parse(_);
function toDate (_, parser) {
  parser = parser || defaultParser;
  return _ == null || _ === '' ? null : parser(_);
}

function vega_util_module_toString (_) {
  return _ == null || _ === '' ? null : _ + '';
}

function vega_util_module_toSet (_) {
  const s = {},
    n = _.length;
  for (let i = 0; i < n; ++i) s[_[i]] = true;
  return s;
}

function truncate (str, length, align, ellipsis) {
  const e = ellipsis != null ? ellipsis : '\u2026',
    s = str + '',
    n = s.length,
    l = Math.max(0, length - e.length);
  return n <= length ? s : align === 'left' ? e + s.slice(n - l) : align === 'center' ? s.slice(0, Math.ceil(l / 2)) + e + s.slice(n - ~~(l / 2)) : s.slice(0, l) + e;
}

function visitArray (array, filter, visitor) {
  if (array) {
    if (filter) {
      const n = array.length;
      for (let i = 0; i < n; ++i) {
        const t = filter(array[i]);
        if (t) visitor(t, i, array);
      }
    } else {
      array.forEach(visitor);
    }
  }
}



;// ../../node_modules/d3-dsv/src/dsv.js
var dsv_EOL = {},
    EOF = {},
    dsv_QUOTE = 34,
    dsv_NEWLINE = 10,
    dsv_RETURN = 13;

function objectConverter(columns) {
  return new Function("d", "return {" + columns.map(function(name, i) {
    return JSON.stringify(name) + ": d[" + i + "] || \"\"";
  }).join(",") + "}");
}

function customConverter(columns, f) {
  var object = objectConverter(columns);
  return function(row, i) {
    return f(object(row), i, columns);
  };
}

// Compute unique columns in order of discovery.
function inferColumns(rows) {
  var columnSet = Object.create(null),
      columns = [];

  rows.forEach(function(row) {
    for (var column in row) {
      if (!(column in columnSet)) {
        columns.push(columnSet[column] = column);
      }
    }
  });

  return columns;
}

function dsv_pad(value, width) {
  var s = value + "", length = s.length;
  return length < width ? new Array(width - length + 1).join(0) + s : s;
}

function dsv_formatYear(year) {
  return year < 0 ? "-" + dsv_pad(-year, 6)
    : year > 9999 ? "+" + dsv_pad(year, 6)
    : dsv_pad(year, 4);
}

function dsv_formatDate(date) {
  var hours = date.getUTCHours(),
      minutes = date.getUTCMinutes(),
      seconds = date.getUTCSeconds(),
      milliseconds = date.getUTCMilliseconds();
  return isNaN(date) ? "Invalid Date"
      : dsv_formatYear(date.getUTCFullYear(), 4) + "-" + dsv_pad(date.getUTCMonth() + 1, 2) + "-" + dsv_pad(date.getUTCDate(), 2)
      + (milliseconds ? "T" + dsv_pad(hours, 2) + ":" + dsv_pad(minutes, 2) + ":" + dsv_pad(seconds, 2) + "." + dsv_pad(milliseconds, 3) + "Z"
      : seconds ? "T" + dsv_pad(hours, 2) + ":" + dsv_pad(minutes, 2) + ":" + dsv_pad(seconds, 2) + "Z"
      : minutes || hours ? "T" + dsv_pad(hours, 2) + ":" + dsv_pad(minutes, 2) + "Z"
      : "");
}

/* harmony default export */ function dsv(delimiter) {
  var reFormat = new RegExp("[\"" + delimiter + "\n\r]"),
      DELIMITER = delimiter.charCodeAt(0);

  function parse(text, f) {
    var convert, columns, rows = parseRows(text, function(row, i) {
      if (convert) return convert(row, i - 1);
      columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
    });
    rows.columns = columns || [];
    return rows;
  }

  function parseRows(text, f) {
    var rows = [], // output rows
        N = text.length,
        I = 0, // current character index
        n = 0, // current line number
        t, // current token
        eof = N <= 0, // current token followed by EOF?
        eol = false; // current token followed by EOL?

    // Strip the trailing newline.
    if (text.charCodeAt(N - 1) === dsv_NEWLINE) --N;
    if (text.charCodeAt(N - 1) === dsv_RETURN) --N;

    function token() {
      if (eof) return EOF;
      if (eol) return eol = false, dsv_EOL;

      // Unescape quotes.
      var i, j = I, c;
      if (text.charCodeAt(j) === dsv_QUOTE) {
        while (I++ < N && text.charCodeAt(I) !== dsv_QUOTE || text.charCodeAt(++I) === dsv_QUOTE);
        if ((i = I) >= N) eof = true;
        else if ((c = text.charCodeAt(I++)) === dsv_NEWLINE) eol = true;
        else if (c === dsv_RETURN) { eol = true; if (text.charCodeAt(I) === dsv_NEWLINE) ++I; }
        return text.slice(j + 1, i - 1).replace(/""/g, "\"");
      }

      // Find next delimiter or newline.
      while (I < N) {
        if ((c = text.charCodeAt(i = I++)) === dsv_NEWLINE) eol = true;
        else if (c === dsv_RETURN) { eol = true; if (text.charCodeAt(I) === dsv_NEWLINE) ++I; }
        else if (c !== DELIMITER) continue;
        return text.slice(j, i);
      }

      // Return last token before EOF.
      return eof = true, text.slice(j, N);
    }

    while ((t = token()) !== EOF) {
      var row = [];
      while (t !== dsv_EOL && t !== EOF) row.push(t), t = token();
      if (f && (row = f(row, n++)) == null) continue;
      rows.push(row);
    }

    return rows;
  }

  function preformatBody(rows, columns) {
    return rows.map(function(row) {
      return columns.map(function(column) {
        return formatValue(row[column]);
      }).join(delimiter);
    });
  }

  function format(rows, columns) {
    if (columns == null) columns = inferColumns(rows);
    return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n");
  }

  function formatBody(rows, columns) {
    if (columns == null) columns = inferColumns(rows);
    return preformatBody(rows, columns).join("\n");
  }

  function formatRows(rows) {
    return rows.map(formatRow).join("\n");
  }

  function formatRow(row) {
    return row.map(formatValue).join(delimiter);
  }

  function formatValue(value) {
    return value == null ? ""
        : value instanceof Date ? dsv_formatDate(value)
        : reFormat.test(value += "") ? "\"" + value.replace(/"/g, "\"\"") + "\""
        : value;
  }

  return {
    parse: parse,
    parseRows: parseRows,
    format: format,
    formatBody: formatBody,
    formatRows: formatRows,
    formatRow: formatRow,
    formatValue: formatValue
  };
}

;// ../../node_modules/topojson-client/src/reverse.js
/* harmony default export */ function src_reverse(array, n) {
  var t, j = array.length, i = j - n;
  while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
}

;// ../../node_modules/topojson-client/src/identity.js
/* harmony default export */ function src_identity(x) {
  return x;
}

;// ../../node_modules/topojson-client/src/transform.js


/* harmony default export */ function transform(transform) {
  if (transform == null) return src_identity;
  var x0,
      y0,
      kx = transform.scale[0],
      ky = transform.scale[1],
      dx = transform.translate[0],
      dy = transform.translate[1];
  return function(input, i) {
    if (!i) x0 = y0 = 0;
    var j = 2, n = input.length, output = new Array(n);
    output[0] = (x0 += input[0]) * kx + dx;
    output[1] = (y0 += input[1]) * ky + dy;
    while (j < n) output[j] = input[j], ++j;
    return output;
  };
}

;// ../../node_modules/topojson-client/src/feature.js



/* harmony default export */ function feature(topology, o) {
  if (typeof o === "string") o = topology.objects[o];
  return o.type === "GeometryCollection"
      ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature_feature(topology, o); })}
      : feature_feature(topology, o);
}

function feature_feature(topology, o) {
  var id = o.id,
      bbox = o.bbox,
      properties = o.properties == null ? {} : o.properties,
      geometry = feature_object(topology, o);
  return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry}
      : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry}
      : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry};
}

function feature_object(topology, o) {
  var transformPoint = transform(topology.transform),
      arcs = topology.arcs;

  function arc(i, points) {
    if (points.length) points.pop();
    for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) {
      points.push(transformPoint(a[k], k));
    }
    if (i < 0) src_reverse(points, n);
  }

  function point(p) {
    return transformPoint(p);
  }

  function line(arcs) {
    var points = [];
    for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
    if (points.length < 2) points.push(points[0]); // This should never happen per the specification.
    return points;
  }

  function ring(arcs) {
    var points = line(arcs);
    while (points.length < 4) points.push(points[0]); // This may happen if an arc has only two points.
    return points;
  }

  function polygon(arcs) {
    return arcs.map(ring);
  }

  function geometry(o) {
    var type = o.type, coordinates;
    switch (type) {
      case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)};
      case "Point": coordinates = point(o.coordinates); break;
      case "MultiPoint": coordinates = o.coordinates.map(point); break;
      case "LineString": coordinates = line(o.arcs); break;
      case "MultiLineString": coordinates = o.arcs.map(line); break;
      case "Polygon": coordinates = polygon(o.arcs); break;
      case "MultiPolygon": coordinates = o.arcs.map(polygon); break;
      default: return null;
    }
    return {type: type, coordinates: coordinates};
  }

  return geometry(o);
}

;// ../../node_modules/topojson-client/src/stitch.js
/* harmony default export */ function stitch(topology, arcs) {
  var stitchedArcs = {},
      fragmentByStart = {},
      fragmentByEnd = {},
      fragments = [],
      emptyIndex = -1;

  // Stitch empty arcs first, since they may be subsumed by other arcs.
  arcs.forEach(function(i, j) {
    var arc = topology.arcs[i < 0 ? ~i : i], t;
    if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
      t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
    }
  });

  arcs.forEach(function(i) {
    var e = ends(i),
        start = e[0],
        end = e[1],
        f, g;

    if (f = fragmentByEnd[start]) {
      delete fragmentByEnd[f.end];
      f.push(i);
      f.end = end;
      if (g = fragmentByStart[end]) {
        delete fragmentByStart[g.start];
        var fg = g === f ? f : f.concat(g);
        fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
      } else {
        fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
      }
    } else if (f = fragmentByStart[end]) {
      delete fragmentByStart[f.start];
      f.unshift(i);
      f.start = start;
      if (g = fragmentByEnd[start]) {
        delete fragmentByEnd[g.end];
        var gf = g === f ? f : g.concat(f);
        fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
      } else {
        fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
      }
    } else {
      f = [i];
      fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
    }
  });

  function ends(i) {
    var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
    if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
    else p1 = arc[arc.length - 1];
    return i < 0 ? [p1, p0] : [p0, p1];
  }

  function flush(fragmentByEnd, fragmentByStart) {
    for (var k in fragmentByEnd) {
      var f = fragmentByEnd[k];
      delete fragmentByStart[f.start];
      delete f.start;
      delete f.end;
      f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
      fragments.push(f);
    }
  }

  flush(fragmentByEnd, fragmentByStart);
  flush(fragmentByStart, fragmentByEnd);
  arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });

  return fragments;
}

;// ../../node_modules/topojson-client/src/mesh.js



/* harmony default export */ function mesh(topology) {
  return feature_object(topology, meshArcs.apply(this, arguments));
}

function meshArcs(topology, object, filter) {
  var arcs, i, n;
  if (arguments.length > 1) arcs = extractArcs(topology, object, filter);
  else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i;
  return {type: "MultiLineString", arcs: stitch(topology, arcs)};
}

function extractArcs(topology, object, filter) {
  var arcs = [],
      geomsByArc = [],
      geom;

  function extract0(i) {
    var j = i < 0 ? ~i : i;
    (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
  }

  function extract1(arcs) {
    arcs.forEach(extract0);
  }

  function extract2(arcs) {
    arcs.forEach(extract1);
  }

  function extract3(arcs) {
    arcs.forEach(extract2);
  }

  function geometry(o) {
    switch (geom = o, o.type) {
      case "GeometryCollection": o.geometries.forEach(geometry); break;
      case "LineString": extract1(o.arcs); break;
      case "MultiLineString": case "Polygon": extract2(o.arcs); break;
      case "MultiPolygon": extract3(o.arcs); break;
    }
  }

  geometry(object);

  geomsByArc.forEach(filter == null
      ? function(geoms) { arcs.push(geoms[0].i); }
      : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });

  return arcs;
}

;// ../../node_modules/d3-array/src/ticks.js
const e10 = Math.sqrt(50),
    e5 = Math.sqrt(10),
    e2 = Math.sqrt(2);

function tickSpec(start, stop, count) {
  const step = (stop - start) / Math.max(0, count),
      power = Math.floor(Math.log10(step)),
      error = step / Math.pow(10, power),
      factor = error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1;
  let i1, i2, inc;
  if (power < 0) {
    inc = Math.pow(10, -power) / factor;
    i1 = Math.round(start * inc);
    i2 = Math.round(stop * inc);
    if (i1 / inc < start) ++i1;
    if (i2 / inc > stop) --i2;
    inc = -inc;
  } else {
    inc = Math.pow(10, power) * factor;
    i1 = Math.round(start / inc);
    i2 = Math.round(stop / inc);
    if (i1 * inc < start) ++i1;
    if (i2 * inc > stop) --i2;
  }
  if (i2 < i1 && 0.5 <= count && count < 2) return tickSpec(start, stop, count * 2);
  return [i1, i2, inc];
}

function ticks(start, stop, count) {
  stop = +stop, start = +start, count = +count;
  if (!(count > 0)) return [];
  if (start === stop) return [start];
  const reverse = stop < start, [i1, i2, inc] = reverse ? tickSpec(stop, start, count) : tickSpec(start, stop, count);
  if (!(i2 >= i1)) return [];
  const n = i2 - i1 + 1, ticks = new Array(n);
  if (reverse) {
    if (inc < 0) for (let i = 0; i < n; ++i) ticks[i] = (i2 - i) / -inc;
    else for (let i = 0; i < n; ++i) ticks[i] = (i2 - i) * inc;
  } else {
    if (inc < 0) for (let i = 0; i < n; ++i) ticks[i] = (i1 + i) / -inc;
    else for (let i = 0; i < n; ++i) ticks[i] = (i1 + i) * inc;
  }
  return ticks;
}

function tickIncrement(start, stop, count) {
  stop = +stop, start = +start, count = +count;
  return tickSpec(start, stop, count)[2];
}

function tickStep(start, stop, count) {
  stop = +stop, start = +start, count = +count;
  const reverse = stop < start, inc = reverse ? tickIncrement(stop, start, count) : tickIncrement(start, stop, count);
  return (reverse ? -1 : 1) * (inc < 0 ? 1 / -inc : inc);
}

;// ../../node_modules/d3-format/src/formatSpecifier.js
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;

function formatSpecifier(specifier) {
  if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
  var match;
  return new FormatSpecifier({
    fill: match[1],
    align: match[2],
    sign: match[3],
    symbol: match[4],
    zero: match[5],
    width: match[6],
    comma: match[7],
    precision: match[8] && match[8].slice(1),
    trim: match[9],
    type: match[10]
  });
}

formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof

function FormatSpecifier(specifier) {
  this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
  this.align = specifier.align === undefined ? ">" : specifier.align + "";
  this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
  this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
  this.zero = !!specifier.zero;
  this.width = specifier.width === undefined ? undefined : +specifier.width;
  this.comma = !!specifier.comma;
  this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
  this.trim = !!specifier.trim;
  this.type = specifier.type === undefined ? "" : specifier.type + "";
}

FormatSpecifier.prototype.toString = function() {
  return this.fill
      + this.align
      + this.sign
      + this.symbol
      + (this.zero ? "0" : "")
      + (this.width === undefined ? "" : Math.max(1, this.width | 0))
      + (this.comma ? "," : "")
      + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
      + (this.trim ? "~" : "")
      + this.type;
};

;// ../../node_modules/d3-format/src/formatDecimal.js
/* harmony default export */ function formatDecimal(x) {
  return Math.abs(x = Math.round(x)) >= 1e21
      ? x.toLocaleString("en").replace(/,/g, "")
      : x.toString(10);
}

// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimalParts(1.23) returns ["123", 0].
function formatDecimalParts(x, p) {
  if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
  var i, coefficient = x.slice(0, i);

  // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
  // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
  return [
    coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
    +x.slice(i + 1)
  ];
}

;// ../../node_modules/d3-format/src/exponent.js


/* harmony default export */ function exponent(x) {
  return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
}

;// ../../node_modules/d3-format/src/precisionPrefix.js


/* harmony default export */ function precisionPrefix(step, value) {
  return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
}

;// ../../node_modules/d3-format/src/precisionRound.js


/* harmony default export */ function precisionRound(step, max) {
  step = Math.abs(step), max = Math.abs(max) - step;
  return Math.max(0, exponent(max) - exponent(step)) + 1;
}

;// ../../node_modules/d3-format/src/precisionFixed.js


/* harmony default export */ function precisionFixed(step) {
  return Math.max(0, -exponent(Math.abs(step)));
}

;// ../../node_modules/d3-format/src/formatGroup.js
/* harmony default export */ function formatGroup(grouping, thousands) {
  return function(value, width) {
    var i = value.length,
        t = [],
        j = 0,
        g = grouping[0],
        length = 0;

    while (i > 0 && g > 0) {
      if (length + g + 1 > width) g = Math.max(1, width - length);
      t.push(value.substring(i -= g, i + g));
      if ((length += g + 1) > width) break;
      g = grouping[j = (j + 1) % grouping.length];
    }

    return t.reverse().join(thousands);
  };
}

;// ../../node_modules/d3-format/src/formatNumerals.js
/* harmony default export */ function formatNumerals(numerals) {
  return function(value) {
    return value.replace(/[0-9]/g, function(i) {
      return numerals[+i];
    });
  };
}

;// ../../node_modules/d3-format/src/formatTrim.js
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
/* harmony default export */ function formatTrim(s) {
  out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
    switch (s[i]) {
      case ".": i0 = i1 = i; break;
      case "0": if (i0 === 0) i0 = i; i1 = i; break;
      default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
    }
  }
  return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}

;// ../../node_modules/d3-format/src/formatPrefixAuto.js


var prefixExponent;

/* harmony default export */ function formatPrefixAuto(x, p) {
  var d = formatDecimalParts(x, p);
  if (!d) return x + "";
  var coefficient = d[0],
      exponent = d[1],
      i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
      n = coefficient.length;
  return i === n ? coefficient
      : i > n ? coefficient + new Array(i - n + 1).join("0")
      : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
      : "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
}

;// ../../node_modules/d3-format/src/formatRounded.js


/* harmony default export */ function formatRounded(x, p) {
  var d = formatDecimalParts(x, p);
  if (!d) return x + "";
  var coefficient = d[0],
      exponent = d[1];
  return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
      : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
      : coefficient + new Array(exponent - coefficient.length + 2).join("0");
}

;// ../../node_modules/d3-format/src/formatTypes.js




/* harmony default export */ const formatTypes = ({
  "%": (x, p) => (x * 100).toFixed(p),
  "b": (x) => Math.round(x).toString(2),
  "c": (x) => x + "",
  "d": formatDecimal,
  "e": (x, p) => x.toExponential(p),
  "f": (x, p) => x.toFixed(p),
  "g": (x, p) => x.toPrecision(p),
  "o": (x) => Math.round(x).toString(8),
  "p": (x, p) => formatRounded(x * 100, p),
  "r": formatRounded,
  "s": formatPrefixAuto,
  "X": (x) => Math.round(x).toString(16).toUpperCase(),
  "x": (x) => Math.round(x).toString(16)
});

;// ../../node_modules/d3-format/src/identity.js
/* harmony default export */ function d3_format_src_identity(x) {
  return x;
}

;// ../../node_modules/d3-format/src/locale.js









var locale_map = Array.prototype.map,
    prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];

/* harmony default export */ function locale(locale) {
  var group = locale.grouping === undefined || locale.thousands === undefined ? d3_format_src_identity : formatGroup(locale_map.call(locale.grouping, Number), locale.thousands + ""),
      currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
      currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
      decimal = locale.decimal === undefined ? "." : locale.decimal + "",
      numerals = locale.numerals === undefined ? d3_format_src_identity : formatNumerals(locale_map.call(locale.numerals, String)),
      percent = locale.percent === undefined ? "%" : locale.percent + "",
      minus = locale.minus === undefined ? "−" : locale.minus + "",
      nan = locale.nan === undefined ? "NaN" : locale.nan + "";

  function newFormat(specifier) {
    specifier = formatSpecifier(specifier);

    var fill = specifier.fill,
        align = specifier.align,
        sign = specifier.sign,
        symbol = specifier.symbol,
        zero = specifier.zero,
        width = specifier.width,
        comma = specifier.comma,
        precision = specifier.precision,
        trim = specifier.trim,
        type = specifier.type;

    // The "n" type is an alias for ",g".
    if (type === "n") comma = true, type = "g";

    // The "" type, and any invalid type, is an alias for ".12~g".
    else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";

    // If zero fill is specified, padding goes after sign and before digits.
    if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";

    // Compute the prefix and suffix.
    // For SI-prefix, the suffix is lazily computed.
    var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
        suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "";

    // What format function should we use?
    // Is this an integer type?
    // Can this type generate exponential notation?
    var formatType = formatTypes[type],
        maybeSuffix = /[defgprs%]/.test(type);

    // Set the default precision if not specified,
    // or clamp the specified precision to the supported range.
    // For significant precision, it must be in [1, 21].
    // For fixed precision, it must be in [0, 20].
    precision = precision === undefined ? 6
        : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
        : Math.max(0, Math.min(20, precision));

    function format(value) {
      var valuePrefix = prefix,
          valueSuffix = suffix,
          i, n, c;

      if (type === "c") {
        valueSuffix = formatType(value) + valueSuffix;
        value = "";
      } else {
        value = +value;

        // Determine the sign. -0 is not less than 0, but 1 / -0 is!
        var valueNegative = value < 0 || 1 / value < 0;

        // Perform the initial formatting.
        value = isNaN(value) ? nan : formatType(Math.abs(value), precision);

        // Trim insignificant zeros.
        if (trim) value = formatTrim(value);

        // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
        if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;

        // Compute the prefix and suffix.
        valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
        valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");

        // Break the formatted value into the integer “value” part that can be
        // grouped, and fractional or exponential “suffix” part that is not.
        if (maybeSuffix) {
          i = -1, n = value.length;
          while (++i < n) {
            if (c = value.charCodeAt(i), 48 > c || c > 57) {
              valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
              value = value.slice(0, i);
              break;
            }
          }
        }
      }

      // If the fill character is not "0", grouping is applied before padding.
      if (comma && !zero) value = group(value, Infinity);

      // Compute the padding.
      var length = valuePrefix.length + value.length + valueSuffix.length,
          padding = length < width ? new Array(width - length + 1).join(fill) : "";

      // If the fill character is "0", grouping is applied after padding.
      if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";

      // Reconstruct the final output based on the desired alignment.
      switch (align) {
        case "<": value = valuePrefix + value + valueSuffix + padding; break;
        case "=": value = valuePrefix + padding + value + valueSuffix; break;
        case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
        default: value = padding + valuePrefix + value + valueSuffix; break;
      }

      return numerals(value);
    }

    format.toString = function() {
      return specifier + "";
    };

    return format;
  }

  function formatPrefix(specifier, value) {
    var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
        e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
        k = Math.pow(10, -e),
        prefix = prefixes[8 + e / 3];
    return function(value) {
      return f(k * value) + prefix;
    };
  }

  return {
    format: newFormat,
    formatPrefix: formatPrefix
  };
}

;// ../../node_modules/d3-format/src/defaultLocale.js


var defaultLocale_locale;
var format;
var formatPrefix;

defaultLocale({
  thousands: ",",
  grouping: [3],
  currency: ["$", ""]
});

function defaultLocale(definition) {
  defaultLocale_locale = locale(definition);
  format = defaultLocale_locale.format;
  formatPrefix = defaultLocale_locale.formatPrefix;
  return defaultLocale_locale;
}

;// ../../node_modules/d3-time/src/interval.js
const interval_t0 = new Date, interval_t1 = new Date;

function timeInterval(floori, offseti, count, field) {

  function interval(date) {
    return floori(date = arguments.length === 0 ? new Date : new Date(+date)), date;
  }

  interval.floor = (date) => {
    return floori(date = new Date(+date)), date;
  };

  interval.ceil = (date) => {
    return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
  };

  interval.round = (date) => {
    const d0 = interval(date), d1 = interval.ceil(date);
    return date - d0 < d1 - date ? d0 : d1;
  };

  interval.offset = (date, step) => {
    return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
  };

  interval.range = (start, stop, step) => {
    const range = [];
    start = interval.ceil(start);
    step = step == null ? 1 : Math.floor(step);
    if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
    let previous;
    do range.push(previous = new Date(+start)), offseti(start, step), floori(start);
    while (previous < start && start < stop);
    return range;
  };

  interval.filter = (test) => {
    return timeInterval((date) => {
      if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
    }, (date, step) => {
      if (date >= date) {
        if (step < 0) while (++step <= 0) {
          while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty
        } else while (--step >= 0) {
          while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty
        }
      }
    });
  };

  if (count) {
    interval.count = (start, end) => {
      interval_t0.setTime(+start), interval_t1.setTime(+end);
      floori(interval_t0), floori(interval_t1);
      return Math.floor(count(interval_t0, interval_t1));
    };

    interval.every = (step) => {
      step = Math.floor(step);
      return !isFinite(step) || !(step > 0) ? null
          : !(step > 1) ? interval
          : interval.filter(field
              ? (d) => field(d) % step === 0
              : (d) => interval.count(0, d) % step === 0);
    };
  }

  return interval;
}

;// ../../node_modules/d3-time/src/duration.js
const durationSecond = 1000;
const durationMinute = durationSecond * 60;
const durationHour = durationMinute * 60;
const durationDay = durationHour * 24;
const durationWeek = durationDay * 7;
const durationMonth = durationDay * 30;
const durationYear = durationDay * 365;

;// ../../node_modules/d3-time/src/day.js



const timeDay = timeInterval(
  date => date.setHours(0, 0, 0, 0),
  (date, step) => date.setDate(date.getDate() + step),
  (start, end) => (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay,
  date => date.getDate() - 1
);

const timeDays = timeDay.range;

const utcDay = timeInterval((date) => {
  date.setUTCHours(0, 0, 0, 0);
}, (date, step) => {
  date.setUTCDate(date.getUTCDate() + step);
}, (start, end) => {
  return (end - start) / durationDay;
}, (date) => {
  return date.getUTCDate() - 1;
});

const utcDays = utcDay.range;

const unixDay = timeInterval((date) => {
  date.setUTCHours(0, 0, 0, 0);
}, (date, step) => {
  date.setUTCDate(date.getUTCDate() + step);
}, (start, end) => {
  return (end - start) / durationDay;
}, (date) => {
  return Math.floor(date / durationDay);
});

const unixDays = unixDay.range;

;// ../../node_modules/d3-time/src/week.js



function timeWeekday(i) {
  return timeInterval((date) => {
    date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
    date.setHours(0, 0, 0, 0);
  }, (date, step) => {
    date.setDate(date.getDate() + step * 7);
  }, (start, end) => {
    return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
  });
}

const timeSunday = timeWeekday(0);
const timeMonday = timeWeekday(1);
const timeTuesday = timeWeekday(2);
const timeWednesday = timeWeekday(3);
const timeThursday = timeWeekday(4);
const timeFriday = timeWeekday(5);
const timeSaturday = timeWeekday(6);

const timeSundays = timeSunday.range;
const timeMondays = timeMonday.range;
const timeTuesdays = timeTuesday.range;
const timeWednesdays = timeWednesday.range;
const timeThursdays = timeThursday.range;
const timeFridays = timeFriday.range;
const timeSaturdays = timeSaturday.range;

function utcWeekday(i) {
  return timeInterval((date) => {
    date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
    date.setUTCHours(0, 0, 0, 0);
  }, (date, step) => {
    date.setUTCDate(date.getUTCDate() + step * 7);
  }, (start, end) => {
    return (end - start) / durationWeek;
  });
}

const utcSunday = utcWeekday(0);
const utcMonday = utcWeekday(1);
const utcTuesday = utcWeekday(2);
const utcWednesday = utcWeekday(3);
const utcThursday = utcWeekday(4);
const utcFriday = utcWeekday(5);
const utcSaturday = utcWeekday(6);

const utcSundays = utcSunday.range;
const utcMondays = utcMonday.range;
const utcTuesdays = utcTuesday.range;
const utcWednesdays = utcWednesday.range;
const utcThursdays = utcThursday.range;
const utcFridays = utcFriday.range;
const utcSaturdays = utcSaturday.range;

;// ../../node_modules/d3-time/src/year.js


const timeYear = timeInterval((date) => {
  date.setMonth(0, 1);
  date.setHours(0, 0, 0, 0);
}, (date, step) => {
  date.setFullYear(date.getFullYear() + step);
}, (start, end) => {
  return end.getFullYear() - start.getFullYear();
}, (date) => {
  return date.getFullYear();
});

// An optimized implementation for this simple case.
timeYear.every = (k) => {
  return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : timeInterval((date) => {
    date.setFullYear(Math.floor(date.getFullYear() / k) * k);
    date.setMonth(0, 1);
    date.setHours(0, 0, 0, 0);
  }, (date, step) => {
    date.setFullYear(date.getFullYear() + step * k);
  });
};

const timeYears = timeYear.range;

const utcYear = timeInterval((date) => {
  date.setUTCMonth(0, 1);
  date.setUTCHours(0, 0, 0, 0);
}, (date, step) => {
  date.setUTCFullYear(date.getUTCFullYear() + step);
}, (start, end) => {
  return end.getUTCFullYear() - start.getUTCFullYear();
}, (date) => {
  return date.getUTCFullYear();
});

// An optimized implementation for this simple case.
utcYear.every = (k) => {
  return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : timeInterval((date) => {
    date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
    date.setUTCMonth(0, 1);
    date.setUTCHours(0, 0, 0, 0);
  }, (date, step) => {
    date.setUTCFullYear(date.getUTCFullYear() + step * k);
  });
};

const utcYears = utcYear.range;

;// ../../node_modules/d3-time/src/month.js


const timeMonth = timeInterval((date) => {
  date.setDate(1);
  date.setHours(0, 0, 0, 0);
}, (date, step) => {
  date.setMonth(date.getMonth() + step);
}, (start, end) => {
  return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
}, (date) => {
  return date.getMonth();
});

const timeMonths = timeMonth.range;

const utcMonth = timeInterval((date) => {
  date.setUTCDate(1);
  date.setUTCHours(0, 0, 0, 0);
}, (date, step) => {
  date.setUTCMonth(date.getUTCMonth() + step);
}, (start, end) => {
  return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
}, (date) => {
  return date.getUTCMonth();
});

const utcMonths = utcMonth.range;

;// ../../node_modules/d3-time/src/hour.js



const timeHour = timeInterval((date) => {
  date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond - date.getMinutes() * durationMinute);
}, (date, step) => {
  date.setTime(+date + step * durationHour);
}, (start, end) => {
  return (end - start) / durationHour;
}, (date) => {
  return date.getHours();
});

const timeHours = timeHour.range;

const utcHour = timeInterval((date) => {
  date.setUTCMinutes(0, 0, 0);
}, (date, step) => {
  date.setTime(+date + step * durationHour);
}, (start, end) => {
  return (end - start) / durationHour;
}, (date) => {
  return date.getUTCHours();
});

const utcHours = utcHour.range;

;// ../../node_modules/d3-time/src/minute.js



const timeMinute = timeInterval((date) => {
  date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond);
}, (date, step) => {
  date.setTime(+date + step * durationMinute);
}, (start, end) => {
  return (end - start) / durationMinute;
}, (date) => {
  return date.getMinutes();
});

const timeMinutes = timeMinute.range;

const utcMinute = timeInterval((date) => {
  date.setUTCSeconds(0, 0);
}, (date, step) => {
  date.setTime(+date + step * durationMinute);
}, (start, end) => {
  return (end - start) / durationMinute;
}, (date) => {
  return date.getUTCMinutes();
});

const utcMinutes = utcMinute.range;

;// ../../node_modules/d3-time/src/second.js



const second = timeInterval((date) => {
  date.setTime(date - date.getMilliseconds());
}, (date, step) => {
  date.setTime(+date + step * durationSecond);
}, (start, end) => {
  return (end - start) / durationSecond;
}, (date) => {
  return date.getUTCSeconds();
});

const second_seconds = second.range;

;// ../../node_modules/d3-time/src/millisecond.js


const millisecond = timeInterval(() => {
  // noop
}, (date, step) => {
  date.setTime(+date + step);
}, (start, end) => {
  return end - start;
});

// An optimized implementation for this simple case.
millisecond.every = (k) => {
  k = Math.floor(k);
  if (!isFinite(k) || !(k > 0)) return null;
  if (!(k > 1)) return millisecond;
  return timeInterval((date) => {
    date.setTime(Math.floor(date / k) * k);
  }, (date, step) => {
    date.setTime(+date + step * k);
  }, (start, end) => {
    return (end - start) / k;
  });
};

const millisecond_milliseconds = millisecond.range;

;// ../../node_modules/d3-array/src/ascending.js
function ascending_ascending(a, b) {
  return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

;// ../../node_modules/d3-array/src/descending.js
function descending(a, b) {
  return a == null || b == null ? NaN
    : b < a ? -1
    : b > a ? 1
    : b >= a ? 0
    : NaN;
}

;// ../../node_modules/d3-array/src/bisector.js



function bisector_bisector(f) {
  let compare1, compare2, delta;

  // If an accessor is specified, promote it to a comparator. In this case we
  // can test whether the search value is (self-) comparable. We can’t do this
  // for a comparator (except for specific, known comparators) because we can’t
  // tell if the comparator is symmetric, and an asymmetric comparator can’t be
  // used to test whether a single value is comparable.
  if (f.length !== 2) {
    compare1 = ascending_ascending;
    compare2 = (d, x) => ascending_ascending(f(d), x);
    delta = (d, x) => f(d) - x;
  } else {
    compare1 = f === ascending_ascending || f === descending ? f : bisector_zero;
    compare2 = f;
    delta = f;
  }

  function left(a, x, lo = 0, hi = a.length) {
    if (lo < hi) {
      if (compare1(x, x) !== 0) return hi;
      do {
        const mid = (lo + hi) >>> 1;
        if (compare2(a[mid], x) < 0) lo = mid + 1;
        else hi = mid;
      } while (lo < hi);
    }
    return lo;
  }

  function right(a, x, lo = 0, hi = a.length) {
    if (lo < hi) {
      if (compare1(x, x) !== 0) return hi;
      do {
        const mid = (lo + hi) >>> 1;
        if (compare2(a[mid], x) <= 0) lo = mid + 1;
        else hi = mid;
      } while (lo < hi);
    }
    return lo;
  }

  function center(a, x, lo = 0, hi = a.length) {
    const i = left(a, x, lo, hi - 1);
    return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
  }

  return {left, center, right};
}

function bisector_zero() {
  return 0;
}

;// ../../node_modules/vega-time/build/vega-time.module.js




const YEAR = 'year';
const QUARTER = 'quarter';
const MONTH = 'month';
const WEEK = 'week';
const DATE = 'date';
const DAY = 'day';
const DAYOFYEAR = 'dayofyear';
const HOURS = 'hours';
const MINUTES = 'minutes';
const SECONDS = 'seconds';
const MILLISECONDS = 'milliseconds';
const TIME_UNITS = [YEAR, QUARTER, MONTH, WEEK, DATE, DAY, DAYOFYEAR, HOURS, MINUTES, SECONDS, MILLISECONDS];
const UNITS = TIME_UNITS.reduce((o, u, i) => (o[u] = 1 + i, o), {});
function timeUnits(units) {
  const u = vega_util_module_array(units).slice(),
    m = {};

  // check validity
  if (!u.length) vega_util_module_error('Missing time unit.');
  u.forEach(unit => {
    if (vega_util_module_has(UNITS, unit)) {
      m[unit] = 1;
    } else {
      vega_util_module_error(`Invalid time unit: ${unit}.`);
    }
  });
  const numTypes = (m[WEEK] || m[DAY] ? 1 : 0) + (m[QUARTER] || m[MONTH] || m[DATE] ? 1 : 0) + (m[DAYOFYEAR] ? 1 : 0);
  if (numTypes > 1) {
    vega_util_module_error(`Incompatible time units: ${units}`);
  }

  // ensure proper sort order
  u.sort((a, b) => UNITS[a] - UNITS[b]);
  return u;
}
const defaultSpecifiers = {
  [YEAR]: '%Y ',
  [QUARTER]: 'Q%q ',
  [MONTH]: '%b ',
  [DATE]: '%d ',
  [WEEK]: 'W%U ',
  [DAY]: '%a ',
  [DAYOFYEAR]: '%j ',
  [HOURS]: '%H:00',
  [MINUTES]: '00:%M',
  [SECONDS]: ':%S',
  [MILLISECONDS]: '.%L',
  [`${YEAR}-${MONTH}`]: '%Y-%m ',
  [`${YEAR}-${MONTH}-${DATE}`]: '%Y-%m-%d ',
  [`${HOURS}-${MINUTES}`]: '%H:%M'
};
function timeUnitSpecifier(units, specifiers) {
  const s = extend({}, defaultSpecifiers, specifiers),
    u = timeUnits(units),
    n = u.length;
  let fmt = '',
    start = 0,
    end,
    key;
  for (start = 0; start < n;) {
    for (end = u.length; end > start; --end) {
      key = u.slice(start, end).join('-');
      if (s[key] != null) {
        fmt += s[key];
        start = end;
        break;
      }
    }
  }
  return fmt.trim();
}

const vega_time_module_t0 = new Date();
function localYear(y) {
  vega_time_module_t0.setFullYear(y);
  vega_time_module_t0.setMonth(0);
  vega_time_module_t0.setDate(1);
  vega_time_module_t0.setHours(0, 0, 0, 0);
  return vega_time_module_t0;
}
function vega_time_module_dayofyear(d) {
  return localDayOfYear(new Date(d));
}
function vega_time_module_week(d) {
  return localWeekNum(new Date(d));
}
function localDayOfYear(d) {
  return timeDay.count(localYear(d.getFullYear()) - 1, d);
}
function localWeekNum(d) {
  return timeSunday.count(localYear(d.getFullYear()) - 1, d);
}
function localFirst(y) {
  return localYear(y).getDay();
}
function localDate(y, m, d, H, M, S, L) {
  if (0 <= y && y < 100) {
    const date = new Date(-1, m, d, H, M, S, L);
    date.setFullYear(y);
    return date;
  }
  return new Date(y, m, d, H, M, S, L);
}
function vega_time_module_utcdayofyear(d) {
  return utcDayOfYear(new Date(d));
}
function vega_time_module_utcweek(d) {
  return utcWeekNum(new Date(d));
}
function utcDayOfYear(d) {
  const y = Date.UTC(d.getUTCFullYear(), 0, 1);
  return utcDay.count(y - 1, d);
}
function utcWeekNum(d) {
  const y = Date.UTC(d.getUTCFullYear(), 0, 1);
  return utcSunday.count(y - 1, d);
}
function utcFirst(y) {
  vega_time_module_t0.setTime(Date.UTC(y, 0, 1));
  return vega_time_module_t0.getUTCDay();
}
function utcDate(y, m, d, H, M, S, L) {
  if (0 <= y && y < 100) {
    const date = new Date(Date.UTC(-1, m, d, H, M, S, L));
    date.setUTCFullYear(d.y);
    return date;
  }
  return new Date(Date.UTC(y, m, d, H, M, S, L));
}

function vega_time_module_floor(units, step, get, inv, newDate) {
  const s = step || 1,
    b = peek(units),
    _ = (unit, p, key) => {
      key = key || unit;
      return getUnit(get[key], inv[key], unit === b && s, p);
    };
  const t = new Date(),
    u = vega_util_module_toSet(units),
    y = u[YEAR] ? _(YEAR) : vega_util_module_constant(2012),
    m = u[MONTH] ? _(MONTH) : u[QUARTER] ? _(QUARTER) : zero,
    d = u[WEEK] && u[DAY] ? _(DAY, 1, WEEK + DAY) : u[WEEK] ? _(WEEK, 1) : u[DAY] ? _(DAY, 1) : u[DATE] ? _(DATE, 1) : u[DAYOFYEAR] ? _(DAYOFYEAR, 1) : one,
    H = u[HOURS] ? _(HOURS) : zero,
    M = u[MINUTES] ? _(MINUTES) : zero,
    S = u[SECONDS] ? _(SECONDS) : zero,
    L = u[MILLISECONDS] ? _(MILLISECONDS) : zero;
  return function (v) {
    t.setTime(+v);
    const year = y(t);
    return newDate(year, m(t), d(t, year), H(t), M(t), S(t), L(t));
  };
}
function getUnit(f, inv, step, phase) {
  const u = step <= 1 ? f : phase ? (d, y) => phase + step * Math.floor((f(d, y) - phase) / step) : (d, y) => step * Math.floor(f(d, y) / step);
  return inv ? (d, y) => inv(u(d, y), y) : u;
}

// returns the day of the year based on week number, day of week,
// and the day of the week for the first day of the year
function weekday(week, day, firstDay) {
  return day + week * 7 - (firstDay + 6) % 7;
}

// -- LOCAL TIME --

const localGet = {
  [YEAR]: d => d.getFullYear(),
  [QUARTER]: d => Math.floor(d.getMonth() / 3),
  [MONTH]: d => d.getMonth(),
  [DATE]: d => d.getDate(),
  [HOURS]: d => d.getHours(),
  [MINUTES]: d => d.getMinutes(),
  [SECONDS]: d => d.getSeconds(),
  [MILLISECONDS]: d => d.getMilliseconds(),
  [DAYOFYEAR]: d => localDayOfYear(d),
  [WEEK]: d => localWeekNum(d),
  [WEEK + DAY]: (d, y) => weekday(localWeekNum(d), d.getDay(), localFirst(y)),
  [DAY]: (d, y) => weekday(1, d.getDay(), localFirst(y))
};
const localInv = {
  [QUARTER]: q => 3 * q,
  [WEEK]: (w, y) => weekday(w, 0, localFirst(y))
};
function timeFloor(units, step) {
  return vega_time_module_floor(units, step || 1, localGet, localInv, localDate);
}

// -- UTC TIME --

const utcGet = {
  [YEAR]: d => d.getUTCFullYear(),
  [QUARTER]: d => Math.floor(d.getUTCMonth() / 3),
  [MONTH]: d => d.getUTCMonth(),
  [DATE]: d => d.getUTCDate(),
  [HOURS]: d => d.getUTCHours(),
  [MINUTES]: d => d.getUTCMinutes(),
  [SECONDS]: d => d.getUTCSeconds(),
  [MILLISECONDS]: d => d.getUTCMilliseconds(),
  [DAYOFYEAR]: d => utcDayOfYear(d),
  [WEEK]: d => utcWeekNum(d),
  [DAY]: (d, y) => weekday(1, d.getUTCDay(), utcFirst(y)),
  [WEEK + DAY]: (d, y) => weekday(utcWeekNum(d), d.getUTCDay(), utcFirst(y))
};
const utcInv = {
  [QUARTER]: q => 3 * q,
  [WEEK]: (w, y) => weekday(w, 0, utcFirst(y))
};
function utcFloor(units, step) {
  return vega_time_module_floor(units, step || 1, utcGet, utcInv, utcDate);
}

const timeIntervals = {
  [YEAR]: timeYear,
  [QUARTER]: timeMonth.every(3),
  [MONTH]: timeMonth,
  [WEEK]: timeSunday,
  [DATE]: timeDay,
  [DAY]: timeDay,
  [DAYOFYEAR]: timeDay,
  [HOURS]: timeHour,
  [MINUTES]: timeMinute,
  [SECONDS]: second,
  [MILLISECONDS]: millisecond
};
const utcIntervals = {
  [YEAR]: utcYear,
  [QUARTER]: utcMonth.every(3),
  [MONTH]: utcMonth,
  [WEEK]: utcSunday,
  [DATE]: utcDay,
  [DAY]: utcDay,
  [DAYOFYEAR]: utcDay,
  [HOURS]: utcHour,
  [MINUTES]: utcMinute,
  [SECONDS]: second,
  [MILLISECONDS]: millisecond
};
function vega_time_module_timeInterval(unit) {
  return timeIntervals[unit];
}
function utcInterval(unit) {
  return utcIntervals[unit];
}
function offset(ival, date, step) {
  return ival ? ival.offset(date, step) : undefined;
}
function timeOffset(unit, date, step) {
  return offset(vega_time_module_timeInterval(unit), date, step);
}
function utcOffset(unit, date, step) {
  return offset(utcInterval(unit), date, step);
}
function vega_time_module_sequence(ival, start, stop, step) {
  return ival ? ival.range(start, stop, step) : undefined;
}
function timeSequence(unit, start, stop, step) {
  return vega_time_module_sequence(vega_time_module_timeInterval(unit), start, stop, step);
}
function utcSequence(unit, start, stop, step) {
  return vega_time_module_sequence(utcInterval(unit), start, stop, step);
}

const vega_time_module_durationSecond = 1000,
  vega_time_module_durationMinute = vega_time_module_durationSecond * 60,
  vega_time_module_durationHour = vega_time_module_durationMinute * 60,
  vega_time_module_durationDay = vega_time_module_durationHour * 24,
  vega_time_module_durationWeek = vega_time_module_durationDay * 7,
  vega_time_module_durationMonth = vega_time_module_durationDay * 30,
  vega_time_module_durationYear = vega_time_module_durationDay * 365;
const Milli = [YEAR, MONTH, DATE, HOURS, MINUTES, SECONDS, MILLISECONDS],
  Seconds = Milli.slice(0, -1),
  Minutes = Seconds.slice(0, -1),
  Hours = Minutes.slice(0, -1),
  Day = Hours.slice(0, -1),
  Week = [YEAR, WEEK],
  Month = [YEAR, MONTH],
  Year = [YEAR];
const intervals = [[Seconds, 1, vega_time_module_durationSecond], [Seconds, 5, 5 * vega_time_module_durationSecond], [Seconds, 15, 15 * vega_time_module_durationSecond], [Seconds, 30, 30 * vega_time_module_durationSecond], [Minutes, 1, vega_time_module_durationMinute], [Minutes, 5, 5 * vega_time_module_durationMinute], [Minutes, 15, 15 * vega_time_module_durationMinute], [Minutes, 30, 30 * vega_time_module_durationMinute], [Hours, 1, vega_time_module_durationHour], [Hours, 3, 3 * vega_time_module_durationHour], [Hours, 6, 6 * vega_time_module_durationHour], [Hours, 12, 12 * vega_time_module_durationHour], [Day, 1, vega_time_module_durationDay], [Week, 1, vega_time_module_durationWeek], [Month, 1, vega_time_module_durationMonth], [Month, 3, 3 * vega_time_module_durationMonth], [Year, 1, vega_time_module_durationYear]];
function vega_time_module_bin (opt) {
  const ext = opt.extent,
    max = opt.maxbins || 40,
    target = Math.abs(span(ext)) / max;
  let i = bisector_bisector(i => i[2]).right(intervals, target),
    units,
    step;
  if (i === intervals.length) {
    units = Year, step = tickStep(ext[0] / vega_time_module_durationYear, ext[1] / vega_time_module_durationYear, max);
  } else if (i) {
    i = intervals[target / intervals[i - 1][2] < intervals[i][2] / target ? i - 1 : i];
    units = i[0];
    step = i[1];
  } else {
    units = Milli;
    step = Math.max(tickStep(ext[0], ext[1], max), 1);
  }
  return {
    units,
    step
  };
}



;// ../../node_modules/d3-time-format/src/locale.js


function locale_localDate(d) {
  if (0 <= d.y && d.y < 100) {
    var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
    date.setFullYear(d.y);
    return date;
  }
  return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
}

function locale_utcDate(d) {
  if (0 <= d.y && d.y < 100) {
    var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
    date.setUTCFullYear(d.y);
    return date;
  }
  return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
}

function newDate(y, m, d) {
  return {y: y, m: m, d: d, H: 0, M: 0, S: 0, L: 0};
}

function formatLocale(locale) {
  var locale_dateTime = locale.dateTime,
      locale_date = locale.date,
      locale_time = locale.time,
      locale_periods = locale.periods,
      locale_weekdays = locale.days,
      locale_shortWeekdays = locale.shortDays,
      locale_months = locale.months,
      locale_shortMonths = locale.shortMonths;

  var periodRe = formatRe(locale_periods),
      periodLookup = formatLookup(locale_periods),
      weekdayRe = formatRe(locale_weekdays),
      weekdayLookup = formatLookup(locale_weekdays),
      shortWeekdayRe = formatRe(locale_shortWeekdays),
      shortWeekdayLookup = formatLookup(locale_shortWeekdays),
      monthRe = formatRe(locale_months),
      monthLookup = formatLookup(locale_months),
      shortMonthRe = formatRe(locale_shortMonths),
      shortMonthLookup = formatLookup(locale_shortMonths);

  var formats = {
    "a": formatShortWeekday,
    "A": formatWeekday,
    "b": formatShortMonth,
    "B": formatMonth,
    "c": null,
    "d": formatDayOfMonth,
    "e": formatDayOfMonth,
    "f": formatMicroseconds,
    "g": formatYearISO,
    "G": formatFullYearISO,
    "H": formatHour24,
    "I": formatHour12,
    "j": formatDayOfYear,
    "L": formatMilliseconds,
    "m": formatMonthNumber,
    "M": formatMinutes,
    "p": formatPeriod,
    "q": formatQuarter,
    "Q": formatUnixTimestamp,
    "s": formatUnixTimestampSeconds,
    "S": formatSeconds,
    "u": formatWeekdayNumberMonday,
    "U": formatWeekNumberSunday,
    "V": formatWeekNumberISO,
    "w": formatWeekdayNumberSunday,
    "W": formatWeekNumberMonday,
    "x": null,
    "X": null,
    "y": locale_formatYear,
    "Y": formatFullYear,
    "Z": formatZone,
    "%": formatLiteralPercent
  };

  var utcFormats = {
    "a": formatUTCShortWeekday,
    "A": formatUTCWeekday,
    "b": formatUTCShortMonth,
    "B": formatUTCMonth,
    "c": null,
    "d": formatUTCDayOfMonth,
    "e": formatUTCDayOfMonth,
    "f": formatUTCMicroseconds,
    "g": formatUTCYearISO,
    "G": formatUTCFullYearISO,
    "H": formatUTCHour24,
    "I": formatUTCHour12,
    "j": formatUTCDayOfYear,
    "L": formatUTCMilliseconds,
    "m": formatUTCMonthNumber,
    "M": formatUTCMinutes,
    "p": formatUTCPeriod,
    "q": formatUTCQuarter,
    "Q": formatUnixTimestamp,
    "s": formatUnixTimestampSeconds,
    "S": formatUTCSeconds,
    "u": formatUTCWeekdayNumberMonday,
    "U": formatUTCWeekNumberSunday,
    "V": formatUTCWeekNumberISO,
    "w": formatUTCWeekdayNumberSunday,
    "W": formatUTCWeekNumberMonday,
    "x": null,
    "X": null,
    "y": formatUTCYear,
    "Y": formatUTCFullYear,
    "Z": formatUTCZone,
    "%": formatLiteralPercent
  };

  var parses = {
    "a": parseShortWeekday,
    "A": parseWeekday,
    "b": parseShortMonth,
    "B": parseMonth,
    "c": parseLocaleDateTime,
    "d": parseDayOfMonth,
    "e": parseDayOfMonth,
    "f": parseMicroseconds,
    "g": parseYear,
    "G": parseFullYear,
    "H": parseHour24,
    "I": parseHour24,
    "j": parseDayOfYear,
    "L": parseMilliseconds,
    "m": parseMonthNumber,
    "M": parseMinutes,
    "p": parsePeriod,
    "q": parseQuarter,
    "Q": parseUnixTimestamp,
    "s": parseUnixTimestampSeconds,
    "S": parseSeconds,
    "u": parseWeekdayNumberMonday,
    "U": parseWeekNumberSunday,
    "V": parseWeekNumberISO,
    "w": parseWeekdayNumberSunday,
    "W": parseWeekNumberMonday,
    "x": parseLocaleDate,
    "X": parseLocaleTime,
    "y": parseYear,
    "Y": parseFullYear,
    "Z": parseZone,
    "%": parseLiteralPercent
  };

  // These recursive directive definitions must be deferred.
  formats.x = newFormat(locale_date, formats);
  formats.X = newFormat(locale_time, formats);
  formats.c = newFormat(locale_dateTime, formats);
  utcFormats.x = newFormat(locale_date, utcFormats);
  utcFormats.X = newFormat(locale_time, utcFormats);
  utcFormats.c = newFormat(locale_dateTime, utcFormats);

  function newFormat(specifier, formats) {
    return function(date) {
      var string = [],
          i = -1,
          j = 0,
          n = specifier.length,
          c,
          pad,
          format;

      if (!(date instanceof Date)) date = new Date(+date);

      while (++i < n) {
        if (specifier.charCodeAt(i) === 37) {
          string.push(specifier.slice(j, i));
          if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
          else pad = c === "e" ? " " : "0";
          if (format = formats[c]) c = format(date, pad);
          string.push(c);
          j = i + 1;
        }
      }

      string.push(specifier.slice(j, i));
      return string.join("");
    };
  }

  function newParse(specifier, Z) {
    return function(string) {
      var d = newDate(1900, undefined, 1),
          i = parseSpecifier(d, specifier, string += "", 0),
          week, day;
      if (i != string.length) return null;

      // If a UNIX timestamp is specified, return it.
      if ("Q" in d) return new Date(d.Q);
      if ("s" in d) return new Date(d.s * 1000 + ("L" in d ? d.L : 0));

      // If this is utcParse, never use the local timezone.
      if (Z && !("Z" in d)) d.Z = 0;

      // The am-pm flag is 0 for AM, and 1 for PM.
      if ("p" in d) d.H = d.H % 12 + d.p * 12;

      // If the month was not specified, inherit from the quarter.
      if (d.m === undefined) d.m = "q" in d ? d.q : 0;

      // Convert day-of-week and week-of-year to day-of-year.
      if ("V" in d) {
        if (d.V < 1 || d.V > 53) return null;
        if (!("w" in d)) d.w = 1;
        if ("Z" in d) {
          week = locale_utcDate(newDate(d.y, 0, 1)), day = week.getUTCDay();
          week = day > 4 || day === 0 ? utcMonday.ceil(week) : utcMonday(week);
          week = utcDay.offset(week, (d.V - 1) * 7);
          d.y = week.getUTCFullYear();
          d.m = week.getUTCMonth();
          d.d = week.getUTCDate() + (d.w + 6) % 7;
        } else {
          week = locale_localDate(newDate(d.y, 0, 1)), day = week.getDay();
          week = day > 4 || day === 0 ? timeMonday.ceil(week) : timeMonday(week);
          week = timeDay.offset(week, (d.V - 1) * 7);
          d.y = week.getFullYear();
          d.m = week.getMonth();
          d.d = week.getDate() + (d.w + 6) % 7;
        }
      } else if ("W" in d || "U" in d) {
        if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0;
        day = "Z" in d ? locale_utcDate(newDate(d.y, 0, 1)).getUTCDay() : locale_localDate(newDate(d.y, 0, 1)).getDay();
        d.m = 0;
        d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;
      }

      // If a time zone is specified, all fields are interpreted as UTC and then
      // offset according to the specified time zone.
      if ("Z" in d) {
        d.H += d.Z / 100 | 0;
        d.M += d.Z % 100;
        return locale_utcDate(d);
      }

      // Otherwise, all fields are in local time.
      return locale_localDate(d);
    };
  }

  function parseSpecifier(d, specifier, string, j) {
    var i = 0,
        n = specifier.length,
        m = string.length,
        c,
        parse;

    while (i < n) {
      if (j >= m) return -1;
      c = specifier.charCodeAt(i++);
      if (c === 37) {
        c = specifier.charAt(i++);
        parse = parses[c in pads ? specifier.charAt(i++) : c];
        if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
      } else if (c != string.charCodeAt(j++)) {
        return -1;
      }
    }

    return j;
  }

  function parsePeriod(d, string, i) {
    var n = periodRe.exec(string.slice(i));
    return n ? (d.p = periodLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  }

  function parseShortWeekday(d, string, i) {
    var n = shortWeekdayRe.exec(string.slice(i));
    return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  }

  function parseWeekday(d, string, i) {
    var n = weekdayRe.exec(string.slice(i));
    return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  }

  function parseShortMonth(d, string, i) {
    var n = shortMonthRe.exec(string.slice(i));
    return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  }

  function parseMonth(d, string, i) {
    var n = monthRe.exec(string.slice(i));
    return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
  }

  function parseLocaleDateTime(d, string, i) {
    return parseSpecifier(d, locale_dateTime, string, i);
  }

  function parseLocaleDate(d, string, i) {
    return parseSpecifier(d, locale_date, string, i);
  }

  function parseLocaleTime(d, string, i) {
    return parseSpecifier(d, locale_time, string, i);
  }

  function formatShortWeekday(d) {
    return locale_shortWeekdays[d.getDay()];
  }

  function formatWeekday(d) {
    return locale_weekdays[d.getDay()];
  }

  function formatShortMonth(d) {
    return locale_shortMonths[d.getMonth()];
  }

  function formatMonth(d) {
    return locale_months[d.getMonth()];
  }

  function formatPeriod(d) {
    return locale_periods[+(d.getHours() >= 12)];
  }

  function formatQuarter(d) {
    return 1 + ~~(d.getMonth() / 3);
  }

  function formatUTCShortWeekday(d) {
    return locale_shortWeekdays[d.getUTCDay()];
  }

  function formatUTCWeekday(d) {
    return locale_weekdays[d.getUTCDay()];
  }

  function formatUTCShortMonth(d) {
    return locale_shortMonths[d.getUTCMonth()];
  }

  function formatUTCMonth(d) {
    return locale_months[d.getUTCMonth()];
  }

  function formatUTCPeriod(d) {
    return locale_periods[+(d.getUTCHours() >= 12)];
  }

  function formatUTCQuarter(d) {
    return 1 + ~~(d.getUTCMonth() / 3);
  }

  return {
    format: function(specifier) {
      var f = newFormat(specifier += "", formats);
      f.toString = function() { return specifier; };
      return f;
    },
    parse: function(specifier) {
      var p = newParse(specifier += "", false);
      p.toString = function() { return specifier; };
      return p;
    },
    utcFormat: function(specifier) {
      var f = newFormat(specifier += "", utcFormats);
      f.toString = function() { return specifier; };
      return f;
    },
    utcParse: function(specifier) {
      var p = newParse(specifier += "", true);
      p.toString = function() { return specifier; };
      return p;
    }
  };
}

var pads = {"-": "", "_": " ", "0": "0"},
    numberRe = /^\s*\d+/, // note: ignores next directive
    percentRe = /^%/,
    requoteRe = /[\\^$*+?|[\]().{}]/g;

function locale_pad(value, fill, width) {
  var sign = value < 0 ? "-" : "",
      string = (sign ? -value : value) + "",
      length = string.length;
  return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
}

function requote(s) {
  return s.replace(requoteRe, "\\$&");
}

function formatRe(names) {
  return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
}

function formatLookup(names) {
  return new Map(names.map((name, i) => [name.toLowerCase(), i]));
}

function parseWeekdayNumberSunday(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 1));
  return n ? (d.w = +n[0], i + n[0].length) : -1;
}

function parseWeekdayNumberMonday(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 1));
  return n ? (d.u = +n[0], i + n[0].length) : -1;
}

function parseWeekNumberSunday(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.U = +n[0], i + n[0].length) : -1;
}

function parseWeekNumberISO(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.V = +n[0], i + n[0].length) : -1;
}

function parseWeekNumberMonday(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.W = +n[0], i + n[0].length) : -1;
}

function parseFullYear(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 4));
  return n ? (d.y = +n[0], i + n[0].length) : -1;
}

function parseYear(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
}

function parseZone(d, string, i) {
  var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6));
  return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
}

function parseQuarter(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 1));
  return n ? (d.q = n[0] * 3 - 3, i + n[0].length) : -1;
}

function parseMonthNumber(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
}

function parseDayOfMonth(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.d = +n[0], i + n[0].length) : -1;
}

function parseDayOfYear(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 3));
  return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
}

function parseHour24(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.H = +n[0], i + n[0].length) : -1;
}

function parseMinutes(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.M = +n[0], i + n[0].length) : -1;
}

function parseSeconds(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 2));
  return n ? (d.S = +n[0], i + n[0].length) : -1;
}

function parseMilliseconds(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 3));
  return n ? (d.L = +n[0], i + n[0].length) : -1;
}

function parseMicroseconds(d, string, i) {
  var n = numberRe.exec(string.slice(i, i + 6));
  return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1;
}

function parseLiteralPercent(d, string, i) {
  var n = percentRe.exec(string.slice(i, i + 1));
  return n ? i + n[0].length : -1;
}

function parseUnixTimestamp(d, string, i) {
  var n = numberRe.exec(string.slice(i));
  return n ? (d.Q = +n[0], i + n[0].length) : -1;
}

function parseUnixTimestampSeconds(d, string, i) {
  var n = numberRe.exec(string.slice(i));
  return n ? (d.s = +n[0], i + n[0].length) : -1;
}

function formatDayOfMonth(d, p) {
  return locale_pad(d.getDate(), p, 2);
}

function formatHour24(d, p) {
  return locale_pad(d.getHours(), p, 2);
}

function formatHour12(d, p) {
  return locale_pad(d.getHours() % 12 || 12, p, 2);
}

function formatDayOfYear(d, p) {
  return locale_pad(1 + timeDay.count(timeYear(d), d), p, 3);
}

function formatMilliseconds(d, p) {
  return locale_pad(d.getMilliseconds(), p, 3);
}

function formatMicroseconds(d, p) {
  return formatMilliseconds(d, p) + "000";
}

function formatMonthNumber(d, p) {
  return locale_pad(d.getMonth() + 1, p, 2);
}

function formatMinutes(d, p) {
  return locale_pad(d.getMinutes(), p, 2);
}

function formatSeconds(d, p) {
  return locale_pad(d.getSeconds(), p, 2);
}

function formatWeekdayNumberMonday(d) {
  var day = d.getDay();
  return day === 0 ? 7 : day;
}

function formatWeekNumberSunday(d, p) {
  return locale_pad(timeSunday.count(timeYear(d) - 1, d), p, 2);
}

function dISO(d) {
  var day = d.getDay();
  return (day >= 4 || day === 0) ? timeThursday(d) : timeThursday.ceil(d);
}

function formatWeekNumberISO(d, p) {
  d = dISO(d);
  return locale_pad(timeThursday.count(timeYear(d), d) + (timeYear(d).getDay() === 4), p, 2);
}

function formatWeekdayNumberSunday(d) {
  return d.getDay();
}

function formatWeekNumberMonday(d, p) {
  return locale_pad(timeMonday.count(timeYear(d) - 1, d), p, 2);
}

function locale_formatYear(d, p) {
  return locale_pad(d.getFullYear() % 100, p, 2);
}

function formatYearISO(d, p) {
  d = dISO(d);
  return locale_pad(d.getFullYear() % 100, p, 2);
}

function formatFullYear(d, p) {
  return locale_pad(d.getFullYear() % 10000, p, 4);
}

function formatFullYearISO(d, p) {
  var day = d.getDay();
  d = (day >= 4 || day === 0) ? timeThursday(d) : timeThursday.ceil(d);
  return locale_pad(d.getFullYear() % 10000, p, 4);
}

function formatZone(d) {
  var z = d.getTimezoneOffset();
  return (z > 0 ? "-" : (z *= -1, "+"))
      + locale_pad(z / 60 | 0, "0", 2)
      + locale_pad(z % 60, "0", 2);
}

function formatUTCDayOfMonth(d, p) {
  return locale_pad(d.getUTCDate(), p, 2);
}

function formatUTCHour24(d, p) {
  return locale_pad(d.getUTCHours(), p, 2);
}

function formatUTCHour12(d, p) {
  return locale_pad(d.getUTCHours() % 12 || 12, p, 2);
}

function formatUTCDayOfYear(d, p) {
  return locale_pad(1 + utcDay.count(utcYear(d), d), p, 3);
}

function formatUTCMilliseconds(d, p) {
  return locale_pad(d.getUTCMilliseconds(), p, 3);
}

function formatUTCMicroseconds(d, p) {
  return formatUTCMilliseconds(d, p) + "000";
}

function formatUTCMonthNumber(d, p) {
  return locale_pad(d.getUTCMonth() + 1, p, 2);
}

function formatUTCMinutes(d, p) {
  return locale_pad(d.getUTCMinutes(), p, 2);
}

function formatUTCSeconds(d, p) {
  return locale_pad(d.getUTCSeconds(), p, 2);
}

function formatUTCWeekdayNumberMonday(d) {
  var dow = d.getUTCDay();
  return dow === 0 ? 7 : dow;
}

function formatUTCWeekNumberSunday(d, p) {
  return locale_pad(utcSunday.count(utcYear(d) - 1, d), p, 2);
}

function UTCdISO(d) {
  var day = d.getUTCDay();
  return (day >= 4 || day === 0) ? utcThursday(d) : utcThursday.ceil(d);
}

function formatUTCWeekNumberISO(d, p) {
  d = UTCdISO(d);
  return locale_pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);
}

function formatUTCWeekdayNumberSunday(d) {
  return d.getUTCDay();
}

function formatUTCWeekNumberMonday(d, p) {
  return locale_pad(utcMonday.count(utcYear(d) - 1, d), p, 2);
}

function formatUTCYear(d, p) {
  return locale_pad(d.getUTCFullYear() % 100, p, 2);
}

function formatUTCYearISO(d, p) {
  d = UTCdISO(d);
  return locale_pad(d.getUTCFullYear() % 100, p, 2);
}

function formatUTCFullYear(d, p) {
  return locale_pad(d.getUTCFullYear() % 10000, p, 4);
}

function formatUTCFullYearISO(d, p) {
  var day = d.getUTCDay();
  d = (day >= 4 || day === 0) ? utcThursday(d) : utcThursday.ceil(d);
  return locale_pad(d.getUTCFullYear() % 10000, p, 4);
}

function formatUTCZone() {
  return "+0000";
}

function formatLiteralPercent() {
  return "%";
}

function formatUnixTimestamp(d) {
  return +d;
}

function formatUnixTimestampSeconds(d) {
  return Math.floor(+d / 1000);
}

;// ../../node_modules/d3-time-format/src/defaultLocale.js


var src_defaultLocale_locale;
var timeFormat;
var timeParse;
var utcFormat;
var utcParse;

defaultLocale_defaultLocale({
  dateTime: "%x, %X",
  date: "%-m/%-d/%Y",
  time: "%-I:%M:%S %p",
  periods: ["AM", "PM"],
  days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
});

function defaultLocale_defaultLocale(definition) {
  src_defaultLocale_locale = formatLocale(definition);
  timeFormat = src_defaultLocale_locale.format;
  timeParse = src_defaultLocale_locale.parse;
  utcFormat = src_defaultLocale_locale.utcFormat;
  utcParse = src_defaultLocale_locale.utcParse;
  return src_defaultLocale_locale;
}

;// ../../node_modules/vega-format/build/vega-format.module.js






function memoize (method) {
  const cache = {};
  return spec => cache[spec] || (cache[spec] = method(spec));
}

function trimZeroes(numberFormat, decimalChar) {
  return x => {
    const str = numberFormat(x),
      dec = str.indexOf(decimalChar);
    if (dec < 0) return str;
    let idx = rightmostDigit(str, dec);
    const end = idx < str.length ? str.slice(idx) : '';
    while (--idx > dec) if (str[idx] !== '0') {
      ++idx;
      break;
    }
    return str.slice(0, idx) + end;
  };
}
function rightmostDigit(str, dec) {
  let i = str.lastIndexOf('e'),
    c;
  if (i > 0) return i;
  for (i = str.length; --i > dec;) {
    c = str.charCodeAt(i);
    if (c >= 48 && c <= 57) return i + 1; // is digit
  }
}
function numberLocale(locale) {
  const format = memoize(locale.format),
    formatPrefix = locale.formatPrefix;
  return {
    format,
    formatPrefix,
    formatFloat(spec) {
      const s = formatSpecifier(spec || ',');
      if (s.precision == null) {
        s.precision = 12;
        switch (s.type) {
          case '%':
            s.precision -= 2;
            break;
          case 'e':
            s.precision -= 1;
            break;
        }
        return trimZeroes(format(s),
        // number format
        format('.1f')(1)[1] // decimal point character
        );
      } else {
        return format(s);
      }
    },
    formatSpan(start, stop, count, specifier) {
      specifier = formatSpecifier(specifier == null ? ',f' : specifier);
      const step = tickStep(start, stop, count),
        value = Math.max(Math.abs(start), Math.abs(stop));
      let precision;
      if (specifier.precision == null) {
        switch (specifier.type) {
          case 's':
            {
              if (!isNaN(precision = precisionPrefix(step, value))) {
                specifier.precision = precision;
              }
              return formatPrefix(specifier, value);
            }
          case '':
          case 'e':
          case 'g':
          case 'p':
          case 'r':
            {
              if (!isNaN(precision = precisionRound(step, value))) {
                specifier.precision = precision - (specifier.type === 'e');
              }
              break;
            }
          case 'f':
          case '%':
            {
              if (!isNaN(precision = precisionFixed(step))) {
                specifier.precision = precision - (specifier.type === '%') * 2;
              }
              break;
            }
        }
      }
      return format(specifier);
    }
  };
}
let defaultNumberLocale;
resetNumberFormatDefaultLocale();
function resetNumberFormatDefaultLocale() {
  return defaultNumberLocale = numberLocale({
    format: format,
    formatPrefix: formatPrefix
  });
}
function numberFormatLocale(definition) {
  return numberLocale(locale(definition));
}
function numberFormatDefaultLocale(definition) {
  return arguments.length ? defaultNumberLocale = numberFormatLocale(definition) : defaultNumberLocale;
}

function timeMultiFormat(format, interval, spec) {
  spec = spec || {};
  if (!vega_util_module_isObject(spec)) {
    vega_util_module_error(`Invalid time multi-format specifier: ${spec}`);
  }
  const second = interval(SECONDS),
    minute = interval(MINUTES),
    hour = interval(HOURS),
    day = interval(DATE),
    week = interval(WEEK),
    month = interval(MONTH),
    quarter = interval(QUARTER),
    year = interval(YEAR),
    L = format(spec[MILLISECONDS] || '.%L'),
    S = format(spec[SECONDS] || ':%S'),
    M = format(spec[MINUTES] || '%I:%M'),
    H = format(spec[HOURS] || '%I %p'),
    d = format(spec[DATE] || spec[DAY] || '%a %d'),
    w = format(spec[WEEK] || '%b %d'),
    m = format(spec[MONTH] || '%B'),
    q = format(spec[QUARTER] || '%B'),
    y = format(spec[YEAR] || '%Y');
  return date => (second(date) < date ? L : minute(date) < date ? S : hour(date) < date ? M : day(date) < date ? H : month(date) < date ? week(date) < date ? d : w : year(date) < date ? quarter(date) < date ? m : q : y)(date);
}
function timeLocale(locale) {
  const timeFormat = memoize(locale.format),
    utcFormat = memoize(locale.utcFormat);
  return {
    timeFormat: spec => vega_util_module_isString(spec) ? timeFormat(spec) : timeMultiFormat(timeFormat, vega_time_module_timeInterval, spec),
    utcFormat: spec => vega_util_module_isString(spec) ? utcFormat(spec) : timeMultiFormat(utcFormat, utcInterval, spec),
    timeParse: memoize(locale.parse),
    utcParse: memoize(locale.utcParse)
  };
}
let defaultTimeLocale;
resetTimeFormatDefaultLocale();
function resetTimeFormatDefaultLocale() {
  return defaultTimeLocale = timeLocale({
    format: timeFormat,
    parse: timeParse,
    utcFormat: utcFormat,
    utcParse: utcParse
  });
}
function timeFormatLocale(definition) {
  return timeLocale(formatLocale(definition));
}
function timeFormatDefaultLocale(definition) {
  return arguments.length ? defaultTimeLocale = timeFormatLocale(definition) : defaultTimeLocale;
}

const createLocale = (number, time) => extend({}, number, time);
function vega_format_module_locale(numberSpec, timeSpec) {
  const number = numberSpec ? numberFormatLocale(numberSpec) : numberFormatDefaultLocale();
  const time = timeSpec ? timeFormatLocale(timeSpec) : timeFormatDefaultLocale();
  return createLocale(number, time);
}
function vega_format_module_defaultLocale(numberSpec, timeSpec) {
  const args = arguments.length;
  if (args && args !== 2) {
    vega_util_module_error('defaultLocale expects either zero or two arguments.');
  }
  return args ? createLocale(numberFormatDefaultLocale(numberSpec), timeFormatDefaultLocale(timeSpec)) : createLocale(numberFormatDefaultLocale(), timeFormatDefaultLocale());
}
function resetDefaultLocale() {
  resetNumberFormatDefaultLocale();
  resetTimeFormatDefaultLocale();
  return vega_format_module_defaultLocale();
}



;// ../../node_modules/vega-loader/build/vega-loader.browser.module.js





// Matches absolute URLs with optional protocol
//   https://...    file://...    //...
const protocol_re = /^(data:|([A-Za-z]+:)?\/\/)/;

// Matches allowed URIs. From https://github.com/cure53/DOMPurify/blob/master/src/regexp.js with added file://
const allowed_re = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|file|data):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
const whitespace_re = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex

// Special treatment in node.js for the file: protocol
const fileProtocol = 'file://';

/**
 * Factory for a loader constructor that provides methods for requesting
 * files from either the network or disk, and for sanitizing request URIs.
 * @param {function} fetch - The Fetch API for HTTP network requests.
 *   If null or undefined, HTTP loading will be disabled.
 * @param {object} fs - The file system interface for file loading.
 *   If null or undefined, local file loading will be disabled.
 * @return {function} A loader constructor with the following signature:
 *   param {object} [options] - Optional default loading options to use.
 *   return {object} - A new loader instance.
 */
function loaderFactory (fetch, fs) {
  return options => ({
    options: options || {},
    sanitize: sanitize,
    load: load,
    fileAccess: false,
    file: fileLoader(fs),
    http: httpLoader(fetch)
  });
}

/**
 * Load an external resource, typically either from the web or from the local
 * filesystem. This function uses {@link sanitize} to first sanitize the uri,
 * then calls either {@link http} (for web requests) or {@link file} (for
 * filesystem loading).
 * @param {string} uri - The resource indicator (e.g., URL or filename).
 * @param {object} [options] - Optional loading options. These options will
 *   override any existing default options.
 * @return {Promise} - A promise that resolves to the loaded content.
 */
async function load(uri, options) {
  const opt = await this.sanitize(uri, options),
    url = opt.href;
  return opt.localFile ? this.file(url) : this.http(url, options);
}

/**
 * URI sanitizer function.
 * @param {string} uri - The uri (url or filename) to check.
 * @param {object} options - An options hash.
 * @return {Promise} - A promise that resolves to an object containing
 *  sanitized uri data, or rejects it the input uri is deemed invalid.
 *  The properties of the resolved object are assumed to be
 *  valid attributes for an HTML 'a' tag. The sanitized uri *must* be
 *  provided by the 'href' property of the returned object.
 */
async function sanitize(uri, options) {
  options = extend({}, this.options, options);
  const fileAccess = this.fileAccess,
    result = {
      href: null
    };
  let isFile, loadFile, base;
  const isAllowed = allowed_re.test(uri.replace(whitespace_re, ''));
  if (uri == null || typeof uri !== 'string' || !isAllowed) {
    vega_util_module_error('Sanitize failure, invalid URI: ' + $(uri));
  }
  const hasProtocol = protocol_re.test(uri);

  // if relative url (no protocol/host), prepend baseURL
  if ((base = options.baseURL) && !hasProtocol) {
    // Ensure that there is a slash between the baseURL (e.g. hostname) and url
    if (!uri.startsWith('/') && !base.endsWith('/')) {
      uri = '/' + uri;
    }
    uri = base + uri;
  }

  // should we load from file system?
  loadFile = (isFile = uri.startsWith(fileProtocol)) || options.mode === 'file' || options.mode !== 'http' && !hasProtocol && fileAccess;
  if (isFile) {
    // strip file protocol
    uri = uri.slice(fileProtocol.length);
  } else if (uri.startsWith('//')) {
    if (options.defaultProtocol === 'file') {
      // if is file, strip protocol and set loadFile flag
      uri = uri.slice(2);
      loadFile = true;
    } else {
      // if relative protocol (starts with '//'), prepend default protocol
      uri = (options.defaultProtocol || 'http') + ':' + uri;
    }
  }

  // set non-enumerable mode flag to indicate local file load
  Object.defineProperty(result, 'localFile', {
    value: !!loadFile
  });

  // set uri
  result.href = uri;

  // set default result target, if specified
  if (options.target) {
    result.target = options.target + '';
  }

  // set default result rel, if specified (#1542)
  if (options.rel) {
    result.rel = options.rel + '';
  }

  // provide control over cross-origin image handling (#2238)
  // https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
  if (options.context === 'image' && options.crossOrigin) {
    result.crossOrigin = options.crossOrigin + '';
  }

  // return
  return result;
}

/**
 * File system loader factory.
 * @param {object} fs - The file system interface.
 * @return {function} - A file loader with the following signature:
 *   param {string} filename - The file system path to load.
 *   param {string} filename - The file system path to load.
 *   return {Promise} A promise that resolves to the file contents.
 */
function fileLoader(fs) {
  return fs ? filename => new Promise((accept, reject) => {
    fs.readFile(filename, (error, data) => {
      if (error) reject(error);else accept(data);
    });
  }) : fileReject;
}

/**
 * Default file system loader that simply rejects.
 */
async function fileReject() {
  vega_util_module_error('No file system access.');
}

/**
 * HTTP request handler factory.
 * @param {function} fetch - The Fetch API method.
 * @return {function} - An http loader with the following signature:
 *   param {string} url - The url to request.
 *   param {object} options - An options hash.
 *   return {Promise} - A promise that resolves to the file contents.
 */
function httpLoader(fetch) {
  return fetch ? async function (url, options) {
    const opt = extend({}, this.options.http, options),
      type = options && options.response,
      response = await fetch(url, opt);
    return !response.ok ? vega_util_module_error(response.status + '' + response.statusText) : vega_util_module_isFunction(response[type]) ? response[type]() : response.text();
  } : httpReject;
}

/**
 * Default http request handler that simply rejects.
 */
async function httpReject() {
  vega_util_module_error('No HTTP fetch method available.');
}

const vega_loader_browser_module_isValid = _ => _ != null && _ === _;
const vega_loader_browser_module_isBoolean = _ => _ === 'true' || _ === 'false' || _ === true || _ === false;
const vega_loader_browser_module_isDate = _ => !Number.isNaN(Date.parse(_));
const vega_loader_browser_module_isNumber = _ => !Number.isNaN(+_) && !(_ instanceof Date);
const isInteger = _ => vega_loader_browser_module_isNumber(_) && Number.isInteger(+_);
const typeParsers = {
  boolean: toBoolean,
  integer: vega_util_module_toNumber,
  number: vega_util_module_toNumber,
  date: toDate,
  string: vega_util_module_toString,
  unknown: vega_util_module_identity
};
const typeTests = [vega_loader_browser_module_isBoolean, isInteger, vega_loader_browser_module_isNumber, vega_loader_browser_module_isDate];
const typeList = ['boolean', 'integer', 'number', 'date'];
function vega_loader_browser_module_inferType(values, field) {
  if (!values || !values.length) return 'unknown';
  const n = values.length,
    m = typeTests.length,
    a = typeTests.map((_, i) => i + 1);
  for (let i = 0, t = 0, j, value; i < n; ++i) {
    value = field ? values[i][field] : values[i];
    for (j = 0; j < m; ++j) {
      if (a[j] && vega_loader_browser_module_isValid(value) && !typeTests[j](value)) {
        a[j] = 0;
        ++t;
        if (t === typeTests.length) return 'string';
      }
    }
  }
  return typeList[a.reduce((u, v) => u === 0 ? v : u, 0) - 1];
}
function inferTypes(data, fields) {
  return fields.reduce((types, field) => {
    types[field] = vega_loader_browser_module_inferType(data, field);
    return types;
  }, {});
}

function delimitedFormat(delimiter) {
  const parse = function (data, format) {
    const delim = {
      delimiter: delimiter
    };
    return vega_loader_browser_module_dsv(data, format ? extend(format, delim) : delim);
  };
  parse.responseType = 'text';
  return parse;
}
function vega_loader_browser_module_dsv(data, format) {
  if (format.header) {
    data = format.header.map($).join(format.delimiter) + '\n' + data;
  }
  return dsv(format.delimiter).parse(data + '');
}
vega_loader_browser_module_dsv.responseType = 'text';

function isBuffer(_) {
  return typeof Buffer === 'function' && vega_util_module_isFunction(Buffer.isBuffer) ? Buffer.isBuffer(_) : false;
}
function json(data, format) {
  const prop = format && format.property ? vega_util_module_field(format.property) : vega_util_module_identity;
  return vega_util_module_isObject(data) && !isBuffer(data) ? parseJSON(prop(data), format) : prop(JSON.parse(data));
}
json.responseType = 'json';
function parseJSON(data, format) {
  if (!vega_util_module_isArray(data) && vega_util_module_isIterable(data)) {
    data = [...data];
  }
  return format && format.copy ? JSON.parse(JSON.stringify(data)) : data;
}

const filters = {
  interior: (a, b) => a !== b,
  exterior: (a, b) => a === b
};
function topojson(data, format) {
  let method, object, property, filter;
  data = json(data, format);
  if (format && format.feature) {
    method = feature;
    property = format.feature;
  } else if (format && format.mesh) {
    method = mesh;
    property = format.mesh;
    filter = filters[format.filter];
  } else {
    vega_util_module_error('Missing TopoJSON feature or mesh parameter.');
  }
  object = (object = data.objects[property]) ? method(data, object, filter) : vega_util_module_error('Invalid TopoJSON object: ' + property);
  return object && object.features || [object];
}
topojson.responseType = 'json';

const vega_loader_browser_module_format = {
  dsv: vega_loader_browser_module_dsv,
  csv: delimitedFormat(','),
  tsv: delimitedFormat('\t'),
  json: json,
  topojson: topojson
};
function vega_loader_browser_module_formats(name, reader) {
  if (arguments.length > 1) {
    vega_loader_browser_module_format[name] = reader;
    return this;
  } else {
    return vega_util_module_has(vega_loader_browser_module_format, name) ? vega_loader_browser_module_format[name] : null;
  }
}
function responseType(type) {
  const f = vega_loader_browser_module_formats(type);
  return f && f.responseType || 'text';
}

function read (data, schema, timeParser, utcParser) {
  schema = schema || {};
  const reader = vega_loader_browser_module_formats(schema.type || 'json');
  if (!reader) vega_util_module_error('Unknown data format type: ' + schema.type);
  data = reader(data, schema);
  if (schema.parse) vega_loader_browser_module_parse(data, schema.parse, timeParser, utcParser);
  if (vega_util_module_has(data, 'columns')) delete data.columns;
  return data;
}
function vega_loader_browser_module_parse(data, types, timeParser, utcParser) {
  if (!data.length) return; // early exit for empty data

  const locale = timeFormatDefaultLocale();
  timeParser = timeParser || locale.timeParse;
  utcParser = utcParser || locale.utcParse;
  let fields = data.columns || Object.keys(data[0]),
    datum,
    field,
    i,
    j,
    n,
    m;
  if (types === 'auto') types = inferTypes(data, fields);
  fields = Object.keys(types);
  const parsers = fields.map(field => {
    const type = types[field];
    let parts, pattern;
    if (type && (type.startsWith('date:') || type.startsWith('utc:'))) {
      parts = type.split(/:(.+)?/, 2); // split on first :
      pattern = parts[1];
      if (pattern[0] === '\'' && pattern[pattern.length - 1] === '\'' || pattern[0] === '"' && pattern[pattern.length - 1] === '"') {
        pattern = pattern.slice(1, -1);
      }
      const parse = parts[0] === 'utc' ? utcParser : timeParser;
      return parse(pattern);
    }
    if (!typeParsers[type]) {
      throw Error('Illegal format pattern: ' + field + ':' + type);
    }
    return typeParsers[type];
  });
  for (i = 0, n = data.length, m = fields.length; i < n; ++i) {
    datum = data[i];
    for (j = 0; j < m; ++j) {
      field = fields[j];
      datum[field] = parsers[j](datum[field]);
    }
  }
}

const loader = loaderFactory(typeof fetch !== 'undefined' && fetch,
// use built-in fetch API
null // no file system access
);



;// ../../node_modules/vega-dataflow/build/vega-dataflow.module.js




function UniqueList(idFunc) {
  const $ = idFunc || vega_util_module_identity,
    list = [],
    ids = {};
  list.add = _ => {
    const id = $(_);
    if (!ids[id]) {
      ids[id] = 1;
      list.push(_);
    }
    return list;
  };
  list.remove = _ => {
    const id = $(_);
    if (ids[id]) {
      ids[id] = 0;
      const idx = list.indexOf(_);
      if (idx >= 0) list.splice(idx, 1);
    }
    return list;
  };
  return list;
}

/**
 * Invoke and await a potentially async callback function. If
 * an error occurs, trap it and route to Dataflow.error.
 * @param {Dataflow} df - The dataflow instance
 * @param {function} callback - A callback function to invoke
 *   and then await. The dataflow will be passed as the single
 *   argument to the function.
 */
async function asyncCallback (df, callback) {
  try {
    await callback(df);
  } catch (err) {
    df.error(err);
  }
}

const TUPLE_ID_KEY = Symbol('vega_id');
let TUPLE_ID = 1;

/**
 * Checks if an input value is a registered tuple.
 * @param {*} t - The value to check.
 * @return {boolean} True if the input is a tuple, false otherwise.
 */
function isTuple(t) {
  return !!(t && tupleid(t));
}

/**
 * Returns the id of a tuple.
 * @param {object} t - The input tuple.
 * @return {*} the tuple id.
 */
function tupleid(t) {
  return t[TUPLE_ID_KEY];
}

/**
 * Sets the id of a tuple.
 * @param {object} t - The input tuple.
 * @param {*} id - The id value to set.
 * @return {object} the input tuple.
 */
function setid(t, id) {
  t[TUPLE_ID_KEY] = id;
  return t;
}

/**
 * Ingest an object or value as a data tuple.
 * If the input value is an object, an id field will be added to it. For
 * efficiency, the input object is modified directly. A copy is not made.
 * If the input value is a literal, it will be wrapped in a new object
 * instance, with the value accessible as the 'data' property.
 * @param datum - The value to ingest.
 * @return {object} The ingested data tuple.
 */
function ingest$1(datum) {
  const t = datum === Object(datum) ? datum : {
    data: datum
  };
  return tupleid(t) ? t : setid(t, TUPLE_ID++);
}

/**
 * Given a source tuple, return a derived copy.
 * @param {object} t - The source tuple.
 * @return {object} The derived tuple.
 */
function vega_dataflow_module_derive(t) {
  return rederive(t, ingest$1({}));
}

/**
 * Rederive a derived tuple by copying values from the source tuple.
 * @param {object} t - The source tuple.
 * @param {object} d - The derived tuple.
 * @return {object} The derived tuple.
 */
function rederive(t, d) {
  for (const k in t) d[k] = t[k];
  return d;
}

/**
 * Replace an existing tuple with a new tuple.
 * @param {object} t - The existing data tuple.
 * @param {object} d - The new tuple that replaces the old.
 * @return {object} The new tuple.
 */
function vega_dataflow_module_replace(t, d) {
  return setid(d, tupleid(t));
}

/**
 * Generate an augmented comparator function that provides stable
 * sorting by tuple id when the given comparator produces ties.
 * @param {function} cmp - The comparator to augment.
 * @param {function} [f] - Optional tuple accessor function.
 * @return {function} An augmented comparator function.
 */
function stableCompare(cmp, f) {
  return !cmp ? null : f ? (a, b) => cmp(a, b) || tupleid(f(a)) - tupleid(f(b)) : (a, b) => cmp(a, b) || tupleid(a) - tupleid(b);
}

function isChangeSet(v) {
  return v && v.constructor === changeset;
}
function changeset() {
  const add = [],
    // insert tuples
    rem = [],
    // remove tuples
    mod = [],
    // modify tuples
    remp = [],
    // remove by predicate
    modp = []; // modify by predicate
  let clean = null,
    reflow = false;
  return {
    constructor: changeset,
    insert(t) {
      const d = vega_util_module_array(t),
        n = d.length;
      for (let i = 0; i < n; ++i) add.push(d[i]);
      return this;
    },
    remove(t) {
      const a = vega_util_module_isFunction(t) ? remp : rem,
        d = vega_util_module_array(t),
        n = d.length;
      for (let i = 0; i < n; ++i) a.push(d[i]);
      return this;
    },
    modify(t, field, value) {
      const m = {
        field: field,
        value: vega_util_module_constant(value)
      };
      if (vega_util_module_isFunction(t)) {
        m.filter = t;
        modp.push(m);
      } else {
        m.tuple = t;
        mod.push(m);
      }
      return this;
    },
    encode(t, set) {
      if (vega_util_module_isFunction(t)) modp.push({
        filter: t,
        field: set
      });else mod.push({
        tuple: t,
        field: set
      });
      return this;
    },
    clean(value) {
      clean = value;
      return this;
    },
    reflow() {
      reflow = true;
      return this;
    },
    pulse(pulse, tuples) {
      const cur = {},
        out = {};
      let i, n, m, f, t, id;

      // build lookup table of current tuples
      for (i = 0, n = tuples.length; i < n; ++i) {
        cur[tupleid(tuples[i])] = 1;
      }

      // process individual tuples to remove
      for (i = 0, n = rem.length; i < n; ++i) {
        t = rem[i];
        cur[tupleid(t)] = -1;
      }

      // process predicate-based removals
      for (i = 0, n = remp.length; i < n; ++i) {
        f = remp[i];
        tuples.forEach(t => {
          if (f(t)) cur[tupleid(t)] = -1;
        });
      }

      // process all add tuples
      for (i = 0, n = add.length; i < n; ++i) {
        t = add[i];
        id = tupleid(t);
        if (cur[id]) {
          // tuple already resides in dataset
          // if flagged for both add and remove, cancel
          cur[id] = 1;
        } else {
          // tuple does not reside in dataset, add
          pulse.add.push(ingest$1(add[i]));
        }
      }

      // populate pulse rem list
      for (i = 0, n = tuples.length; i < n; ++i) {
        t = tuples[i];
        if (cur[tupleid(t)] < 0) pulse.rem.push(t);
      }

      // modify helper method
      function modify(t, f, v) {
        if (v) {
          t[f] = v(t);
        } else {
          pulse.encode = f;
        }
        if (!reflow) out[tupleid(t)] = t;
      }

      // process individual tuples to modify
      for (i = 0, n = mod.length; i < n; ++i) {
        m = mod[i];
        t = m.tuple;
        f = m.field;
        id = cur[tupleid(t)];
        if (id > 0) {
          modify(t, f, m.value);
          pulse.modifies(f);
        }
      }

      // process predicate-based modifications
      for (i = 0, n = modp.length; i < n; ++i) {
        m = modp[i];
        f = m.filter;
        tuples.forEach(t => {
          if (f(t) && cur[tupleid(t)] > 0) {
            modify(t, m.field, m.value);
          }
        });
        pulse.modifies(m.field);
      }

      // upon reflow request, populate mod with all non-removed tuples
      // otherwise, populate mod with modified tuples only
      if (reflow) {
        pulse.mod = rem.length || remp.length ? tuples.filter(t => cur[tupleid(t)] > 0) : tuples.slice();
      } else {
        for (id in out) pulse.mod.push(out[id]);
      }

      // set pulse garbage collection request
      if (clean || clean == null && (rem.length || remp.length)) {
        pulse.clean(true);
      }
      return pulse;
    }
  };
}

const CACHE = '_:mod:_';

/**
 * Hash that tracks modifications to assigned values.
 * Callers *must* use the set method to update values.
 */
function Parameters() {
  Object.defineProperty(this, CACHE, {
    writable: true,
    value: {}
  });
}
Parameters.prototype = {
  /**
   * Set a parameter value. If the parameter value changes, the parameter
   * will be recorded as modified.
   * @param {string} name - The parameter name.
   * @param {number} index - The index into an array-value parameter. Ignored if
   *   the argument is undefined, null or less than zero.
   * @param {*} value - The parameter value to set.
   * @param {boolean} [force=false] - If true, records the parameter as modified
   *   even if the value is unchanged.
   * @return {Parameters} - This parameter object.
   */
  set(name, index, value, force) {
    const o = this,
      v = o[name],
      mod = o[CACHE];
    if (index != null && index >= 0) {
      if (v[index] !== value || force) {
        v[index] = value;
        mod[index + ':' + name] = -1;
        mod[name] = -1;
      }
    } else if (v !== value || force) {
      o[name] = value;
      mod[name] = vega_util_module_isArray(value) ? 1 + value.length : -1;
    }
    return o;
  },
  /**
   * Tests if one or more parameters has been modified. If invoked with no
   * arguments, returns true if any parameter value has changed. If the first
   * argument is array, returns trues if any parameter name in the array has
   * changed. Otherwise, tests if the given name and optional array index has
   * changed.
   * @param {string} name - The parameter name to test.
   * @param {number} [index=undefined] - The parameter array index to test.
   * @return {boolean} - Returns true if a queried parameter was modified.
   */
  modified(name, index) {
    const mod = this[CACHE];
    if (!arguments.length) {
      for (const k in mod) {
        if (mod[k]) return true;
      }
      return false;
    } else if (vega_util_module_isArray(name)) {
      for (let k = 0; k < name.length; ++k) {
        if (mod[name[k]]) return true;
      }
      return false;
    }
    return index != null && index >= 0 ? index + 1 < mod[name] || !!mod[index + ':' + name] : !!mod[name];
  },
  /**
   * Clears the modification records. After calling this method,
   * all parameters are considered unmodified.
   */
  clear() {
    this[CACHE] = {};
    return this;
  }
};

let OP_ID = 0;
const PULSE = 'pulse',
  NO_PARAMS = new Parameters();

// Boolean Flags
const SKIP$1 = 1,
  MODIFIED = 2;

/**
 * An Operator is a processing node in a dataflow graph.
 * Each operator stores a value and an optional value update function.
 * Operators can accept a hash of named parameters. Parameter values can
 * either be direct (JavaScript literals, arrays, objects) or indirect
 * (other operators whose values will be pulled dynamically). Operators
 * included as parameters will have this operator added as a dependency.
 * @constructor
 * @param {*} [init] - The initial value for this operator.
 * @param {function(object, Pulse)} [update] - An update function. Upon
 *   evaluation of this operator, the update function will be invoked and the
 *   return value will be used as the new value of this operator.
 * @param {object} [params] - The parameters for this operator.
 * @param {boolean} [react=true] - Flag indicating if this operator should
 *   listen for changes to upstream operators included as parameters.
 * @see parameters
 */
function Operator(init, update, params, react) {
  this.id = ++OP_ID;
  this.value = init;
  this.stamp = -1;
  this.rank = -1;
  this.qrank = -1;
  this.flags = 0;
  if (update) {
    this._update = update;
  }
  if (params) this.parameters(params, react);
}
function flag(bit) {
  return function (state) {
    const f = this.flags;
    if (arguments.length === 0) return !!(f & bit);
    this.flags = state ? f | bit : f & ~bit;
    return this;
  };
}
Operator.prototype = {
  /**
   * Returns a list of target operators dependent on this operator.
   * If this list does not exist, it is created and then returned.
   * @return {UniqueList}
   */
  targets() {
    return this._targets || (this._targets = UniqueList(id));
  },
  /**
   * Sets the value of this operator.
   * @param {*} value - the value to set.
   * @return {Number} Returns 1 if the operator value has changed
   *   according to strict equality, returns 0 otherwise.
   */
  set(value) {
    if (this.value !== value) {
      this.value = value;
      return 1;
    } else {
      return 0;
    }
  },
  /**
   * Indicates that operator evaluation should be skipped on the next pulse.
   * This operator will still propagate incoming pulses, but its update function
   * will not be invoked. The skip flag is reset after every pulse, so calling
   * this method will affect processing of the next pulse only.
   */
  skip: flag(SKIP$1),
  /**
   * Indicates that this operator's value has been modified on its most recent
   * pulse. Normally modification is checked via strict equality; however, in
   * some cases it is more efficient to update the internal state of an object.
   * In those cases, the modified flag can be used to trigger propagation. Once
   * set, the modification flag persists across pulses until unset. The flag can
   * be used with the last timestamp to test if a modification is recent.
   */
  modified: flag(MODIFIED),
  /**
   * Sets the parameters for this operator. The parameter values are analyzed for
   * operator instances. If found, this operator will be added as a dependency
   * of the parameterizing operator. Operator values are dynamically marshalled
   * from each operator parameter prior to evaluation. If a parameter value is
   * an array, the array will also be searched for Operator instances. However,
   * the search does not recurse into sub-arrays or object properties.
   * @param {object} params - A hash of operator parameters.
   * @param {boolean} [react=true] - A flag indicating if this operator should
   *   automatically update (react) when parameter values change. In other words,
   *   this flag determines if the operator registers itself as a listener on
   *   any upstream operators included in the parameters.
   * @param {boolean} [initonly=false] - A flag indicating if this operator
   *   should calculate an update only upon its initial evaluation, then
   *   deregister dependencies and suppress all future update invocations.
   * @return {Operator[]} - An array of upstream dependencies.
   */
  parameters(params, react, initonly) {
    react = react !== false;
    const argval = this._argval = this._argval || new Parameters(),
      argops = this._argops = this._argops || [],
      deps = [];
    let name, value, n, i;
    const add = (name, index, value) => {
      if (value instanceof Operator) {
        if (value !== this) {
          if (react) value.targets().add(this);
          deps.push(value);
        }
        argops.push({
          op: value,
          name: name,
          index: index
        });
      } else {
        argval.set(name, index, value);
      }
    };
    for (name in params) {
      value = params[name];
      if (name === PULSE) {
        vega_util_module_array(value).forEach(op => {
          if (!(op instanceof Operator)) {
            vega_util_module_error('Pulse parameters must be operator instances.');
          } else if (op !== this) {
            op.targets().add(this);
            deps.push(op);
          }
        });
        this.source = value;
      } else if (vega_util_module_isArray(value)) {
        argval.set(name, -1, Array(n = value.length));
        for (i = 0; i < n; ++i) add(name, i, value[i]);
      } else {
        add(name, -1, value);
      }
    }
    this.marshall().clear(); // initialize values
    if (initonly) argops.initonly = true;
    return deps;
  },
  /**
   * Internal method for marshalling parameter values.
   * Visits each operator dependency to pull the latest value.
   * @return {Parameters} A Parameters object to pass to the update function.
   */
  marshall(stamp) {
    const argval = this._argval || NO_PARAMS,
      argops = this._argops;
    let item, i, op, mod;
    if (argops) {
      const n = argops.length;
      for (i = 0; i < n; ++i) {
        item = argops[i];
        op = item.op;
        mod = op.modified() && op.stamp === stamp;
        argval.set(item.name, item.index, op.value, mod);
      }
      if (argops.initonly) {
        for (i = 0; i < n; ++i) {
          item = argops[i];
          item.op.targets().remove(this);
        }
        this._argops = null;
        this._update = null;
      }
    }
    return argval;
  },
  /**
   * Detach this operator from the dataflow.
   * Unregisters listeners on upstream dependencies.
   */
  detach() {
    const argops = this._argops;
    let i, n, item, op;
    if (argops) {
      for (i = 0, n = argops.length; i < n; ++i) {
        item = argops[i];
        op = item.op;
        if (op._targets) {
          op._targets.remove(this);
        }
      }
    }

    // remove references to the source and pulse object,
    // if present, to prevent memory leaks of old data.
    this.pulse = null;
    this.source = null;
  },
  /**
   * Delegate method to perform operator processing.
   * Subclasses can override this method to perform custom processing.
   * By default, it marshalls parameters and calls the update function
   * if that function is defined. If the update function does not
   * change the operator value then StopPropagation is returned.
   * If no update function is defined, this method does nothing.
   * @param {Pulse} pulse - the current dataflow pulse.
   * @return The output pulse or StopPropagation. A falsy return value
   *   (including undefined) will let the input pulse pass through.
   */
  evaluate(pulse) {
    const update = this._update;
    if (update) {
      const params = this.marshall(pulse.stamp),
        v = update.call(this, params, pulse);
      params.clear();
      if (v !== this.value) {
        this.value = v;
      } else if (!this.modified()) {
        return pulse.StopPropagation;
      }
    }
  },
  /**
   * Run this operator for the current pulse. If this operator has already
   * been run at (or after) the pulse timestamp, returns StopPropagation.
   * Internally, this method calls {@link evaluate} to perform processing.
   * If {@link evaluate} returns a falsy value, the input pulse is returned.
   * This method should NOT be overridden, instead overrride {@link evaluate}.
   * @param {Pulse} pulse - the current dataflow pulse.
   * @return the output pulse for this operator (or StopPropagation)
   */
  run(pulse) {
    if (pulse.stamp < this.stamp) return pulse.StopPropagation;
    let rv;
    if (this.skip()) {
      this.skip(false);
      rv = 0;
    } else {
      rv = this.evaluate(pulse);
    }
    return this.pulse = rv || pulse;
  }
};

/**
 * Add an operator to the dataflow graph. This function accepts a
 * variety of input argument types. The basic signature supports an
 * initial value, update function and parameters. If the first parameter
 * is an Operator instance, it will be added directly. If it is a
 * constructor for an Operator subclass, a new instance will be instantiated.
 * Otherwise, if the first parameter is a function instance, it will be used
 * as the update function and a null initial value is assumed.
 * @param {*} init - One of: the operator to add, the initial value of
 *   the operator, an operator class to instantiate, or an update function.
 * @param {function} [update] - The operator update function.
 * @param {object} [params] - The operator parameters.
 * @param {boolean} [react=true] - Flag indicating if this operator should
 *   listen for changes to upstream operators included as parameters.
 * @return {Operator} - The added operator.
 */
function add (init, update, params, react) {
  let shift = 1,
    op;
  if (init instanceof Operator) {
    op = init;
  } else if (init && init.prototype instanceof Operator) {
    op = new init();
  } else if (vega_util_module_isFunction(init)) {
    op = new Operator(null, init);
  } else {
    shift = 0;
    op = new Operator(init, update);
  }
  this.rank(op);
  if (shift) {
    react = params;
    params = update;
  }
  if (params) this.connect(op, op.parameters(params, react));
  this.touch(op);
  return op;
}

/**
 * Connect a target operator as a dependent of source operators.
 * If necessary, this method will rerank the target operator and its
 * dependents to ensure propagation proceeds in a topologically sorted order.
 * @param {Operator} target - The target operator.
 * @param {Array<Operator>} - The source operators that should propagate
 *   to the target operator.
 */
function connect (target, sources) {
  const targetRank = target.rank,
    n = sources.length;
  for (let i = 0; i < n; ++i) {
    if (targetRank < sources[i].rank) {
      this.rerank(target);
      return;
    }
  }
}

let STREAM_ID = 0;

/**
 * Models an event stream.
 * @constructor
 * @param {function(Object, number): boolean} [filter] - Filter predicate.
 *   Events pass through when truthy, events are suppressed when falsy.
 * @param {function(Object): *} [apply] - Applied to input events to produce
 *   new event values.
 * @param {function(Object)} [receive] - Event callback function to invoke
 *   upon receipt of a new event. Use to override standard event processing.
 */
function EventStream(filter, apply, receive) {
  this.id = ++STREAM_ID;
  this.value = null;
  if (receive) this.receive = receive;
  if (filter) this._filter = filter;
  if (apply) this._apply = apply;
}

/**
 * Creates a new event stream instance with the provided
 * (optional) filter, apply and receive functions.
 * @param {function(Object, number): boolean} [filter] - Filter predicate.
 *   Events pass through when truthy, events are suppressed when falsy.
 * @param {function(Object): *} [apply] - Applied to input events to produce
 *   new event values.
 * @see EventStream
 */
function stream(filter, apply, receive) {
  return new EventStream(filter, apply, receive);
}
EventStream.prototype = {
  _filter: truthy,
  _apply: vega_util_module_identity,
  targets() {
    return this._targets || (this._targets = UniqueList(id));
  },
  consume(_) {
    if (!arguments.length) return !!this._consume;
    this._consume = !!_;
    return this;
  },
  receive(evt) {
    if (this._filter(evt)) {
      const val = this.value = this._apply(evt),
        trg = this._targets,
        n = trg ? trg.length : 0;
      for (let i = 0; i < n; ++i) trg[i].receive(val);
      if (this._consume) {
        evt.preventDefault();
        evt.stopPropagation();
      }
    }
  },
  filter(filter) {
    const s = stream(filter);
    this.targets().add(s);
    return s;
  },
  apply(apply) {
    const s = stream(null, apply);
    this.targets().add(s);
    return s;
  },
  merge() {
    const s = stream();
    this.targets().add(s);
    for (let i = 0, n = arguments.length; i < n; ++i) {
      arguments[i].targets().add(s);
    }
    return s;
  },
  throttle(pause) {
    let t = -1;
    return this.filter(() => {
      const now = Date.now();
      if (now - t > pause) {
        t = now;
        return 1;
      } else {
        return 0;
      }
    });
  },
  debounce(delay) {
    const s = stream();
    this.targets().add(stream(null, null, debounce(delay, e => {
      const df = e.dataflow;
      s.receive(e);
      if (df && df.run) df.run();
    })));
    return s;
  },
  between(a, b) {
    let active = false;
    a.targets().add(stream(null, null, () => active = true));
    b.targets().add(stream(null, null, () => active = false));
    return this.filter(() => active);
  },
  detach() {
    // ensures compatibility with operators (#2753)
    // remove references to other streams and filter functions that may
    // be bound to subcontexts that need to be garbage collected.
    this._filter = truthy;
    this._targets = null;
  }
};

/**
 * Create a new event stream from an event source.
 * @param {object} source - The event source to monitor. The input must
 *  support the addEventListener method.
 * @param {string} type - The event type.
 * @param {function(object): boolean} [filter] - Event filter function.
 * @param {function(object): *} [apply] - Event application function.
 *   If provided, this function will be invoked and the result will be
 *   used as the downstream event value.
 * @return {EventStream}
 */
function events (source, type, filter, apply) {
  const df = this,
    s = stream(filter, apply),
    send = function (e) {
      e.dataflow = df;
      try {
        s.receive(e);
      } catch (error) {
        df.error(error);
      } finally {
        df.run();
      }
    };
  let sources;
  if (typeof source === 'string' && typeof document !== 'undefined') {
    sources = document.querySelectorAll(source);
  } else {
    sources = vega_util_module_array(source);
  }
  const n = sources.length;
  for (let i = 0; i < n; ++i) {
    sources[i].addEventListener(type, send);
  }
  return s;
}

function vega_dataflow_module_parse(data, format) {
  const locale = this.locale();
  return read(data, format, locale.timeParse, locale.utcParse);
}

/**
 * Ingests new data into the dataflow. First parses the data using the
 * vega-loader read method, then pulses a changeset to the target operator.
 * @param {Operator} target - The Operator to target with ingested data,
 *   typically a Collect transform instance.
 * @param {*} data - The input data, prior to parsing. For JSON this may
 *   be a string or an object. For CSV, TSV, etc should be a string.
 * @param {object} format - The data format description for parsing
 *   loaded data. This object is passed to the vega-loader read method.
 * @returns {Dataflow}
 */
function ingest(target, data, format) {
  data = this.parse(data, format);
  return this.pulse(target, this.changeset().insert(data));
}

/**
 * Request data from an external source, parse it, and return a Promise.
 * @param {string} url - The URL from which to load the data. This string
 *   is passed to the vega-loader load method.
 * @param {object} [format] - The data format description for parsing
 *   loaded data. This object is passed to the vega-loader read method.
 * @return {Promise} A Promise that resolves upon completion of the request.
 *   The resolved object contains the following properties:
 *   - data: an array of parsed data (or null upon error)
 *   - status: a code for success (0), load fail (-1), or parse fail (-2)
 */
async function request(url, format) {
  const df = this;
  let status = 0,
    data;
  try {
    data = await df.loader().load(url, {
      context: 'dataflow',
      response: responseType(format && format.type)
    });
    try {
      data = df.parse(data, format);
    } catch (err) {
      status = -2;
      df.warn('Data ingestion failed', url, err);
    }
  } catch (err) {
    status = -1;
    df.warn('Loading failed', url, err);
  }
  return {
    data,
    status
  };
}
async function preload(target, url, format) {
  const df = this,
    pending = df._pending || loadPending(df);
  pending.requests += 1;
  const res = await df.request(url, format);
  df.pulse(target, df.changeset().remove(truthy).insert(res.data || []));
  pending.done();
  return res;
}
function loadPending(df) {
  let accept;
  const pending = new Promise(a => accept = a);
  pending.requests = 0;
  pending.done = () => {
    if (--pending.requests === 0) {
      df._pending = null;
      accept(df);
    }
  };
  return df._pending = pending;
}

const SKIP = {
  skip: true
};

/**
 * Perform operator updates in response to events. Applies an
 * update function to compute a new operator value. If the update function
 * returns a {@link ChangeSet}, the operator will be pulsed with those tuple
 * changes. Otherwise, the operator value will be updated to the return value.
 * @param {EventStream|Operator} source - The event source to react to.
 *   This argument can be either an EventStream or an Operator.
 * @param {Operator|function(object):Operator} target - The operator to update.
 *   This argument can either be an Operator instance or (if the source
 *   argument is an EventStream), a function that accepts an event object as
 *   input and returns an Operator to target.
 * @param {function(Parameters,Event): *} [update] - Optional update function
 *   to compute the new operator value, or a literal value to set. Update
 *   functions expect to receive a parameter object and event as arguments.
 *   This function can either return a new operator value or (if the source
 *   argument is an EventStream) a {@link ChangeSet} instance to pulse
 *   the target operator with tuple changes.
 * @param {object} [params] - The update function parameters.
 * @param {object} [options] - Additional options hash. If not overridden,
 *   updated operators will be skipped by default.
 * @param {boolean} [options.skip] - If true, the operator will
 *  be skipped: it will not be evaluated, but its dependents will be.
 * @param {boolean} [options.force] - If true, the operator will
 *   be re-evaluated even if its value has not changed.
 * @return {Dataflow}
 */
function on (source, target, update, params, options) {
  const fn = source instanceof Operator ? onOperator : onStream;
  fn(this, source, target, update, params, options);
  return this;
}
function onStream(df, stream, target, update, params, options) {
  const opt = extend({}, options, SKIP);
  let func, op;
  if (!vega_util_module_isFunction(target)) target = vega_util_module_constant(target);
  if (update === undefined) {
    func = e => df.touch(target(e));
  } else if (vega_util_module_isFunction(update)) {
    op = new Operator(null, update, params, false);
    func = e => {
      op.evaluate(e);
      const t = target(e),
        v = op.value;
      isChangeSet(v) ? df.pulse(t, v, options) : df.update(t, v, opt);
    };
  } else {
    func = e => df.update(target(e), update, opt);
  }
  stream.apply(func);
}
function onOperator(df, source, target, update, params, options) {
  if (update === undefined) {
    source.targets().add(target);
  } else {
    const opt = options || {},
      op = new Operator(null, updater(target, update), params, false);
    op.modified(opt.force);
    op.rank = source.rank; // immediately follow source
    source.targets().add(op); // add dependency

    if (target) {
      op.skip(true); // skip first invocation
      op.value = target.value; // initialize value
      op.targets().add(target); // chain dependencies
      df.connect(target, [op]); // rerank as needed, #1672
    }
  }
}
function updater(target, update) {
  update = vega_util_module_isFunction(update) ? update : vega_util_module_constant(update);
  return target ? function (_, pulse) {
    const value = update(_, pulse);
    if (!target.skip()) {
      target.skip(value !== this.value).value = value;
    }
    return value;
  } : update;
}

/**
 * Assigns a rank to an operator. Ranks are assigned in increasing order
 * by incrementing an internal rank counter.
 * @param {Operator} op - The operator to assign a rank.
 */
function vega_dataflow_module_rank(op) {
  op.rank = ++this._rank;
}

/**
 * Re-ranks an operator and all downstream target dependencies. This
 * is necessary when upstream dependencies of higher rank are added to
 * a target operator.
 * @param {Operator} op - The operator to re-rank.
 */
function rerank(op) {
  const queue = [op];
  let cur, list, i;
  while (queue.length) {
    this.rank(cur = queue.pop());
    if (list = cur._targets) {
      for (i = list.length; --i >= 0;) {
        queue.push(cur = list[i]);
        if (cur === op) vega_util_module_error('Cycle detected in dataflow graph.');
      }
    }
  }
}

/**
 * Sentinel value indicating pulse propagation should stop.
 */
const StopPropagation = {};

// Pulse visit type flags
const ADD = 1 << 0,
  REM = 1 << 1,
  MOD = 1 << 2,
  ADD_REM = ADD | REM,
  ADD_MOD = ADD | MOD,
  vega_dataflow_module_ALL = ADD | REM | MOD,
  REFLOW = 1 << 3,
  SOURCE = 1 << 4,
  NO_SOURCE = 1 << 5,
  NO_FIELDS = 1 << 6;

/**
 * A Pulse enables inter-operator communication during a run of the
 * dataflow graph. In addition to the current timestamp, a pulse may also
 * contain a change-set of added, removed or modified data tuples, as well as
 * a pointer to a full backing data source. Tuple change sets may not
 * be fully materialized; for example, to prevent needless array creation
 * a change set may include larger arrays and corresponding filter functions.
 * The pulse provides a {@link visit} method to enable proper and efficient
 * iteration over requested data tuples.
 *
 * In addition, each pulse can track modification flags for data tuple fields.
 * Responsible transform operators should call the {@link modifies} method to
 * indicate changes to data fields. The {@link modified} method enables
 * querying of this modification state.
 *
 * @constructor
 * @param {Dataflow} dataflow - The backing dataflow instance.
 * @param {number} stamp - The current propagation timestamp.
 * @param {string} [encode] - An optional encoding set name, which is then
 *   accessible as Pulse.encode. Operators can respond to (or ignore) this
 *   setting as appropriate. This parameter can be used in conjunction with
 *   the Encode transform in the vega-encode module.
 */
function Pulse(dataflow, stamp, encode) {
  this.dataflow = dataflow;
  this.stamp = stamp == null ? -1 : stamp;
  this.add = [];
  this.rem = [];
  this.mod = [];
  this.fields = null;
  this.encode = encode || null;
}
function materialize(data, filter) {
  const out = [];
  visitArray(data, filter, _ => out.push(_));
  return out;
}
function vega_dataflow_module_filter(pulse, flags) {
  const map = {};
  pulse.visit(flags, t => {
    map[tupleid(t)] = 1;
  });
  return t => map[tupleid(t)] ? null : t;
}
function addFilter(a, b) {
  return a ? (t, i) => a(t, i) && b(t, i) : b;
}
Pulse.prototype = {
  /**
   * Sentinel value indicating pulse propagation should stop.
   */
  StopPropagation,
  /**
   * Boolean flag indicating ADD (added) tuples.
   */
  ADD,
  /**
   * Boolean flag indicating REM (removed) tuples.
   */
  REM,
  /**
   * Boolean flag indicating MOD (modified) tuples.
   */
  MOD,
  /**
   * Boolean flag indicating ADD (added) and REM (removed) tuples.
   */
  ADD_REM,
  /**
   * Boolean flag indicating ADD (added) and MOD (modified) tuples.
   */
  ADD_MOD,
  /**
   * Boolean flag indicating ADD, REM and MOD tuples.
   */
  ALL: vega_dataflow_module_ALL,
  /**
   * Boolean flag indicating all tuples in a data source
   * except for the ADD, REM and MOD tuples.
   */
  REFLOW,
  /**
   * Boolean flag indicating a 'pass-through' to a
   * backing data source, ignoring ADD, REM and MOD tuples.
   */
  SOURCE,
  /**
   * Boolean flag indicating that source data should be
   * suppressed when creating a forked pulse.
   */
  NO_SOURCE,
  /**
   * Boolean flag indicating that field modifications should be
   * suppressed when creating a forked pulse.
   */
  NO_FIELDS,
  /**
   * Creates a new pulse based on the values of this pulse.
   * The dataflow, time stamp and field modification values are copied over.
   * By default, new empty ADD, REM and MOD arrays are created.
   * @param {number} flags - Integer of boolean flags indicating which (if any)
   *   tuple arrays should be copied to the new pulse. The supported flag values
   *   are ADD, REM and MOD. Array references are copied directly: new array
   *   instances are not created.
   * @return {Pulse} - The forked pulse instance.
   * @see init
   */
  fork(flags) {
    return new Pulse(this.dataflow).init(this, flags);
  },
  /**
   * Creates a copy of this pulse with new materialized array
   * instances for the ADD, REM, MOD, and SOURCE arrays.
   * The dataflow, time stamp and field modification values are copied over.
   * @return {Pulse} - The cloned pulse instance.
   * @see init
   */
  clone() {
    const p = this.fork(vega_dataflow_module_ALL);
    p.add = p.add.slice();
    p.rem = p.rem.slice();
    p.mod = p.mod.slice();
    if (p.source) p.source = p.source.slice();
    return p.materialize(vega_dataflow_module_ALL | SOURCE);
  },
  /**
   * Returns a pulse that adds all tuples from a backing source. This is
   * useful for cases where operators are added to a dataflow after an
   * upstream data pipeline has already been processed, ensuring that
   * new operators can observe all tuples within a stream.
   * @return {Pulse} - A pulse instance with all source tuples included
   *   in the add array. If the current pulse already has all source
   *   tuples in its add array, it is returned directly. If the current
   *   pulse does not have a backing source, it is returned directly.
   */
  addAll() {
    let p = this;
    const reuse = !p.source || p.add === p.rem // special case for indexed set (e.g., crossfilter)
    || !p.rem.length && p.source.length === p.add.length;
    if (reuse) {
      return p;
    } else {
      p = new Pulse(this.dataflow).init(this);
      p.add = p.source;
      p.rem = []; // new operators can ignore rem #2769
      return p;
    }
  },
  /**
   * Initialize this pulse based on the values of another pulse. This method
   * is used internally by {@link fork} to initialize a new forked tuple.
   * The dataflow, time stamp and field modification values are copied over.
   * By default, new empty ADD, REM and MOD arrays are created.
   * @param {Pulse} src - The source pulse to copy from.
   * @param {number} flags - Integer of boolean flags indicating which (if any)
   *   tuple arrays should be copied to the new pulse. The supported flag values
   *   are ADD, REM and MOD. Array references are copied directly: new array
   *   instances are not created. By default, source data arrays are copied
   *   to the new pulse. Use the NO_SOURCE flag to enforce a null source.
   * @return {Pulse} - Returns this Pulse instance.
   */
  init(src, flags) {
    const p = this;
    p.stamp = src.stamp;
    p.encode = src.encode;
    if (src.fields && !(flags & NO_FIELDS)) {
      p.fields = src.fields;
    }
    if (flags & ADD) {
      p.addF = src.addF;
      p.add = src.add;
    } else {
      p.addF = null;
      p.add = [];
    }
    if (flags & REM) {
      p.remF = src.remF;
      p.rem = src.rem;
    } else {
      p.remF = null;
      p.rem = [];
    }
    if (flags & MOD) {
      p.modF = src.modF;
      p.mod = src.mod;
    } else {
      p.modF = null;
      p.mod = [];
    }
    if (flags & NO_SOURCE) {
      p.srcF = null;
      p.source = null;
    } else {
      p.srcF = src.srcF;
      p.source = src.source;
      if (src.cleans) p.cleans = src.cleans;
    }
    return p;
  },
  /**
   * Schedules a function to run after pulse propagation completes.
   * @param {function} func - The function to run.
   */
  runAfter(func) {
    this.dataflow.runAfter(func);
  },
  /**
   * Indicates if tuples have been added, removed or modified.
   * @param {number} [flags] - The tuple types (ADD, REM or MOD) to query.
   *   Defaults to ALL, returning true if any tuple type has changed.
   * @return {boolean} - Returns true if one or more queried tuple types have
   *   changed, false otherwise.
   */
  changed(flags) {
    const f = flags || vega_dataflow_module_ALL;
    return f & ADD && this.add.length || f & REM && this.rem.length || f & MOD && this.mod.length;
  },
  /**
   * Forces a "reflow" of tuple values, such that all tuples in the backing
   * source are added to the MOD set, unless already present in the ADD set.
   * @param {boolean} [fork=false] - If true, returns a forked copy of this
   *   pulse, and invokes reflow on that derived pulse.
   * @return {Pulse} - The reflowed pulse instance.
   */
  reflow(fork) {
    if (fork) return this.fork(vega_dataflow_module_ALL).reflow();
    const len = this.add.length,
      src = this.source && this.source.length;
    if (src && src !== len) {
      this.mod = this.source;
      if (len) this.filter(MOD, vega_dataflow_module_filter(this, ADD));
    }
    return this;
  },
  /**
   * Get/set metadata to pulse requesting garbage collection
   * to reclaim currently unused resources.
   */
  clean(value) {
    if (arguments.length) {
      this.cleans = !!value;
      return this;
    } else {
      return this.cleans;
    }
  },
  /**
   * Marks one or more data field names as modified to assist dependency
   * tracking and incremental processing by transform operators.
   * @param {string|Array<string>} _ - The field(s) to mark as modified.
   * @return {Pulse} - This pulse instance.
   */
  modifies(_) {
    const hash = this.fields || (this.fields = {});
    if (vega_util_module_isArray(_)) {
      _.forEach(f => hash[f] = true);
    } else {
      hash[_] = true;
    }
    return this;
  },
  /**
   * Checks if one or more data fields have been modified during this pulse
   * propagation timestamp.
   * @param {string|Array<string>} _ - The field(s) to check for modified.
   * @param {boolean} nomod - If true, will check the modified flag even if
   *   no mod tuples exist. If false (default), mod tuples must be present.
   * @return {boolean} - Returns true if any of the provided fields has been
   *   marked as modified, false otherwise.
   */
  modified(_, nomod) {
    const fields = this.fields;
    return !((nomod || this.mod.length) && fields) ? false : !arguments.length ? !!fields : vega_util_module_isArray(_) ? _.some(f => fields[f]) : fields[_];
  },
  /**
   * Adds a filter function to one more tuple sets. Filters are applied to
   * backing tuple arrays, to determine the actual set of tuples considered
   * added, removed or modified. They can be used to delay materialization of
   * a tuple set in order to avoid expensive array copies. In addition, the
   * filter functions can serve as value transformers: unlike standard predicate
   * function (which return boolean values), Pulse filters should return the
   * actual tuple value to process. If a tuple set is already filtered, the
   * new filter function will be appended into a conjuntive ('and') query.
   * @param {number} flags - Flags indicating the tuple set(s) to filter.
   * @param {function(*):object} filter - Filter function that will be applied
   *   to the tuple set array, and should return a data tuple if the value
   *   should be included in the tuple set, and falsy (or null) otherwise.
   * @return {Pulse} - Returns this pulse instance.
   */
  filter(flags, filter) {
    const p = this;
    if (flags & ADD) p.addF = addFilter(p.addF, filter);
    if (flags & REM) p.remF = addFilter(p.remF, filter);
    if (flags & MOD) p.modF = addFilter(p.modF, filter);
    if (flags & SOURCE) p.srcF = addFilter(p.srcF, filter);
    return p;
  },
  /**
   * Materialize one or more tuple sets in this pulse. If the tuple set(s) have
   * a registered filter function, it will be applied and the tuple set(s) will
   * be replaced with materialized tuple arrays.
   * @param {number} flags - Flags indicating the tuple set(s) to materialize.
   * @return {Pulse} - Returns this pulse instance.
   */
  materialize(flags) {
    flags = flags || vega_dataflow_module_ALL;
    const p = this;
    if (flags & ADD && p.addF) {
      p.add = materialize(p.add, p.addF);
      p.addF = null;
    }
    if (flags & REM && p.remF) {
      p.rem = materialize(p.rem, p.remF);
      p.remF = null;
    }
    if (flags & MOD && p.modF) {
      p.mod = materialize(p.mod, p.modF);
      p.modF = null;
    }
    if (flags & SOURCE && p.srcF) {
      p.source = p.source.filter(p.srcF);
      p.srcF = null;
    }
    return p;
  },
  /**
   * Visit one or more tuple sets in this pulse.
   * @param {number} flags - Flags indicating the tuple set(s) to visit.
   *   Legal values are ADD, REM, MOD and SOURCE (if a backing data source
   *   has been set).
   * @param {function(object):*} - Visitor function invoked per-tuple.
   * @return {Pulse} - Returns this pulse instance.
   */
  visit(flags, visitor) {
    const p = this,
      v = visitor;
    if (flags & SOURCE) {
      visitArray(p.source, p.srcF, v);
      return p;
    }
    if (flags & ADD) visitArray(p.add, p.addF, v);
    if (flags & REM) visitArray(p.rem, p.remF, v);
    if (flags & MOD) visitArray(p.mod, p.modF, v);
    const src = p.source;
    if (flags & REFLOW && src) {
      const sum = p.add.length + p.mod.length;
      if (sum === src.length) ; else if (sum) {
        visitArray(src, vega_dataflow_module_filter(p, ADD_MOD), v);
      } else {
        // if no add/rem/mod tuples, visit source
        visitArray(src, p.srcF, v);
      }
    }
    return p;
  }
};

/**
 * Represents a set of multiple pulses. Used as input for operators
 * that accept multiple pulses at a time. Contained pulses are
 * accessible via the public "pulses" array property. This pulse doe
 * not carry added, removed or modified tuples directly. However,
 * the visit method can be used to traverse all such tuples contained
 * in sub-pulses with a timestamp matching this parent multi-pulse.
 * @constructor
 * @param {Dataflow} dataflow - The backing dataflow instance.
 * @param {number} stamp - The timestamp.
 * @param {Array<Pulse>} pulses - The sub-pulses for this multi-pulse.
 */
function MultiPulse(dataflow, stamp, pulses, encode) {
  const p = this;
  let c = 0;
  this.dataflow = dataflow;
  this.stamp = stamp;
  this.fields = null;
  this.encode = encode || null;
  this.pulses = pulses;
  for (const pulse of pulses) {
    if (pulse.stamp !== stamp) continue;
    if (pulse.fields) {
      const hash = p.fields || (p.fields = {});
      for (const f in pulse.fields) {
        hash[f] = 1;
      }
    }
    if (pulse.changed(p.ADD)) c |= p.ADD;
    if (pulse.changed(p.REM)) c |= p.REM;
    if (pulse.changed(p.MOD)) c |= p.MOD;
  }
  this.changes = c;
}
inherits(MultiPulse, Pulse, {
  /**
   * Creates a new pulse based on the values of this pulse.
   * The dataflow, time stamp and field modification values are copied over.
   * @return {Pulse}
   */
  fork(flags) {
    const p = new Pulse(this.dataflow).init(this, flags & this.NO_FIELDS);
    if (flags !== undefined) {
      if (flags & p.ADD) this.visit(p.ADD, t => p.add.push(t));
      if (flags & p.REM) this.visit(p.REM, t => p.rem.push(t));
      if (flags & p.MOD) this.visit(p.MOD, t => p.mod.push(t));
    }
    return p;
  },
  changed(flags) {
    return this.changes & flags;
  },
  modified(_) {
    const p = this,
      fields = p.fields;
    return !(fields && p.changes & p.MOD) ? 0 : vega_util_module_isArray(_) ? _.some(f => fields[f]) : fields[_];
  },
  filter() {
    vega_util_module_error('MultiPulse does not support filtering.');
  },
  materialize() {
    vega_util_module_error('MultiPulse does not support materialization.');
  },
  visit(flags, visitor) {
    const p = this,
      pulses = p.pulses,
      n = pulses.length;
    let i = 0;
    if (flags & p.SOURCE) {
      for (; i < n; ++i) {
        pulses[i].visit(flags, visitor);
      }
    } else {
      for (; i < n; ++i) {
        if (pulses[i].stamp === p.stamp) {
          pulses[i].visit(flags, visitor);
        }
      }
    }
    return p;
  }
});

/* eslint-disable require-atomic-updates */

/**
 * Evaluates the dataflow and returns a Promise that resolves when pulse
 * propagation completes. This method will increment the current timestamp
 * and process all updated, pulsed and touched operators. When invoked for
 * the first time, all registered operators will be processed. This method
 * should not be invoked by third-party clients, use {@link runAsync} or
 * {@link run} instead.
 * @param {string} [encode] - The name of an encoding set to invoke during
 *   propagation. This value is added to generated Pulse instances;
 *   operators can then respond to (or ignore) this setting as appropriate.
 *   This parameter can be used in conjunction with the Encode transform in
 *   the vega-encode package.
 * @param {function} [prerun] - An optional callback function to invoke
 *   immediately before dataflow evaluation commences.
 * @param {function} [postrun] - An optional callback function to invoke
 *   after dataflow evaluation completes. The callback will be invoked
 *   after those registered via {@link runAfter}.
 * @return {Promise} - A promise that resolves to this dataflow after
 *   evaluation completes.
 */
async function evaluate(encode, prerun, postrun) {
  const df = this,
    async = [];

  // if the pulse value is set, this is a re-entrant call
  if (df._pulse) return reentrant(df);

  // wait for pending datasets to load
  if (df._pending) await df._pending;

  // invoke prerun function, if provided
  if (prerun) await asyncCallback(df, prerun);

  // exit early if there are no updates
  if (!df._touched.length) {
    df.debug('Dataflow invoked, but nothing to do.');
    return df;
  }

  // increment timestamp clock
  const stamp = ++df._clock;

  // set the current pulse
  df._pulse = new Pulse(df, stamp, encode);

  // initialize priority queue, reset touched operators
  df._touched.forEach(op => df._enqueue(op, true));
  df._touched = UniqueList(id);
  let count = 0,
    op,
    next,
    error;
  try {
    while (df._heap.size() > 0) {
      // dequeue operator with highest priority
      op = df._heap.pop();

      // re-queue if rank changed
      if (op.rank !== op.qrank) {
        df._enqueue(op, true);
        continue;
      }

      // otherwise, evaluate the operator
      next = op.run(df._getPulse(op, encode));
      if (next.then) {
        // await if operator returns a promise directly
        next = await next;
      } else if (next.async) {
        // queue parallel asynchronous execution
        async.push(next.async);
        next = StopPropagation;
      }

      // propagate evaluation, enqueue dependent operators
      if (next !== StopPropagation) {
        if (op._targets) op._targets.forEach(op => df._enqueue(op));
      }

      // increment visit counter
      ++count;
    }
  } catch (err) {
    df._heap.clear();
    error = err;
  }

  // reset pulse map
  df._input = {};
  df._pulse = null;
  df.debug(`Pulse ${stamp}: ${count} operators`);
  if (error) {
    df._postrun = [];
    df.error(error);
  }

  // invoke callbacks queued via runAfter
  if (df._postrun.length) {
    const pr = df._postrun.sort((a, b) => b.priority - a.priority);
    df._postrun = [];
    for (let i = 0; i < pr.length; ++i) {
      await asyncCallback(df, pr[i].callback);
    }
  }

  // invoke postrun function, if provided
  if (postrun) await asyncCallback(df, postrun);

  // handle non-blocking asynchronous callbacks
  if (async.length) {
    Promise.all(async).then(cb => df.runAsync(null, () => {
      cb.forEach(f => {
        try {
          f(df);
        } catch (err) {
          df.error(err);
        }
      });
    }));
  }
  return df;
}

/**
 * Queues dataflow evaluation to run once any other queued evaluations have
 * completed and returns a Promise that resolves when the queued pulse
 * propagation completes. If provided, a callback function will be invoked
 * immediately before evaluation commences. This method will ensure a
 * separate evaluation is invoked for each time it is called.
 * @param {string} [encode] - The name of an encoding set to invoke during
 *   propagation. This value is added to generated Pulse instances;
 *   operators can then respond to (or ignore) this setting as appropriate.
 *   This parameter can be used in conjunction with the Encode transform in
 *   the vega-encode package.
 * @param {function} [prerun] - An optional callback function to invoke
 *   immediately before dataflow evaluation commences.
 * @param {function} [postrun] - An optional callback function to invoke
 *   after dataflow evaluation completes. The callback will be invoked
 *   after those registered via {@link runAfter}.
 * @return {Promise} - A promise that resolves to this dataflow after
 *   evaluation completes.
 */
async function runAsync(encode, prerun, postrun) {
  // await previously queued functions
  while (this._running) await this._running;

  // run dataflow, manage running promise
  const clear = () => this._running = null;
  (this._running = this.evaluate(encode, prerun, postrun)).then(clear, clear);
  return this._running;
}

/**
 * Requests dataflow evaluation and the immediately returns this dataflow
 * instance. If there are pending data loading or other asynchronous
 * operations, the dataflow will evaluate asynchronously after this method
 * has been invoked. To track when dataflow evaluation completes, use the
 * {@link runAsync} method instead. This method will raise an error if
 * invoked while the dataflow is already in the midst of evaluation.
 * @param {string} [encode] - The name of an encoding set to invoke during
 *   propagation. This value is added to generated Pulse instances;
 *   operators can then respond to (or ignore) this setting as appropriate.
 *   This parameter can be used in conjunction with the Encode transform in
 *   the vega-encode module.
 * @param {function} [prerun] - An optional callback function to invoke
 *   immediately before dataflow evaluation commences.
 * @param {function} [postrun] - An optional callback function to invoke
 *   after dataflow evaluation completes. The callback will be invoked
 *   after those registered via {@link runAfter}.
 * @return {Dataflow} - This dataflow instance.
 */
function vega_dataflow_module_run(encode, prerun, postrun) {
  return this._pulse ? reentrant(this) : (this.evaluate(encode, prerun, postrun), this);
}

/**
 * Schedules a callback function to be invoked after the current pulse
 * propagation completes. If no propagation is currently occurring,
 * the function is invoked immediately. Callbacks scheduled via runAfter
 * are invoked immediately upon completion of the current cycle, before
 * any request queued via runAsync. This method is primarily intended for
 * internal use. Third-party callers using runAfter to schedule a callback
 * that invokes {@link run} or {@link runAsync} should not use this method,
 * but instead use {@link runAsync} with prerun or postrun arguments.
 * @param {function(Dataflow)} callback - The callback function to run.
 *   The callback will be invoked with this Dataflow instance as its
 *   sole argument.
 * @param {boolean} enqueue - A boolean flag indicating that the
 *   callback should be queued up to run after the next propagation
 *   cycle, suppressing immediate invocation when propagation is not
 *   currently occurring.
 * @param {number} [priority] - A priority value used to sort registered
 *   callbacks to determine execution order. This argument is intended
 *   for internal Vega use only.
 */
function runAfter(callback, enqueue, priority) {
  if (this._pulse || enqueue) {
    // pulse propagation is currently running, queue to run after
    this._postrun.push({
      priority: priority || 0,
      callback: callback
    });
  } else {
    // pulse propagation already complete, invoke immediately
    try {
      callback(this);
    } catch (err) {
      this.error(err);
    }
  }
}

/**
 * Raise an error for re-entrant dataflow evaluation.
 */
function reentrant(df) {
  df.error('Dataflow already running. Use runAsync() to chain invocations.');
  return df;
}

/**
 * Enqueue an operator into the priority queue for evaluation. The operator
 * will be enqueued if it has no registered pulse for the current cycle, or if
 * the force argument is true. Upon enqueue, this method also sets the
 * operator's qrank to the current rank value.
 * @param {Operator} op - The operator to enqueue.
 * @param {boolean} [force] - A flag indicating if the operator should be
 *   forceably added to the queue, even if it has already been previously
 *   enqueued during the current pulse propagation. This is useful when the
 *   dataflow graph is dynamically modified and the operator rank changes.
 */
function enqueue(op, force) {
  const q = op.stamp < this._clock;
  if (q) op.stamp = this._clock;
  if (q || force) {
    op.qrank = op.rank;
    this._heap.push(op);
  }
}

/**
 * Provide a correct pulse for evaluating an operator. If the operator has an
 * explicit source operator, we will try to pull the pulse(s) from it.
 * If there is an array of source operators, we build a multi-pulse.
 * Otherwise, we return a current pulse with correct source data.
 * If the pulse is the pulse map has an explicit target set, we use that.
 * Else if the pulse on the upstream source operator is current, we use that.
 * Else we use the pulse from the pulse map, but copy the source tuple array.
 * @param {Operator} op - The operator for which to get an input pulse.
 * @param {string} [encode] - An (optional) encoding set name with which to
 *   annotate the returned pulse. See {@link run} for more information.
 */
function getPulse(op, encode) {
  const s = op.source,
    stamp = this._clock;
  return s && vega_util_module_isArray(s) ? new MultiPulse(this, stamp, s.map(_ => _.pulse), encode) : this._input[op.id] || singlePulse(this._pulse, s && s.pulse);
}
function singlePulse(p, s) {
  if (s && s.stamp === p.stamp) {
    return s;
  }
  p = p.fork();
  if (s && s !== StopPropagation) {
    p.source = s.source;
  }
  return p;
}

const NO_OPT = {
  skip: false,
  force: false
};

/**
 * Touches an operator, scheduling it to be evaluated. If invoked outside of
 * a pulse propagation, the operator will be evaluated the next time this
 * dataflow is run. If invoked in the midst of pulse propagation, the operator
 * will be queued for evaluation if and only if the operator has not yet been
 * evaluated on the current propagation timestamp.
 * @param {Operator} op - The operator to touch.
 * @param {object} [options] - Additional options hash.
 * @param {boolean} [options.skip] - If true, the operator will
 *   be skipped: it will not be evaluated, but its dependents will be.
 * @return {Dataflow}
 */
function touch(op, options) {
  const opt = options || NO_OPT;
  if (this._pulse) {
    // if in midst of propagation, add to priority queue
    this._enqueue(op);
  } else {
    // otherwise, queue for next propagation
    this._touched.add(op);
  }
  if (opt.skip) op.skip(true);
  return this;
}

/**
 * Updates the value of the given operator.
 * @param {Operator} op - The operator to update.
 * @param {*} value - The value to set.
 * @param {object} [options] - Additional options hash.
 * @param {boolean} [options.force] - If true, the operator will
 *   be re-evaluated even if its value has not changed.
 * @param {boolean} [options.skip] - If true, the operator will
 *   be skipped: it will not be evaluated, but its dependents will be.
 * @return {Dataflow}
 */
function vega_dataflow_module_update(op, value, options) {
  const opt = options || NO_OPT;
  if (op.set(value) || opt.force) {
    this.touch(op, opt);
  }
  return this;
}

/**
 * Pulses an operator with a changeset of tuples. If invoked outside of
 * a pulse propagation, the pulse will be applied the next time this
 * dataflow is run. If invoked in the midst of pulse propagation, the pulse
 * will be added to the set of active pulses and will be applied if and
 * only if the target operator has not yet been evaluated on the current
 * propagation timestamp.
 * @param {Operator} op - The operator to pulse.
 * @param {ChangeSet} value - The tuple changeset to apply.
 * @param {object} [options] - Additional options hash.
 * @param {boolean} [options.skip] - If true, the operator will
 *   be skipped: it will not be evaluated, but its dependents will be.
 * @return {Dataflow}
 */
function pulse(op, changeset, options) {
  this.touch(op, options || NO_OPT);
  const p = new Pulse(this, this._clock + (this._pulse ? 0 : 1)),
    t = op.pulse && op.pulse.source || [];
  p.target = op;
  this._input[op.id] = changeset.pulse(p, t);
  return this;
}

function Heap(cmp) {
  let nodes = [];
  return {
    clear: () => nodes = [],
    size: () => nodes.length,
    peek: () => nodes[0],
    push: x => {
      nodes.push(x);
      return siftdown(nodes, 0, nodes.length - 1, cmp);
    },
    pop: () => {
      const last = nodes.pop();
      let item;
      if (nodes.length) {
        item = nodes[0];
        nodes[0] = last;
        siftup(nodes, 0, cmp);
      } else {
        item = last;
      }
      return item;
    }
  };
}
function siftdown(array, start, idx, cmp) {
  let parent, pidx;
  const item = array[idx];
  while (idx > start) {
    pidx = idx - 1 >> 1;
    parent = array[pidx];
    if (cmp(item, parent) < 0) {
      array[idx] = parent;
      idx = pidx;
      continue;
    }
    break;
  }
  return array[idx] = item;
}
function siftup(array, idx, cmp) {
  const start = idx,
    end = array.length,
    item = array[idx];
  let cidx = (idx << 1) + 1,
    ridx;
  while (cidx < end) {
    ridx = cidx + 1;
    if (ridx < end && cmp(array[cidx], array[ridx]) >= 0) {
      cidx = ridx;
    }
    array[idx] = array[cidx];
    idx = cidx;
    cidx = (idx << 1) + 1;
  }
  array[idx] = item;
  return siftdown(array, start, idx, cmp);
}

/**
 * A dataflow graph for reactive processing of data streams.
 * @constructor
 */
function Dataflow() {
  this.logger(logger());
  this.logLevel(Error$1);
  this._clock = 0;
  this._rank = 0;
  this._locale = vega_format_module_defaultLocale();
  try {
    this._loader = loader();
  } catch (e) {
    // do nothing if loader module is unavailable
  }
  this._touched = UniqueList(id);
  this._input = {};
  this._pulse = null;
  this._heap = Heap((a, b) => a.qrank - b.qrank);
  this._postrun = [];
}
function logMethod(method) {
  return function () {
    return this._log[method].apply(this, arguments);
  };
}
Dataflow.prototype = {
  /**
   * The current timestamp of this dataflow. This value reflects the
   * timestamp of the previous dataflow run. The dataflow is initialized
   * with a stamp value of 0. The initial run of the dataflow will have
   * a timestap of 1, and so on. This value will match the
   * {@link Pulse.stamp} property.
   * @return {number} - The current timestamp value.
   */
  stamp() {
    return this._clock;
  },
  /**
   * Gets or sets the loader instance to use for data file loading. A
   * loader object must provide a "load" method for loading files and a
   * "sanitize" method for checking URL/filename validity. Both methods
   * should accept a URI and options hash as arguments, and return a Promise
   * that resolves to the loaded file contents (load) or a hash containing
   * sanitized URI data with the sanitized url assigned to the "href" property
   * (sanitize).
   * @param {object} _ - The loader instance to use.
   * @return {object|Dataflow} - If no arguments are provided, returns
   *   the current loader instance. Otherwise returns this Dataflow instance.
   */
  loader(_) {
    if (arguments.length) {
      this._loader = _;
      return this;
    } else {
      return this._loader;
    }
  },
  /**
   * Gets or sets the locale instance to use for formatting and parsing
   * string values. The locale object should be provided by the
   * vega-format library, and include methods such as format, timeFormat,
   * utcFormat, timeParse, and utcParse.
   * @param {object} _ - The locale instance to use.
   * @return {object|Dataflow} - If no arguments are provided, returns
   *   the current locale instance. Otherwise returns this Dataflow instance.
   */
  locale(_) {
    if (arguments.length) {
      this._locale = _;
      return this;
    } else {
      return this._locale;
    }
  },
  /**
   * Get or set the logger instance used to log messages. If no arguments are
   * provided, returns the current logger instance. Otherwise, sets the logger
   * and return this Dataflow instance. Provided loggers must support the full
   * API of logger objects generated by the vega-util logger method. Note that
   * by default the log level of the new logger will be used; use the logLevel
   * method to adjust the log level as needed.
   */
  logger(logger) {
    if (arguments.length) {
      this._log = logger;
      return this;
    } else {
      return this._log;
    }
  },
  /**
   * Logs an error message. By default, logged messages are written to console
   * output. The message will only be logged if the current log level is high
   * enough to permit error messages.
   */
  error: logMethod('error'),
  /**
   * Logs a warning message. By default, logged messages are written to console
   * output. The message will only be logged if the current log level is high
   * enough to permit warning messages.
   */
  warn: logMethod('warn'),
  /**
   * Logs a information message. By default, logged messages are written to
   * console output. The message will only be logged if the current log level is
   * high enough to permit information messages.
   */
  info: logMethod('info'),
  /**
   * Logs a debug message. By default, logged messages are written to console
   * output. The message will only be logged if the current log level is high
   * enough to permit debug messages.
   */
  debug: logMethod('debug'),
  /**
   * Get or set the current log level. If an argument is provided, it
   * will be used as the new log level.
   * @param {number} [level] - Should be one of None, Warn, Info
   * @return {number} - The current log level.
   */
  logLevel: logMethod('level'),
  /**
   * Empty entry threshold for garbage cleaning. Map data structures will
   * perform cleaning once the number of empty entries exceeds this value.
   */
  cleanThreshold: 1e4,
  // OPERATOR REGISTRATION
  add,
  connect,
  rank: vega_dataflow_module_rank,
  rerank,
  // OPERATOR UPDATES
  pulse,
  touch,
  update: vega_dataflow_module_update,
  changeset,
  // DATA LOADING
  ingest,
  parse: vega_dataflow_module_parse,
  preload,
  request,
  // EVENT HANDLING
  events,
  on,
  // PULSE PROPAGATION
  evaluate,
  run: vega_dataflow_module_run,
  runAsync,
  runAfter,
  _enqueue: enqueue,
  _getPulse: getPulse
};

/**
 * Abstract class for operators that process data tuples.
 * Subclasses must provide a {@link transform} method for operator processing.
 * @constructor
 * @param {*} [init] - The initial value for this operator.
 * @param {object} [params] - The parameters for this operator.
 * @param {Operator} [source] - The operator from which to receive pulses.
 */
function Transform(init, params) {
  Operator.call(this, init, null, params);
}
inherits(Transform, Operator, {
  /**
   * Overrides {@link Operator.evaluate} for transform operators.
   * Internally, this method calls {@link evaluate} to perform processing.
   * If {@link evaluate} returns a falsy value, the input pulse is returned.
   * This method should NOT be overridden, instead overrride {@link evaluate}.
   * @param {Pulse} pulse - the current dataflow pulse.
   * @return the output pulse for this operator (or StopPropagation)
   */
  run(pulse) {
    if (pulse.stamp < this.stamp) return pulse.StopPropagation;
    let rv;
    if (this.skip()) {
      this.skip(false);
    } else {
      rv = this.evaluate(pulse);
    }
    rv = rv || pulse;
    if (rv.then) {
      rv = rv.then(_ => this.pulse = _);
    } else if (rv !== pulse.StopPropagation) {
      this.pulse = rv;
    }
    return rv;
  },
  /**
   * Overrides {@link Operator.evaluate} for transform operators.
   * Marshalls parameter values and then invokes {@link transform}.
   * @param {Pulse} pulse - the current dataflow pulse.
   * @return {Pulse} The output pulse (or StopPropagation). A falsy return
       value (including undefined) will let the input pulse pass through.
  */
  evaluate(pulse) {
    const params = this.marshall(pulse.stamp),
      out = this.transform(params, pulse);
    params.clear();
    return out;
  },
  /**
   * Process incoming pulses.
   * Subclasses should override this method to implement transforms.
   * @param {Parameters} _ - The operator parameter values.
   * @param {Pulse} pulse - The current dataflow pulse.
   * @return {Pulse} The output pulse (or StopPropagation). A falsy return
   *   value (including undefined) will let the input pulse pass through.
   */
  transform() {}
});

const vega_dataflow_module_transforms = {};
function definition(type) {
  const t = vega_dataflow_module_transform(type);
  return t && t.Definition || null;
}
function vega_dataflow_module_transform(type) {
  type = type && type.toLowerCase();
  return vega_util_module_has(vega_dataflow_module_transforms, type) ? vega_dataflow_module_transforms[type] : null;
}



;// ../../node_modules/d3-array/src/max.js
function max_max(values, valueof) {
  let max;
  if (valueof === undefined) {
    for (const value of values) {
      if (value != null
          && (max < value || (max === undefined && value >= value))) {
        max = value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if ((value = valueof(value, ++index, values)) != null
          && (max < value || (max === undefined && value >= value))) {
        max = value;
      }
    }
  }
  return max;
}

;// ../../node_modules/d3-array/src/min.js
function min_min(values, valueof) {
  let min;
  if (valueof === undefined) {
    for (const value of values) {
      if (value != null
          && (min > value || (min === undefined && value >= value))) {
        min = value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if ((value = valueof(value, ++index, values)) != null
          && (min > value || (min === undefined && value >= value))) {
        min = value;
      }
    }
  }
  return min;
}

;// ../../node_modules/d3-array/src/sort.js



function sort(values, ...F) {
  if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
  values = Array.from(values);
  let [f] = F;
  if ((f && f.length !== 2) || F.length > 1) {
    const index = Uint32Array.from(values, (d, i) => i);
    if (F.length > 1) {
      F = F.map(f => values.map(f));
      index.sort((i, j) => {
        for (const f of F) {
          const c = sort_ascendingDefined(f[i], f[j]);
          if (c) return c;
        }
      });
    } else {
      f = values.map(f);
      index.sort((i, j) => sort_ascendingDefined(f[i], f[j]));
    }
    return permute(values, index);
  }
  return values.sort(compareDefined(f));
}

function compareDefined(compare = ascending_ascending) {
  if (compare === ascending_ascending) return sort_ascendingDefined;
  if (typeof compare !== "function") throw new TypeError("compare is not a function");
  return (a, b) => {
    const x = compare(a, b);
    if (x || x === 0) return x;
    return (compare(b, b) === 0) - (compare(a, a) === 0);
  };
}

function sort_ascendingDefined(a, b) {
  return (a == null || !(a >= a)) - (b == null || !(b >= b)) || (a < b ? -1 : a > b ? 1 : 0);
}

;// ../../node_modules/d3-array/src/quickselect.js


// Based on https://github.com/mourner/quickselect
// ISC license, Copyright 2018 Vladimir Agafonkin.
function quickselect_quickselect(array, k, left = 0, right = Infinity, compare) {
  k = Math.floor(k);
  left = Math.floor(Math.max(0, left));
  right = Math.floor(Math.min(array.length - 1, right));

  if (!(left <= k && k <= right)) return array;

  compare = compare === undefined ? sort_ascendingDefined : compareDefined(compare);

  while (right > left) {
    if (right - left > 600) {
      const n = right - left + 1;
      const m = k - left + 1;
      const z = Math.log(n);
      const s = 0.5 * Math.exp(2 * z / 3);
      const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
      const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
      const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
      quickselect_quickselect(array, k, newLeft, newRight, compare);
    }

    const t = array[k];
    let i = left;
    let j = right;

    swap(array, left, k);
    if (compare(array[right], t) > 0) swap(array, left, right);

    while (i < j) {
      swap(array, i, j), ++i, --j;
      while (compare(array[i], t) < 0) ++i;
      while (compare(array[j], t) > 0) --j;
    }

    if (compare(array[left], t) === 0) swap(array, left, j);
    else ++j, swap(array, j, right);

    if (j <= k) left = j + 1;
    if (k <= j) right = j - 1;
  }

  return array;
}

function swap(array, i, j) {
  const t = array[i];
  array[i] = array[j];
  array[j] = t;
}

;// ../../node_modules/d3-array/src/number.js
function number_number(x) {
  return x === null ? NaN : +x;
}

function* numbers(values, valueof) {
  if (valueof === undefined) {
    for (let value of values) {
      if (value != null && (value = +value) >= value) {
        yield value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
        yield value;
      }
    }
  }
}

;// ../../node_modules/d3-array/src/quantile.js









function quantile_quantile(values, p, valueof) {
  values = Float64Array.from(numbers(values, valueof));
  if (!(n = values.length) || isNaN(p = +p)) return;
  if (p <= 0 || n < 2) return min_min(values);
  if (p >= 1) return max_max(values);
  var n,
      i = (n - 1) * p,
      i0 = Math.floor(i),
      value0 = max_max(quickselect_quickselect(values, i0).subarray(0, i0 + 1)),
      value1 = min_min(values.subarray(i0 + 1));
  return value0 + (value1 - value0) * (i - i0);
}

function quantileSorted(values, p, valueof = number_number) {
  if (!(n = values.length) || isNaN(p = +p)) return;
  if (p <= 0 || n < 2) return +valueof(values[0], 0, values);
  if (p >= 1) return +valueof(values[n - 1], n - 1, values);
  var n,
      i = (n - 1) * p,
      i0 = Math.floor(i),
      value0 = +valueof(values[i0], i0, values),
      value1 = +valueof(values[i0 + 1], i0 + 1, values);
  return value0 + (value1 - value0) * (i - i0);
}

function quantile_quantileIndex(values, p, valueof = number) {
  if (isNaN(p = +p)) return;
  numbers = Float64Array.from(values, (_, i) => number(valueof(values[i], i, values)));
  if (p <= 0) return minIndex(numbers);
  if (p >= 1) return maxIndex(numbers);
  var numbers,
      index = Uint32Array.from(values, (_, i) => i),
      j = numbers.length - 1,
      i = Math.floor(j * p);
  quickselect(index, i, 0, j, (i, j) => ascendingDefined(numbers[i], numbers[j]));
  i = greatest(index.subarray(0, i + 1), (i) => numbers[i]);
  return i >= 0 ? i : -1;
}

;// ../../node_modules/d3-array/src/variance.js
function variance(values, valueof) {
  let count = 0;
  let delta;
  let mean = 0;
  let sum = 0;
  if (valueof === undefined) {
    for (let value of values) {
      if (value != null && (value = +value) >= value) {
        delta = value - mean;
        mean += delta / ++count;
        sum += delta * (value - mean);
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
        delta = value - mean;
        mean += delta / ++count;
        sum += delta * (value - mean);
      }
    }
  }
  if (count > 1) return sum / (count - 1);
}

;// ../../node_modules/d3-array/src/deviation.js


function deviation(values, valueof) {
  const v = variance(values, valueof);
  return v ? Math.sqrt(v) : v;
}

;// ../../node_modules/d3-array/src/median.js


function median(values, valueof) {
  return quantile_quantile(values, 0.5, valueof);
}

function medianIndex(values, valueof) {
  return quantileIndex(values, 0.5, valueof);
}

;// ../../node_modules/vega-statistics/build/vega-statistics.module.js


function* vega_statistics_module_numbers (values, valueof) {
  if (valueof == null) {
    for (let value of values) {
      if (value != null && value !== '' && (value = +value) >= value) {
        yield value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      value = valueof(value, ++index, values);
      if (value != null && value !== '' && (value = +value) >= value) {
        yield value;
      }
    }
  }
}

function quantiles (array, p, f) {
  const values = Float64Array.from(vega_statistics_module_numbers(array, f));

  // don't depend on return value from typed array sort call
  // protects against undefined sort results in Safari (vega/vega-lite#4964)
  values.sort(ascending_ascending);
  return p.map(_ => quantileSorted(values, _));
}

function quartiles (array, f) {
  return quantiles(array, [0.25, 0.50, 0.75], f);
}

// Scott, D. W. (1992) Multivariate Density Estimation:
// Theory, Practice, and Visualization. Wiley.
function estimateBandwidth (array, f) {
  const n = array.length,
    d = deviation(array, f),
    q = quartiles(array, f),
    h = (q[2] - q[0]) / 1.34,
    v = Math.min(d, h) || d || Math.abs(q[0]) || 1;
  return 1.06 * v * Math.pow(n, -0.2);
}

function vega_statistics_module_bin (_) {
  // determine range
  const maxb = _.maxbins || 20,
    base = _.base || 10,
    logb = Math.log(base),
    div = _.divide || [5, 2];
  let min = _.extent[0],
    max = _.extent[1],
    step,
    level,
    minstep,
    v,
    i,
    n;
  const span = _.span || max - min || Math.abs(min) || 1;
  if (_.step) {
    // if step size is explicitly given, use that
    step = _.step;
  } else if (_.steps) {
    // if provided, limit choice to acceptable step sizes
    v = span / maxb;
    for (i = 0, n = _.steps.length; i < n && _.steps[i] < v; ++i);
    step = _.steps[Math.max(0, i - 1)];
  } else {
    // else use span to determine step size
    level = Math.ceil(Math.log(maxb) / logb);
    minstep = _.minstep || 0;
    step = Math.max(minstep, Math.pow(base, Math.round(Math.log(span) / logb) - level));

    // increase step size if too many bins
    while (Math.ceil(span / step) > maxb) {
      step *= base;
    }

    // decrease step size if allowed
    for (i = 0, n = div.length; i < n; ++i) {
      v = step / div[i];
      if (v >= minstep && span / v <= maxb) step = v;
    }
  }

  // update precision, min and max
  v = Math.log(step);
  const precision = v >= 0 ? 0 : ~~(-v / logb) + 1,
    eps = Math.pow(base, -precision - 1);
  if (_.nice || _.nice === undefined) {
    v = Math.floor(min / step + eps) * step;
    min = min < v ? v - step : v;
    max = Math.ceil(max / step) * step;
  }
  return {
    start: min,
    stop: max === min ? min + step : max,
    step: step
  };
}

var vega_statistics_module_random = Math.random;
function setRandom(r) {
  vega_statistics_module_random = r;
}

function bootstrapCI (array, samples, alpha, f) {
  if (!array.length) return [undefined, undefined];
  const values = Float64Array.from(vega_statistics_module_numbers(array, f)),
    n = values.length,
    m = samples;
  let a, i, j, mu;
  for (j = 0, mu = Array(m); j < m; ++j) {
    for (a = 0, i = 0; i < n; ++i) {
      a += values[~~(vega_statistics_module_random() * n)];
    }
    mu[j] = a / n;
  }
  mu.sort(ascending_ascending);
  return [quantile_quantile(mu, alpha / 2), quantile_quantile(mu, 1 - alpha / 2)];
}

// Dot density binning for dot plot construction.
// Based on Leland Wilkinson, Dot Plots, The American Statistician, 1999.
// https://www.cs.uic.edu/~wilkinson/Publications/dotplots.pdf
function dotbin (array, step, smooth, f) {
  f = f || (_ => _);
  const n = array.length,
    v = new Float64Array(n);
  let i = 0,
    j = 1,
    a = f(array[0]),
    b = a,
    w = a + step,
    x;
  for (; j < n; ++j) {
    x = f(array[j]);
    if (x >= w) {
      b = (a + b) / 2;
      for (; i < j; ++i) v[i] = b;
      w = x + step;
      a = x;
    }
    b = x;
  }
  b = (a + b) / 2;
  for (; i < j; ++i) v[i] = b;
  return smooth ? smoothing(v, step + step / 4) : v;
}

// perform smoothing to reduce variance
// swap points between "adjacent" stacks
// Wilkinson defines adjacent as within step/4 units
function smoothing(v, thresh) {
  const n = v.length;
  let a = 0,
    b = 1,
    c,
    d;

  // get left stack
  while (v[a] === v[b]) ++b;
  while (b < n) {
    // get right stack
    c = b + 1;
    while (v[b] === v[c]) ++c;

    // are stacks adjacent?
    // if so, compare sizes and swap as needed
    if (v[b] - v[b - 1] < thresh) {
      d = b + (a + c - b - b >> 1);
      while (d < b) v[d++] = v[b];
      while (d > b) v[d--] = v[a];
    }

    // update left stack indices
    a = b;
    b = c;
  }
  return v;
}

function vega_statistics_module_lcg (seed) {
  // Random numbers using a Linear Congruential Generator with seed value
  // Uses glibc values from https://en.wikipedia.org/wiki/Linear_congruential_generator
  return function () {
    seed = (1103515245 * seed + 12345) % 2147483647;
    return seed / 2147483647;
  };
}

function integer (min, max) {
  if (max == null) {
    max = min;
    min = 0;
  }
  let a, b, d;
  const dist = {
    min(_) {
      if (arguments.length) {
        a = _ || 0;
        d = b - a;
        return dist;
      } else {
        return a;
      }
    },
    max(_) {
      if (arguments.length) {
        b = _ || 0;
        d = b - a;
        return dist;
      } else {
        return b;
      }
    },
    sample() {
      return a + Math.floor(d * vega_statistics_module_random());
    },
    pdf(x) {
      return x === Math.floor(x) && x >= a && x < b ? 1 / d : 0;
    },
    cdf(x) {
      const v = Math.floor(x);
      return v < a ? 0 : v >= b ? 1 : (v - a + 1) / d;
    },
    icdf(p) {
      return p >= 0 && p <= 1 ? a - 1 + Math.floor(p * d) : NaN;
    }
  };
  return dist.min(min).max(max);
}

const SQRT2PI = Math.sqrt(2 * Math.PI);
const SQRT2 = Math.SQRT2;

let nextSample = NaN;
function sampleNormal(mean, stdev) {
  mean = mean || 0;
  stdev = stdev == null ? 1 : stdev;
  let x = 0,
    y = 0,
    rds,
    c;
  if (nextSample === nextSample) {
    x = nextSample;
    nextSample = NaN;
  } else {
    do {
      x = vega_statistics_module_random() * 2 - 1;
      y = vega_statistics_module_random() * 2 - 1;
      rds = x * x + y * y;
    } while (rds === 0 || rds > 1);
    c = Math.sqrt(-2 * Math.log(rds) / rds); // Box-Muller transform
    x *= c;
    nextSample = y * c;
  }
  return mean + x * stdev;
}
function densityNormal(value, mean, stdev) {
  stdev = stdev == null ? 1 : stdev;
  const z = (value - (mean || 0)) / stdev;
  return Math.exp(-0.5 * z * z) / (stdev * SQRT2PI);
}

// Approximation from West (2009)
// Better Approximations to Cumulative Normal Functions
function cumulativeNormal(value, mean, stdev) {
  mean = mean || 0;
  stdev = stdev == null ? 1 : stdev;
  const z = (value - mean) / stdev,
    Z = Math.abs(z);
  let cd;
  if (Z > 37) {
    cd = 0;
  } else {
    const exp = Math.exp(-Z * Z / 2);
    let sum;
    if (Z < 7.07106781186547) {
      sum = 3.52624965998911e-02 * Z + 0.700383064443688;
      sum = sum * Z + 6.37396220353165;
      sum = sum * Z + 33.912866078383;
      sum = sum * Z + 112.079291497871;
      sum = sum * Z + 221.213596169931;
      sum = sum * Z + 220.206867912376;
      cd = exp * sum;
      sum = 8.83883476483184e-02 * Z + 1.75566716318264;
      sum = sum * Z + 16.064177579207;
      sum = sum * Z + 86.7807322029461;
      sum = sum * Z + 296.564248779674;
      sum = sum * Z + 637.333633378831;
      sum = sum * Z + 793.826512519948;
      sum = sum * Z + 440.413735824752;
      cd = cd / sum;
    } else {
      sum = Z + 0.65;
      sum = Z + 4 / sum;
      sum = Z + 3 / sum;
      sum = Z + 2 / sum;
      sum = Z + 1 / sum;
      cd = exp / sum / 2.506628274631;
    }
  }
  return z > 0 ? 1 - cd : cd;
}

// Approximation of Probit function using inverse error function.
function quantileNormal(p, mean, stdev) {
  if (p < 0 || p > 1) return NaN;
  return (mean || 0) + (stdev == null ? 1 : stdev) * SQRT2 * erfinv(2 * p - 1);
}

// Approximate inverse error function. Implementation from "Approximating
// the erfinv function" by Mike Giles, GPU Computing Gems, volume 2, 2010.
// Ported from Apache Commons Math, http://www.apache.org/licenses/LICENSE-2.0
function erfinv(x) {
  // beware that the logarithm argument must be
  // commputed as (1.0 - x) * (1.0 + x),
  // it must NOT be simplified as 1.0 - x * x as this
  // would induce rounding errors near the boundaries +/-1
  let w = -Math.log((1 - x) * (1 + x)),
    p;
  if (w < 6.25) {
    w -= 3.125;
    p = -3.6444120640178196996e-21;
    p = -1.685059138182016589e-19 + p * w;
    p = 1.2858480715256400167e-18 + p * w;
    p = 1.115787767802518096e-17 + p * w;
    p = -1.333171662854620906e-16 + p * w;
    p = 2.0972767875968561637e-17 + p * w;
    p = 6.6376381343583238325e-15 + p * w;
    p = -4.0545662729752068639e-14 + p * w;
    p = -8.1519341976054721522e-14 + p * w;
    p = 2.6335093153082322977e-12 + p * w;
    p = -1.2975133253453532498e-11 + p * w;
    p = -5.4154120542946279317e-11 + p * w;
    p = 1.051212273321532285e-09 + p * w;
    p = -4.1126339803469836976e-09 + p * w;
    p = -2.9070369957882005086e-08 + p * w;
    p = 4.2347877827932403518e-07 + p * w;
    p = -1.3654692000834678645e-06 + p * w;
    p = -1.3882523362786468719e-05 + p * w;
    p = 0.0001867342080340571352 + p * w;
    p = -0.00074070253416626697512 + p * w;
    p = -0.0060336708714301490533 + p * w;
    p = 0.24015818242558961693 + p * w;
    p = 1.6536545626831027356 + p * w;
  } else if (w < 16.0) {
    w = Math.sqrt(w) - 3.25;
    p = 2.2137376921775787049e-09;
    p = 9.0756561938885390979e-08 + p * w;
    p = -2.7517406297064545428e-07 + p * w;
    p = 1.8239629214389227755e-08 + p * w;
    p = 1.5027403968909827627e-06 + p * w;
    p = -4.013867526981545969e-06 + p * w;
    p = 2.9234449089955446044e-06 + p * w;
    p = 1.2475304481671778723e-05 + p * w;
    p = -4.7318229009055733981e-05 + p * w;
    p = 6.8284851459573175448e-05 + p * w;
    p = 2.4031110387097893999e-05 + p * w;
    p = -0.0003550375203628474796 + p * w;
    p = 0.00095328937973738049703 + p * w;
    p = -0.0016882755560235047313 + p * w;
    p = 0.0024914420961078508066 + p * w;
    p = -0.0037512085075692412107 + p * w;
    p = 0.005370914553590063617 + p * w;
    p = 1.0052589676941592334 + p * w;
    p = 3.0838856104922207635 + p * w;
  } else if (Number.isFinite(w)) {
    w = Math.sqrt(w) - 5.0;
    p = -2.7109920616438573243e-11;
    p = -2.5556418169965252055e-10 + p * w;
    p = 1.5076572693500548083e-09 + p * w;
    p = -3.7894654401267369937e-09 + p * w;
    p = 7.6157012080783393804e-09 + p * w;
    p = -1.4960026627149240478e-08 + p * w;
    p = 2.9147953450901080826e-08 + p * w;
    p = -6.7711997758452339498e-08 + p * w;
    p = 2.2900482228026654717e-07 + p * w;
    p = -9.9298272942317002539e-07 + p * w;
    p = 4.5260625972231537039e-06 + p * w;
    p = -1.9681778105531670567e-05 + p * w;
    p = 7.5995277030017761139e-05 + p * w;
    p = -0.00021503011930044477347 + p * w;
    p = -0.00013871931833623122026 + p * w;
    p = 1.0103004648645343977 + p * w;
    p = 4.8499064014085844221 + p * w;
  } else {
    p = Infinity;
  }
  return p * x;
}
function gaussian (mean, stdev) {
  let mu, sigma;
  const dist = {
    mean(_) {
      if (arguments.length) {
        mu = _ || 0;
        return dist;
      } else {
        return mu;
      }
    },
    stdev(_) {
      if (arguments.length) {
        sigma = _ == null ? 1 : _;
        return dist;
      } else {
        return sigma;
      }
    },
    sample: () => sampleNormal(mu, sigma),
    pdf: value => densityNormal(value, mu, sigma),
    cdf: value => cumulativeNormal(value, mu, sigma),
    icdf: p => quantileNormal(p, mu, sigma)
  };
  return dist.mean(mean).stdev(stdev);
}

function kde (support, bandwidth) {
  const kernel = gaussian();
  let n = 0;
  const dist = {
    data(_) {
      if (arguments.length) {
        support = _;
        n = _ ? _.length : 0;
        return dist.bandwidth(bandwidth);
      } else {
        return support;
      }
    },
    bandwidth(_) {
      if (!arguments.length) return bandwidth;
      bandwidth = _;
      if (!bandwidth && support) bandwidth = estimateBandwidth(support);
      return dist;
    },
    sample() {
      return support[~~(vega_statistics_module_random() * n)] + bandwidth * kernel.sample();
    },
    pdf(x) {
      let y = 0,
        i = 0;
      for (; i < n; ++i) {
        y += kernel.pdf((x - support[i]) / bandwidth);
      }
      return y / bandwidth / n;
    },
    cdf(x) {
      let y = 0,
        i = 0;
      for (; i < n; ++i) {
        y += kernel.cdf((x - support[i]) / bandwidth);
      }
      return y / n;
    },
    icdf() {
      throw Error('KDE icdf not supported.');
    }
  };
  return dist.data(support);
}

function sampleLogNormal(mean, stdev) {
  mean = mean || 0;
  stdev = stdev == null ? 1 : stdev;
  return Math.exp(mean + sampleNormal() * stdev);
}
function densityLogNormal(value, mean, stdev) {
  if (value <= 0) return 0;
  mean = mean || 0;
  stdev = stdev == null ? 1 : stdev;
  const z = (Math.log(value) - mean) / stdev;
  return Math.exp(-0.5 * z * z) / (stdev * SQRT2PI * value);
}
function cumulativeLogNormal(value, mean, stdev) {
  return cumulativeNormal(Math.log(value), mean, stdev);
}
function quantileLogNormal(p, mean, stdev) {
  return Math.exp(quantileNormal(p, mean, stdev));
}
function lognormal (mean, stdev) {
  let mu, sigma;
  const dist = {
    mean(_) {
      if (arguments.length) {
        mu = _ || 0;
        return dist;
      } else {
        return mu;
      }
    },
    stdev(_) {
      if (arguments.length) {
        sigma = _ == null ? 1 : _;
        return dist;
      } else {
        return sigma;
      }
    },
    sample: () => sampleLogNormal(mu, sigma),
    pdf: value => densityLogNormal(value, mu, sigma),
    cdf: value => cumulativeLogNormal(value, mu, sigma),
    icdf: p => quantileLogNormal(p, mu, sigma)
  };
  return dist.mean(mean).stdev(stdev);
}

function mixture (dists, weights) {
  let m = 0,
    w;
  function normalize(x) {
    const w = [];
    let sum = 0,
      i;
    for (i = 0; i < m; ++i) {
      sum += w[i] = x[i] == null ? 1 : +x[i];
    }
    for (i = 0; i < m; ++i) {
      w[i] /= sum;
    }
    return w;
  }
  const dist = {
    weights(_) {
      if (arguments.length) {
        w = normalize(weights = _ || []);
        return dist;
      }
      return weights;
    },
    distributions(_) {
      if (arguments.length) {
        if (_) {
          m = _.length;
          dists = _;
        } else {
          m = 0;
          dists = [];
        }
        return dist.weights(weights);
      }
      return dists;
    },
    sample() {
      const r = vega_statistics_module_random();
      let d = dists[m - 1],
        v = w[0],
        i = 0;

      // first select distribution
      for (; i < m - 1; v += w[++i]) {
        if (r < v) {
          d = dists[i];
          break;
        }
      }
      // then sample from it
      return d.sample();
    },
    pdf(x) {
      let p = 0,
        i = 0;
      for (; i < m; ++i) {
        p += w[i] * dists[i].pdf(x);
      }
      return p;
    },
    cdf(x) {
      let p = 0,
        i = 0;
      for (; i < m; ++i) {
        p += w[i] * dists[i].cdf(x);
      }
      return p;
    },
    icdf() {
      throw Error('Mixture icdf not supported.');
    }
  };
  return dist.distributions(dists).weights(weights);
}

function sampleUniform(min, max) {
  if (max == null) {
    max = min == null ? 1 : min;
    min = 0;
  }
  return min + (max - min) * vega_statistics_module_random();
}
function densityUniform(value, min, max) {
  if (max == null) {
    max = min == null ? 1 : min;
    min = 0;
  }
  return value >= min && value <= max ? 1 / (max - min) : 0;
}
function cumulativeUniform(value, min, max) {
  if (max == null) {
    max = min == null ? 1 : min;
    min = 0;
  }
  return value < min ? 0 : value > max ? 1 : (value - min) / (max - min);
}
function quantileUniform(p, min, max) {
  if (max == null) {
    max = min == null ? 1 : min;
    min = 0;
  }
  return p >= 0 && p <= 1 ? min + p * (max - min) : NaN;
}
function uniform (min, max) {
  let a, b;
  const dist = {
    min(_) {
      if (arguments.length) {
        a = _ || 0;
        return dist;
      } else {
        return a;
      }
    },
    max(_) {
      if (arguments.length) {
        b = _ == null ? 1 : _;
        return dist;
      } else {
        return b;
      }
    },
    sample: () => sampleUniform(a, b),
    pdf: value => densityUniform(value, a, b),
    cdf: value => cumulativeUniform(value, a, b),
    icdf: p => quantileUniform(p, a, b)
  };
  if (max == null) {
    max = min == null ? 1 : min;
    min = 0;
  }
  return dist.min(min).max(max);
}

function vega_statistics_module_constant (data, x, y) {
  let mean = 0,
    n = 0;
  for (const d of data) {
    const val = y(d);
    if (x(d) == null || val == null || isNaN(val)) continue;
    mean += (val - mean) / ++n;
  }
  return {
    coef: [mean],
    predict: () => mean,
    rSquared: 0
  };
}

// Ordinary Least Squares
function ols (uX, uY, uXY, uX2) {
  const delta = uX2 - uX * uX,
    slope = Math.abs(delta) < 1e-24 ? 0 : (uXY - uX * uY) / delta,
    intercept = uY - slope * uX;
  return [intercept, slope];
}

function points(data, x, y, sort) {
  data = data.filter(d => {
    let u = x(d),
      v = y(d);
    return u != null && (u = +u) >= u && v != null && (v = +v) >= v;
  });
  if (sort) {
    data.sort((a, b) => x(a) - x(b));
  }
  const n = data.length,
    X = new Float64Array(n),
    Y = new Float64Array(n);

  // extract values, calculate means
  let i = 0,
    ux = 0,
    uy = 0,
    xv,
    yv,
    d;
  for (d of data) {
    X[i] = xv = +x(d);
    Y[i] = yv = +y(d);
    ++i;
    ux += (xv - ux) / i;
    uy += (yv - uy) / i;
  }

  // mean center the data
  for (i = 0; i < n; ++i) {
    X[i] -= ux;
    Y[i] -= uy;
  }
  return [X, Y, ux, uy];
}
function visitPoints(data, x, y, callback) {
  let i = -1,
    u,
    v;
  for (const d of data) {
    u = x(d);
    v = y(d);
    if (u != null && (u = +u) >= u && v != null && (v = +v) >= v) {
      callback(u, v, ++i);
    }
  }
}

// Adapted from d3-regression by Harry Stevens
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE
function rSquared (data, x, y, uY, predict) {
  let SSE = 0,
    SST = 0;
  visitPoints(data, x, y, (dx, dy) => {
    const sse = dy - predict(dx),
      sst = dy - uY;
    SSE += sse * sse;
    SST += sst * sst;
  });
  return 1 - SSE / SST;
}

// Adapted from d3-regression by Harry Stevens
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE
function vega_statistics_module_linear (data, x, y) {
  let X = 0,
    Y = 0,
    XY = 0,
    X2 = 0,
    n = 0;
  visitPoints(data, x, y, (dx, dy) => {
    ++n;
    X += (dx - X) / n;
    Y += (dy - Y) / n;
    XY += (dx * dy - XY) / n;
    X2 += (dx * dx - X2) / n;
  });
  const coef = ols(X, Y, XY, X2),
    predict = x => coef[0] + coef[1] * x;
  return {
    coef: coef,
    predict: predict,
    rSquared: rSquared(data, x, y, Y, predict)
  };
}

// Adapted from d3-regression by Harry Stevens
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE
function vega_statistics_module_log (data, x, y) {
  let X = 0,
    Y = 0,
    XY = 0,
    X2 = 0,
    n = 0;
  visitPoints(data, x, y, (dx, dy) => {
    ++n;
    dx = Math.log(dx);
    X += (dx - X) / n;
    Y += (dy - Y) / n;
    XY += (dx * dy - XY) / n;
    X2 += (dx * dx - X2) / n;
  });
  const coef = ols(X, Y, XY, X2),
    predict = x => coef[0] + coef[1] * Math.log(x);
  return {
    coef: coef,
    predict: predict,
    rSquared: rSquared(data, x, y, Y, predict)
  };
}

function vega_statistics_module_exp (data, x, y) {
  // eslint-disable-next-line no-unused-vars
  const [xv, yv, ux, uy] = points(data, x, y);
  let YL = 0,
    XY = 0,
    XYL = 0,
    X2Y = 0,
    n = 0,
    dx,
    ly,
    xy;
  visitPoints(data, x, y, (_, dy) => {
    dx = xv[n++];
    ly = Math.log(dy);
    xy = dx * dy;
    YL += (dy * ly - YL) / n;
    XY += (xy - XY) / n;
    XYL += (xy * ly - XYL) / n;
    X2Y += (dx * xy - X2Y) / n;
  });
  const [c0, c1] = ols(XY / uy, YL / uy, XYL / uy, X2Y / uy),
    predict = x => Math.exp(c0 + c1 * (x - ux));
  return {
    coef: [Math.exp(c0 - c1 * ux), c1],
    predict: predict,
    rSquared: rSquared(data, x, y, uy, predict)
  };
}

// Adapted from d3-regression by Harry Stevens
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE
function vega_statistics_module_pow (data, x, y) {
  let X = 0,
    Y = 0,
    XY = 0,
    X2 = 0,
    YS = 0,
    n = 0;
  visitPoints(data, x, y, (dx, dy) => {
    const lx = Math.log(dx),
      ly = Math.log(dy);
    ++n;
    X += (lx - X) / n;
    Y += (ly - Y) / n;
    XY += (lx * ly - XY) / n;
    X2 += (lx * lx - X2) / n;
    YS += (dy - YS) / n;
  });
  const coef = ols(X, Y, XY, X2),
    predict = x => coef[0] * Math.pow(x, coef[1]);
  coef[0] = Math.exp(coef[0]);
  return {
    coef: coef,
    predict: predict,
    rSquared: rSquared(data, x, y, YS, predict)
  };
}

function quad (data, x, y) {
  const [xv, yv, ux, uy] = points(data, x, y),
    n = xv.length;
  let X2 = 0,
    X3 = 0,
    X4 = 0,
    XY = 0,
    X2Y = 0,
    i,
    dx,
    dy,
    x2;
  for (i = 0; i < n;) {
    dx = xv[i];
    dy = yv[i++];
    x2 = dx * dx;
    X2 += (x2 - X2) / i;
    X3 += (x2 * dx - X3) / i;
    X4 += (x2 * x2 - X4) / i;
    XY += (dx * dy - XY) / i;
    X2Y += (x2 * dy - X2Y) / i;
  }
  const X2X2 = X4 - X2 * X2,
    d = X2 * X2X2 - X3 * X3,
    a = (X2Y * X2 - XY * X3) / d,
    b = (XY * X2X2 - X2Y * X3) / d,
    c = -a * X2,
    predict = x => {
      x = x - ux;
      return a * x * x + b * x + c + uy;
    };

  // transform coefficients back from mean-centered space
  return {
    coef: [c - b * ux + a * ux * ux + uy, b - 2 * a * ux, a],
    predict: predict,
    rSquared: rSquared(data, x, y, uy, predict)
  };
}

// Adapted from d3-regression by Harry Stevens
// License: https://github.com/HarryStevens/d3-regression/blob/master/LICENSE
// ... which was adapted from regression-js by Tom Alexander
// Source: https://github.com/Tom-Alexander/regression-js/blob/master/src/regression.js#L246
// License: https://github.com/Tom-Alexander/regression-js/blob/master/LICENSE
function poly (data, x, y, order) {
  // use more efficient methods for lower orders
  if (order === 0) return vega_statistics_module_constant(data, x, y);
  if (order === 1) return vega_statistics_module_linear(data, x, y);
  if (order === 2) return quad(data, x, y);
  const [xv, yv, ux, uy] = points(data, x, y),
    n = xv.length,
    lhs = [],
    rhs = [],
    k = order + 1;
  let i, j, l, v, c;
  for (i = 0; i < k; ++i) {
    for (l = 0, v = 0; l < n; ++l) {
      v += Math.pow(xv[l], i) * yv[l];
    }
    lhs.push(v);
    c = new Float64Array(k);
    for (j = 0; j < k; ++j) {
      for (l = 0, v = 0; l < n; ++l) {
        v += Math.pow(xv[l], i + j);
      }
      c[j] = v;
    }
    rhs.push(c);
  }
  rhs.push(lhs);
  const coef = gaussianElimination(rhs),
    predict = x => {
      x -= ux;
      let y = uy + coef[0] + coef[1] * x + coef[2] * x * x;
      for (i = 3; i < k; ++i) y += coef[i] * Math.pow(x, i);
      return y;
    };
  return {
    coef: uncenter(k, coef, -ux, uy),
    predict: predict,
    rSquared: rSquared(data, x, y, uy, predict)
  };
}
function uncenter(k, a, x, y) {
  const z = Array(k);
  let i, j, v, c;

  // initialize to zero
  for (i = 0; i < k; ++i) z[i] = 0;

  // polynomial expansion
  for (i = k - 1; i >= 0; --i) {
    v = a[i];
    c = 1;
    z[i] += v;
    for (j = 1; j <= i; ++j) {
      c *= (i + 1 - j) / j; // binomial coefficent
      z[i - j] += v * Math.pow(x, j) * c;
    }
  }

  // bias term
  z[0] += y;
  return z;
}

// Given an array for a two-dimensional matrix and the polynomial order,
// solve A * x = b using Gaussian elimination.
function gaussianElimination(matrix) {
  const n = matrix.length - 1,
    coef = [];
  let i, j, k, r, t;
  for (i = 0; i < n; ++i) {
    r = i; // max row
    for (j = i + 1; j < n; ++j) {
      if (Math.abs(matrix[i][j]) > Math.abs(matrix[i][r])) {
        r = j;
      }
    }
    for (k = i; k < n + 1; ++k) {
      t = matrix[k][i];
      matrix[k][i] = matrix[k][r];
      matrix[k][r] = t;
    }
    for (j = i + 1; j < n; ++j) {
      for (k = n; k >= i; k--) {
        matrix[k][j] -= matrix[k][i] * matrix[i][j] / matrix[i][i];
      }
    }
  }
  for (j = n - 1; j >= 0; --j) {
    t = 0;
    for (k = j + 1; k < n; ++k) {
      t += matrix[k][j] * coef[k];
    }
    coef[j] = (matrix[n][j] - t) / matrix[j][j];
  }
  return coef;
}

const maxiters = 2,
  epsilon = 1e-12;

// Adapted from science.js by Jason Davies
// Source: https://github.com/jasondavies/science.js/blob/master/src/stats/loess.js
// License: https://github.com/jasondavies/science.js/blob/master/LICENSE
function loess (data, x, y, bandwidth) {
  const [xv, yv, ux, uy] = points(data, x, y, true),
    n = xv.length,
    bw = Math.max(2, ~~(bandwidth * n)),
    // # nearest neighbors
    yhat = new Float64Array(n),
    residuals = new Float64Array(n),
    robustWeights = new Float64Array(n).fill(1);
  for (let iter = -1; ++iter <= maxiters;) {
    const interval = [0, bw - 1];
    for (let i = 0; i < n; ++i) {
      const dx = xv[i],
        i0 = interval[0],
        i1 = interval[1],
        edge = dx - xv[i0] > xv[i1] - dx ? i0 : i1;
      let W = 0,
        X = 0,
        Y = 0,
        XY = 0,
        X2 = 0;
      const denom = 1 / Math.abs(xv[edge] - dx || 1); // avoid singularity!

      for (let k = i0; k <= i1; ++k) {
        const xk = xv[k],
          yk = yv[k],
          w = tricube(Math.abs(dx - xk) * denom) * robustWeights[k],
          xkw = xk * w;
        W += w;
        X += xkw;
        Y += yk * w;
        XY += yk * xkw;
        X2 += xk * xkw;
      }

      // linear regression fit
      const [a, b] = ols(X / W, Y / W, XY / W, X2 / W);
      yhat[i] = a + b * dx;
      residuals[i] = Math.abs(yv[i] - yhat[i]);
      updateInterval(xv, i + 1, interval);
    }
    if (iter === maxiters) {
      break;
    }
    const medianResidual = median(residuals);
    if (Math.abs(medianResidual) < epsilon) break;
    for (let i = 0, arg, w; i < n; ++i) {
      arg = residuals[i] / (6 * medianResidual);
      // default to epsilon (rather than zero) for large deviations
      // keeping weights tiny but non-zero prevents singularites
      robustWeights[i] = arg >= 1 ? epsilon : (w = 1 - arg * arg) * w;
    }
  }
  return vega_statistics_module_output(xv, yhat, ux, uy);
}

// weighting kernel for local regression
function tricube(x) {
  return (x = 1 - x * x * x) * x * x;
}

// advance sliding window interval of nearest neighbors
function updateInterval(xv, i, interval) {
  const val = xv[i];
  let left = interval[0],
    right = interval[1] + 1;
  if (right >= xv.length) return;

  // step right if distance to new right edge is <= distance to old left edge
  // step when distance is equal to ensure movement over duplicate x values
  while (i > left && xv[right] - val <= val - xv[left]) {
    interval[0] = ++left;
    interval[1] = right;
    ++right;
  }
}

// generate smoothed output points
// average points with repeated x values
function vega_statistics_module_output(xv, yhat, ux, uy) {
  const n = xv.length,
    out = [];
  let i = 0,
    cnt = 0,
    prev = [],
    v;
  for (; i < n; ++i) {
    v = xv[i] + ux;
    if (prev[0] === v) {
      // average output values via online update
      prev[1] += (yhat[i] - prev[1]) / ++cnt;
    } else {
      // add new output point
      cnt = 0;
      prev[1] += uy;
      prev = [v, yhat[i]];
      out.push(prev);
    }
  }
  prev[1] += uy;
  return out;
}

// subdivide up to accuracy of 0.5 degrees
const MIN_RADIANS = 0.5 * Math.PI / 180;

// Adaptively sample an interpolated function over a domain extent
function sampleCurve (f, extent, minSteps, maxSteps) {
  minSteps = minSteps || 25;
  maxSteps = Math.max(minSteps, maxSteps || 200);
  const point = x => [x, f(x)],
    minX = extent[0],
    maxX = extent[1],
    span = maxX - minX,
    stop = span / maxSteps,
    prev = [point(minX)],
    next = [];
  if (minSteps === maxSteps) {
    // no adaptation, sample uniform grid directly and return
    for (let i = 1; i < maxSteps; ++i) {
      prev.push(point(minX + i / minSteps * span));
    }
    prev.push(point(maxX));
    return prev;
  } else {
    // sample minimum points on uniform grid
    // then move on to perform adaptive refinement
    next.push(point(maxX));
    for (let i = minSteps; --i > 0;) {
      next.push(point(minX + i / minSteps * span));
    }
  }
  let p0 = prev[0];
  let p1 = next[next.length - 1];
  const sx = 1 / span;
  const sy = scaleY(p0[1], next);
  while (p1) {
    // midpoint for potential curve subdivision
    const pm = point((p0[0] + p1[0]) / 2);
    const dx = pm[0] - p0[0] >= stop;
    if (dx && angleDelta(p0, pm, p1, sx, sy) > MIN_RADIANS) {
      // maximum resolution has not yet been met, and
      // subdivision midpoint is sufficiently different from endpoint
      // save subdivision, push midpoint onto the visitation stack
      next.push(pm);
    } else {
      // subdivision midpoint sufficiently similar to endpoint
      // skip subdivision, store endpoint, move to next point on the stack
      p0 = p1;
      prev.push(p1);
      next.pop();
    }
    p1 = next[next.length - 1];
  }
  return prev;
}
function scaleY(init, points) {
  let ymin = init;
  let ymax = init;
  const n = points.length;
  for (let i = 0; i < n; ++i) {
    const y = points[i][1];
    if (y < ymin) ymin = y;
    if (y > ymax) ymax = y;
  }
  return 1 / (ymax - ymin);
}
function angleDelta(p, q, r, sx, sy) {
  const a0 = Math.atan2(sy * (r[1] - p[1]), sx * (r[0] - p[0])),
    a1 = Math.atan2(sy * (q[1] - p[1]), sx * (q[0] - p[0]));
  return Math.abs(a0 - a1);
}



;// ../../node_modules/d3-array/src/mean.js
function mean(values, valueof) {
  let count = 0;
  let sum = 0;
  if (valueof === undefined) {
    for (let value of values) {
      if (value != null && (value = +value) >= value) {
        ++count, sum += value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
        ++count, sum += value;
      }
    }
  }
  if (count) return sum / count;
}

;// ../../node_modules/d3-array/src/range.js
function range_range(start, stop, step) {
  start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;

  var i = -1,
      n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
      range = new Array(n);

  while (++i < n) {
    range[i] = start + i * step;
  }

  return range;
}

;// ../../node_modules/vega-transforms/build/vega-transforms.module.js






function multikey(f) {
  return x => {
    const n = f.length;
    let i = 1,
      k = String(f[0](x));
    for (; i < n; ++i) {
      k += '|' + f[i](x);
    }
    return k;
  };
}
function groupkey(fields) {
  return !fields || !fields.length ? function () {
    return '';
  } : fields.length === 1 ? fields[0] : multikey(fields);
}

function measureName(op, field, as) {
  return as || op + (!field ? '' : '_' + field);
}
const vega_transforms_module_noop = () => {};
const base_op = {
  init: vega_transforms_module_noop,
  add: vega_transforms_module_noop,
  rem: vega_transforms_module_noop,
  idx: 0
};
const AggregateOps = {
  values: {
    init: m => m.cell.store = true,
    value: m => m.cell.data.values(),
    idx: -1
  },
  count: {
    value: m => m.cell.num
  },
  __count__: {
    value: m => m.missing + m.valid
  },
  missing: {
    value: m => m.missing
  },
  valid: {
    value: m => m.valid
  },
  sum: {
    init: m => m.sum = 0,
    value: m => m.valid ? m.sum : undefined,
    add: (m, v) => m.sum += +v,
    rem: (m, v) => m.sum -= v
  },
  product: {
    init: m => m.product = 1,
    value: m => m.valid ? m.product : undefined,
    add: (m, v) => m.product *= v,
    rem: (m, v) => m.product /= v
  },
  mean: {
    init: m => m.mean = 0,
    value: m => m.valid ? m.mean : undefined,
    add: (m, v) => (m.mean_d = v - m.mean, m.mean += m.mean_d / m.valid),
    rem: (m, v) => (m.mean_d = v - m.mean, m.mean -= m.valid ? m.mean_d / m.valid : m.mean)
  },
  average: {
    value: m => m.valid ? m.mean : undefined,
    req: ['mean'],
    idx: 1
  },
  variance: {
    init: m => m.dev = 0,
    value: m => m.valid > 1 ? m.dev / (m.valid - 1) : undefined,
    add: (m, v) => m.dev += m.mean_d * (v - m.mean),
    rem: (m, v) => m.dev -= m.mean_d * (v - m.mean),
    req: ['mean'],
    idx: 1
  },
  variancep: {
    value: m => m.valid > 1 ? m.dev / m.valid : undefined,
    req: ['variance'],
    idx: 2
  },
  stdev: {
    value: m => m.valid > 1 ? Math.sqrt(m.dev / (m.valid - 1)) : undefined,
    req: ['variance'],
    idx: 2
  },
  stdevp: {
    value: m => m.valid > 1 ? Math.sqrt(m.dev / m.valid) : undefined,
    req: ['variance'],
    idx: 2
  },
  stderr: {
    value: m => m.valid > 1 ? Math.sqrt(m.dev / (m.valid * (m.valid - 1))) : undefined,
    req: ['variance'],
    idx: 2
  },
  distinct: {
    value: m => m.cell.data.distinct(m.get),
    req: ['values'],
    idx: 3
  },
  ci0: {
    value: m => m.cell.data.ci0(m.get),
    req: ['values'],
    idx: 3
  },
  ci1: {
    value: m => m.cell.data.ci1(m.get),
    req: ['values'],
    idx: 3
  },
  median: {
    value: m => m.cell.data.q2(m.get),
    req: ['values'],
    idx: 3
  },
  q1: {
    value: m => m.cell.data.q1(m.get),
    req: ['values'],
    idx: 3
  },
  q3: {
    value: m => m.cell.data.q3(m.get),
    req: ['values'],
    idx: 3
  },
  min: {
    init: m => m.min = undefined,
    value: m => m.min = Number.isNaN(m.min) ? m.cell.data.min(m.get) : m.min,
    add: (m, v) => {
      if (v < m.min || m.min === undefined) m.min = v;
    },
    rem: (m, v) => {
      if (v <= m.min) m.min = NaN;
    },
    req: ['values'],
    idx: 4
  },
  max: {
    init: m => m.max = undefined,
    value: m => m.max = Number.isNaN(m.max) ? m.cell.data.max(m.get) : m.max,
    add: (m, v) => {
      if (v > m.max || m.max === undefined) m.max = v;
    },
    rem: (m, v) => {
      if (v >= m.max) m.max = NaN;
    },
    req: ['values'],
    idx: 4
  },
  argmin: {
    init: m => m.argmin = undefined,
    value: m => m.argmin || m.cell.data.argmin(m.get),
    add: (m, v, t) => {
      if (v < m.min) m.argmin = t;
    },
    rem: (m, v) => {
      if (v <= m.min) m.argmin = undefined;
    },
    req: ['min', 'values'],
    idx: 3
  },
  argmax: {
    init: m => m.argmax = undefined,
    value: m => m.argmax || m.cell.data.argmax(m.get),
    add: (m, v, t) => {
      if (v > m.max) m.argmax = t;
    },
    rem: (m, v) => {
      if (v >= m.max) m.argmax = undefined;
    },
    req: ['max', 'values'],
    idx: 3
  },
  exponential: {
    init: (m, r) => {
      m.exp = 0;
      m.exp_r = r;
    },
    value: m => m.valid ? m.exp * (1 - m.exp_r) / (1 - m.exp_r ** m.valid) : undefined,
    add: (m, v) => m.exp = m.exp_r * m.exp + v,
    rem: (m, v) => m.exp = (m.exp - v / m.exp_r ** (m.valid - 1)) / m.exp_r
  },
  exponentialb: {
    value: m => m.valid ? m.exp * (1 - m.exp_r) : undefined,
    req: ['exponential'],
    idx: 1
  }
};
const ValidAggregateOps = Object.keys(AggregateOps).filter(d => d !== '__count__');
function measure(key, value) {
  return (out, aggregate_param) => extend({
    name: key,
    aggregate_param: aggregate_param,
    out: out || key
  }, base_op, value);
}
[...ValidAggregateOps, '__count__'].forEach(key => {
  AggregateOps[key] = measure(key, AggregateOps[key]);
});
function createMeasure(op, param, name) {
  return AggregateOps[op](name, param);
}
function compareIndex(a, b) {
  return a.idx - b.idx;
}
function vega_transforms_module_resolve(agg) {
  const map = {};
  agg.forEach(a => map[a.name] = a);
  const getreqs = a => {
    if (!a.req) return;
    a.req.forEach(key => {
      if (!map[key]) getreqs(map[key] = AggregateOps[key]());
    });
  };
  agg.forEach(getreqs);
  return Object.values(map).sort(compareIndex);
}
function vega_transforms_module_init() {
  this.valid = 0;
  this.missing = 0;
  this._ops.forEach(op => op.aggregate_param == null ? op.init(this) : op.init(this, op.aggregate_param));
}
function vega_transforms_module_add(v, t) {
  if (v == null || v === '') {
    ++this.missing;
    return;
  }
  if (v !== v) return;
  ++this.valid;
  this._ops.forEach(op => op.add(this, v, t));
}
function rem(v, t) {
  if (v == null || v === '') {
    --this.missing;
    return;
  }
  if (v !== v) return;
  --this.valid;
  this._ops.forEach(op => op.rem(this, v, t));
}
function set(t) {
  this._out.forEach(op => t[op.out] = op.value(this));
  return t;
}
function compileMeasures(agg, field) {
  const get = field || vega_util_module_identity,
    ops = vega_transforms_module_resolve(agg),
    out = agg.slice().sort(compareIndex);
  function ctr(cell) {
    this._ops = ops;
    this._out = out;
    this.cell = cell;
    this.init();
  }
  ctr.prototype.init = vega_transforms_module_init;
  ctr.prototype.add = vega_transforms_module_add;
  ctr.prototype.rem = rem;
  ctr.prototype.set = set;
  ctr.prototype.get = get;
  ctr.fields = agg.map(op => op.out);
  return ctr;
}

function TupleStore(key) {
  this._key = key ? vega_util_module_field(key) : tupleid;
  this.reset();
}
const prototype$1 = TupleStore.prototype;
prototype$1.reset = function () {
  this._add = [];
  this._rem = [];
  this._ext = null;
  this._get = null;
  this._q = null;
};
prototype$1.add = function (v) {
  this._add.push(v);
};
prototype$1.rem = function (v) {
  this._rem.push(v);
};
prototype$1.values = function () {
  this._get = null;
  if (this._rem.length === 0) return this._add;
  const a = this._add,
    r = this._rem,
    k = this._key,
    n = a.length,
    m = r.length,
    x = Array(n - m),
    map = {};
  let i, j, v;

  // use unique key field to clear removed values
  for (i = 0; i < m; ++i) {
    map[k(r[i])] = 1;
  }
  for (i = 0, j = 0; i < n; ++i) {
    if (map[k(v = a[i])]) {
      map[k(v)] = 0;
    } else {
      x[j++] = v;
    }
  }
  this._rem = [];
  return this._add = x;
};

// memoizing statistics methods

prototype$1.distinct = function (get) {
  const v = this.values(),
    map = {};
  let n = v.length,
    count = 0,
    s;
  while (--n >= 0) {
    s = get(v[n]) + '';
    if (!vega_util_module_has(map, s)) {
      map[s] = 1;
      ++count;
    }
  }
  return count;
};
prototype$1.extent = function (get) {
  if (this._get !== get || !this._ext) {
    const v = this.values(),
      i = extentIndex(v, get);
    this._ext = [v[i[0]], v[i[1]]];
    this._get = get;
  }
  return this._ext;
};
prototype$1.argmin = function (get) {
  return this.extent(get)[0] || {};
};
prototype$1.argmax = function (get) {
  return this.extent(get)[1] || {};
};
prototype$1.min = function (get) {
  const m = this.extent(get)[0];
  return m != null ? get(m) : undefined;
};
prototype$1.max = function (get) {
  const m = this.extent(get)[1];
  return m != null ? get(m) : undefined;
};
prototype$1.quartile = function (get) {
  if (this._get !== get || !this._q) {
    this._q = quartiles(this.values(), get);
    this._get = get;
  }
  return this._q;
};
prototype$1.q1 = function (get) {
  return this.quartile(get)[0];
};
prototype$1.q2 = function (get) {
  return this.quartile(get)[1];
};
prototype$1.q3 = function (get) {
  return this.quartile(get)[2];
};
prototype$1.ci = function (get) {
  if (this._get !== get || !this._ci) {
    this._ci = bootstrapCI(this.values(), 1000, 0.05, get);
    this._get = get;
  }
  return this._ci;
};
prototype$1.ci0 = function (get) {
  return this.ci(get)[0];
};
prototype$1.ci1 = function (get) {
  return this.ci(get)[1];
};

/**
 * Group-by aggregation operator.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors to groupby.
 * @param {Array<function(object): *>} [params.fields] - An array of accessors to aggregate.
 * @param {Array<string>} [params.ops] - An array of strings indicating aggregation operations.
 * @param {Array<number>} [params.aggregate_params] - An optional array of parameters for aggregation operations.
 * @param {Array<string>} [params.as] - An array of output field names for aggregated values.
 * @param {boolean} [params.cross=false] - A flag indicating that the full
 *   cross-product of groupby values should be generated, including empty cells.
 *   If true, the drop parameter is ignored and empty cells are retained.
 * @param {boolean} [params.drop=true] - A flag indicating if empty cells should be removed.
 */
function Aggregate(params) {
  Transform.call(this, null, params);
  this._adds = []; // array of added output tuples
  this._mods = []; // array of modified output tuples
  this._alen = 0; // number of active added tuples
  this._mlen = 0; // number of active modified tuples
  this._drop = true; // should empty aggregation cells be removed
  this._cross = false; // produce full cross-product of group-by values

  this._dims = []; // group-by dimension accessors
  this._dnames = []; // group-by dimension names

  this._measures = []; // collection of aggregation monoids
  this._countOnly = false; // flag indicating only count aggregation
  this._counts = null; // collection of count fields
  this._prev = null; // previous aggregation cells

  this._inputs = null; // array of dependent input tuple field names
  this._outputs = null; // array of output tuple field names
}
Aggregate.Definition = {
  'type': 'Aggregate',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'ops',
    'type': 'enum',
    'array': true,
    'values': ValidAggregateOps
  }, {
    'name': 'aggregate_params',
    'type': 'number',
    'null': true,
    'array': true
  }, {
    'name': 'fields',
    'type': 'field',
    'null': true,
    'array': true
  }, {
    'name': 'as',
    'type': 'string',
    'null': true,
    'array': true
  }, {
    'name': 'drop',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'cross',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'key',
    'type': 'field'
  }]
};
inherits(Aggregate, Transform, {
  transform(_, pulse) {
    const aggr = this,
      out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      mod = _.modified();
    aggr.stamp = out.stamp;
    if (aggr.value && (mod || pulse.modified(aggr._inputs, true))) {
      aggr._prev = aggr.value;
      aggr.value = mod ? aggr.init(_) : Object.create(null);
      pulse.visit(pulse.SOURCE, t => aggr.add(t));
    } else {
      aggr.value = aggr.value || aggr.init(_);
      pulse.visit(pulse.REM, t => aggr.rem(t));
      pulse.visit(pulse.ADD, t => aggr.add(t));
    }

    // Indicate output fields and return aggregate tuples.
    out.modifies(aggr._outputs);

    // Should empty cells be dropped?
    aggr._drop = _.drop !== false;

    // If domain cross-product requested, generate empty cells as needed
    // and ensure that empty cells are not dropped
    if (_.cross && aggr._dims.length > 1) {
      aggr._drop = false;
      aggr.cross();
    }
    if (pulse.clean() && aggr._drop) {
      out.clean(true).runAfter(() => this.clean());
    }
    return aggr.changes(out);
  },
  cross() {
    const aggr = this,
      curr = aggr.value,
      dims = aggr._dnames,
      vals = dims.map(() => ({})),
      n = dims.length;

    // collect all group-by domain values
    function collect(cells) {
      let key, i, t, v;
      for (key in cells) {
        t = cells[key].tuple;
        for (i = 0; i < n; ++i) {
          vals[i][v = t[dims[i]]] = v;
        }
      }
    }
    collect(aggr._prev);
    collect(curr);

    // iterate over key cross-product, create cells as needed
    function generate(base, tuple, index) {
      const name = dims[index],
        v = vals[index++];
      for (const k in v) {
        const key = base ? base + '|' + k : k;
        tuple[name] = v[k];
        if (index < n) generate(key, tuple, index);else if (!curr[key]) aggr.cell(key, tuple);
      }
    }
    generate('', {}, 0);
  },
  init(_) {
    // initialize input and output fields
    const inputs = this._inputs = [],
      outputs = this._outputs = [],
      inputMap = {};
    function inputVisit(get) {
      const fields = vega_util_module_array(accessorFields(get)),
        n = fields.length;
      let i = 0,
        f;
      for (; i < n; ++i) {
        if (!inputMap[f = fields[i]]) {
          inputMap[f] = 1;
          inputs.push(f);
        }
      }
    }

    // initialize group-by dimensions
    this._dims = vega_util_module_array(_.groupby);
    this._dnames = this._dims.map(d => {
      const dname = accessorName(d);
      inputVisit(d);
      outputs.push(dname);
      return dname;
    });
    this.cellkey = _.key ? _.key : groupkey(this._dims);

    // initialize aggregate measures
    this._countOnly = true;
    this._counts = [];
    this._measures = [];
    const fields = _.fields || [null],
      ops = _.ops || ['count'],
      aggregate_params = _.aggregate_params || [null],
      as = _.as || [],
      n = fields.length,
      map = {};
    let field, op, aggregate_param, m, mname, outname, i;
    if (n !== ops.length) {
      vega_util_module_error('Unmatched number of fields and aggregate ops.');
    }
    for (i = 0; i < n; ++i) {
      field = fields[i];
      op = ops[i];
      aggregate_param = aggregate_params[i] || null;
      if (field == null && op !== 'count') {
        vega_util_module_error('Null aggregate field specified.');
      }
      mname = accessorName(field);
      outname = measureName(op, mname, as[i]);
      outputs.push(outname);
      if (op === 'count') {
        this._counts.push(outname);
        continue;
      }
      m = map[mname];
      if (!m) {
        inputVisit(field);
        m = map[mname] = [];
        m.field = field;
        this._measures.push(m);
      }
      if (op !== 'count') this._countOnly = false;
      m.push(createMeasure(op, aggregate_param, outname));
    }
    this._measures = this._measures.map(m => compileMeasures(m, m.field));
    return Object.create(null); // aggregation cells (this.value)
  },
  // -- Cell Management -----

  cellkey: groupkey(),
  cell(key, t) {
    let cell = this.value[key];
    if (!cell) {
      cell = this.value[key] = this.newcell(key, t);
      this._adds[this._alen++] = cell;
    } else if (cell.num === 0 && this._drop && cell.stamp < this.stamp) {
      cell.stamp = this.stamp;
      this._adds[this._alen++] = cell;
    } else if (cell.stamp < this.stamp) {
      cell.stamp = this.stamp;
      this._mods[this._mlen++] = cell;
    }
    return cell;
  },
  newcell(key, t) {
    const cell = {
      key: key,
      num: 0,
      agg: null,
      tuple: this.newtuple(t, this._prev && this._prev[key]),
      stamp: this.stamp,
      store: false
    };
    if (!this._countOnly) {
      const measures = this._measures,
        n = measures.length;
      cell.agg = Array(n);
      for (let i = 0; i < n; ++i) {
        cell.agg[i] = new measures[i](cell);
      }
    }
    if (cell.store) {
      cell.data = new TupleStore();
    }
    return cell;
  },
  newtuple(t, p) {
    const names = this._dnames,
      dims = this._dims,
      n = dims.length,
      x = {};
    for (let i = 0; i < n; ++i) {
      x[names[i]] = dims[i](t);
    }
    return p ? vega_dataflow_module_replace(p.tuple, x) : ingest$1(x);
  },
  clean() {
    const cells = this.value;
    for (const key in cells) {
      if (cells[key].num === 0) {
        delete cells[key];
      }
    }
  },
  // -- Process Tuples -----

  add(t) {
    const key = this.cellkey(t),
      cell = this.cell(key, t);
    cell.num += 1;
    if (this._countOnly) return;
    if (cell.store) cell.data.add(t);
    const agg = cell.agg;
    for (let i = 0, n = agg.length; i < n; ++i) {
      agg[i].add(agg[i].get(t), t);
    }
  },
  rem(t) {
    const key = this.cellkey(t),
      cell = this.cell(key, t);
    cell.num -= 1;
    if (this._countOnly) return;
    if (cell.store) cell.data.rem(t);
    const agg = cell.agg;
    for (let i = 0, n = agg.length; i < n; ++i) {
      agg[i].rem(agg[i].get(t), t);
    }
  },
  celltuple(cell) {
    const tuple = cell.tuple,
      counts = this._counts;

    // consolidate stored values
    if (cell.store) {
      cell.data.values();
    }

    // update tuple properties
    for (let i = 0, n = counts.length; i < n; ++i) {
      tuple[counts[i]] = cell.num;
    }
    if (!this._countOnly) {
      const agg = cell.agg;
      for (let i = 0, n = agg.length; i < n; ++i) {
        agg[i].set(tuple);
      }
    }
    return tuple;
  },
  changes(out) {
    const adds = this._adds,
      mods = this._mods,
      prev = this._prev,
      drop = this._drop,
      add = out.add,
      rem = out.rem,
      mod = out.mod;
    let cell, key, i, n;
    if (prev) for (key in prev) {
      cell = prev[key];
      if (!drop || cell.num) rem.push(cell.tuple);
    }
    for (i = 0, n = this._alen; i < n; ++i) {
      add.push(this.celltuple(adds[i]));
      adds[i] = null; // for garbage collection
    }
    for (i = 0, n = this._mlen; i < n; ++i) {
      cell = mods[i];
      (cell.num === 0 && drop ? rem : mod).push(this.celltuple(cell));
      mods[i] = null; // for garbage collection
    }
    this._alen = this._mlen = 0; // reset list of active cells
    this._prev = null;
    return out;
  }
});

// epsilon bias to offset floating point error (#1737)
const EPSILON$1 = 1e-14;

/**
 * Generates a binning function for discretizing data.
 * @constructor
 * @param {object} params - The parameters for this operator. The
 *   provided values should be valid options for the {@link bin} function.
 * @param {function(object): *} params.field - The data field to bin.
 */
function Bin(params) {
  Transform.call(this, null, params);
}
Bin.Definition = {
  'type': 'Bin',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'interval',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'anchor',
    'type': 'number'
  }, {
    'name': 'maxbins',
    'type': 'number',
    'default': 20
  }, {
    'name': 'base',
    'type': 'number',
    'default': 10
  }, {
    'name': 'divide',
    'type': 'number',
    'array': true,
    'default': [5, 2]
  }, {
    'name': 'extent',
    'type': 'number',
    'array': true,
    'length': 2,
    'required': true
  }, {
    'name': 'span',
    'type': 'number'
  }, {
    'name': 'step',
    'type': 'number'
  }, {
    'name': 'steps',
    'type': 'number',
    'array': true
  }, {
    'name': 'minstep',
    'type': 'number',
    'default': 0
  }, {
    'name': 'nice',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'name',
    'type': 'string'
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['bin0', 'bin1']
  }]
};
inherits(Bin, Transform, {
  transform(_, pulse) {
    const band = _.interval !== false,
      bins = this._bins(_),
      start = bins.start,
      step = bins.step,
      as = _.as || ['bin0', 'bin1'],
      b0 = as[0],
      b1 = as[1];
    let flag;
    if (_.modified()) {
      pulse = pulse.reflow(true);
      flag = pulse.SOURCE;
    } else {
      flag = pulse.modified(accessorFields(_.field)) ? pulse.ADD_MOD : pulse.ADD;
    }
    pulse.visit(flag, band ? t => {
      const v = bins(t);
      // minimum bin value (inclusive)
      t[b0] = v;
      // maximum bin value (exclusive)
      // use convoluted math for better floating point agreement
      // see https://github.com/vega/vega/issues/830
      // infinite values propagate through this formula! #2227
      t[b1] = v == null ? null : start + step * (1 + (v - start) / step);
    } : t => t[b0] = bins(t));
    return pulse.modifies(band ? as : b0);
  },
  _bins(_) {
    if (this.value && !_.modified()) {
      return this.value;
    }
    const field = _.field,
      bins = vega_statistics_module_bin(_),
      step = bins.step;
    let start = bins.start,
      stop = start + Math.ceil((bins.stop - start) / step) * step,
      a,
      d;
    if ((a = _.anchor) != null) {
      d = a - (start + step * Math.floor((a - start) / step));
      start += d;
      stop += d;
    }
    const f = function (t) {
      let v = vega_util_module_toNumber(field(t));
      return v == null ? null : v < start ? -Infinity : v > stop ? +Infinity : (v = Math.max(start, Math.min(v, stop - step)), start + step * Math.floor(EPSILON$1 + (v - start) / step));
    };
    f.start = start;
    f.stop = bins.stop;
    f.step = step;
    return this.value = accessor(f, accessorFields(field), _.name || 'bin_' + accessorName(field));
  }
});

function SortedList (idFunc, source, input) {
  const $ = idFunc;
  let data = source || [],
    add = input || [],
    rem = {},
    cnt = 0;
  return {
    add: t => add.push(t),
    remove: t => rem[$(t)] = ++cnt,
    size: () => data.length,
    data: (compare, resort) => {
      if (cnt) {
        data = data.filter(t => !rem[$(t)]);
        rem = {};
        cnt = 0;
      }
      if (resort && compare) {
        data.sort(compare);
      }
      if (add.length) {
        data = compare ? merge(compare, data, add.sort(compare)) : data.concat(add);
        add = [];
      }
      return data;
    }
  };
}

/**
 * Collects all data tuples that pass through this operator.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(*,*): number} [params.sort] - An optional
 *   comparator function for additionally sorting the collected tuples.
 */
function Collect(params) {
  Transform.call(this, [], params);
}
Collect.Definition = {
  'type': 'Collect',
  'metadata': {
    'source': true
  },
  'params': [{
    'name': 'sort',
    'type': 'compare'
  }]
};
inherits(Collect, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.ALL),
      list = SortedList(tupleid, this.value, out.materialize(out.ADD).add),
      sort = _.sort,
      mod = pulse.changed() || sort && (_.modified('sort') || pulse.modified(sort.fields));
    out.visit(out.REM, list.remove);
    this.modified(mod);
    this.value = out.source = list.data(stableCompare(sort), mod);

    // propagate tree root if defined
    if (pulse.source && pulse.source.root) {
      this.value.root = pulse.source.root;
    }
    return out;
  }
});

/**
 * Generates a comparator function.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<string|function>} params.fields - The fields to compare.
 * @param {Array<string>} [params.orders] - The sort orders.
 *   Each entry should be one of "ascending" (default) or "descending".
 */
function Compare(params) {
  Operator.call(this, null, update$5, params);
}
inherits(Compare, Operator);
function update$5(_) {
  return this.value && !_.modified() ? this.value : vega_util_module_compare(_.fields, _.orders);
}

/**
 * Count regexp-defined pattern occurrences in a text field.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - An accessor for the text field.
 * @param {string} [params.pattern] - RegExp string defining the text pattern.
 * @param {string} [params.case] - One of 'lower', 'upper' or null (mixed) case.
 * @param {string} [params.stopwords] - RegExp string of words to ignore.
 */
function CountPattern(params) {
  Transform.call(this, null, params);
}
CountPattern.Definition = {
  'type': 'CountPattern',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'case',
    'type': 'enum',
    'values': ['upper', 'lower', 'mixed'],
    'default': 'mixed'
  }, {
    'name': 'pattern',
    'type': 'string',
    'default': '[\\w"]+'
  }, {
    'name': 'stopwords',
    'type': 'string',
    'default': ''
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['text', 'count']
  }]
};
function tokenize(text, tcase, match) {
  switch (tcase) {
    case 'upper':
      text = text.toUpperCase();
      break;
    case 'lower':
      text = text.toLowerCase();
      break;
  }
  return text.match(match);
}
inherits(CountPattern, Transform, {
  transform(_, pulse) {
    const process = update => tuple => {
      var tokens = tokenize(get(tuple), _.case, match) || [],
        t;
      for (var i = 0, n = tokens.length; i < n; ++i) {
        if (!stop.test(t = tokens[i])) update(t);
      }
    };
    const init = this._parameterCheck(_, pulse),
      counts = this._counts,
      match = this._match,
      stop = this._stop,
      get = _.field,
      as = _.as || ['text', 'count'],
      add = process(t => counts[t] = 1 + (counts[t] || 0)),
      rem = process(t => counts[t] -= 1);
    if (init) {
      pulse.visit(pulse.SOURCE, add);
    } else {
      pulse.visit(pulse.ADD, add);
      pulse.visit(pulse.REM, rem);
    }
    return this._finish(pulse, as); // generate output tuples
  },
  _parameterCheck(_, pulse) {
    let init = false;
    if (_.modified('stopwords') || !this._stop) {
      this._stop = new RegExp('^' + (_.stopwords || '') + '$', 'i');
      init = true;
    }
    if (_.modified('pattern') || !this._match) {
      this._match = new RegExp(_.pattern || '[\\w\']+', 'g');
      init = true;
    }
    if (_.modified('field') || pulse.modified(_.field.fields)) {
      init = true;
    }
    if (init) this._counts = {};
    return init;
  },
  _finish(pulse, as) {
    const counts = this._counts,
      tuples = this._tuples || (this._tuples = {}),
      text = as[0],
      count = as[1],
      out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
    let w, t, c;
    for (w in counts) {
      t = tuples[w];
      c = counts[w] || 0;
      if (!t && c) {
        tuples[w] = t = ingest$1({});
        t[text] = w;
        t[count] = c;
        out.add.push(t);
      } else if (c === 0) {
        if (t) out.rem.push(t);
        counts[w] = null;
        tuples[w] = null;
      } else if (t[count] !== c) {
        t[count] = c;
        out.mod.push(t);
      }
    }
    return out.modifies(as);
  }
});

/**
 * Perform a cross-product of a tuple stream with itself.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object):boolean} [params.filter] - An optional filter
 *   function for selectively including tuples in the cross product.
 * @param {Array<string>} [params.as] - The names of the output fields.
 */
function Cross(params) {
  Transform.call(this, null, params);
}
Cross.Definition = {
  'type': 'Cross',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'filter',
    'type': 'expr'
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['a', 'b']
  }]
};
inherits(Cross, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE),
      as = _.as || ['a', 'b'],
      a = as[0],
      b = as[1],
      reset = !this.value || pulse.changed(pulse.ADD_REM) || _.modified('as') || _.modified('filter');
    let data = this.value;
    if (reset) {
      if (data) out.rem = data;
      data = pulse.materialize(pulse.SOURCE).source;
      out.add = this.value = vega_transforms_module_cross(data, a, b, _.filter || truthy);
    } else {
      out.mod = data;
    }
    out.source = this.value;
    return out.modifies(as);
  }
});
function vega_transforms_module_cross(input, a, b, filter) {
  var data = [],
    t = {},
    n = input.length,
    i = 0,
    j,
    left;
  for (; i < n; ++i) {
    t[a] = left = input[i];
    for (j = 0; j < n; ++j) {
      t[b] = input[j];
      if (filter(t)) {
        data.push(ingest$1(t));
        t = {};
        t[a] = left;
      }
    }
  }
  return data;
}

const Distributions = {
  kde: kde,
  mixture: mixture,
  normal: gaussian,
  lognormal: lognormal,
  uniform: uniform
};
const DISTRIBUTIONS = 'distributions',
  FUNCTION = 'function',
  FIELD = 'field';

/**
 * Parse a parameter object for a probability distribution.
 * @param {object} def - The distribution parameter object.
 * @param {function():Array<object>} - A method for requesting
 *   source data. Used for distributions (such as KDE) that
 *   require sample data points. This method will only be
 *   invoked if the 'from' parameter for a target data source
 *   is not provided. Typically this method returns backing
 *   source data for a Pulse object.
 * @return {object} - The output distribution object.
 */
function vega_transforms_module_parse(def, data) {
  const func = def[FUNCTION];
  if (!vega_util_module_has(Distributions, func)) {
    vega_util_module_error('Unknown distribution function: ' + func);
  }
  const d = Distributions[func]();
  for (const name in def) {
    // if data field, extract values
    if (name === FIELD) {
      d.data((def.from || data()).map(def[name]));
    }

    // if distribution mixture, recurse to parse each definition
    else if (name === DISTRIBUTIONS) {
      d[name](def[name].map(_ => vega_transforms_module_parse(_, data)));
    }

    // otherwise, simply set the parameter
    else if (typeof d[name] === FUNCTION) {
      d[name](def[name]);
    }
  }
  return d;
}

/**
 * Grid sample points for a probability density. Given a distribution and
 * a sampling extent, will generate points suitable for plotting either
 * PDF (probability density function) or CDF (cumulative distribution
 * function) curves.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {object} params.distribution - The probability distribution. This
 *   is an object parameter dependent on the distribution type.
 * @param {string} [params.method='pdf'] - The distribution method to sample.
 *   One of 'pdf' or 'cdf'.
 * @param {Array<number>} [params.extent] - The [min, max] extent over which
 *   to sample the distribution. This argument is required in most cases, but
 *   can be omitted if the distribution (e.g., 'kde') supports a 'data' method
 *   that returns numerical sample points from which the extent can be deduced.
 * @param {number} [params.minsteps=25] - The minimum number of curve samples
 *   for plotting the density.
 * @param {number} [params.maxsteps=200] - The maximum number of curve samples
 *   for plotting the density.
 * @param {number} [params.steps] - The exact number of curve samples for
 *   plotting the density. If specified, overrides both minsteps and maxsteps
 *   to set an exact number of uniform samples. Useful in conjunction with
 *   a fixed extent to ensure consistent sample points for stacked densities.
 */
function Density(params) {
  Transform.call(this, null, params);
}
const distributions = [{
  'key': {
    'function': 'normal'
  },
  'params': [{
    'name': 'mean',
    'type': 'number',
    'default': 0
  }, {
    'name': 'stdev',
    'type': 'number',
    'default': 1
  }]
}, {
  'key': {
    'function': 'lognormal'
  },
  'params': [{
    'name': 'mean',
    'type': 'number',
    'default': 0
  }, {
    'name': 'stdev',
    'type': 'number',
    'default': 1
  }]
}, {
  'key': {
    'function': 'uniform'
  },
  'params': [{
    'name': 'min',
    'type': 'number',
    'default': 0
  }, {
    'name': 'max',
    'type': 'number',
    'default': 1
  }]
}, {
  'key': {
    'function': 'kde'
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'from',
    'type': 'data'
  }, {
    'name': 'bandwidth',
    'type': 'number',
    'default': 0
  }]
}];
const vega_transforms_module_mixture = {
  'key': {
    'function': 'mixture'
  },
  'params': [{
    'name': 'distributions',
    'type': 'param',
    'array': true,
    'params': distributions
  }, {
    'name': 'weights',
    'type': 'number',
    'array': true
  }]
};
Density.Definition = {
  'type': 'Density',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'extent',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'steps',
    'type': 'number'
  }, {
    'name': 'minsteps',
    'type': 'number',
    'default': 25
  }, {
    'name': 'maxsteps',
    'type': 'number',
    'default': 200
  }, {
    'name': 'method',
    'type': 'string',
    'default': 'pdf',
    'values': ['pdf', 'cdf']
  }, {
    'name': 'distribution',
    'type': 'param',
    'params': distributions.concat(vega_transforms_module_mixture)
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'default': ['value', 'density']
  }]
};
inherits(Density, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
    if (!this.value || pulse.changed() || _.modified()) {
      const dist = vega_transforms_module_parse(_.distribution, vega_transforms_module_source(pulse)),
        minsteps = _.steps || _.minsteps || 25,
        maxsteps = _.steps || _.maxsteps || 200;
      let method = _.method || 'pdf';
      if (method !== 'pdf' && method !== 'cdf') {
        vega_util_module_error('Invalid density method: ' + method);
      }
      if (!_.extent && !dist.data) {
        vega_util_module_error('Missing density extent parameter.');
      }
      method = dist[method];
      const as = _.as || ['value', 'density'],
        domain = _.extent || extent(dist.data()),
        values = sampleCurve(method, domain, minsteps, maxsteps).map(v => {
          const tuple = {};
          tuple[as[0]] = v[0];
          tuple[as[1]] = v[1];
          return ingest$1(tuple);
        });
      if (this.value) out.rem = this.value;
      this.value = out.add = out.source = values;
    }
    return out;
  }
});
function vega_transforms_module_source(pulse) {
  return () => pulse.materialize(pulse.SOURCE).source;
}

// use either provided alias or accessor field name
function fieldNames(fields, as) {
  if (!fields) return null;
  return fields.map((f, i) => as[i] || accessorName(f));
}
function partition$1(data, groupby, field) {
  const groups = [],
    get = f => f(t);
  let map, i, n, t, k, g;

  // partition data points into groups
  if (groupby == null) {
    groups.push(data.map(field));
  } else {
    for (map = {}, i = 0, n = data.length; i < n; ++i) {
      t = data[i];
      k = groupby.map(get);
      g = map[k];
      if (!g) {
        map[k] = g = [];
        g.dims = k;
        groups.push(g);
      }
      g.push(field(t));
    }
  }
  return groups;
}

const Output = 'bin';

/**
 * Dot density binning for dot plot construction.
 * Based on Leland Wilkinson, Dot Plots, The American Statistician, 1999.
 * https://www.cs.uic.edu/~wilkinson/Publications/dotplots.pdf
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to bin.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors to groupby.
 * @param {number} [params.step] - The step size (bin width) within which dots should be
 *   stacked. Defaults to 1/30 of the extent of the data *field*.
 * @param {boolean} [params.smooth=false] - A boolean flag indicating if dot density
 *   stacks should be smoothed to reduce variance.
 */
function DotBin(params) {
  Transform.call(this, null, params);
}
DotBin.Definition = {
  'type': 'DotBin',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'step',
    'type': 'number'
  }, {
    'name': 'smooth',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'as',
    'type': 'string',
    'default': Output
  }]
};
const autostep = (data, field) => span(extent(data, field)) / 30;
inherits(DotBin, Transform, {
  transform(_, pulse) {
    if (this.value && !(_.modified() || pulse.changed())) {
      return pulse; // early exit
    }
    const source = pulse.materialize(pulse.SOURCE).source,
      groups = partition$1(pulse.source, _.groupby, vega_util_module_identity),
      smooth = _.smooth || false,
      field = _.field,
      step = _.step || autostep(source, field),
      sort = stableCompare((a, b) => field(a) - field(b)),
      as = _.as || Output,
      n = groups.length;

    // compute dotplot bins per group
    let min = Infinity,
      max = -Infinity,
      i = 0,
      j;
    for (; i < n; ++i) {
      const g = groups[i].sort(sort);
      j = -1;
      for (const v of dotbin(g, step, smooth, field)) {
        if (v < min) min = v;
        if (v > max) max = v;
        g[++j][as] = v;
      }
    }
    this.value = {
      start: min,
      stop: max,
      step: step
    };
    return pulse.reflow(true).modifies(as);
  }
});

/**
 * Wraps an expression function with access to external parameters.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function} params.expr - The expression function. The
 *  function should accept both a datum and a parameter object.
 *  This operator's value will be a new function that wraps the
 *  expression function with access to this operator's parameters.
 */
function Expression(params) {
  Operator.call(this, null, update$4, params);
  this.modified(true);
}
inherits(Expression, Operator);
function update$4(_) {
  const expr = _.expr;
  return this.value && !_.modified('expr') ? this.value : accessor(datum => expr(datum, _), accessorFields(expr), accessorName(expr));
}

/**
 * Computes extents (min/max) for a data field.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The field over which to compute extends.
 */
function Extent(params) {
  Transform.call(this, [undefined, undefined], params);
}
Extent.Definition = {
  'type': 'Extent',
  'metadata': {},
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }]
};
inherits(Extent, Transform, {
  transform(_, pulse) {
    const extent = this.value,
      field = _.field,
      mod = pulse.changed() || pulse.modified(field.fields) || _.modified('field');
    let min = extent[0],
      max = extent[1];
    if (mod || min == null) {
      min = +Infinity;
      max = -Infinity;
    }
    pulse.visit(mod ? pulse.SOURCE : pulse.ADD, t => {
      const v = vega_util_module_toNumber(field(t));
      if (v != null) {
        // NaNs will fail all comparisons!
        if (v < min) min = v;
        if (v > max) max = v;
      }
    });
    if (!Number.isFinite(min) || !Number.isFinite(max)) {
      let name = accessorName(field);
      if (name) name = ` for field "${name}"`;
      pulse.dataflow.warn(`Infinite extent${name}: [${min}, ${max}]`);
      min = max = undefined;
    }
    this.value = [min, max];
  }
});

/**
 * Provides a bridge between a parent transform and a target subflow that
 * consumes only a subset of the tuples that pass through the parent.
 * @constructor
 * @param {Pulse} pulse - A pulse to use as the value of this operator.
 * @param {Transform} parent - The parent transform (typically a Facet instance).
 */
function Subflow(pulse, parent) {
  Operator.call(this, pulse);
  this.parent = parent;
  this.count = 0;
}
inherits(Subflow, Operator, {
  /**
   * Routes pulses from this subflow to a target transform.
   * @param {Transform} target - A transform that receives the subflow of tuples.
   */
  connect(target) {
    this.detachSubflow = target.detachSubflow;
    this.targets().add(target);
    return target.source = this;
  },
  /**
   * Add an 'add' tuple to the subflow pulse.
   * @param {Tuple} t - The tuple being added.
   */
  add(t) {
    this.count += 1;
    this.value.add.push(t);
  },
  /**
   * Add a 'rem' tuple to the subflow pulse.
   * @param {Tuple} t - The tuple being removed.
   */
  rem(t) {
    this.count -= 1;
    this.value.rem.push(t);
  },
  /**
   * Add a 'mod' tuple to the subflow pulse.
   * @param {Tuple} t - The tuple being modified.
   */
  mod(t) {
    this.value.mod.push(t);
  },
  /**
   * Re-initialize this operator's pulse value.
   * @param {Pulse} pulse - The pulse to copy from.
   * @see Pulse.init
   */
  init(pulse) {
    this.value.init(pulse, pulse.NO_SOURCE);
  },
  /**
   * Evaluate this operator. This method overrides the
   * default behavior to simply return the contained pulse value.
   * @return {Pulse}
   */
  evaluate() {
    // assert: this.value.stamp === pulse.stamp
    return this.value;
  }
});

/**
 * Facets a dataflow into a set of subflows based on a key.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(Dataflow, string): Operator} params.subflow - A function
 *   that generates a subflow of operators and returns its root operator.
 * @param {function(object): *} params.key - The key field to facet by.
 */
function Facet(params) {
  Transform.call(this, {}, params);
  this._keys = fastmap(); // cache previously calculated key values

  // keep track of active subflows, use as targets array for listeners
  // this allows us to limit propagation to only updated subflows
  const a = this._targets = [];
  a.active = 0;
  a.forEach = f => {
    for (let i = 0, n = a.active; i < n; ++i) {
      f(a[i], i, a);
    }
  };
}
inherits(Facet, Transform, {
  activate(flow) {
    this._targets[this._targets.active++] = flow;
  },
  // parent argument provided by PreFacet subclass
  subflow(key, flow, pulse, parent) {
    const flows = this.value;
    let sf = vega_util_module_has(flows, key) && flows[key],
      df,
      p;
    if (!sf) {
      p = parent || (p = this._group[key]) && p.tuple;
      df = pulse.dataflow;
      sf = new Subflow(pulse.fork(pulse.NO_SOURCE), this);
      df.add(sf).connect(flow(df, key, p));
      flows[key] = sf;
      this.activate(sf);
    } else if (sf.value.stamp < pulse.stamp) {
      sf.init(pulse);
      this.activate(sf);
    }
    return sf;
  },
  clean() {
    const flows = this.value;
    let detached = 0;
    for (const key in flows) {
      if (flows[key].count === 0) {
        const detach = flows[key].detachSubflow;
        if (detach) detach();
        delete flows[key];
        ++detached;
      }
    }

    // remove inactive targets from the active targets array
    if (detached) {
      const active = this._targets.filter(sf => sf && sf.count > 0);
      this.initTargets(active);
    }
  },
  initTargets(act) {
    const a = this._targets,
      n = a.length,
      m = act ? act.length : 0;
    let i = 0;
    for (; i < m; ++i) {
      a[i] = act[i];
    }
    for (; i < n && a[i] != null; ++i) {
      a[i] = null; // ensure old flows can be garbage collected
    }
    a.active = m;
  },
  transform(_, pulse) {
    const df = pulse.dataflow,
      key = _.key,
      flow = _.subflow,
      cache = this._keys,
      rekey = _.modified('key'),
      subflow = key => this.subflow(key, flow, pulse);
    this._group = _.group || {};
    this.initTargets(); // reset list of active subflows

    pulse.visit(pulse.REM, t => {
      const id = tupleid(t),
        k = cache.get(id);
      if (k !== undefined) {
        cache.delete(id);
        subflow(k).rem(t);
      }
    });
    pulse.visit(pulse.ADD, t => {
      const k = key(t);
      cache.set(tupleid(t), k);
      subflow(k).add(t);
    });
    if (rekey || pulse.modified(key.fields)) {
      pulse.visit(pulse.MOD, t => {
        const id = tupleid(t),
          k0 = cache.get(id),
          k1 = key(t);
        if (k0 === k1) {
          subflow(k1).mod(t);
        } else {
          cache.set(id, k1);
          subflow(k0).rem(t);
          subflow(k1).add(t);
        }
      });
    } else if (pulse.changed(pulse.MOD)) {
      pulse.visit(pulse.MOD, t => {
        subflow(cache.get(tupleid(t))).mod(t);
      });
    }
    if (rekey) {
      pulse.visit(pulse.REFLOW, t => {
        const id = tupleid(t),
          k0 = cache.get(id),
          k1 = key(t);
        if (k0 !== k1) {
          cache.set(id, k1);
          subflow(k0).rem(t);
          subflow(k1).add(t);
        }
      });
    }
    if (pulse.clean()) {
      df.runAfter(() => {
        this.clean();
        cache.clean();
      });
    } else if (cache.empty > df.cleanThreshold) {
      df.runAfter(cache.clean);
    }
    return pulse;
  }
});

/**
 * Generates one or more field accessor functions.
 * If the 'name' parameter is an array, an array of field accessors
 * will be created and the 'as' parameter will be ignored.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {string} params.name - The field name(s) to access.
 * @param {string} params.as - The accessor function name.
 */
function Field(params) {
  Operator.call(this, null, update$3, params);
}
inherits(Field, Operator);
function update$3(_) {
  return this.value && !_.modified() ? this.value : vega_util_module_isArray(_.name) ? vega_util_module_array(_.name).map(f => vega_util_module_field(f)) : vega_util_module_field(_.name, _.as);
}

/**
 * Filters data tuples according to a predicate function.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.expr - The predicate expression function
 *   that determines a tuple's filter status. Truthy values pass the filter.
 */
function Filter(params) {
  Transform.call(this, fastmap(), params);
}
Filter.Definition = {
  'type': 'Filter',
  'metadata': {
    'changes': true
  },
  'params': [{
    'name': 'expr',
    'type': 'expr',
    'required': true
  }]
};
inherits(Filter, Transform, {
  transform(_, pulse) {
    const df = pulse.dataflow,
      cache = this.value,
      // cache ids of filtered tuples
      output = pulse.fork(),
      add = output.add,
      rem = output.rem,
      mod = output.mod,
      test = _.expr;
    let isMod = true;
    pulse.visit(pulse.REM, t => {
      const id = tupleid(t);
      if (!cache.has(id)) rem.push(t);else cache.delete(id);
    });
    pulse.visit(pulse.ADD, t => {
      if (test(t, _)) add.push(t);else cache.set(tupleid(t), 1);
    });
    function revisit(t) {
      const id = tupleid(t),
        b = test(t, _),
        s = cache.get(id);
      if (b && s) {
        cache.delete(id);
        add.push(t);
      } else if (!b && !s) {
        cache.set(id, 1);
        rem.push(t);
      } else if (isMod && b && !s) {
        mod.push(t);
      }
    }
    pulse.visit(pulse.MOD, revisit);
    if (_.modified()) {
      isMod = false;
      pulse.visit(pulse.REFLOW, revisit);
    }
    if (cache.empty > df.cleanThreshold) df.runAfter(cache.clean);
    return output;
  }
});

/**
 * Flattens array-typed field values into new data objects.
 * If multiple fields are specified, they are treated as parallel arrays,
 * with output values included for each matching index (or null if missing).
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} params.fields - An array of field
 *   accessors for the tuple fields that should be flattened.
 * @param {string} [params.index] - Optional output field name for index
 *   value. If unspecified, no index field is included in the output.
 * @param {Array<string>} [params.as] - Output field names for flattened
 *   array fields. Any unspecified fields will use the field name provided
 *   by the fields accessors.
 */
function Flatten(params) {
  Transform.call(this, [], params);
}
Flatten.Definition = {
  'type': 'Flatten',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'fields',
    'type': 'field',
    'array': true,
    'required': true
  }, {
    'name': 'index',
    'type': 'string'
  }, {
    'name': 'as',
    'type': 'string',
    'array': true
  }]
};
inherits(Flatten, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE),
      fields = _.fields,
      as = fieldNames(fields, _.as || []),
      index = _.index || null,
      m = as.length;

    // remove any previous results
    out.rem = this.value;

    // generate flattened tuples
    pulse.visit(pulse.SOURCE, t => {
      const arrays = fields.map(f => f(t)),
        maxlen = arrays.reduce((l, a) => Math.max(l, a.length), 0);
      let i = 0,
        j,
        d,
        v;
      for (; i < maxlen; ++i) {
        d = vega_dataflow_module_derive(t);
        for (j = 0; j < m; ++j) {
          d[as[j]] = (v = arrays[j][i]) == null ? null : v;
        }
        if (index) {
          d[index] = i;
        }
        out.add.push(d);
      }
    });
    this.value = out.source = out.add;
    if (index) out.modifies(index);
    return out.modifies(as);
  }
});

/**
 * Folds one more tuple fields into multiple tuples in which the field
 * name and values are available under new 'key' and 'value' fields.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.fields - An array of field accessors
 *   for the tuple fields that should be folded.
 * @param {Array<string>} [params.as] - Output field names for folded key
 *   and value fields, defaults to ['key', 'value'].
 */
function Fold(params) {
  Transform.call(this, [], params);
}
Fold.Definition = {
  'type': 'Fold',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'fields',
    'type': 'field',
    'array': true,
    'required': true
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['key', 'value']
  }]
};
inherits(Fold, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE),
      fields = _.fields,
      fnames = fields.map(accessorName),
      as = _.as || ['key', 'value'],
      k = as[0],
      v = as[1],
      n = fields.length;
    out.rem = this.value;
    pulse.visit(pulse.SOURCE, t => {
      for (let i = 0, d; i < n; ++i) {
        d = vega_dataflow_module_derive(t);
        d[k] = fnames[i];
        d[v] = fields[i](t);
        out.add.push(d);
      }
    });
    this.value = out.source = out.add;
    return out.modifies(as);
  }
});

/**
 * Invokes a function for each data tuple and saves the results as a new field.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.expr - The formula function to invoke for each tuple.
 * @param {string} params.as - The field name under which to save the result.
 * @param {boolean} [params.initonly=false] - If true, the formula is applied to
 *   added tuples only, and does not update in response to modifications.
 */
function Formula(params) {
  Transform.call(this, null, params);
}
Formula.Definition = {
  'type': 'Formula',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'expr',
    'type': 'expr',
    'required': true
  }, {
    'name': 'as',
    'type': 'string',
    'required': true
  }, {
    'name': 'initonly',
    'type': 'boolean'
  }]
};
inherits(Formula, Transform, {
  transform(_, pulse) {
    const func = _.expr,
      as = _.as,
      mod = _.modified(),
      flag = _.initonly ? pulse.ADD : mod ? pulse.SOURCE : pulse.modified(func.fields) || pulse.modified(as) ? pulse.ADD_MOD : pulse.ADD;
    if (mod) {
      // parameters updated, need to reflow
      pulse = pulse.materialize().reflow(true);
    }
    if (!_.initonly) {
      pulse.modifies(as);
    }
    return pulse.visit(flag, t => t[as] = func(t, _));
  }
});

/**
 * Generates data tuples using a provided generator function.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(Parameters): object} params.generator - A tuple generator
 *   function. This function is given the operator parameters as input.
 *   Changes to any additional parameters will not trigger re-calculation
 *   of previously generated tuples. Only future tuples are affected.
 * @param {number} params.size - The number of tuples to produce.
 */
function Generate(params) {
  Transform.call(this, [], params);
}
inherits(Generate, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.ALL),
      gen = _.generator;
    let data = this.value,
      num = _.size - data.length,
      add,
      rem,
      t;
    if (num > 0) {
      // need more tuples, generate and add
      for (add = []; --num >= 0;) {
        add.push(t = ingest$1(gen(_)));
        data.push(t);
      }
      out.add = out.add.length ? out.materialize(out.ADD).add.concat(add) : add;
    } else {
      // need fewer tuples, remove
      rem = data.slice(0, -num);
      out.rem = out.rem.length ? out.materialize(out.REM).rem.concat(rem) : rem;
      data = data.slice(-num);
    }
    out.source = this.value = data;
    return out;
  }
});

const Methods = {
  value: 'value',
  median: median,
  mean: mean,
  min: min_min,
  max: max_max
};
const Empty = [];

/**
 * Impute missing values.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to impute.
 * @param {Array<function(object): *>} [params.groupby] - An array of
 *   accessors to determine series within which to perform imputation.
 * @param {function(object): *} params.key - An accessor for a key value.
 *   Each key value should be unique within a group. New tuples will be
 *   imputed for any key values that are not found within a group.
 * @param {Array<*>} [params.keyvals] - Optional array of required key
 *   values. New tuples will be imputed for any key values that are not
 *   found within a group. In addition, these values will be automatically
 *   augmented with the key values observed in the input data.
 * @param {string} [method='value'] - The imputation method to use. One of
 *   'value', 'mean', 'median', 'max', 'min'.
 * @param {*} [value=0] - The constant value to use for imputation
 *   when using method 'value'.
 */
function Impute(params) {
  Transform.call(this, [], params);
}
Impute.Definition = {
  'type': 'Impute',
  'metadata': {
    'changes': true
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'key',
    'type': 'field',
    'required': true
  }, {
    'name': 'keyvals',
    'array': true
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'method',
    'type': 'enum',
    'default': 'value',
    'values': ['value', 'mean', 'median', 'max', 'min']
  }, {
    'name': 'value',
    'default': 0
  }]
};
function getValue(_) {
  var m = _.method || Methods.value,
    v;
  if (Methods[m] == null) {
    vega_util_module_error('Unrecognized imputation method: ' + m);
  } else if (m === Methods.value) {
    v = _.value !== undefined ? _.value : 0;
    return () => v;
  } else {
    return Methods[m];
  }
}
function getField(_) {
  const f = _.field;
  return t => t ? f(t) : NaN;
}
inherits(Impute, Transform, {
  transform(_, pulse) {
    var out = pulse.fork(pulse.ALL),
      impute = getValue(_),
      field = getField(_),
      fName = accessorName(_.field),
      kName = accessorName(_.key),
      gNames = (_.groupby || []).map(accessorName),
      groups = partition(pulse.source, _.groupby, _.key, _.keyvals),
      curr = [],
      prev = this.value,
      m = groups.domain.length,
      group,
      value,
      gVals,
      kVal,
      g,
      i,
      j,
      l,
      n,
      t;
    for (g = 0, l = groups.length; g < l; ++g) {
      group = groups[g];
      gVals = group.values;
      value = NaN;

      // add tuples for missing values
      for (j = 0; j < m; ++j) {
        if (group[j] != null) continue;
        kVal = groups.domain[j];
        t = {
          _impute: true
        };
        for (i = 0, n = gVals.length; i < n; ++i) t[gNames[i]] = gVals[i];
        t[kName] = kVal;
        t[fName] = Number.isNaN(value) ? value = impute(group, field) : value;
        curr.push(ingest$1(t));
      }
    }

    // update pulse with imputed tuples
    if (curr.length) out.add = out.materialize(out.ADD).add.concat(curr);
    if (prev.length) out.rem = out.materialize(out.REM).rem.concat(prev);
    this.value = curr;
    return out;
  }
});
function partition(data, groupby, key, keyvals) {
  var get = f => f(t),
    groups = [],
    domain = keyvals ? keyvals.slice() : [],
    kMap = {},
    gMap = {},
    gVals,
    gKey,
    group,
    i,
    j,
    k,
    n,
    t;
  domain.forEach((k, i) => kMap[k] = i + 1);
  for (i = 0, n = data.length; i < n; ++i) {
    t = data[i];
    k = key(t);
    j = kMap[k] || (kMap[k] = domain.push(k));
    gKey = (gVals = groupby ? groupby.map(get) : Empty) + '';
    if (!(group = gMap[gKey])) {
      group = gMap[gKey] = [];
      groups.push(group);
      group.values = gVals;
    }
    group[j - 1] = t;
  }
  groups.domain = domain;
  return groups;
}

/**
 * Extend input tuples with aggregate values.
 * Calcuates aggregate values and joins them with the input stream.
 * @constructor
 */
function JoinAggregate(params) {
  Aggregate.call(this, params);
}
JoinAggregate.Definition = {
  'type': 'JoinAggregate',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'fields',
    'type': 'field',
    'null': true,
    'array': true
  }, {
    'name': 'ops',
    'type': 'enum',
    'array': true,
    'values': ValidAggregateOps
  }, {
    'name': 'as',
    'type': 'string',
    'null': true,
    'array': true
  }, {
    'name': 'key',
    'type': 'field'
  }]
};
inherits(JoinAggregate, Aggregate, {
  transform(_, pulse) {
    const aggr = this,
      mod = _.modified();
    let cells;

    // process all input tuples to calculate aggregates
    if (aggr.value && (mod || pulse.modified(aggr._inputs, true))) {
      cells = aggr.value = mod ? aggr.init(_) : {};
      pulse.visit(pulse.SOURCE, t => aggr.add(t));
    } else {
      cells = aggr.value = aggr.value || this.init(_);
      pulse.visit(pulse.REM, t => aggr.rem(t));
      pulse.visit(pulse.ADD, t => aggr.add(t));
    }

    // update aggregation cells
    aggr.changes();

    // write aggregate values to input tuples
    pulse.visit(pulse.SOURCE, t => {
      extend(t, cells[aggr.cellkey(t)].tuple);
    });
    return pulse.reflow(mod).modifies(this._outputs);
  },
  changes() {
    const adds = this._adds,
      mods = this._mods;
    let i, n;
    for (i = 0, n = this._alen; i < n; ++i) {
      this.celltuple(adds[i]);
      adds[i] = null; // for garbage collection
    }
    for (i = 0, n = this._mlen; i < n; ++i) {
      this.celltuple(mods[i]);
      mods[i] = null; // for garbage collection
    }
    this._alen = this._mlen = 0; // reset list of active cells
  }
});

/**
 * Compute kernel density estimates (KDE) for one or more data groups.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors
 *   to groupby.
 * @param {function(object): *} params.field - An accessor for the data field
 *   to estimate.
 * @param {number} [params.bandwidth=0] - The KDE kernel bandwidth.
 *   If zero or unspecified, the bandwidth is automatically determined.
 * @param {boolean} [params.counts=false] - A boolean flag indicating if the
 *   output values should be probability estimates (false, default) or
 *   smoothed counts (true).
 * @param {string} [params.cumulative=false] - A boolean flag indicating if a
 *   density (false) or cumulative distribution (true) should be generated.
 * @param {Array<number>} [params.extent] - The domain extent over which to
 *   plot the density. If unspecified, the [min, max] data extent is used.
 * @param {string} [params.resolve='independent'] - Indicates how parameters for
 *   multiple densities should be resolved. If "independent" (the default), each
 *   density may have its own domain extent and dynamic number of curve sample
 *   steps. If "shared", the KDE transform will ensure that all densities are
 *   defined over a shared domain and curve steps, enabling stacking.
 * @param {number} [params.minsteps=25] - The minimum number of curve samples
 *   for plotting the density.
 * @param {number} [params.maxsteps=200] - The maximum number of curve samples
 *   for plotting the density.
 * @param {number} [params.steps] - The exact number of curve samples for
 *   plotting the density. If specified, overrides both minsteps and maxsteps
 *   to set an exact number of uniform samples. Useful in conjunction with
 *   a fixed extent to ensure consistent sample points for stacked densities.
 */
function KDE(params) {
  Transform.call(this, null, params);
}
KDE.Definition = {
  'type': 'KDE',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'cumulative',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'counts',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'bandwidth',
    'type': 'number',
    'default': 0
  }, {
    'name': 'extent',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'resolve',
    'type': 'enum',
    'values': ['shared', 'independent'],
    'default': 'independent'
  }, {
    'name': 'steps',
    'type': 'number'
  }, {
    'name': 'minsteps',
    'type': 'number',
    'default': 25
  }, {
    'name': 'maxsteps',
    'type': 'number',
    'default': 200
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'default': ['value', 'density']
  }]
};
inherits(KDE, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
    if (!this.value || pulse.changed() || _.modified()) {
      const source = pulse.materialize(pulse.SOURCE).source,
        groups = partition$1(source, _.groupby, _.field),
        names = (_.groupby || []).map(accessorName),
        bandwidth = _.bandwidth,
        method = _.cumulative ? 'cdf' : 'pdf',
        as = _.as || ['value', 'density'],
        values = [];
      let domain = _.extent,
        minsteps = _.steps || _.minsteps || 25,
        maxsteps = _.steps || _.maxsteps || 200;
      if (method !== 'pdf' && method !== 'cdf') {
        vega_util_module_error('Invalid density method: ' + method);
      }
      if (_.resolve === 'shared') {
        if (!domain) domain = extent(source, _.field);
        minsteps = maxsteps = _.steps || maxsteps;
      }
      groups.forEach(g => {
        const density = kde(g, bandwidth)[method],
          scale = _.counts ? g.length : 1,
          local = domain || extent(g);
        sampleCurve(density, local, minsteps, maxsteps).forEach(v => {
          const t = {};
          for (let i = 0; i < names.length; ++i) {
            t[names[i]] = g.dims[i];
          }
          t[as[0]] = v[0];
          t[as[1]] = v[1] * scale;
          values.push(ingest$1(t));
        });
      });
      if (this.value) out.rem = this.value;
      this.value = out.add = out.source = values;
    }
    return out;
  }
});

/**
 * Generates a key function.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<string>} params.fields - The field name(s) for the key function.
 * @param {boolean} params.flat - A boolean flag indicating if the field names
 *  should be treated as flat property names, side-stepping nested field
 *  lookups normally indicated by dot or bracket notation.
 */
function Key(params) {
  Operator.call(this, null, update$2, params);
}
inherits(Key, Operator);
function update$2(_) {
  return this.value && !_.modified() ? this.value : vega_util_module_key(_.fields, _.flat);
}

/**
 * Load and parse data from an external source. Marshalls parameter
 * values and then invokes the Dataflow request method.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {string} params.url - The URL to load from.
 * @param {object} params.format - The data format options.
 */
function Load(params) {
  Transform.call(this, [], params);
  this._pending = null;
}
inherits(Load, Transform, {
  transform(_, pulse) {
    const df = pulse.dataflow;
    if (this._pending) {
      // update state and return pulse
      return vega_transforms_module_output(this, pulse, this._pending);
    }
    if (stop(_)) return pulse.StopPropagation;
    if (_.values) {
      // parse and ingest values, return output pulse
      return vega_transforms_module_output(this, pulse, df.parse(_.values, _.format));
    } else if (_.async) {
      // return promise for non-blocking async loading
      const p = df.request(_.url, _.format).then(res => {
        this._pending = vega_util_module_array(res.data);
        return df => df.touch(this);
      });
      return {
        async: p
      };
    } else {
      // return promise for synchronous loading
      return df.request(_.url, _.format).then(res => vega_transforms_module_output(this, pulse, vega_util_module_array(res.data)));
    }
  }
});
function stop(_) {
  return _.modified('async') && !(_.modified('values') || _.modified('url') || _.modified('format'));
}
function vega_transforms_module_output(op, pulse, data) {
  data.forEach(ingest$1);
  const out = pulse.fork(pulse.NO_FIELDS & pulse.NO_SOURCE);
  out.rem = op.value;
  op.value = out.source = out.add = data;
  op._pending = null;
  if (out.rem.length) out.clean(true);
  return out;
}

/**
 * Extend tuples by joining them with values from a lookup table.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Map} params.index - The lookup table map.
 * @param {Array<function(object): *} params.fields - The fields to lookup.
 * @param {Array<string>} params.as - Output field names for each lookup value.
 * @param {*} [params.default] - A default value to use if lookup fails.
 */
function Lookup(params) {
  Transform.call(this, {}, params);
}
Lookup.Definition = {
  'type': 'Lookup',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'index',
    'type': 'index',
    'params': [{
      'name': 'from',
      'type': 'data',
      'required': true
    }, {
      'name': 'key',
      'type': 'field',
      'required': true
    }]
  }, {
    'name': 'values',
    'type': 'field',
    'array': true
  }, {
    'name': 'fields',
    'type': 'field',
    'array': true,
    'required': true
  }, {
    'name': 'as',
    'type': 'string',
    'array': true
  }, {
    'name': 'default',
    'default': null
  }]
};
inherits(Lookup, Transform, {
  transform(_, pulse) {
    const keys = _.fields,
      index = _.index,
      values = _.values,
      defaultValue = _.default == null ? null : _.default,
      reset = _.modified(),
      n = keys.length;
    let flag = reset ? pulse.SOURCE : pulse.ADD,
      out = pulse,
      as = _.as,
      set,
      m,
      mods;
    if (values) {
      m = values.length;
      if (n > 1 && !as) {
        vega_util_module_error('Multi-field lookup requires explicit "as" parameter.');
      }
      if (as && as.length !== n * m) {
        vega_util_module_error('The "as" parameter has too few output field names.');
      }
      as = as || values.map(accessorName);
      set = function (t) {
        for (var i = 0, k = 0, j, v; i < n; ++i) {
          v = index.get(keys[i](t));
          if (v == null) for (j = 0; j < m; ++j, ++k) t[as[k]] = defaultValue;else for (j = 0; j < m; ++j, ++k) t[as[k]] = values[j](v);
        }
      };
    } else {
      if (!as) {
        vega_util_module_error('Missing output field names.');
      }
      set = function (t) {
        for (var i = 0, v; i < n; ++i) {
          v = index.get(keys[i](t));
          t[as[i]] = v == null ? defaultValue : v;
        }
      };
    }
    if (reset) {
      out = pulse.reflow(true);
    } else {
      mods = keys.some(k => pulse.modified(k.fields));
      flag |= mods ? pulse.MOD : 0;
    }
    pulse.visit(flag, set);
    return out.modifies(as);
  }
});

/**
 * Computes global min/max extents over a collection of extents.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<Array<number>>} params.extents - The input extents.
 */
function MultiExtent(params) {
  Operator.call(this, null, update$1, params);
}
inherits(MultiExtent, Operator);
function update$1(_) {
  if (this.value && !_.modified()) {
    return this.value;
  }
  const ext = _.extents,
    n = ext.length;
  let min = +Infinity,
    max = -Infinity,
    i,
    e;
  for (i = 0; i < n; ++i) {
    e = ext[i];
    if (e[0] < min) min = e[0];
    if (e[1] > max) max = e[1];
  }
  return [min, max];
}

/**
 * Merge a collection of value arrays.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<Array<*>>} params.values - The input value arrrays.
 */
function MultiValues(params) {
  Operator.call(this, null, vega_transforms_module_update, params);
}
inherits(MultiValues, Operator);
function vega_transforms_module_update(_) {
  return this.value && !_.modified() ? this.value : _.values.reduce((data, _) => data.concat(_), []);
}

/**
 * Operator whose value is simply its parameter hash. This operator is
 * useful for enabling reactive updates to values of nested objects.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function Params(params) {
  Transform.call(this, null, params);
}
inherits(Params, Transform, {
  transform(_, pulse) {
    this.modified(_.modified());
    this.value = _;
    return pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS); // do not pass tuples
  }
});

/**
 * Aggregate and pivot selected field values to become new fields.
 * This operator is useful to construction cross-tabulations.
 * @constructor
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors
 *  to groupby. These fields act just like groupby fields of an Aggregate transform.
 * @param {function(object): *} params.field - The field to pivot on. The unique
 *  values of this field become new field names in the output stream.
 * @param {function(object): *} params.value - The field to populate pivoted fields.
 *  The aggregate values of this field become the values of the new pivoted fields.
 * @param {string} [params.op] - The aggregation operation for the value field,
 *  applied per cell in the output stream. The default is "sum".
 * @param {number} [params.limit] - An optional parameter indicating the maximum
 *  number of pivoted fields to generate. The pivoted field names are sorted in
 *  ascending order prior to enforcing the limit.
 */
function Pivot(params) {
  Aggregate.call(this, params);
}
Pivot.Definition = {
  'type': 'Pivot',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'value',
    'type': 'field',
    'required': true
  }, {
    'name': 'op',
    'type': 'enum',
    'values': ValidAggregateOps,
    'default': 'sum'
  }, {
    'name': 'limit',
    'type': 'number',
    'default': 0
  }, {
    'name': 'key',
    'type': 'field'
  }]
};
inherits(Pivot, Aggregate, {
  _transform: Aggregate.prototype.transform,
  transform(_, pulse) {
    return this._transform(aggregateParams(_, pulse), pulse);
  }
});

// Shoehorn a pivot transform into an aggregate transform!
// First collect all unique pivot field values.
// Then generate aggregate fields for each output pivot field.
function aggregateParams(_, pulse) {
  const key = _.field,
    value = _.value,
    op = (_.op === 'count' ? '__count__' : _.op) || 'sum',
    fields = accessorFields(key).concat(accessorFields(value)),
    keys = vega_transforms_module_pivotKeys(key, _.limit || 0, pulse);

  // if data stream content changes, pivot fields may change
  // flag parameter modification to ensure re-initialization
  if (pulse.changed()) _.set('__pivot__', null, null, true);
  return {
    key: _.key,
    groupby: _.groupby,
    ops: keys.map(() => op),
    fields: keys.map(k => vega_transforms_module_get(k, key, value, fields)),
    as: keys.map(k => k + ''),
    modified: _.modified.bind(_)
  };
}

// Generate aggregate field accessor.
// Output NaN for non-existent values; aggregator will ignore!
function vega_transforms_module_get(k, key, value, fields) {
  return accessor(d => key(d) === k ? value(d) : NaN, fields, k + '');
}

// Collect (and optionally limit) all unique pivot values.
function vega_transforms_module_pivotKeys(key, limit, pulse) {
  const map = {},
    list = [];
  pulse.visit(pulse.SOURCE, t => {
    const k = key(t);
    if (!map[k]) {
      map[k] = 1;
      list.push(k);
    }
  });
  list.sort(vega_util_module_ascending);
  return limit ? list.slice(0, limit) : list;
}

/**
 * Partitions pre-faceted data into tuple subflows.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(Dataflow, string): Operator} params.subflow - A function
 *   that generates a subflow of operators and returns its root operator.
 * @param {function(object): Array<object>} params.field - The field
 *   accessor for an array of subflow tuple objects.
 */
function PreFacet(params) {
  Facet.call(this, params);
}
inherits(PreFacet, Facet, {
  transform(_, pulse) {
    const flow = _.subflow,
      field = _.field,
      subflow = t => this.subflow(tupleid(t), flow, pulse, t);
    if (_.modified('field') || field && pulse.modified(accessorFields(field))) {
      vega_util_module_error('PreFacet does not support field modification.');
    }
    this.initTargets(); // reset list of active subflows

    if (field) {
      pulse.visit(pulse.MOD, t => {
        const sf = subflow(t);
        field(t).forEach(_ => sf.mod(_));
      });
      pulse.visit(pulse.ADD, t => {
        const sf = subflow(t);
        field(t).forEach(_ => sf.add(ingest$1(_)));
      });
      pulse.visit(pulse.REM, t => {
        const sf = subflow(t);
        field(t).forEach(_ => sf.rem(_));
      });
    } else {
      pulse.visit(pulse.MOD, t => subflow(t).mod(t));
      pulse.visit(pulse.ADD, t => subflow(t).add(t));
      pulse.visit(pulse.REM, t => subflow(t).rem(t));
    }
    if (pulse.clean()) {
      pulse.runAfter(() => this.clean());
    }
    return pulse;
  }
});

/**
 * Performs a relational projection, copying selected fields from source
 * tuples to a new set of derived tuples.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *} params.fields - The fields to project,
 *   as an array of field accessors. If unspecified, all fields will be
 *   copied with names unchanged.
 * @param {Array<string>} [params.as] - Output field names for each projected
 *   field. Any unspecified fields will use the field name provided by
 *   the field accessor.
 */
function Project(params) {
  Transform.call(this, null, params);
}
Project.Definition = {
  'type': 'Project',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'fields',
    'type': 'field',
    'array': true
  }, {
    'name': 'as',
    'type': 'string',
    'null': true,
    'array': true
  }]
};
inherits(Project, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE),
      fields = _.fields,
      as = fieldNames(_.fields, _.as || []),
      derive = fields ? (s, t) => project(s, t, fields, as) : rederive;
    let lut;
    if (this.value) {
      lut = this.value;
    } else {
      pulse = pulse.addAll();
      lut = this.value = {};
    }
    pulse.visit(pulse.REM, t => {
      const id = tupleid(t);
      out.rem.push(lut[id]);
      lut[id] = null;
    });
    pulse.visit(pulse.ADD, t => {
      const dt = derive(t, ingest$1({}));
      lut[tupleid(t)] = dt;
      out.add.push(dt);
    });
    pulse.visit(pulse.MOD, t => {
      out.mod.push(derive(t, lut[tupleid(t)]));
    });
    return out;
  }
});
function project(s, t, fields, as) {
  for (let i = 0, n = fields.length; i < n; ++i) {
    t[as[i]] = fields[i](s);
  }
  return t;
}

/**
 * Proxy the value of another operator as a pure signal value.
 * Ensures no tuples are propagated.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {*} params.value - The value to proxy, becomes the value of this operator.
 */
function extension_Proxy(params) {
  Transform.call(this, null, params);
}
inherits(extension_Proxy, Transform, {
  transform(_, pulse) {
    this.value = _.value;
    return _.modified('value') ? pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS) : pulse.StopPropagation;
  }
});

/**
 * Generates sample quantile values from an input data stream.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - An accessor for the data field
 *   over which to calculate quantile values.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors
 *   to groupby.
 * @param {Array<number>} [params.probs] - An array of probabilities in
 *   the range (0, 1) for which to compute quantile values. If not specified,
 *   the *step* parameter will be used.
 * @param {Array<number>} [params.step=0.01] - A probability step size for
 *   sampling quantile values. All values from one-half the step size up to
 *   1 (exclusive) will be sampled. This parameter is only used if the
 *   *quantiles* parameter is not provided.
 */
function Quantile(params) {
  Transform.call(this, null, params);
}
Quantile.Definition = {
  'type': 'Quantile',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'probs',
    'type': 'number',
    'array': true
  }, {
    'name': 'step',
    'type': 'number',
    'default': 0.01
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'default': ['prob', 'value']
  }]
};
const EPSILON = 1e-14;
inherits(Quantile, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      as = _.as || ['prob', 'value'];
    if (this.value && !_.modified() && !pulse.changed()) {
      out.source = this.value;
      return out;
    }
    const source = pulse.materialize(pulse.SOURCE).source,
      groups = partition$1(source, _.groupby, _.field),
      names = (_.groupby || []).map(accessorName),
      values = [],
      step = _.step || 0.01,
      p = _.probs || range_range(step / 2, 1 - EPSILON, step),
      n = p.length;
    groups.forEach(g => {
      const q = quantiles(g, p);
      for (let i = 0; i < n; ++i) {
        const t = {};
        for (let i = 0; i < names.length; ++i) {
          t[names[i]] = g.dims[i];
        }
        t[as[0]] = p[i];
        t[as[1]] = q[i];
        values.push(ingest$1(t));
      }
    });
    if (this.value) out.rem = this.value;
    this.value = out.add = out.source = values;
    return out;
  }
});

/**
 * Relays a data stream between data processing pipelines.
 * If the derive parameter is set, this transform will create derived
 * copies of observed tuples. This provides derived data streams in which
 * modifications to the tuples do not pollute an upstream data source.
 * @param {object} params - The parameters for this operator.
 * @param {number} [params.derive=false] - Boolean flag indicating if
 *   the transform should make derived copies of incoming tuples.
 * @constructor
 */
function Relay(params) {
  Transform.call(this, null, params);
}
inherits(Relay, Transform, {
  transform(_, pulse) {
    let out, lut;
    if (this.value) {
      lut = this.value;
    } else {
      out = pulse = pulse.addAll();
      lut = this.value = {};
    }
    if (_.derive) {
      out = pulse.fork(pulse.NO_SOURCE);
      pulse.visit(pulse.REM, t => {
        const id = tupleid(t);
        out.rem.push(lut[id]);
        lut[id] = null;
      });
      pulse.visit(pulse.ADD, t => {
        const dt = vega_dataflow_module_derive(t);
        lut[tupleid(t)] = dt;
        out.add.push(dt);
      });
      pulse.visit(pulse.MOD, t => {
        const dt = lut[tupleid(t)];
        for (const k in t) {
          dt[k] = t[k];
          // down stream writes may overwrite re-derived tuples
          // conservatively mark all source fields as modified
          out.modifies(k);
        }
        out.mod.push(dt);
      });
    }
    return out;
  }
});

/**
 * Samples tuples passing through this operator.
 * Uses reservoir sampling to maintain a representative sample.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {number} [params.size=1000] - The maximum number of samples.
 */
function Sample(params) {
  Transform.call(this, [], params);
  this.count = 0;
}
Sample.Definition = {
  'type': 'Sample',
  'metadata': {},
  'params': [{
    'name': 'size',
    'type': 'number',
    'default': 1000
  }]
};
inherits(Sample, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE),
      mod = _.modified('size'),
      num = _.size,
      map = this.value.reduce((m, t) => (m[tupleid(t)] = 1, m), {});
    let res = this.value,
      cnt = this.count,
      cap = 0;

    // sample reservoir update function
    function update(t) {
      let p, idx;
      if (res.length < num) {
        res.push(t);
      } else {
        idx = ~~((cnt + 1) * vega_statistics_module_random());
        if (idx < res.length && idx >= cap) {
          p = res[idx];
          if (map[tupleid(p)]) out.rem.push(p); // eviction
          res[idx] = t;
        }
      }
      ++cnt;
    }
    if (pulse.rem.length) {
      // find all tuples that should be removed, add to output
      pulse.visit(pulse.REM, t => {
        const id = tupleid(t);
        if (map[id]) {
          map[id] = -1;
          out.rem.push(t);
        }
        --cnt;
      });

      // filter removed tuples out of the sample reservoir
      res = res.filter(t => map[tupleid(t)] !== -1);
    }
    if ((pulse.rem.length || mod) && res.length < num && pulse.source) {
      // replenish sample if backing data source is available
      cap = cnt = res.length;
      pulse.visit(pulse.SOURCE, t => {
        // update, but skip previously sampled tuples
        if (!map[tupleid(t)]) update(t);
      });
      cap = -1;
    }
    if (mod && res.length > num) {
      const n = res.length - num;
      for (let i = 0; i < n; ++i) {
        map[tupleid(res[i])] = -1;
        out.rem.push(res[i]);
      }
      res = res.slice(n);
    }
    if (pulse.mod.length) {
      // propagate modified tuples in the sample reservoir
      pulse.visit(pulse.MOD, t => {
        if (map[tupleid(t)]) out.mod.push(t);
      });
    }
    if (pulse.add.length) {
      // update sample reservoir
      pulse.visit(pulse.ADD, update);
    }
    if (pulse.add.length || cap < 0) {
      // output newly added tuples
      out.add = res.filter(t => !map[tupleid(t)]);
    }
    this.count = cnt;
    this.value = out.source = res;
    return out;
  }
});

/**
 * Generates data tuples for a specified sequence range of numbers.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {number} params.start - The first number in the sequence.
 * @param {number} params.stop - The last number (exclusive) in the sequence.
 * @param {number} [params.step=1] - The step size between numbers in the sequence.
 */
function Sequence(params) {
  Transform.call(this, null, params);
}
Sequence.Definition = {
  'type': 'Sequence',
  'metadata': {
    'generates': true,
    'changes': true
  },
  'params': [{
    'name': 'start',
    'type': 'number',
    'required': true
  }, {
    'name': 'stop',
    'type': 'number',
    'required': true
  }, {
    'name': 'step',
    'type': 'number',
    'default': 1
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'data'
  }]
};
inherits(Sequence, Transform, {
  transform(_, pulse) {
    if (this.value && !_.modified()) return;
    const out = pulse.materialize().fork(pulse.MOD),
      as = _.as || 'data';
    out.rem = this.value ? pulse.rem.concat(this.value) : pulse.rem;
    this.value = range_range(_.start, _.stop, _.step || 1).map(v => {
      const t = {};
      t[as] = v;
      return ingest$1(t);
    });
    out.add = pulse.add.concat(this.value);
    return out;
  }
});

/**
 * Propagates a new pulse without any tuples so long as the input
 * pulse contains some added, removed or modified tuples.
 * @param {object} params - The parameters for this operator.
 * @constructor
 */
function Sieve(params) {
  Transform.call(this, null, params);
  this.modified(true); // always treat as modified
}
inherits(Sieve, Transform, {
  transform(_, pulse) {
    this.value = pulse.source;
    return pulse.changed() ? pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS) : pulse.StopPropagation;
  }
});

/**
 * Discretize dates to specific time units.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The data field containing date/time values.
 */
function vega_transforms_module_TimeUnit(params) {
  Transform.call(this, null, params);
}
const OUTPUT = ['unit0', 'unit1'];
vega_transforms_module_TimeUnit.Definition = {
  'type': 'TimeUnit',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field',
    'required': true
  }, {
    'name': 'interval',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'units',
    'type': 'enum',
    'values': TIME_UNITS,
    'array': true
  }, {
    'name': 'step',
    'type': 'number',
    'default': 1
  }, {
    'name': 'maxbins',
    'type': 'number',
    'default': 40
  }, {
    'name': 'extent',
    'type': 'date',
    'array': true
  }, {
    'name': 'timezone',
    'type': 'enum',
    'default': 'local',
    'values': ['local', 'utc']
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': OUTPUT
  }]
};
inherits(vega_transforms_module_TimeUnit, Transform, {
  transform(_, pulse) {
    const field = _.field,
      band = _.interval !== false,
      utc = _.timezone === 'utc',
      floor = this._floor(_, pulse),
      offset = (utc ? utcInterval : vega_time_module_timeInterval)(floor.unit).offset,
      as = _.as || OUTPUT,
      u0 = as[0],
      u1 = as[1],
      step = floor.step;
    let min = floor.start || Infinity,
      max = floor.stop || -Infinity,
      flag = pulse.ADD;
    if (_.modified() || pulse.changed(pulse.REM) || pulse.modified(accessorFields(field))) {
      pulse = pulse.reflow(true);
      flag = pulse.SOURCE;
      min = Infinity;
      max = -Infinity;
    }
    pulse.visit(flag, t => {
      const v = field(t);
      let a, b;
      if (v == null) {
        t[u0] = null;
        if (band) t[u1] = null;
      } else {
        t[u0] = a = b = floor(v);
        if (band) t[u1] = b = offset(a, step);
        if (a < min) min = a;
        if (b > max) max = b;
      }
    });
    floor.start = min;
    floor.stop = max;
    return pulse.modifies(band ? as : u0);
  },
  _floor(_, pulse) {
    const utc = _.timezone === 'utc';

    // get parameters
    const {
      units,
      step
    } = _.units ? {
      units: _.units,
      step: _.step || 1
    } : vega_time_module_bin({
      extent: _.extent || extent(pulse.materialize(pulse.SOURCE).source, _.field),
      maxbins: _.maxbins
    });

    // check / standardize time units
    const tunits = timeUnits(units),
      prev = this.value || {},
      floor = (utc ? utcFloor : timeFloor)(tunits, step);
    floor.unit = peek(tunits);
    floor.units = tunits;
    floor.step = step;
    floor.start = prev.start;
    floor.stop = prev.stop;
    return this.value = floor;
  }
});

/**
 * An index that maps from unique, string-coerced, field values to tuples.
 * Assumes that the field serves as a unique key with no duplicate values.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The field accessor to index.
 */
function TupleIndex(params) {
  Transform.call(this, fastmap(), params);
}
inherits(TupleIndex, Transform, {
  transform(_, pulse) {
    const df = pulse.dataflow,
      field = _.field,
      index = this.value,
      set = t => index.set(field(t), t);
    let mod = true;
    if (_.modified('field') || pulse.modified(field.fields)) {
      index.clear();
      pulse.visit(pulse.SOURCE, set);
    } else if (pulse.changed()) {
      pulse.visit(pulse.REM, t => index.delete(field(t)));
      pulse.visit(pulse.ADD, set);
    } else {
      mod = false;
    }
    this.modified(mod);
    if (index.empty > df.cleanThreshold) df.runAfter(index.clean);
    return pulse.fork();
  }
});

/**
 * Extracts an array of values. Assumes the source data has already been
 * reduced as needed (e.g., by an upstream Aggregate transform).
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The domain field to extract.
 * @param {function(*,*): number} [params.sort] - An optional
 *   comparator function for sorting the values. The comparator will be
 *   applied to backing tuples prior to value extraction.
 */
function Values(params) {
  Transform.call(this, null, params);
}
inherits(Values, Transform, {
  transform(_, pulse) {
    const run = !this.value || _.modified('field') || _.modified('sort') || pulse.changed() || _.sort && pulse.modified(_.sort.fields);
    if (run) {
      this.value = (_.sort ? pulse.source.slice().sort(stableCompare(_.sort)) : pulse.source).map(_.field);
    }
  }
});

function WindowOp(op, field, param, as) {
  const fn = WindowOps[op](field, param);
  return {
    init: fn.init || zero,
    update: function (w, t) {
      t[as] = fn.next(w);
    }
  };
}
const WindowOps = {
  row_number: function () {
    return {
      next: w => w.index + 1
    };
  },
  rank: function () {
    let rank;
    return {
      init: () => rank = 1,
      next: w => {
        const i = w.index,
          data = w.data;
        return i && w.compare(data[i - 1], data[i]) ? rank = i + 1 : rank;
      }
    };
  },
  dense_rank: function () {
    let drank;
    return {
      init: () => drank = 1,
      next: w => {
        const i = w.index,
          d = w.data;
        return i && w.compare(d[i - 1], d[i]) ? ++drank : drank;
      }
    };
  },
  percent_rank: function () {
    const rank = WindowOps.rank(),
      next = rank.next;
    return {
      init: rank.init,
      next: w => (next(w) - 1) / (w.data.length - 1)
    };
  },
  cume_dist: function () {
    let cume;
    return {
      init: () => cume = 0,
      next: w => {
        const d = w.data,
          c = w.compare;
        let i = w.index;
        if (cume < i) {
          while (i + 1 < d.length && !c(d[i], d[i + 1])) ++i;
          cume = i;
        }
        return (1 + cume) / d.length;
      }
    };
  },
  ntile: function (field, num) {
    num = +num;
    if (!(num > 0)) vega_util_module_error('ntile num must be greater than zero.');
    const cume = WindowOps.cume_dist(),
      next = cume.next;
    return {
      init: cume.init,
      next: w => Math.ceil(num * next(w))
    };
  },
  lag: function (field, offset) {
    offset = +offset || 1;
    return {
      next: w => {
        const i = w.index - offset;
        return i >= 0 ? field(w.data[i]) : null;
      }
    };
  },
  lead: function (field, offset) {
    offset = +offset || 1;
    return {
      next: w => {
        const i = w.index + offset,
          d = w.data;
        return i < d.length ? field(d[i]) : null;
      }
    };
  },
  first_value: function (field) {
    return {
      next: w => field(w.data[w.i0])
    };
  },
  last_value: function (field) {
    return {
      next: w => field(w.data[w.i1 - 1])
    };
  },
  nth_value: function (field, nth) {
    nth = +nth;
    if (!(nth > 0)) vega_util_module_error('nth_value nth must be greater than zero.');
    return {
      next: w => {
        const i = w.i0 + (nth - 1);
        return i < w.i1 ? field(w.data[i]) : null;
      }
    };
  },
  prev_value: function (field) {
    let prev;
    return {
      init: () => prev = null,
      next: w => {
        const v = field(w.data[w.index]);
        return v != null ? prev = v : prev;
      }
    };
  },
  next_value: function (field) {
    let v, i;
    return {
      init: () => (v = null, i = -1),
      next: w => {
        const d = w.data;
        return w.index <= i ? v : (i = vega_transforms_module_find(field, d, w.index)) < 0 ? (i = d.length, v = null) : v = field(d[i]);
      }
    };
  }
};
function vega_transforms_module_find(field, data, index) {
  for (let n = data.length; index < n; ++index) {
    const v = field(data[index]);
    if (v != null) return index;
  }
  return -1;
}
const ValidWindowOps = Object.keys(WindowOps);

function WindowState(_) {
  const ops = vega_util_module_array(_.ops),
    fields = vega_util_module_array(_.fields),
    params = vega_util_module_array(_.params),
    aggregate_params = vega_util_module_array(_.aggregate_params),
    as = vega_util_module_array(_.as),
    outputs = this.outputs = [],
    windows = this.windows = [],
    inputs = {},
    map = {},
    counts = [],
    measures = [];
  let countOnly = true;
  function visitInputs(f) {
    vega_util_module_array(accessorFields(f)).forEach(_ => inputs[_] = 1);
  }
  visitInputs(_.sort);
  ops.forEach((op, i) => {
    const field = fields[i],
      param = params[i],
      aggregate_param = aggregate_params[i] || null,
      mname = accessorName(field),
      name = measureName(op, mname, as[i]);
    visitInputs(field);
    outputs.push(name);

    // Window operation
    if (vega_util_module_has(WindowOps, op)) {
      windows.push(WindowOp(op, field, param, name));
    }

    // Aggregate operation
    else {
      if (field == null && op !== 'count') {
        vega_util_module_error('Null aggregate field specified.');
      }
      if (op === 'count') {
        counts.push(name);
        return;
      }
      countOnly = false;
      let m = map[mname];
      if (!m) {
        m = map[mname] = [];
        m.field = field;
        measures.push(m);
      }
      m.push(createMeasure(op, aggregate_param, name));
    }
  });
  if (counts.length || measures.length) {
    this.cell = cell(measures, counts, countOnly);
  }
  this.inputs = Object.keys(inputs);
}
const vega_transforms_module_prototype = WindowState.prototype;
vega_transforms_module_prototype.init = function () {
  this.windows.forEach(_ => _.init());
  if (this.cell) this.cell.init();
};
vega_transforms_module_prototype.update = function (w, t) {
  const cell = this.cell,
    wind = this.windows,
    data = w.data,
    m = wind && wind.length;
  let j;
  if (cell) {
    for (j = w.p0; j < w.i0; ++j) cell.rem(data[j]);
    for (j = w.p1; j < w.i1; ++j) cell.add(data[j]);
    cell.set(t);
  }
  for (j = 0; j < m; ++j) wind[j].update(w, t);
};
function cell(measures, counts, countOnly) {
  measures = measures.map(m => compileMeasures(m, m.field));
  const cell = {
    num: 0,
    agg: null,
    store: false,
    count: counts
  };
  if (!countOnly) {
    var n = measures.length,
      a = cell.agg = Array(n),
      i = 0;
    for (; i < n; ++i) a[i] = new measures[i](cell);
  }
  if (cell.store) {
    var store = cell.data = new TupleStore();
  }
  cell.add = function (t) {
    cell.num += 1;
    if (countOnly) return;
    if (store) store.add(t);
    for (let i = 0; i < n; ++i) {
      a[i].add(a[i].get(t), t);
    }
  };
  cell.rem = function (t) {
    cell.num -= 1;
    if (countOnly) return;
    if (store) store.rem(t);
    for (let i = 0; i < n; ++i) {
      a[i].rem(a[i].get(t), t);
    }
  };
  cell.set = function (t) {
    let i, n;

    // consolidate stored values
    if (store) store.values();

    // update tuple properties
    for (i = 0, n = counts.length; i < n; ++i) t[counts[i]] = cell.num;
    if (!countOnly) for (i = 0, n = a.length; i < n; ++i) a[i].set(t);
  };
  cell.init = function () {
    cell.num = 0;
    if (store) store.reset();
    for (let i = 0; i < n; ++i) a[i].init();
  };
  return cell;
}

/**
 * Perform window calculations and write results to the input stream.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(*,*): number} [params.sort] - A comparator function for sorting tuples within a window.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors by which to partition tuples into separate windows.
 * @param {Array<string>} params.ops - An array of strings indicating window operations to perform.
 * @param {Array<function(object): *>} [params.fields] - An array of accessors
 *   for data fields to use as inputs to window operations.
 * @param {Array<*>} [params.params] - An array of parameter values for window operations.
 * @param {Array<number>} [params.aggregate_params] - An optional array of parameter values for aggregation operations.
 * @param {Array<string>} [params.as] - An array of output field names for window operations.
 * @param {Array<number>} [params.frame] - Window frame definition as two-element array.
 * @param {boolean} [params.ignorePeers=false] - If true, base window frame boundaries on row
 *   number alone, ignoring peers with identical sort values. If false (default),
 *   the window boundaries will be adjusted to include peer values.
 */
function Window(params) {
  Transform.call(this, {}, params);
  this._mlen = 0;
  this._mods = [];
}
Window.Definition = {
  'type': 'Window',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'ops',
    'type': 'enum',
    'array': true,
    'values': ValidWindowOps.concat(ValidAggregateOps)
  }, {
    'name': 'params',
    'type': 'number',
    'null': true,
    'array': true
  }, {
    'name': 'aggregate_params',
    'type': 'number',
    'null': true,
    'array': true
  }, {
    'name': 'fields',
    'type': 'field',
    'null': true,
    'array': true
  }, {
    'name': 'as',
    'type': 'string',
    'null': true,
    'array': true
  }, {
    'name': 'frame',
    'type': 'number',
    'null': true,
    'array': true,
    'length': 2,
    'default': [null, 0]
  }, {
    'name': 'ignorePeers',
    'type': 'boolean',
    'default': false
  }]
};
inherits(Window, Transform, {
  transform(_, pulse) {
    this.stamp = pulse.stamp;
    const mod = _.modified(),
      cmp = stableCompare(_.sort),
      key = groupkey(_.groupby),
      group = t => this.group(key(t));

    // initialize window state
    let state = this.state;
    if (!state || mod) {
      state = this.state = new WindowState(_);
    }

    // partition input tuples
    if (mod || pulse.modified(state.inputs)) {
      this.value = {};
      pulse.visit(pulse.SOURCE, t => group(t).add(t));
    } else {
      pulse.visit(pulse.REM, t => group(t).remove(t));
      pulse.visit(pulse.ADD, t => group(t).add(t));
    }

    // perform window calculations for each modified partition
    for (let i = 0, n = this._mlen; i < n; ++i) {
      processPartition(this._mods[i], state, cmp, _);
    }
    this._mlen = 0;
    this._mods = [];

    // TODO don't reflow everything?
    return pulse.reflow(mod).modifies(state.outputs);
  },
  group(key) {
    let group = this.value[key];
    if (!group) {
      group = this.value[key] = SortedList(tupleid);
      group.stamp = -1;
    }
    if (group.stamp < this.stamp) {
      group.stamp = this.stamp;
      this._mods[this._mlen++] = group;
    }
    return group;
  }
});
function processPartition(list, state, cmp, _) {
  const sort = _.sort,
    range = sort && !_.ignorePeers,
    frame = _.frame || [null, 0],
    data = list.data(cmp),
    // use cmp for stable sort
    n = data.length,
    b = range ? bisector_bisector(sort) : null,
    w = {
      i0: 0,
      i1: 0,
      p0: 0,
      p1: 0,
      index: 0,
      data: data,
      compare: sort || vega_util_module_constant(-1)
    };
  state.init();
  for (let i = 0; i < n; ++i) {
    setWindow(w, frame, i, n);
    if (range) adjustRange(w, b);
    state.update(w, data[i]);
  }
}
function setWindow(w, f, i, n) {
  w.p0 = w.i0;
  w.p1 = w.i1;
  w.i0 = f[0] == null ? 0 : Math.max(0, i - Math.abs(f[0]));
  w.i1 = f[1] == null ? n : Math.min(n, i + Math.abs(f[1]) + 1);
  w.index = i;
}

// if frame type is 'range', adjust window for peer values
function adjustRange(w, bisect) {
  const r0 = w.i0,
    r1 = w.i1 - 1,
    c = w.compare,
    d = w.data,
    n = d.length - 1;
  if (r0 > 0 && !c(d[r0], d[r0 - 1])) w.i0 = bisect.left(d, d[r0]);
  if (r1 < n && !c(d[r1], d[r1 + 1])) w.i1 = bisect.right(d, d[r1]);
}



;// ../../node_modules/d3-shape/src/curve/basis.js
function point(that, x, y) {
  that._context.bezierCurveTo(
    (2 * that._x0 + that._x1) / 3,
    (2 * that._y0 + that._y1) / 3,
    (that._x0 + 2 * that._x1) / 3,
    (that._y0 + 2 * that._y1) / 3,
    (that._x0 + 4 * that._x1 + x) / 6,
    (that._y0 + 4 * that._y1 + y) / 6
  );
}

function Basis(context) {
  this._context = context;
}

Basis.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 =
    this._y0 = this._y1 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 3: point(this, this._x1, this._y1); // falls through
      case 2: this._context.lineTo(this._x1, this._y1); break;
    }
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // falls through
      default: point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = x;
    this._y0 = this._y1, this._y1 = y;
  }
};

/* harmony default export */ function basis(context) {
  return new Basis(context);
}

;// ../../node_modules/d3-shape/src/noop.js
/* harmony default export */ function src_noop() {}

;// ../../node_modules/d3-shape/src/curve/basisClosed.js



function BasisClosed(context) {
  this._context = context;
}

BasisClosed.prototype = {
  areaStart: src_noop,
  areaEnd: src_noop,
  lineStart: function() {
    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 1: {
        this._context.moveTo(this._x2, this._y2);
        this._context.closePath();
        break;
      }
      case 2: {
        this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
        this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
        this._context.closePath();
        break;
      }
      case 3: {
        this.point(this._x2, this._y2);
        this.point(this._x3, this._y3);
        this.point(this._x4, this._y4);
        break;
      }
    }
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
      case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
      case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break;
      default: point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = x;
    this._y0 = this._y1, this._y1 = y;
  }
};

/* harmony default export */ function basisClosed(context) {
  return new BasisClosed(context);
}

;// ../../node_modules/d3-shape/src/curve/basisOpen.js


function BasisOpen(context) {
  this._context = context;
}

BasisOpen.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 =
    this._y0 = this._y1 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break;
      case 3: this._point = 4; // falls through
      default: point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = x;
    this._y0 = this._y1, this._y1 = y;
  }
};

/* harmony default export */ function basisOpen(context) {
  return new BasisOpen(context);
}

;// ../../node_modules/d3-shape/src/curve/bundle.js


function Bundle(context, beta) {
  this._basis = new Basis(context);
  this._beta = beta;
}

Bundle.prototype = {
  lineStart: function() {
    this._x = [];
    this._y = [];
    this._basis.lineStart();
  },
  lineEnd: function() {
    var x = this._x,
        y = this._y,
        j = x.length - 1;

    if (j > 0) {
      var x0 = x[0],
          y0 = y[0],
          dx = x[j] - x0,
          dy = y[j] - y0,
          i = -1,
          t;

      while (++i <= j) {
        t = i / j;
        this._basis.point(
          this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
          this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
        );
      }
    }

    this._x = this._y = null;
    this._basis.lineEnd();
  },
  point: function(x, y) {
    this._x.push(+x);
    this._y.push(+y);
  }
};

/* harmony default export */ const bundle = ((function custom(beta) {

  function bundle(context) {
    return beta === 1 ? new Basis(context) : new Bundle(context, beta);
  }

  bundle.beta = function(beta) {
    return custom(+beta);
  };

  return bundle;
})(0.85));

;// ../../node_modules/d3-shape/src/curve/cardinal.js
function cardinal_point(that, x, y) {
  that._context.bezierCurveTo(
    that._x1 + that._k * (that._x2 - that._x0),
    that._y1 + that._k * (that._y2 - that._y0),
    that._x2 + that._k * (that._x1 - x),
    that._y2 + that._k * (that._y1 - y),
    that._x2,
    that._y2
  );
}

function Cardinal(context, tension) {
  this._context = context;
  this._k = (1 - tension) / 6;
}

Cardinal.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 = this._x2 =
    this._y0 = this._y1 = this._y2 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 2: this._context.lineTo(this._x2, this._y2); break;
      case 3: cardinal_point(this, this._x1, this._y1); break;
    }
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
      case 2: this._point = 3; // falls through
      default: cardinal_point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const cardinal = ((function custom(tension) {

  function cardinal(context) {
    return new Cardinal(context, tension);
  }

  cardinal.tension = function(tension) {
    return custom(+tension);
  };

  return cardinal;
})(0));

;// ../../node_modules/d3-shape/src/curve/cardinalOpen.js


function CardinalOpen(context, tension) {
  this._context = context;
  this._k = (1 - tension) / 6;
}

CardinalOpen.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 = this._x2 =
    this._y0 = this._y1 = this._y2 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
      case 3: this._point = 4; // falls through
      default: cardinal_point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const cardinalOpen = ((function custom(tension) {

  function cardinal(context) {
    return new CardinalOpen(context, tension);
  }

  cardinal.tension = function(tension) {
    return custom(+tension);
  };

  return cardinal;
})(0));

;// ../../node_modules/d3-shape/src/curve/cardinalClosed.js



function CardinalClosed(context, tension) {
  this._context = context;
  this._k = (1 - tension) / 6;
}

CardinalClosed.prototype = {
  areaStart: src_noop,
  areaEnd: src_noop,
  lineStart: function() {
    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 1: {
        this._context.moveTo(this._x3, this._y3);
        this._context.closePath();
        break;
      }
      case 2: {
        this._context.lineTo(this._x3, this._y3);
        this._context.closePath();
        break;
      }
      case 3: {
        this.point(this._x3, this._y3);
        this.point(this._x4, this._y4);
        this.point(this._x5, this._y5);
        break;
      }
    }
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
      case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
      case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
      default: cardinal_point(this, x, y); break;
    }
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const cardinalClosed = ((function custom(tension) {

  function cardinal(context) {
    return new CardinalClosed(context, tension);
  }

  cardinal.tension = function(tension) {
    return custom(+tension);
  };

  return cardinal;
})(0));

;// ../../node_modules/d3-shape/src/math.js
const math_abs = Math.abs;
const math_atan2 = Math.atan2;
const math_cos = Math.cos;
const math_max = Math.max;
const math_min = Math.min;
const math_sin = Math.sin;
const math_sqrt = Math.sqrt;

const math_epsilon = 1e-12;
const pi = Math.PI;
const halfPi = pi / 2;
const tau = 2 * pi;

function math_acos(x) {
  return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
}

function math_asin(x) {
  return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x);
}

;// ../../node_modules/d3-shape/src/curve/catmullRom.js



function catmullRom_point(that, x, y) {
  var x1 = that._x1,
      y1 = that._y1,
      x2 = that._x2,
      y2 = that._y2;

  if (that._l01_a > math_epsilon) {
    var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
        n = 3 * that._l01_a * (that._l01_a + that._l12_a);
    x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
    y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
  }

  if (that._l23_a > math_epsilon) {
    var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
        m = 3 * that._l23_a * (that._l23_a + that._l12_a);
    x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
    y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
  }

  that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
}

function CatmullRom(context, alpha) {
  this._context = context;
  this._alpha = alpha;
}

CatmullRom.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 = this._x2 =
    this._y0 = this._y1 = this._y2 = NaN;
    this._l01_a = this._l12_a = this._l23_a =
    this._l01_2a = this._l12_2a = this._l23_2a =
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 2: this._context.lineTo(this._x2, this._y2); break;
      case 3: this.point(this._x2, this._y2); break;
    }
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;

    if (this._point) {
      var x23 = this._x2 - x,
          y23 = this._y2 - y;
      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
    }

    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; // falls through
      default: catmullRom_point(this, x, y); break;
    }

    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const catmullRom = ((function custom(alpha) {

  function catmullRom(context) {
    return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
  }

  catmullRom.alpha = function(alpha) {
    return custom(+alpha);
  };

  return catmullRom;
})(0.5));

;// ../../node_modules/d3-shape/src/curve/catmullRomClosed.js




function CatmullRomClosed(context, alpha) {
  this._context = context;
  this._alpha = alpha;
}

CatmullRomClosed.prototype = {
  areaStart: src_noop,
  areaEnd: src_noop,
  lineStart: function() {
    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
    this._l01_a = this._l12_a = this._l23_a =
    this._l01_2a = this._l12_2a = this._l23_2a =
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 1: {
        this._context.moveTo(this._x3, this._y3);
        this._context.closePath();
        break;
      }
      case 2: {
        this._context.lineTo(this._x3, this._y3);
        this._context.closePath();
        break;
      }
      case 3: {
        this.point(this._x3, this._y3);
        this.point(this._x4, this._y4);
        this.point(this._x5, this._y5);
        break;
      }
    }
  },
  point: function(x, y) {
    x = +x, y = +y;

    if (this._point) {
      var x23 = this._x2 - x,
          y23 = this._y2 - y;
      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
    }

    switch (this._point) {
      case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
      case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
      case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
      default: catmullRom_point(this, x, y); break;
    }

    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const catmullRomClosed = ((function custom(alpha) {

  function catmullRom(context) {
    return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
  }

  catmullRom.alpha = function(alpha) {
    return custom(+alpha);
  };

  return catmullRom;
})(0.5));

;// ../../node_modules/d3-shape/src/curve/catmullRomOpen.js



function CatmullRomOpen(context, alpha) {
  this._context = context;
  this._alpha = alpha;
}

CatmullRomOpen.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 = this._x2 =
    this._y0 = this._y1 = this._y2 = NaN;
    this._l01_a = this._l12_a = this._l23_a =
    this._l01_2a = this._l12_2a = this._l23_2a =
    this._point = 0;
  },
  lineEnd: function() {
    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;

    if (this._point) {
      var x23 = this._x2 - x,
          y23 = this._y2 - y;
      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
    }

    switch (this._point) {
      case 0: this._point = 1; break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
      case 3: this._point = 4; // falls through
      default: catmullRom_point(this, x, y); break;
    }

    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  }
};

/* harmony default export */ const catmullRomOpen = ((function custom(alpha) {

  function catmullRom(context) {
    return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
  }

  catmullRom.alpha = function(alpha) {
    return custom(+alpha);
  };

  return catmullRom;
})(0.5));

;// ../../node_modules/d3-shape/src/curve/linear.js
function Linear(context) {
  this._context = context;
}

Linear.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._point = 0;
  },
  lineEnd: function() {
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; // falls through
      default: this._context.lineTo(x, y); break;
    }
  }
};

/* harmony default export */ function curve_linear(context) {
  return new Linear(context);
}

;// ../../node_modules/d3-shape/src/curve/linearClosed.js


function LinearClosed(context) {
  this._context = context;
}

LinearClosed.prototype = {
  areaStart: src_noop,
  areaEnd: src_noop,
  lineStart: function() {
    this._point = 0;
  },
  lineEnd: function() {
    if (this._point) this._context.closePath();
  },
  point: function(x, y) {
    x = +x, y = +y;
    if (this._point) this._context.lineTo(x, y);
    else this._point = 1, this._context.moveTo(x, y);
  }
};

/* harmony default export */ function linearClosed(context) {
  return new LinearClosed(context);
}

;// ../../node_modules/d3-shape/src/curve/monotone.js
function monotone_sign(x) {
  return x < 0 ? -1 : 1;
}

// Calculate the slopes of the tangents (Hermite-type interpolation) based on
// the following paper: Steffen, M. 1990. A Simple Method for Monotonic
// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
// NOV(II), P. 443, 1990.
function slope3(that, x2, y2) {
  var h0 = that._x1 - that._x0,
      h1 = x2 - that._x1,
      s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
      s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
      p = (s0 * h1 + s1 * h0) / (h0 + h1);
  return (monotone_sign(s0) + monotone_sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
}

// Calculate a one-sided slope.
function slope2(that, t) {
  var h = that._x1 - that._x0;
  return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
}

// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
function monotone_point(that, t0, t1) {
  var x0 = that._x0,
      y0 = that._y0,
      x1 = that._x1,
      y1 = that._y1,
      dx = (x1 - x0) / 3;
  that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
}

function MonotoneX(context) {
  this._context = context;
}

MonotoneX.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x0 = this._x1 =
    this._y0 = this._y1 =
    this._t0 = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    switch (this._point) {
      case 2: this._context.lineTo(this._x1, this._y1); break;
      case 3: monotone_point(this, this._t0, slope2(this, this._t0)); break;
    }
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    this._line = 1 - this._line;
  },
  point: function(x, y) {
    var t1 = NaN;

    x = +x, y = +y;
    if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; break;
      case 2: this._point = 3; monotone_point(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
      default: monotone_point(this, this._t0, t1 = slope3(this, x, y)); break;
    }

    this._x0 = this._x1, this._x1 = x;
    this._y0 = this._y1, this._y1 = y;
    this._t0 = t1;
  }
}

function MonotoneY(context) {
  this._context = new ReflectContext(context);
}

(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
  MonotoneX.prototype.point.call(this, y, x);
};

function ReflectContext(context) {
  this._context = context;
}

ReflectContext.prototype = {
  moveTo: function(x, y) { this._context.moveTo(y, x); },
  closePath: function() { this._context.closePath(); },
  lineTo: function(x, y) { this._context.lineTo(y, x); },
  bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
};

function monotoneX(context) {
  return new MonotoneX(context);
}

function monotoneY(context) {
  return new MonotoneY(context);
}

;// ../../node_modules/d3-shape/src/curve/natural.js
function Natural(context) {
  this._context = context;
}

Natural.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x = [];
    this._y = [];
  },
  lineEnd: function() {
    var x = this._x,
        y = this._y,
        n = x.length;

    if (n) {
      this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
      if (n === 2) {
        this._context.lineTo(x[1], y[1]);
      } else {
        var px = controlPoints(x),
            py = controlPoints(y);
        for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
          this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
        }
      }
    }

    if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
    this._line = 1 - this._line;
    this._x = this._y = null;
  },
  point: function(x, y) {
    this._x.push(+x);
    this._y.push(+y);
  }
};

// See https://www.particleincell.com/2012/bezier-splines/ for derivation.
function controlPoints(x) {
  var i,
      n = x.length - 1,
      m,
      a = new Array(n),
      b = new Array(n),
      r = new Array(n);
  a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
  for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
  a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
  for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
  a[n - 1] = r[n - 1] / b[n - 1];
  for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
  b[n - 1] = (x[n] + a[n - 1]) / 2;
  for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
  return [a, b];
}

/* harmony default export */ function natural(context) {
  return new Natural(context);
}

;// ../../node_modules/d3-shape/src/curve/step.js
function Step(context, t) {
  this._context = context;
  this._t = t;
}

Step.prototype = {
  areaStart: function() {
    this._line = 0;
  },
  areaEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._x = this._y = NaN;
    this._point = 0;
  },
  lineEnd: function() {
    if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
    if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
  },
  point: function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; // falls through
      default: {
        if (this._t <= 0) {
          this._context.lineTo(this._x, y);
          this._context.lineTo(x, y);
        } else {
          var x1 = this._x * (1 - this._t) + x * this._t;
          this._context.lineTo(x1, this._y);
          this._context.lineTo(x1, y);
        }
        break;
      }
    }
    this._x = x, this._y = y;
  }
};

/* harmony default export */ function step(context) {
  return new Step(context, 0.5);
}

function stepBefore(context) {
  return new Step(context, 0);
}

function stepAfter(context) {
  return new Step(context, 1);
}

;// ../../node_modules/d3-shape/src/constant.js
/* harmony default export */ function src_constant(x) {
  return function constant() {
    return x;
  };
}

;// ../../node_modules/d3-path/src/path.js
const path_pi = Math.PI,
    path_tau = 2 * path_pi,
    path_epsilon = 1e-6,
    tauEpsilon = path_tau - path_epsilon;

function path_append(strings) {
  this._ += strings[0];
  for (let i = 1, n = strings.length; i < n; ++i) {
    this._ += arguments[i] + strings[i];
  }
}

function appendRound(digits) {
  let d = Math.floor(digits);
  if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);
  if (d > 15) return path_append;
  const k = 10 ** d;
  return function(strings) {
    this._ += strings[0];
    for (let i = 1, n = strings.length; i < n; ++i) {
      this._ += Math.round(arguments[i] * k) / k + strings[i];
    }
  };
}

class Path {
  constructor(digits) {
    this._x0 = this._y0 = // start of current subpath
    this._x1 = this._y1 = null; // end of current subpath
    this._ = "";
    this._append = digits == null ? path_append : appendRound(digits);
  }
  moveTo(x, y) {
    this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}`;
  }
  closePath() {
    if (this._x1 !== null) {
      this._x1 = this._x0, this._y1 = this._y0;
      this._append`Z`;
    }
  }
  lineTo(x, y) {
    this._append`L${this._x1 = +x},${this._y1 = +y}`;
  }
  quadraticCurveTo(x1, y1, x, y) {
    this._append`Q${+x1},${+y1},${this._x1 = +x},${this._y1 = +y}`;
  }
  bezierCurveTo(x1, y1, x2, y2, x, y) {
    this._append`C${+x1},${+y1},${+x2},${+y2},${this._x1 = +x},${this._y1 = +y}`;
  }
  arcTo(x1, y1, x2, y2, r) {
    x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;

    // Is the radius negative? Error.
    if (r < 0) throw new Error(`negative radius: ${r}`);

    let x0 = this._x1,
        y0 = this._y1,
        x21 = x2 - x1,
        y21 = y2 - y1,
        x01 = x0 - x1,
        y01 = y0 - y1,
        l01_2 = x01 * x01 + y01 * y01;

    // Is this path empty? Move to (x1,y1).
    if (this._x1 === null) {
      this._append`M${this._x1 = x1},${this._y1 = y1}`;
    }

    // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
    else if (!(l01_2 > path_epsilon));

    // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
    // Equivalently, is (x1,y1) coincident with (x2,y2)?
    // Or, is the radius zero? Line to (x1,y1).
    else if (!(Math.abs(y01 * x21 - y21 * x01) > path_epsilon) || !r) {
      this._append`L${this._x1 = x1},${this._y1 = y1}`;
    }

    // Otherwise, draw an arc!
    else {
      let x20 = x2 - x0,
          y20 = y2 - y0,
          l21_2 = x21 * x21 + y21 * y21,
          l20_2 = x20 * x20 + y20 * y20,
          l21 = Math.sqrt(l21_2),
          l01 = Math.sqrt(l01_2),
          l = r * Math.tan((path_pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
          t01 = l / l01,
          t21 = l / l21;

      // If the start tangent is not coincident with (x0,y0), line to.
      if (Math.abs(t01 - 1) > path_epsilon) {
        this._append`L${x1 + t01 * x01},${y1 + t01 * y01}`;
      }

      this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x1 + t21 * x21},${this._y1 = y1 + t21 * y21}`;
    }
  }
  arc(x, y, r, a0, a1, ccw) {
    x = +x, y = +y, r = +r, ccw = !!ccw;

    // Is the radius negative? Error.
    if (r < 0) throw new Error(`negative radius: ${r}`);

    let dx = r * Math.cos(a0),
        dy = r * Math.sin(a0),
        x0 = x + dx,
        y0 = y + dy,
        cw = 1 ^ ccw,
        da = ccw ? a0 - a1 : a1 - a0;

    // Is this path empty? Move to (x0,y0).
    if (this._x1 === null) {
      this._append`M${x0},${y0}`;
    }

    // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
    else if (Math.abs(this._x1 - x0) > path_epsilon || Math.abs(this._y1 - y0) > path_epsilon) {
      this._append`L${x0},${y0}`;
    }

    // Is this arc empty? We’re done.
    if (!r) return;

    // Does the angle go the wrong way? Flip the direction.
    if (da < 0) da = da % path_tau + path_tau;

    // Is this a complete circle? Draw two arcs to complete the circle.
    if (da > tauEpsilon) {
      this._append`A${r},${r},0,1,${cw},${x - dx},${y - dy}A${r},${r},0,1,${cw},${this._x1 = x0},${this._y1 = y0}`;
    }

    // Is this arc non-empty? Draw an arc!
    else if (da > path_epsilon) {
      this._append`A${r},${r},0,${+(da >= path_pi)},${cw},${this._x1 = x + r * Math.cos(a1)},${this._y1 = y + r * Math.sin(a1)}`;
    }
  }
  rect(x, y, w, h) {
    this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}h${w = +w}v${+h}h${-w}Z`;
  }
  toString() {
    return this._;
  }
}

function path() {
  return new Path;
}

// Allow instanceof d3.path
path.prototype = Path.prototype;

function pathRound(digits = 3) {
  return new Path(+digits);
}

;// ../../node_modules/d3-shape/src/path.js


function withPath(shape) {
  let digits = 3;

  shape.digits = function(_) {
    if (!arguments.length) return digits;
    if (_ == null) {
      digits = null;
    } else {
      const d = Math.floor(_);
      if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);
      digits = d;
    }
    return shape;
  };

  return () => new Path(digits);
}

;// ../../node_modules/d3-shape/src/arc.js




function arcInnerRadius(d) {
  return d.innerRadius;
}

function arcOuterRadius(d) {
  return d.outerRadius;
}

function arcStartAngle(d) {
  return d.startAngle;
}

function arcEndAngle(d) {
  return d.endAngle;
}

function arcPadAngle(d) {
  return d && d.padAngle; // Note: optional!
}

function arc_intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
  var x10 = x1 - x0, y10 = y1 - y0,
      x32 = x3 - x2, y32 = y3 - y2,
      t = y32 * x10 - x32 * y10;
  if (t * t < math_epsilon) return;
  t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;
  return [x0 + t * x10, y0 + t * y10];
}

// Compute perpendicular offset line of length rc.
// http://mathworld.wolfram.com/Circle-LineIntersection.html
function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
  var x01 = x0 - x1,
      y01 = y0 - y1,
      lo = (cw ? rc : -rc) / math_sqrt(x01 * x01 + y01 * y01),
      ox = lo * y01,
      oy = -lo * x01,
      x11 = x0 + ox,
      y11 = y0 + oy,
      x10 = x1 + ox,
      y10 = y1 + oy,
      x00 = (x11 + x10) / 2,
      y00 = (y11 + y10) / 2,
      dx = x10 - x11,
      dy = y10 - y11,
      d2 = dx * dx + dy * dy,
      r = r1 - rc,
      D = x11 * y10 - x10 * y11,
      d = (dy < 0 ? -1 : 1) * math_sqrt(math_max(0, r * r * d2 - D * D)),
      cx0 = (D * dy - dx * d) / d2,
      cy0 = (-D * dx - dy * d) / d2,
      cx1 = (D * dy + dx * d) / d2,
      cy1 = (-D * dx + dy * d) / d2,
      dx0 = cx0 - x00,
      dy0 = cy0 - y00,
      dx1 = cx1 - x00,
      dy1 = cy1 - y00;

  // Pick the closer of the two intersection points.
  // TODO Is there a faster way to determine which intersection to use?
  if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;

  return {
    cx: cx0,
    cy: cy0,
    x01: -ox,
    y01: -oy,
    x11: cx0 * (r1 / r - 1),
    y11: cy0 * (r1 / r - 1)
  };
}

/* harmony default export */ function arc() {
  var innerRadius = arcInnerRadius,
      outerRadius = arcOuterRadius,
      cornerRadius = src_constant(0),
      padRadius = null,
      startAngle = arcStartAngle,
      endAngle = arcEndAngle,
      padAngle = arcPadAngle,
      context = null,
      path = withPath(arc);

  function arc() {
    var buffer,
        r,
        r0 = +innerRadius.apply(this, arguments),
        r1 = +outerRadius.apply(this, arguments),
        a0 = startAngle.apply(this, arguments) - halfPi,
        a1 = endAngle.apply(this, arguments) - halfPi,
        da = math_abs(a1 - a0),
        cw = a1 > a0;

    if (!context) context = buffer = path();

    // Ensure that the outer radius is always larger than the inner radius.
    if (r1 < r0) r = r1, r1 = r0, r0 = r;

    // Is it a point?
    if (!(r1 > math_epsilon)) context.moveTo(0, 0);

    // Or is it a circle or annulus?
    else if (da > tau - math_epsilon) {
      context.moveTo(r1 * math_cos(a0), r1 * math_sin(a0));
      context.arc(0, 0, r1, a0, a1, !cw);
      if (r0 > math_epsilon) {
        context.moveTo(r0 * math_cos(a1), r0 * math_sin(a1));
        context.arc(0, 0, r0, a1, a0, cw);
      }
    }

    // Or is it a circular or annular sector?
    else {
      var a01 = a0,
          a11 = a1,
          a00 = a0,
          a10 = a1,
          da0 = da,
          da1 = da,
          ap = padAngle.apply(this, arguments) / 2,
          rp = (ap > math_epsilon) && (padRadius ? +padRadius.apply(this, arguments) : math_sqrt(r0 * r0 + r1 * r1)),
          rc = math_min(math_abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
          rc0 = rc,
          rc1 = rc,
          t0,
          t1;

      // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
      if (rp > math_epsilon) {
        var p0 = math_asin(rp / r0 * math_sin(ap)),
            p1 = math_asin(rp / r1 * math_sin(ap));
        if ((da0 -= p0 * 2) > math_epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
        else da0 = 0, a00 = a10 = (a0 + a1) / 2;
        if ((da1 -= p1 * 2) > math_epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
        else da1 = 0, a01 = a11 = (a0 + a1) / 2;
      }

      var x01 = r1 * math_cos(a01),
          y01 = r1 * math_sin(a01),
          x10 = r0 * math_cos(a10),
          y10 = r0 * math_sin(a10);

      // Apply rounded corners?
      if (rc > math_epsilon) {
        var x11 = r1 * math_cos(a11),
            y11 = r1 * math_sin(a11),
            x00 = r0 * math_cos(a00),
            y00 = r0 * math_sin(a00),
            oc;

        // Restrict the corner radius according to the sector angle. If this
        // intersection fails, it’s probably because the arc is too small, so
        // disable the corner radius entirely.
        if (da < pi) {
          if (oc = arc_intersect(x01, y01, x00, y00, x11, y11, x10, y10)) {
            var ax = x01 - oc[0],
                ay = y01 - oc[1],
                bx = x11 - oc[0],
                by = y11 - oc[1],
                kc = 1 / math_sin(math_acos((ax * bx + ay * by) / (math_sqrt(ax * ax + ay * ay) * math_sqrt(bx * bx + by * by))) / 2),
                lc = math_sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
            rc0 = math_min(rc, (r0 - lc) / (kc - 1));
            rc1 = math_min(rc, (r1 - lc) / (kc + 1));
          } else {
            rc0 = rc1 = 0;
          }
        }
      }

      // Is the sector collapsed to a line?
      if (!(da1 > math_epsilon)) context.moveTo(x01, y01);

      // Does the sector’s outer ring have rounded corners?
      else if (rc1 > math_epsilon) {
        t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
        t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);

        context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);

        // Have the corners merged?
        if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, math_atan2(t0.y01, t0.x01), math_atan2(t1.y01, t1.x01), !cw);

        // Otherwise, draw the two corners and the ring.
        else {
          context.arc(t0.cx, t0.cy, rc1, math_atan2(t0.y01, t0.x01), math_atan2(t0.y11, t0.x11), !cw);
          context.arc(0, 0, r1, math_atan2(t0.cy + t0.y11, t0.cx + t0.x11), math_atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
          context.arc(t1.cx, t1.cy, rc1, math_atan2(t1.y11, t1.x11), math_atan2(t1.y01, t1.x01), !cw);
        }
      }

      // Or is the outer ring just a circular arc?
      else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);

      // Is there no inner ring, and it’s a circular sector?
      // Or perhaps it’s an annular sector collapsed due to padding?
      if (!(r0 > math_epsilon) || !(da0 > math_epsilon)) context.lineTo(x10, y10);

      // Does the sector’s inner ring (or point) have rounded corners?
      else if (rc0 > math_epsilon) {
        t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
        t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);

        context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);

        // Have the corners merged?
        if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, math_atan2(t0.y01, t0.x01), math_atan2(t1.y01, t1.x01), !cw);

        // Otherwise, draw the two corners and the ring.
        else {
          context.arc(t0.cx, t0.cy, rc0, math_atan2(t0.y01, t0.x01), math_atan2(t0.y11, t0.x11), !cw);
          context.arc(0, 0, r0, math_atan2(t0.cy + t0.y11, t0.cx + t0.x11), math_atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);
          context.arc(t1.cx, t1.cy, rc0, math_atan2(t1.y11, t1.x11), math_atan2(t1.y01, t1.x01), !cw);
        }
      }

      // Or is the inner ring just a circular arc?
      else context.arc(0, 0, r0, a10, a00, cw);
    }

    context.closePath();

    if (buffer) return context = null, buffer + "" || null;
  }

  arc.centroid = function() {
    var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
        a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2;
    return [math_cos(a) * r, math_sin(a) * r];
  };

  arc.innerRadius = function(_) {
    return arguments.length ? (innerRadius = typeof _ === "function" ? _ : src_constant(+_), arc) : innerRadius;
  };

  arc.outerRadius = function(_) {
    return arguments.length ? (outerRadius = typeof _ === "function" ? _ : src_constant(+_), arc) : outerRadius;
  };

  arc.cornerRadius = function(_) {
    return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : src_constant(+_), arc) : cornerRadius;
  };

  arc.padRadius = function(_) {
    return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : src_constant(+_), arc) : padRadius;
  };

  arc.startAngle = function(_) {
    return arguments.length ? (startAngle = typeof _ === "function" ? _ : src_constant(+_), arc) : startAngle;
  };

  arc.endAngle = function(_) {
    return arguments.length ? (endAngle = typeof _ === "function" ? _ : src_constant(+_), arc) : endAngle;
  };

  arc.padAngle = function(_) {
    return arguments.length ? (padAngle = typeof _ === "function" ? _ : src_constant(+_), arc) : padAngle;
  };

  arc.context = function(_) {
    return arguments.length ? ((context = _ == null ? null : _), arc) : context;
  };

  return arc;
}

;// ../../node_modules/d3-shape/src/array.js
var array_slice = Array.prototype.slice;

/* harmony default export */ function src_array(x) {
  return typeof x === "object" && "length" in x
    ? x // Array, TypedArray, NodeList, array-like
    : Array.from(x); // Map, Set, iterable, string, or anything else
}

;// ../../node_modules/d3-shape/src/point.js
function point_x(p) {
  return p[0];
}

function point_y(p) {
  return p[1];
}

;// ../../node_modules/d3-shape/src/line.js






/* harmony default export */ function line(x, y) {
  var defined = src_constant(true),
      context = null,
      curve = curve_linear,
      output = null,
      path = withPath(line);

  x = typeof x === "function" ? x : (x === undefined) ? point_x : src_constant(x);
  y = typeof y === "function" ? y : (y === undefined) ? point_y : src_constant(y);

  function line(data) {
    var i,
        n = (data = src_array(data)).length,
        d,
        defined0 = false,
        buffer;

    if (context == null) output = curve(buffer = path());

    for (i = 0; i <= n; ++i) {
      if (!(i < n && defined(d = data[i], i, data)) === defined0) {
        if (defined0 = !defined0) output.lineStart();
        else output.lineEnd();
      }
      if (defined0) output.point(+x(d, i, data), +y(d, i, data));
    }

    if (buffer) return output = null, buffer + "" || null;
  }

  line.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : src_constant(+_), line) : x;
  };

  line.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : src_constant(+_), line) : y;
  };

  line.defined = function(_) {
    return arguments.length ? (defined = typeof _ === "function" ? _ : src_constant(!!_), line) : defined;
  };

  line.curve = function(_) {
    return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
  };

  line.context = function(_) {
    return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
  };

  return line;
}

;// ../../node_modules/d3-shape/src/area.js







/* harmony default export */ function src_area(x0, y0, y1) {
  var x1 = null,
      defined = src_constant(true),
      context = null,
      curve = curve_linear,
      output = null,
      path = withPath(area);

  x0 = typeof x0 === "function" ? x0 : (x0 === undefined) ? point_x : src_constant(+x0);
  y0 = typeof y0 === "function" ? y0 : (y0 === undefined) ? src_constant(0) : src_constant(+y0);
  y1 = typeof y1 === "function" ? y1 : (y1 === undefined) ? point_y : src_constant(+y1);

  function area(data) {
    var i,
        j,
        k,
        n = (data = src_array(data)).length,
        d,
        defined0 = false,
        buffer,
        x0z = new Array(n),
        y0z = new Array(n);

    if (context == null) output = curve(buffer = path());

    for (i = 0; i <= n; ++i) {
      if (!(i < n && defined(d = data[i], i, data)) === defined0) {
        if (defined0 = !defined0) {
          j = i;
          output.areaStart();
          output.lineStart();
        } else {
          output.lineEnd();
          output.lineStart();
          for (k = i - 1; k >= j; --k) {
            output.point(x0z[k], y0z[k]);
          }
          output.lineEnd();
          output.areaEnd();
        }
      }
      if (defined0) {
        x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
        output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
      }
    }

    if (buffer) return output = null, buffer + "" || null;
  }

  function arealine() {
    return line().defined(defined).curve(curve).context(context);
  }

  area.x = function(_) {
    return arguments.length ? (x0 = typeof _ === "function" ? _ : src_constant(+_), x1 = null, area) : x0;
  };

  area.x0 = function(_) {
    return arguments.length ? (x0 = typeof _ === "function" ? _ : src_constant(+_), area) : x0;
  };

  area.x1 = function(_) {
    return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : src_constant(+_), area) : x1;
  };

  area.y = function(_) {
    return arguments.length ? (y0 = typeof _ === "function" ? _ : src_constant(+_), y1 = null, area) : y0;
  };

  area.y0 = function(_) {
    return arguments.length ? (y0 = typeof _ === "function" ? _ : src_constant(+_), area) : y0;
  };

  area.y1 = function(_) {
    return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : src_constant(+_), area) : y1;
  };

  area.lineX0 =
  area.lineY0 = function() {
    return arealine().x(x0).y(y0);
  };

  area.lineY1 = function() {
    return arealine().x(x0).y(y1);
  };

  area.lineX1 = function() {
    return arealine().x(x1).y(y0);
  };

  area.defined = function(_) {
    return arguments.length ? (defined = typeof _ === "function" ? _ : src_constant(!!_), area) : defined;
  };

  area.curve = function(_) {
    return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
  };

  area.context = function(_) {
    return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
  };

  return area;
}

;// ../../node_modules/d3-shape/src/symbol/asterisk.js


const sqrt3 = math_sqrt(3);

/* harmony default export */ const asterisk = ({
  draw(context, size) {
    const r = math_sqrt(size + math_min(size / 28, 0.75)) * 0.59436;
    const t = r / 2;
    const u = t * sqrt3;
    context.moveTo(0, r);
    context.lineTo(0, -r);
    context.moveTo(-u, -t);
    context.lineTo(u, t);
    context.moveTo(-u, t);
    context.lineTo(u, -t);
  }
});

;// ../../node_modules/d3-shape/src/symbol/circle.js


/* harmony default export */ const circle = ({
  draw(context, size) {
    const r = math_sqrt(size / pi);
    context.moveTo(r, 0);
    context.arc(0, 0, r, 0, tau);
  }
});

;// ../../node_modules/d3-shape/src/symbol/cross.js


/* harmony default export */ const symbol_cross = ({
  draw(context, size) {
    const r = math_sqrt(size / 5) / 2;
    context.moveTo(-3 * r, -r);
    context.lineTo(-r, -r);
    context.lineTo(-r, -3 * r);
    context.lineTo(r, -3 * r);
    context.lineTo(r, -r);
    context.lineTo(3 * r, -r);
    context.lineTo(3 * r, r);
    context.lineTo(r, r);
    context.lineTo(r, 3 * r);
    context.lineTo(-r, 3 * r);
    context.lineTo(-r, r);
    context.lineTo(-3 * r, r);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/diamond.js


const tan30 = math_sqrt(1 / 3);
const tan30_2 = tan30 * 2;

/* harmony default export */ const diamond = ({
  draw(context, size) {
    const y = math_sqrt(size / tan30_2);
    const x = y * tan30;
    context.moveTo(0, -y);
    context.lineTo(x, 0);
    context.lineTo(0, y);
    context.lineTo(-x, 0);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/diamond2.js


/* harmony default export */ const diamond2 = ({
  draw(context, size) {
    const r = math_sqrt(size) * 0.62625;
    context.moveTo(0, -r);
    context.lineTo(r, 0);
    context.lineTo(0, r);
    context.lineTo(-r, 0);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/plus.js


/* harmony default export */ const plus = ({
  draw(context, size) {
    const r = math_sqrt(size - math_min(size / 7, 2)) * 0.87559;
    context.moveTo(-r, 0);
    context.lineTo(r, 0);
    context.moveTo(0, r);
    context.lineTo(0, -r);
  }
});

;// ../../node_modules/d3-shape/src/symbol/square.js


/* harmony default export */ const square = ({
  draw(context, size) {
    const w = math_sqrt(size);
    const x = -w / 2;
    context.rect(x, x, w, w);
  }
});

;// ../../node_modules/d3-shape/src/symbol/square2.js


/* harmony default export */ const square2 = ({
  draw(context, size) {
    const r = math_sqrt(size) * 0.4431;
    context.moveTo(r, r);
    context.lineTo(r, -r);
    context.lineTo(-r, -r);
    context.lineTo(-r, r);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/star.js


const ka = 0.89081309152928522810;
const kr = math_sin(pi / 10) / math_sin(7 * pi / 10);
const kx = math_sin(tau / 10) * kr;
const ky = -math_cos(tau / 10) * kr;

/* harmony default export */ const star = ({
  draw(context, size) {
    const r = math_sqrt(size * ka);
    const x = kx * r;
    const y = ky * r;
    context.moveTo(0, -r);
    context.lineTo(x, y);
    for (let i = 1; i < 5; ++i) {
      const a = tau * i / 5;
      const c = math_cos(a);
      const s = math_sin(a);
      context.lineTo(s * r, -c * r);
      context.lineTo(c * x - s * y, s * x + c * y);
    }
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/triangle.js


const triangle_sqrt3 = math_sqrt(3);

/* harmony default export */ const triangle = ({
  draw(context, size) {
    const y = -math_sqrt(size / (triangle_sqrt3 * 3));
    context.moveTo(0, y * 2);
    context.lineTo(-triangle_sqrt3 * y, -y);
    context.lineTo(triangle_sqrt3 * y, -y);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/triangle2.js


const triangle2_sqrt3 = math_sqrt(3);

/* harmony default export */ const triangle2 = ({
  draw(context, size) {
    const s = math_sqrt(size) * 0.6824;
    const t = s  / 2;
    const u = (s * triangle2_sqrt3) / 2; // cos(Math.PI / 6)
    context.moveTo(0, -s);
    context.lineTo(u, t);
    context.lineTo(-u, t);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/wye.js


const c = -0.5;
const s = math_sqrt(3) / 2;
const k = 1 / math_sqrt(12);
const a = (k / 2 + 1) * 3;

/* harmony default export */ const wye = ({
  draw(context, size) {
    const r = math_sqrt(size / a);
    const x0 = r / 2, y0 = r * k;
    const x1 = x0, y1 = r * k + r;
    const x2 = -x1, y2 = y1;
    context.moveTo(x0, y0);
    context.lineTo(x1, y1);
    context.lineTo(x2, y2);
    context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
    context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
    context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
    context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
    context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
    context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
    context.closePath();
  }
});

;// ../../node_modules/d3-shape/src/symbol/times.js


/* harmony default export */ const times = ({
  draw(context, size) {
    const r = math_sqrt(size - math_min(size / 6, 1.7)) * 0.6189;
    context.moveTo(-r, -r);
    context.lineTo(r, r);
    context.moveTo(-r, r);
    context.lineTo(r, -r);
  }
});

;// ../../node_modules/d3-shape/src/symbol.js
















// These symbols are designed to be filled.
const symbolsFill = [
  circle,
  symbol_cross,
  diamond,
  square,
  star,
  triangle,
  wye
];

// These symbols are designed to be stroked (with a width of 1.5px and round caps).
const symbolsStroke = [
  circle,
  plus,
  times,
  triangle2,
  asterisk,
  square2,
  diamond2
];

function symbol_Symbol(type, size) {
  let context = null,
      path = withPath(symbol);

  type = typeof type === "function" ? type : src_constant(type || circle);
  size = typeof size === "function" ? size : src_constant(size === undefined ? 64 : +size);

  function symbol() {
    let buffer;
    if (!context) context = buffer = path();
    type.apply(this, arguments).draw(context, +size.apply(this, arguments));
    if (buffer) return context = null, buffer + "" || null;
  }

  symbol.type = function(_) {
    return arguments.length ? (type = typeof _ === "function" ? _ : src_constant(_), symbol) : type;
  };

  symbol.size = function(_) {
    return arguments.length ? (size = typeof _ === "function" ? _ : src_constant(+_), symbol) : size;
  };

  symbol.context = function(_) {
    return arguments.length ? (context = _ == null ? null : _, symbol) : context;
  };

  return symbol;
}

;// ../../node_modules/vega-canvas/build/vega-canvas.browser.module.js
function domCanvas(w, h) {
  if (typeof document !== 'undefined' && document.createElement) {
    const c = document.createElement('canvas');
    if (c && c.getContext) {
      c.width = w;
      c.height = h;
      return c;
    }
  }
  return null;
}
const domImage = () => typeof Image !== 'undefined' ? Image : null;



;// ../../node_modules/d3-array/src/bisect.js




const ascendingBisect = bisector_bisector(ascending_ascending);
const bisectRight = ascendingBisect.right;
const bisectLeft = ascendingBisect.left;
const bisectCenter = bisector_bisector(number_number).center;
/* harmony default export */ const src_bisect = (bisectRight);

;// ../../node_modules/d3-color/src/define.js
/* harmony default export */ function src_define(constructor, factory, prototype) {
  constructor.prototype = factory.prototype = prototype;
  prototype.constructor = constructor;
}

function define_extend(parent, definition) {
  var prototype = Object.create(parent.prototype);
  for (var key in definition) prototype[key] = definition[key];
  return prototype;
}

;// ../../node_modules/d3-color/src/color.js


function Color() {}

var darker = 0.7;
var brighter = 1 / darker;

var reI = "\\s*([+-]?\\d+)\\s*",
    reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",
    reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
    reHex = /^#([0-9a-f]{3,8})$/,
    reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`),
    reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`),
    reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`),
    reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`),
    reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`),
    reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`);

var named = {
  aliceblue: 0xf0f8ff,
  antiquewhite: 0xfaebd7,
  aqua: 0x00ffff,
  aquamarine: 0x7fffd4,
  azure: 0xf0ffff,
  beige: 0xf5f5dc,
  bisque: 0xffe4c4,
  black: 0x000000,
  blanchedalmond: 0xffebcd,
  blue: 0x0000ff,
  blueviolet: 0x8a2be2,
  brown: 0xa52a2a,
  burlywood: 0xdeb887,
  cadetblue: 0x5f9ea0,
  chartreuse: 0x7fff00,
  chocolate: 0xd2691e,
  coral: 0xff7f50,
  cornflowerblue: 0x6495ed,
  cornsilk: 0xfff8dc,
  crimson: 0xdc143c,
  cyan: 0x00ffff,
  darkblue: 0x00008b,
  darkcyan: 0x008b8b,
  darkgoldenrod: 0xb8860b,
  darkgray: 0xa9a9a9,
  darkgreen: 0x006400,
  darkgrey: 0xa9a9a9,
  darkkhaki: 0xbdb76b,
  darkmagenta: 0x8b008b,
  darkolivegreen: 0x556b2f,
  darkorange: 0xff8c00,
  darkorchid: 0x9932cc,
  darkred: 0x8b0000,
  darksalmon: 0xe9967a,
  darkseagreen: 0x8fbc8f,
  darkslateblue: 0x483d8b,
  darkslategray: 0x2f4f4f,
  darkslategrey: 0x2f4f4f,
  darkturquoise: 0x00ced1,
  darkviolet: 0x9400d3,
  deeppink: 0xff1493,
  deepskyblue: 0x00bfff,
  dimgray: 0x696969,
  dimgrey: 0x696969,
  dodgerblue: 0x1e90ff,
  firebrick: 0xb22222,
  floralwhite: 0xfffaf0,
  forestgreen: 0x228b22,
  fuchsia: 0xff00ff,
  gainsboro: 0xdcdcdc,
  ghostwhite: 0xf8f8ff,
  gold: 0xffd700,
  goldenrod: 0xdaa520,
  gray: 0x808080,
  green: 0x008000,
  greenyellow: 0xadff2f,
  grey: 0x808080,
  honeydew: 0xf0fff0,
  hotpink: 0xff69b4,
  indianred: 0xcd5c5c,
  indigo: 0x4b0082,
  ivory: 0xfffff0,
  khaki: 0xf0e68c,
  lavender: 0xe6e6fa,
  lavenderblush: 0xfff0f5,
  lawngreen: 0x7cfc00,
  lemonchiffon: 0xfffacd,
  lightblue: 0xadd8e6,
  lightcoral: 0xf08080,
  lightcyan: 0xe0ffff,
  lightgoldenrodyellow: 0xfafad2,
  lightgray: 0xd3d3d3,
  lightgreen: 0x90ee90,
  lightgrey: 0xd3d3d3,
  lightpink: 0xffb6c1,
  lightsalmon: 0xffa07a,
  lightseagreen: 0x20b2aa,
  lightskyblue: 0x87cefa,
  lightslategray: 0x778899,
  lightslategrey: 0x778899,
  lightsteelblue: 0xb0c4de,
  lightyellow: 0xffffe0,
  lime: 0x00ff00,
  limegreen: 0x32cd32,
  linen: 0xfaf0e6,
  magenta: 0xff00ff,
  maroon: 0x800000,
  mediumaquamarine: 0x66cdaa,
  mediumblue: 0x0000cd,
  mediumorchid: 0xba55d3,
  mediumpurple: 0x9370db,
  mediumseagreen: 0x3cb371,
  mediumslateblue: 0x7b68ee,
  mediumspringgreen: 0x00fa9a,
  mediumturquoise: 0x48d1cc,
  mediumvioletred: 0xc71585,
  midnightblue: 0x191970,
  mintcream: 0xf5fffa,
  mistyrose: 0xffe4e1,
  moccasin: 0xffe4b5,
  navajowhite: 0xffdead,
  navy: 0x000080,
  oldlace: 0xfdf5e6,
  olive: 0x808000,
  olivedrab: 0x6b8e23,
  orange: 0xffa500,
  orangered: 0xff4500,
  orchid: 0xda70d6,
  palegoldenrod: 0xeee8aa,
  palegreen: 0x98fb98,
  paleturquoise: 0xafeeee,
  palevioletred: 0xdb7093,
  papayawhip: 0xffefd5,
  peachpuff: 0xffdab9,
  peru: 0xcd853f,
  pink: 0xffc0cb,
  plum: 0xdda0dd,
  powderblue: 0xb0e0e6,
  purple: 0x800080,
  rebeccapurple: 0x663399,
  red: 0xff0000,
  rosybrown: 0xbc8f8f,
  royalblue: 0x4169e1,
  saddlebrown: 0x8b4513,
  salmon: 0xfa8072,
  sandybrown: 0xf4a460,
  seagreen: 0x2e8b57,
  seashell: 0xfff5ee,
  sienna: 0xa0522d,
  silver: 0xc0c0c0,
  skyblue: 0x87ceeb,
  slateblue: 0x6a5acd,
  slategray: 0x708090,
  slategrey: 0x708090,
  snow: 0xfffafa,
  springgreen: 0x00ff7f,
  steelblue: 0x4682b4,
  tan: 0xd2b48c,
  teal: 0x008080,
  thistle: 0xd8bfd8,
  tomato: 0xff6347,
  turquoise: 0x40e0d0,
  violet: 0xee82ee,
  wheat: 0xf5deb3,
  white: 0xffffff,
  whitesmoke: 0xf5f5f5,
  yellow: 0xffff00,
  yellowgreen: 0x9acd32
};

src_define(Color, color, {
  copy(channels) {
    return Object.assign(new this.constructor, this, channels);
  },
  displayable() {
    return this.rgb().displayable();
  },
  hex: color_formatHex, // Deprecated! Use color.formatHex.
  formatHex: color_formatHex,
  formatHex8: color_formatHex8,
  formatHsl: color_formatHsl,
  formatRgb: color_formatRgb,
  toString: color_formatRgb
});

function color_formatHex() {
  return this.rgb().formatHex();
}

function color_formatHex8() {
  return this.rgb().formatHex8();
}

function color_formatHsl() {
  return hslConvert(this).formatHsl();
}

function color_formatRgb() {
  return this.rgb().formatRgb();
}

function color(format) {
  var m, l;
  format = (format + "").trim().toLowerCase();
  return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
      : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00
      : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
      : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000
      : null) // invalid hex
      : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
      : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
      : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
      : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
      : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
      : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
      : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
      : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
      : null;
}

function rgbn(n) {
  return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}

function rgba(r, g, b, a) {
  if (a <= 0) r = g = b = NaN;
  return new Rgb(r, g, b, a);
}

function rgbConvert(o) {
  if (!(o instanceof Color)) o = color(o);
  if (!o) return new Rgb;
  o = o.rgb();
  return new Rgb(o.r, o.g, o.b, o.opacity);
}

function color_rgb(r, g, b, opacity) {
  return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
}

function Rgb(r, g, b, opacity) {
  this.r = +r;
  this.g = +g;
  this.b = +b;
  this.opacity = +opacity;
}

src_define(Rgb, color_rgb, define_extend(Color, {
  brighter(k) {
    k = k == null ? brighter : Math.pow(brighter, k);
    return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
  },
  darker(k) {
    k = k == null ? darker : Math.pow(darker, k);
    return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
  },
  rgb() {
    return this;
  },
  clamp() {
    return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));
  },
  displayable() {
    return (-0.5 <= this.r && this.r < 255.5)
        && (-0.5 <= this.g && this.g < 255.5)
        && (-0.5 <= this.b && this.b < 255.5)
        && (0 <= this.opacity && this.opacity <= 1);
  },
  hex: rgb_formatHex, // Deprecated! Use color.formatHex.
  formatHex: rgb_formatHex,
  formatHex8: rgb_formatHex8,
  formatRgb: rgb_formatRgb,
  toString: rgb_formatRgb
}));

function rgb_formatHex() {
  return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;
}

function rgb_formatHex8() {
  return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;
}

function rgb_formatRgb() {
  const a = clampa(this.opacity);
  return `${a === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? ")" : `, ${a})`}`;
}

function clampa(opacity) {
  return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity));
}

function clampi(value) {
  return Math.max(0, Math.min(255, Math.round(value) || 0));
}

function hex(value) {
  value = clampi(value);
  return (value < 16 ? "0" : "") + value.toString(16);
}

function hsla(h, s, l, a) {
  if (a <= 0) h = s = l = NaN;
  else if (l <= 0 || l >= 1) h = s = NaN;
  else if (s <= 0) h = NaN;
  return new Hsl(h, s, l, a);
}

function hslConvert(o) {
  if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
  if (!(o instanceof Color)) o = color(o);
  if (!o) return new Hsl;
  if (o instanceof Hsl) return o;
  o = o.rgb();
  var r = o.r / 255,
      g = o.g / 255,
      b = o.b / 255,
      min = Math.min(r, g, b),
      max = Math.max(r, g, b),
      h = NaN,
      s = max - min,
      l = (max + min) / 2;
  if (s) {
    if (r === max) h = (g - b) / s + (g < b) * 6;
    else if (g === max) h = (b - r) / s + 2;
    else h = (r - g) / s + 4;
    s /= l < 0.5 ? max + min : 2 - max - min;
    h *= 60;
  } else {
    s = l > 0 && l < 1 ? 0 : h;
  }
  return new Hsl(h, s, l, o.opacity);
}

function hsl(h, s, l, opacity) {
  return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
}

function Hsl(h, s, l, opacity) {
  this.h = +h;
  this.s = +s;
  this.l = +l;
  this.opacity = +opacity;
}

src_define(Hsl, hsl, define_extend(Color, {
  brighter(k) {
    k = k == null ? brighter : Math.pow(brighter, k);
    return new Hsl(this.h, this.s, this.l * k, this.opacity);
  },
  darker(k) {
    k = k == null ? darker : Math.pow(darker, k);
    return new Hsl(this.h, this.s, this.l * k, this.opacity);
  },
  rgb() {
    var h = this.h % 360 + (this.h < 0) * 360,
        s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
        l = this.l,
        m2 = l + (l < 0.5 ? l : 1 - l) * s,
        m1 = 2 * l - m2;
    return new Rgb(
      hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
      hsl2rgb(h, m1, m2),
      hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
      this.opacity
    );
  },
  clamp() {
    return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));
  },
  displayable() {
    return (0 <= this.s && this.s <= 1 || isNaN(this.s))
        && (0 <= this.l && this.l <= 1)
        && (0 <= this.opacity && this.opacity <= 1);
  },
  formatHsl() {
    const a = clampa(this.opacity);
    return `${a === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ")" : `, ${a})`}`;
  }
}));

function clamph(value) {
  value = (value || 0) % 360;
  return value < 0 ? value + 360 : value;
}

function clampt(value) {
  return Math.max(0, Math.min(1, value || 0));
}

/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb(h, m1, m2) {
  return (h < 60 ? m1 + (m2 - m1) * h / 60
      : h < 180 ? m2
      : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
      : m1) * 255;
}

;// ../../node_modules/d3-interpolate/src/basis.js
function basis_basis(t1, v0, v1, v2, v3) {
  var t2 = t1 * t1, t3 = t2 * t1;
  return ((1 - 3 * t1 + 3 * t2 - t3) * v0
      + (4 - 6 * t2 + 3 * t3) * v1
      + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
      + t3 * v3) / 6;
}

/* harmony default export */ function src_basis(values) {
  var n = values.length - 1;
  return function(t) {
    var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
        v1 = values[i],
        v2 = values[i + 1],
        v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
        v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
    return basis_basis((t - i / n) * n, v0, v1, v2, v3);
  };
}

;// ../../node_modules/d3-interpolate/src/basisClosed.js


/* harmony default export */ function src_basisClosed(values) {
  var n = values.length;
  return function(t) {
    var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
        v0 = values[(i + n - 1) % n],
        v1 = values[i % n],
        v2 = values[(i + 1) % n],
        v3 = values[(i + 2) % n];
    return basis_basis((t - i / n) * n, v0, v1, v2, v3);
  };
}

;// ../../node_modules/d3-interpolate/src/constant.js
/* harmony default export */ const d3_interpolate_src_constant = (x => () => x);

;// ../../node_modules/d3-interpolate/src/color.js


function color_linear(a, d) {
  return function(t) {
    return a + t * d;
  };
}

function exponential(a, b, y) {
  return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
    return Math.pow(a + t * b, y);
  };
}

function hue(a, b) {
  var d = b - a;
  return d ? color_linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : d3_interpolate_src_constant(isNaN(a) ? b : a);
}

function gamma(y) {
  return (y = +y) === 1 ? nogamma : function(a, b) {
    return b - a ? exponential(a, b, y) : d3_interpolate_src_constant(isNaN(a) ? b : a);
  };
}

function nogamma(a, b) {
  var d = b - a;
  return d ? color_linear(a, d) : d3_interpolate_src_constant(isNaN(a) ? b : a);
}

;// ../../node_modules/d3-interpolate/src/rgb.js





/* harmony default export */ const rgb = ((function rgbGamma(y) {
  var color = gamma(y);

  function rgb(start, end) {
    var r = color((start = color_rgb(start)).r, (end = color_rgb(end)).r),
        g = color(start.g, end.g),
        b = color(start.b, end.b),
        opacity = nogamma(start.opacity, end.opacity);
    return function(t) {
      start.r = r(t);
      start.g = g(t);
      start.b = b(t);
      start.opacity = opacity(t);
      return start + "";
    };
  }

  rgb.gamma = rgbGamma;

  return rgb;
})(1));

function rgbSpline(spline) {
  return function(colors) {
    var n = colors.length,
        r = new Array(n),
        g = new Array(n),
        b = new Array(n),
        i, color;
    for (i = 0; i < n; ++i) {
      color = color_rgb(colors[i]);
      r[i] = color.r || 0;
      g[i] = color.g || 0;
      b[i] = color.b || 0;
    }
    r = spline(r);
    g = spline(g);
    b = spline(b);
    color.opacity = 1;
    return function(t) {
      color.r = r(t);
      color.g = g(t);
      color.b = b(t);
      return color + "";
    };
  };
}

var rgbBasis = rgbSpline(src_basis);
var rgbBasisClosed = rgbSpline(src_basisClosed);

;// ../../node_modules/d3-interpolate/src/numberArray.js
/* harmony default export */ function numberArray(a, b) {
  if (!b) b = [];
  var n = a ? Math.min(b.length, a.length) : 0,
      c = b.slice(),
      i;
  return function(t) {
    for (i = 0; i < n; ++i) c[i] = a[i] * (1 - t) + b[i] * t;
    return c;
  };
}

function isNumberArray(x) {
  return ArrayBuffer.isView(x) && !(x instanceof DataView);
}

;// ../../node_modules/d3-interpolate/src/array.js



/* harmony default export */ function d3_interpolate_src_array(a, b) {
  return (isNumberArray(b) ? numberArray : genericArray)(a, b);
}

function genericArray(a, b) {
  var nb = b ? b.length : 0,
      na = a ? Math.min(nb, a.length) : 0,
      x = new Array(na),
      c = new Array(nb),
      i;

  for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]);
  for (; i < nb; ++i) c[i] = b[i];

  return function(t) {
    for (i = 0; i < na; ++i) c[i] = x[i](t);
    return c;
  };
}

;// ../../node_modules/d3-interpolate/src/date.js
/* harmony default export */ function src_date(a, b) {
  var d = new Date;
  return a = +a, b = +b, function(t) {
    return d.setTime(a * (1 - t) + b * t), d;
  };
}

;// ../../node_modules/d3-interpolate/src/number.js
/* harmony default export */ function src_number(a, b) {
  return a = +a, b = +b, function(t) {
    return a * (1 - t) + b * t;
  };
}

;// ../../node_modules/d3-interpolate/src/object.js


/* harmony default export */ function src_object(a, b) {
  var i = {},
      c = {},
      k;

  if (a === null || typeof a !== "object") a = {};
  if (b === null || typeof b !== "object") b = {};

  for (k in b) {
    if (k in a) {
      i[k] = value(a[k], b[k]);
    } else {
      c[k] = b[k];
    }
  }

  return function(t) {
    for (k in i) c[k] = i[k](t);
    return c;
  };
}

;// ../../node_modules/d3-interpolate/src/string.js


var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
    reB = new RegExp(reA.source, "g");

function string_zero(b) {
  return function() {
    return b;
  };
}

function string_one(b) {
  return function(t) {
    return b(t) + "";
  };
}

/* harmony default export */ function string(a, b) {
  var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
      am, // current match in a
      bm, // current match in b
      bs, // string preceding current number in b, if any
      i = -1, // index in s
      s = [], // string constants and placeholders
      q = []; // number interpolators

  // Coerce inputs to strings.
  a = a + "", b = b + "";

  // Interpolate pairs of numbers in a & b.
  while ((am = reA.exec(a))
      && (bm = reB.exec(b))) {
    if ((bs = bm.index) > bi) { // a string precedes the next number in b
      bs = b.slice(bi, bs);
      if (s[i]) s[i] += bs; // coalesce with previous string
      else s[++i] = bs;
    }
    if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
      if (s[i]) s[i] += bm; // coalesce with previous string
      else s[++i] = bm;
    } else { // interpolate non-matching numbers
      s[++i] = null;
      q.push({i: i, x: src_number(am, bm)});
    }
    bi = reB.lastIndex;
  }

  // Add remains of b.
  if (bi < b.length) {
    bs = b.slice(bi);
    if (s[i]) s[i] += bs; // coalesce with previous string
    else s[++i] = bs;
  }

  // Special optimization for only a single match.
  // Otherwise, interpolate each of the numbers and rejoin the string.
  return s.length < 2 ? (q[0]
      ? string_one(q[0].x)
      : string_zero(b))
      : (b = q.length, function(t) {
          for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
          return s.join("");
        });
}

;// ../../node_modules/d3-interpolate/src/value.js










/* harmony default export */ function value(a, b) {
  var t = typeof b, c;
  return b == null || t === "boolean" ? d3_interpolate_src_constant(b)
      : (t === "number" ? src_number
      : t === "string" ? ((c = color(b)) ? (b = c, rgb) : string)
      : b instanceof color ? rgb
      : b instanceof Date ? src_date
      : isNumberArray(b) ? numberArray
      : Array.isArray(b) ? genericArray
      : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? src_object
      : src_number)(a, b);
}

;// ../../node_modules/d3-interpolate/src/round.js
/* harmony default export */ function src_round(a, b) {
  return a = +a, b = +b, function(t) {
    return Math.round(a * (1 - t) + b * t);
  };
}

;// ../../node_modules/d3-scale/src/constant.js
function constant_constants(x) {
  return function() {
    return x;
  };
}

;// ../../node_modules/d3-scale/src/number.js
function src_number_number(x) {
  return +x;
}

;// ../../node_modules/d3-scale/src/continuous.js





var unit = [0, 1];

function continuous_identity(x) {
  return x;
}

function continuous_normalize(a, b) {
  return (b -= (a = +a))
      ? function(x) { return (x - a) / b; }
      : constant_constants(isNaN(b) ? NaN : 0.5);
}

function clamper(a, b) {
  var t;
  if (a > b) t = a, a = b, b = t;
  return function(x) { return Math.max(a, Math.min(b, x)); };
}

// normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
// interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
function bimap(domain, range, interpolate) {
  var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
  if (d1 < d0) d0 = continuous_normalize(d1, d0), r0 = interpolate(r1, r0);
  else d0 = continuous_normalize(d0, d1), r0 = interpolate(r0, r1);
  return function(x) { return r0(d0(x)); };
}

function polymap(domain, range, interpolate) {
  var j = Math.min(domain.length, range.length) - 1,
      d = new Array(j),
      r = new Array(j),
      i = -1;

  // Reverse descending domains.
  if (domain[j] < domain[0]) {
    domain = domain.slice().reverse();
    range = range.slice().reverse();
  }

  while (++i < j) {
    d[i] = continuous_normalize(domain[i], domain[i + 1]);
    r[i] = interpolate(range[i], range[i + 1]);
  }

  return function(x) {
    var i = src_bisect(domain, x, 1, j) - 1;
    return r[i](d[i](x));
  };
}

function copy(source, target) {
  return target
      .domain(source.domain())
      .range(source.range())
      .interpolate(source.interpolate())
      .clamp(source.clamp())
      .unknown(source.unknown());
}

function transformer() {
  var domain = unit,
      range = unit,
      interpolate = value,
      transform,
      untransform,
      unknown,
      clamp = continuous_identity,
      piecewise,
      output,
      input;

  function rescale() {
    var n = Math.min(domain.length, range.length);
    if (clamp !== continuous_identity) clamp = clamper(domain[0], domain[n - 1]);
    piecewise = n > 2 ? polymap : bimap;
    output = input = null;
    return scale;
  }

  function scale(x) {
    return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
  }

  scale.invert = function(y) {
    return clamp(untransform((input || (input = piecewise(range, domain.map(transform), src_number)))(y)));
  };

  scale.domain = function(_) {
    return arguments.length ? (domain = Array.from(_, src_number_number), rescale()) : domain.slice();
  };

  scale.range = function(_) {
    return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
  };

  scale.rangeRound = function(_) {
    return range = Array.from(_), interpolate = src_round, rescale();
  };

  scale.clamp = function(_) {
    return arguments.length ? (clamp = _ ? true : continuous_identity, rescale()) : clamp !== continuous_identity;
  };

  scale.interpolate = function(_) {
    return arguments.length ? (interpolate = _, rescale()) : interpolate;
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  return function(t, u) {
    transform = t, untransform = u;
    return rescale();
  };
}

function continuous() {
  return transformer()(continuous_identity, continuous_identity);
}

;// ../../node_modules/d3-scale/src/init.js
function initRange(domain, range) {
  switch (arguments.length) {
    case 0: break;
    case 1: this.range(domain); break;
    default: this.range(range).domain(domain); break;
  }
  return this;
}

function initInterpolator(domain, interpolator) {
  switch (arguments.length) {
    case 0: break;
    case 1: {
      if (typeof domain === "function") this.interpolator(domain);
      else this.range(domain);
      break;
    }
    default: {
      this.domain(domain);
      if (typeof interpolator === "function") this.interpolator(interpolator);
      else this.range(interpolator);
      break;
    }
  }
  return this;
}

;// ../../node_modules/d3-scale/src/tickFormat.js



function tickFormat(start, stop, count, specifier) {
  var step = tickStep(start, stop, count),
      precision;
  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
  switch (specifier.type) {
    case "s": {
      var value = Math.max(Math.abs(start), Math.abs(stop));
      if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
      return formatPrefix(specifier, value);
    }
    case "":
    case "e":
    case "g":
    case "p":
    case "r": {
      if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
      break;
    }
    case "f":
    case "%": {
      if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
      break;
    }
  }
  return format(specifier);
}

;// ../../node_modules/d3-scale/src/linear.js





function linearish(scale) {
  var domain = scale.domain;

  scale.ticks = function(count) {
    var d = domain();
    return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
  };

  scale.tickFormat = function(count, specifier) {
    var d = domain();
    return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
  };

  scale.nice = function(count) {
    if (count == null) count = 10;

    var d = domain();
    var i0 = 0;
    var i1 = d.length - 1;
    var start = d[i0];
    var stop = d[i1];
    var prestep;
    var step;
    var maxIter = 10;

    if (stop < start) {
      step = start, start = stop, stop = step;
      step = i0, i0 = i1, i1 = step;
    }
    
    while (maxIter-- > 0) {
      step = tickIncrement(start, stop, count);
      if (step === prestep) {
        d[i0] = start
        d[i1] = stop
        return domain(d);
      } else if (step > 0) {
        start = Math.floor(start / step) * step;
        stop = Math.ceil(stop / step) * step;
      } else if (step < 0) {
        start = Math.ceil(start * step) / step;
        stop = Math.floor(stop * step) / step;
      } else {
        break;
      }
      prestep = step;
    }

    return scale;
  };

  return scale;
}

function linear_linear() {
  var scale = continuous();

  scale.copy = function() {
    return copy(scale, linear_linear());
  };

  initRange.apply(scale, arguments);

  return linearish(scale);
}

;// ../../node_modules/d3-scale/src/identity.js



function src_identity_identity(domain) {
  var unknown;

  function scale(x) {
    return x == null || isNaN(x = +x) ? unknown : x;
  }

  scale.invert = scale;

  scale.domain = scale.range = function(_) {
    return arguments.length ? (domain = Array.from(_, src_number_number), scale) : domain.slice();
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  scale.copy = function() {
    return src_identity_identity(domain).unknown(unknown);
  };

  domain = arguments.length ? Array.from(domain, src_number_number) : [0, 1];

  return linearish(scale);
}

;// ../../node_modules/d3-scale/src/nice.js
function nice(domain, interval) {
  domain = domain.slice();

  var i0 = 0,
      i1 = domain.length - 1,
      x0 = domain[i0],
      x1 = domain[i1],
      t;

  if (x1 < x0) {
    t = i0, i0 = i1, i1 = t;
    t = x0, x0 = x1, x1 = t;
  }

  domain[i0] = interval.floor(x0);
  domain[i1] = interval.ceil(x1);
  return domain;
}

;// ../../node_modules/d3-scale/src/log.js






function transformLog(x) {
  return Math.log(x);
}

function transformExp(x) {
  return Math.exp(x);
}

function transformLogn(x) {
  return -Math.log(-x);
}

function transformExpn(x) {
  return -Math.exp(-x);
}

function pow10(x) {
  return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
}

function powp(base) {
  return base === 10 ? pow10
      : base === Math.E ? Math.exp
      : x => Math.pow(base, x);
}

function logp(base) {
  return base === Math.E ? Math.log
      : base === 10 && Math.log10
      || base === 2 && Math.log2
      || (base = Math.log(base), x => Math.log(x) / base);
}

function reflect(f) {
  return (x, k) => -f(-x, k);
}

function loggish(transform) {
  const scale = transform(transformLog, transformExp);
  const domain = scale.domain;
  let base = 10;
  let logs;
  let pows;

  function rescale() {
    logs = logp(base), pows = powp(base);
    if (domain()[0] < 0) {
      logs = reflect(logs), pows = reflect(pows);
      transform(transformLogn, transformExpn);
    } else {
      transform(transformLog, transformExp);
    }
    return scale;
  }

  scale.base = function(_) {
    return arguments.length ? (base = +_, rescale()) : base;
  };

  scale.domain = function(_) {
    return arguments.length ? (domain(_), rescale()) : domain();
  };

  scale.ticks = count => {
    const d = domain();
    let u = d[0];
    let v = d[d.length - 1];
    const r = v < u;

    if (r) ([u, v] = [v, u]);

    let i = logs(u);
    let j = logs(v);
    let k;
    let t;
    const n = count == null ? 10 : +count;
    let z = [];

    if (!(base % 1) && j - i < n) {
      i = Math.floor(i), j = Math.ceil(j);
      if (u > 0) for (; i <= j; ++i) {
        for (k = 1; k < base; ++k) {
          t = i < 0 ? k / pows(-i) : k * pows(i);
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      } else for (; i <= j; ++i) {
        for (k = base - 1; k >= 1; --k) {
          t = i > 0 ? k / pows(-i) : k * pows(i);
          if (t < u) continue;
          if (t > v) break;
          z.push(t);
        }
      }
      if (z.length * 2 < n) z = ticks(u, v, n);
    } else {
      z = ticks(i, j, Math.min(j - i, n)).map(pows);
    }
    return r ? z.reverse() : z;
  };

  scale.tickFormat = (count, specifier) => {
    if (count == null) count = 10;
    if (specifier == null) specifier = base === 10 ? "s" : ",";
    if (typeof specifier !== "function") {
      if (!(base % 1) && (specifier = formatSpecifier(specifier)).precision == null) specifier.trim = true;
      specifier = format(specifier);
    }
    if (count === Infinity) return specifier;
    const k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
    return d => {
      let i = d / pows(Math.round(logs(d)));
      if (i * base < base - 0.5) i *= base;
      return i <= k ? specifier(d) : "";
    };
  };

  scale.nice = () => {
    return domain(nice(domain(), {
      floor: x => pows(Math.floor(logs(x))),
      ceil: x => pows(Math.ceil(logs(x)))
    }));
  };

  return scale;
}

function log_log() {
  const scale = loggish(transformer()).domain([1, 10]);
  scale.copy = () => copy(scale, log_log()).base(scale.base());
  initRange.apply(scale, arguments);
  return scale;
}

;// ../../node_modules/d3-scale/src/pow.js




function transformPow(exponent) {
  return function(x) {
    return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
  };
}

function transformSqrt(x) {
  return x < 0 ? -Math.sqrt(-x) : Math.sqrt(x);
}

function transformSquare(x) {
  return x < 0 ? -x * x : x * x;
}

function powish(transform) {
  var scale = transform(continuous_identity, continuous_identity),
      exponent = 1;

  function rescale() {
    return exponent === 1 ? transform(continuous_identity, continuous_identity)
        : exponent === 0.5 ? transform(transformSqrt, transformSquare)
        : transform(transformPow(exponent), transformPow(1 / exponent));
  }

  scale.exponent = function(_) {
    return arguments.length ? (exponent = +_, rescale()) : exponent;
  };

  return linearish(scale);
}

function pow_pow() {
  var scale = powish(transformer());

  scale.copy = function() {
    return copy(scale, pow_pow()).exponent(scale.exponent());
  };

  initRange.apply(scale, arguments);

  return scale;
}

function pow_sqrt() {
  return pow_pow.apply(null, arguments).exponent(0.5);
}

;// ../../node_modules/d3-scale/src/symlog.js




function transformSymlog(c) {
  return function(x) {
    return Math.sign(x) * Math.log1p(Math.abs(x / c));
  };
}

function transformSymexp(c) {
  return function(x) {
    return Math.sign(x) * Math.expm1(Math.abs(x)) * c;
  };
}

function symlogish(transform) {
  var c = 1, scale = transform(transformSymlog(c), transformSymexp(c));

  scale.constant = function(_) {
    return arguments.length ? transform(transformSymlog(c = +_), transformSymexp(c)) : c;
  };

  return linearish(scale);
}

function symlog_symlog() {
  var scale = symlogish(transformer());

  scale.copy = function() {
    return copy(scale, symlog_symlog()).constant(scale.constant());
  };

  return initRange.apply(scale, arguments);
}

;// ../../node_modules/d3-time/src/ticks.js











function ticker(year, month, week, day, hour, minute) {

  const tickIntervals = [
    [second,  1,      durationSecond],
    [second,  5,  5 * durationSecond],
    [second, 15, 15 * durationSecond],
    [second, 30, 30 * durationSecond],
    [minute,  1,      durationMinute],
    [minute,  5,  5 * durationMinute],
    [minute, 15, 15 * durationMinute],
    [minute, 30, 30 * durationMinute],
    [  hour,  1,      durationHour  ],
    [  hour,  3,  3 * durationHour  ],
    [  hour,  6,  6 * durationHour  ],
    [  hour, 12, 12 * durationHour  ],
    [   day,  1,      durationDay   ],
    [   day,  2,  2 * durationDay   ],
    [  week,  1,      durationWeek  ],
    [ month,  1,      durationMonth ],
    [ month,  3,  3 * durationMonth ],
    [  year,  1,      durationYear  ]
  ];

  function ticks(start, stop, count) {
    const reverse = stop < start;
    if (reverse) [start, stop] = [stop, start];
    const interval = count && typeof count.range === "function" ? count : tickInterval(start, stop, count);
    const ticks = interval ? interval.range(start, +stop + 1) : []; // inclusive stop
    return reverse ? ticks.reverse() : ticks;
  }

  function tickInterval(start, stop, count) {
    const target = Math.abs(stop - start) / count;
    const i = bisector_bisector(([,, step]) => step).right(tickIntervals, target);
    if (i === tickIntervals.length) return year.every(tickStep(start / durationYear, stop / durationYear, count));
    if (i === 0) return millisecond.every(Math.max(tickStep(start, stop, count), 1));
    const [t, step] = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
    return t.every(step);
  }

  return [ticks, tickInterval];
}

const [utcTicks, utcTickInterval] = ticker(utcYear, utcMonth, utcSunday, unixDay, utcHour, utcMinute);
const [timeTicks, timeTickInterval] = ticker(timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute);



;// ../../node_modules/d3-scale/src/time.js






function time_date(t) {
  return new Date(t);
}

function time_number(t) {
  return t instanceof Date ? +t : +new Date(+t);
}

function calendar(ticks, tickInterval, year, month, week, day, hour, minute, second, format) {
  var scale = continuous(),
      invert = scale.invert,
      domain = scale.domain;

  var formatMillisecond = format(".%L"),
      formatSecond = format(":%S"),
      formatMinute = format("%I:%M"),
      formatHour = format("%I %p"),
      formatDay = format("%a %d"),
      formatWeek = format("%b %d"),
      formatMonth = format("%B"),
      formatYear = format("%Y");

  function tickFormat(date) {
    return (second(date) < date ? formatMillisecond
        : minute(date) < date ? formatSecond
        : hour(date) < date ? formatMinute
        : day(date) < date ? formatHour
        : month(date) < date ? (week(date) < date ? formatDay : formatWeek)
        : year(date) < date ? formatMonth
        : formatYear)(date);
  }

  scale.invert = function(y) {
    return new Date(invert(y));
  };

  scale.domain = function(_) {
    return arguments.length ? domain(Array.from(_, time_number)) : domain().map(time_date);
  };

  scale.ticks = function(interval) {
    var d = domain();
    return ticks(d[0], d[d.length - 1], interval == null ? 10 : interval);
  };

  scale.tickFormat = function(count, specifier) {
    return specifier == null ? tickFormat : format(specifier);
  };

  scale.nice = function(interval) {
    var d = domain();
    if (!interval || typeof interval.range !== "function") interval = tickInterval(d[0], d[d.length - 1], interval == null ? 10 : interval);
    return interval ? domain(nice(d, interval)) : scale;
  };

  scale.copy = function() {
    return copy(scale, calendar(ticks, tickInterval, year, month, week, day, hour, minute, second, format));
  };

  return scale;
}

function time_time() {
  return initRange.apply(calendar(timeTicks, timeTickInterval, timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute, second, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]), arguments);
}

;// ../../node_modules/d3-scale/src/utcTime.js





function utcTime() {
  return initRange.apply(calendar(utcTicks, utcTickInterval, utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]), arguments);
}

;// ../../node_modules/d3-scale/src/sequential.js








function sequential_transformer() {
  var x0 = 0,
      x1 = 1,
      t0,
      t1,
      k10,
      transform,
      interpolator = continuous_identity,
      clamp = false,
      unknown;

  function scale(x) {
    return x == null || isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
  }

  scale.domain = function(_) {
    return arguments.length ? ([x0, x1] = _, t0 = transform(x0 = +x0), t1 = transform(x1 = +x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0), scale) : [x0, x1];
  };

  scale.clamp = function(_) {
    return arguments.length ? (clamp = !!_, scale) : clamp;
  };

  scale.interpolator = function(_) {
    return arguments.length ? (interpolator = _, scale) : interpolator;
  };

  function range(interpolate) {
    return function(_) {
      var r0, r1;
      return arguments.length ? ([r0, r1] = _, interpolator = interpolate(r0, r1), scale) : [interpolator(0), interpolator(1)];
    };
  }

  scale.range = range(value);

  scale.rangeRound = range(src_round);

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  return function(t) {
    transform = t, t0 = t(x0), t1 = t(x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0);
    return scale;
  };
}

function sequential_copy(source, target) {
  return target
      .domain(source.domain())
      .interpolator(source.interpolator())
      .clamp(source.clamp())
      .unknown(source.unknown());
}

function sequential() {
  var scale = linearish(sequential_transformer()(continuous_identity));

  scale.copy = function() {
    return sequential_copy(scale, sequential());
  };

  return initInterpolator.apply(scale, arguments);
}

function sequentialLog() {
  var scale = loggish(sequential_transformer()).domain([1, 10]);

  scale.copy = function() {
    return sequential_copy(scale, sequentialLog()).base(scale.base());
  };

  return initInterpolator.apply(scale, arguments);
}

function sequentialSymlog() {
  var scale = symlogish(sequential_transformer());

  scale.copy = function() {
    return sequential_copy(scale, sequentialSymlog()).constant(scale.constant());
  };

  return initInterpolator.apply(scale, arguments);
}

function sequentialPow() {
  var scale = powish(sequential_transformer());

  scale.copy = function() {
    return sequential_copy(scale, sequentialPow()).exponent(scale.exponent());
  };

  return initInterpolator.apply(scale, arguments);
}

function sequentialSqrt() {
  return sequentialPow.apply(null, arguments).exponent(0.5);
}

;// ../../node_modules/d3-interpolate/src/piecewise.js


function piecewise(interpolate, values) {
  if (values === undefined) values = interpolate, interpolate = value;
  var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n);
  while (i < n) I[i] = interpolate(v, v = values[++i]);
  return function(t) {
    var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));
    return I[i](t - i);
  };
}

;// ../../node_modules/d3-scale/src/diverging.js









function diverging_transformer() {
  var x0 = 0,
      x1 = 0.5,
      x2 = 1,
      s = 1,
      t0,
      t1,
      t2,
      k10,
      k21,
      interpolator = continuous_identity,
      transform,
      clamp = false,
      unknown;

  function scale(x) {
    return isNaN(x = +x) ? unknown : (x = 0.5 + ((x = +transform(x)) - t1) * (s * x < s * t1 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x)) : x));
  }

  scale.domain = function(_) {
    return arguments.length ? ([x0, x1, x2] = _, t0 = transform(x0 = +x0), t1 = transform(x1 = +x1), t2 = transform(x2 = +x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), s = t1 < t0 ? -1 : 1, scale) : [x0, x1, x2];
  };

  scale.clamp = function(_) {
    return arguments.length ? (clamp = !!_, scale) : clamp;
  };

  scale.interpolator = function(_) {
    return arguments.length ? (interpolator = _, scale) : interpolator;
  };

  function range(interpolate) {
    return function(_) {
      var r0, r1, r2;
      return arguments.length ? ([r0, r1, r2] = _, interpolator = piecewise(interpolate, [r0, r1, r2]), scale) : [interpolator(0), interpolator(0.5), interpolator(1)];
    };
  }

  scale.range = range(value);

  scale.rangeRound = range(src_round);

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  return function(t) {
    transform = t, t0 = t(x0), t1 = t(x1), t2 = t(x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), s = t1 < t0 ? -1 : 1;
    return scale;
  };
}

function diverging() {
  var scale = linearish(diverging_transformer()(continuous_identity));

  scale.copy = function() {
    return sequential_copy(scale, diverging());
  };

  return initInterpolator.apply(scale, arguments);
}

function divergingLog() {
  var scale = loggish(diverging_transformer()).domain([0.1, 1, 10]);

  scale.copy = function() {
    return sequential_copy(scale, divergingLog()).base(scale.base());
  };

  return initInterpolator.apply(scale, arguments);
}

function divergingSymlog() {
  var scale = symlogish(diverging_transformer());

  scale.copy = function() {
    return sequential_copy(scale, divergingSymlog()).constant(scale.constant());
  };

  return initInterpolator.apply(scale, arguments);
}

function divergingPow() {
  var scale = powish(diverging_transformer());

  scale.copy = function() {
    return sequential_copy(scale, divergingPow()).exponent(scale.exponent());
  };

  return initInterpolator.apply(scale, arguments);
}

function divergingSqrt() {
  return divergingPow.apply(null, arguments).exponent(0.5);
}

;// ../../node_modules/d3-scale/src/quantile.js



function src_quantile_quantile() {
  var domain = [],
      range = [],
      thresholds = [],
      unknown;

  function rescale() {
    var i = 0, n = Math.max(1, range.length);
    thresholds = new Array(n - 1);
    while (++i < n) thresholds[i - 1] = quantileSorted(domain, i / n);
    return scale;
  }

  function scale(x) {
    return x == null || isNaN(x = +x) ? unknown : range[src_bisect(thresholds, x)];
  }

  scale.invertExtent = function(y) {
    var i = range.indexOf(y);
    return i < 0 ? [NaN, NaN] : [
      i > 0 ? thresholds[i - 1] : domain[0],
      i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
    ];
  };

  scale.domain = function(_) {
    if (!arguments.length) return domain.slice();
    domain = [];
    for (let d of _) if (d != null && !isNaN(d = +d)) domain.push(d);
    domain.sort(ascending_ascending);
    return rescale();
  };

  scale.range = function(_) {
    return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  scale.quantiles = function() {
    return thresholds.slice();
  };

  scale.copy = function() {
    return src_quantile_quantile()
        .domain(domain)
        .range(range)
        .unknown(unknown);
  };

  return initRange.apply(scale, arguments);
}

;// ../../node_modules/d3-scale/src/quantize.js




function quantize() {
  var x0 = 0,
      x1 = 1,
      n = 1,
      domain = [0.5],
      range = [0, 1],
      unknown;

  function scale(x) {
    return x != null && x <= x ? range[src_bisect(domain, x, 0, n)] : unknown;
  }

  function rescale() {
    var i = -1;
    domain = new Array(n);
    while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
    return scale;
  }

  scale.domain = function(_) {
    return arguments.length ? ([x0, x1] = _, x0 = +x0, x1 = +x1, rescale()) : [x0, x1];
  };

  scale.range = function(_) {
    return arguments.length ? (n = (range = Array.from(_)).length - 1, rescale()) : range.slice();
  };

  scale.invertExtent = function(y) {
    var i = range.indexOf(y);
    return i < 0 ? [NaN, NaN]
        : i < 1 ? [x0, domain[0]]
        : i >= n ? [domain[n - 1], x1]
        : [domain[i - 1], domain[i]];
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : scale;
  };

  scale.thresholds = function() {
    return domain.slice();
  };

  scale.copy = function() {
    return quantize()
        .domain([x0, x1])
        .range(range)
        .unknown(unknown);
  };

  return initRange.apply(linearish(scale), arguments);
}

;// ../../node_modules/d3-scale/src/threshold.js



function threshold() {
  var domain = [0.5],
      range = [0, 1],
      unknown,
      n = 1;

  function scale(x) {
    return x != null && x <= x ? range[src_bisect(domain, x, 0, n)] : unknown;
  }

  scale.domain = function(_) {
    return arguments.length ? (domain = Array.from(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice();
  };

  scale.range = function(_) {
    return arguments.length ? (range = Array.from(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice();
  };

  scale.invertExtent = function(y) {
    var i = range.indexOf(y);
    return [domain[i - 1], domain[i]];
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  scale.copy = function() {
    return threshold()
        .domain(domain)
        .range(range)
        .unknown(unknown);
  };

  return initRange.apply(scale, arguments);
}

;// ../../node_modules/internmap/src/index.js
class InternMap extends Map {
  constructor(entries, key = keyof) {
    super();
    Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}});
    if (entries != null) for (const [key, value] of entries) this.set(key, value);
  }
  get(key) {
    return super.get(intern_get(this, key));
  }
  has(key) {
    return super.has(intern_get(this, key));
  }
  set(key, value) {
    return super.set(intern_set(this, key), value);
  }
  delete(key) {
    return super.delete(intern_delete(this, key));
  }
}

class InternSet extends Set {
  constructor(values, key = keyof) {
    super();
    Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}});
    if (values != null) for (const value of values) this.add(value);
  }
  has(value) {
    return super.has(intern_get(this, value));
  }
  add(value) {
    return super.add(intern_set(this, value));
  }
  delete(value) {
    return super.delete(intern_delete(this, value));
  }
}

function intern_get({_intern, _key}, value) {
  const key = _key(value);
  return _intern.has(key) ? _intern.get(key) : value;
}

function intern_set({_intern, _key}, value) {
  const key = _key(value);
  if (_intern.has(key)) return _intern.get(key);
  _intern.set(key, value);
  return value;
}

function intern_delete({_intern, _key}, value) {
  const key = _key(value);
  if (_intern.has(key)) {
    value = _intern.get(key);
    _intern.delete(key);
  }
  return value;
}

function keyof(value) {
  return value !== null && typeof value === "object" ? value.valueOf() : value;
}

;// ../../node_modules/d3-scale/src/ordinal.js



const implicit = Symbol("implicit");

function ordinal() {
  var index = new InternMap(),
      domain = [],
      range = [],
      unknown = implicit;

  function scale(d) {
    let i = index.get(d);
    if (i === undefined) {
      if (unknown !== implicit) return unknown;
      index.set(d, i = domain.push(d) - 1);
    }
    return range[i % range.length];
  }

  scale.domain = function(_) {
    if (!arguments.length) return domain.slice();
    domain = [], index = new InternMap();
    for (const value of _) {
      if (index.has(value)) continue;
      index.set(value, domain.push(value) - 1);
    }
    return scale;
  };

  scale.range = function(_) {
    return arguments.length ? (range = Array.from(_), scale) : range.slice();
  };

  scale.unknown = function(_) {
    return arguments.length ? (unknown = _, scale) : unknown;
  };

  scale.copy = function() {
    return ordinal(domain, range).unknown(unknown);
  };

  initRange.apply(scale, arguments);

  return scale;
}

;// ../../node_modules/d3-interpolate/src/discrete.js
/* harmony default export */ function discrete(range) {
  var n = range.length;
  return function(t) {
    return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
  };
}

;// ../../node_modules/d3-interpolate/src/hue.js


/* harmony default export */ function src_hue(a, b) {
  var i = hue(+a, +b);
  return function(t) {
    var x = i(t);
    return x - 360 * Math.floor(x / 360);
  };
}

;// ../../node_modules/d3-interpolate/src/transform/decompose.js
var decompose_degrees = 180 / Math.PI;

var decompose_identity = {
  translateX: 0,
  translateY: 0,
  rotate: 0,
  skewX: 0,
  scaleX: 1,
  scaleY: 1
};

/* harmony default export */ function decompose(a, b, c, d, e, f) {
  var scaleX, scaleY, skewX;
  if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
  if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
  if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
  if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
  return {
    translateX: e,
    translateY: f,
    rotate: Math.atan2(b, a) * decompose_degrees,
    skewX: Math.atan(skewX) * decompose_degrees,
    scaleX: scaleX,
    scaleY: scaleY
  };
}

;// ../../node_modules/d3-interpolate/src/transform/parse.js


var svgNode;

/* eslint-disable no-undef */
function parseCss(value) {
  const m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
  return m.isIdentity ? decompose_identity : decompose(m.a, m.b, m.c, m.d, m.e, m.f);
}

function parseSvg(value) {
  if (value == null) return decompose_identity;
  if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
  svgNode.setAttribute("transform", value);
  if (!(value = svgNode.transform.baseVal.consolidate())) return decompose_identity;
  value = value.matrix;
  return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
}

;// ../../node_modules/d3-interpolate/src/transform/index.js



function interpolateTransform(parse, pxComma, pxParen, degParen) {

  function pop(s) {
    return s.length ? s.pop() + " " : "";
  }

  function translate(xa, ya, xb, yb, s, q) {
    if (xa !== xb || ya !== yb) {
      var i = s.push("translate(", null, pxComma, null, pxParen);
      q.push({i: i - 4, x: src_number(xa, xb)}, {i: i - 2, x: src_number(ya, yb)});
    } else if (xb || yb) {
      s.push("translate(" + xb + pxComma + yb + pxParen);
    }
  }

  function rotate(a, b, s, q) {
    if (a !== b) {
      if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
      q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: src_number(a, b)});
    } else if (b) {
      s.push(pop(s) + "rotate(" + b + degParen);
    }
  }

  function skewX(a, b, s, q) {
    if (a !== b) {
      q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: src_number(a, b)});
    } else if (b) {
      s.push(pop(s) + "skewX(" + b + degParen);
    }
  }

  function scale(xa, ya, xb, yb, s, q) {
    if (xa !== xb || ya !== yb) {
      var i = s.push(pop(s) + "scale(", null, ",", null, ")");
      q.push({i: i - 4, x: src_number(xa, xb)}, {i: i - 2, x: src_number(ya, yb)});
    } else if (xb !== 1 || yb !== 1) {
      s.push(pop(s) + "scale(" + xb + "," + yb + ")");
    }
  }

  return function(a, b) {
    var s = [], // string constants and placeholders
        q = []; // number interpolators
    a = parse(a), b = parse(b);
    translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
    rotate(a.rotate, b.rotate, s, q);
    skewX(a.skewX, b.skewX, s, q);
    scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
    a = b = null; // gc
    return function(t) {
      var i = -1, n = q.length, o;
      while (++i < n) s[(o = q[i]).i] = o.x(t);
      return s.join("");
    };
  };
}

var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");

;// ../../node_modules/d3-interpolate/src/zoom.js
var epsilon2 = 1e-12;

function zoom_cosh(x) {
  return ((x = Math.exp(x)) + 1 / x) / 2;
}

function zoom_sinh(x) {
  return ((x = Math.exp(x)) - 1 / x) / 2;
}

function zoom_tanh(x) {
  return ((x = Math.exp(2 * x)) - 1) / (x + 1);
}

/* harmony default export */ const src_zoom = ((function zoomRho(rho, rho2, rho4) {

  // p0 = [ux0, uy0, w0]
  // p1 = [ux1, uy1, w1]
  function zoom(p0, p1) {
    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
        ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
        dx = ux1 - ux0,
        dy = uy1 - uy0,
        d2 = dx * dx + dy * dy,
        i,
        S;

    // Special case for u0 ≅ u1.
    if (d2 < epsilon2) {
      S = Math.log(w1 / w0) / rho;
      i = function(t) {
        return [
          ux0 + t * dx,
          uy0 + t * dy,
          w0 * Math.exp(rho * t * S)
        ];
      }
    }

    // General case.
    else {
      var d1 = Math.sqrt(d2),
          b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
          b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
          r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
          r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
      S = (r1 - r0) / rho;
      i = function(t) {
        var s = t * S,
            coshr0 = zoom_cosh(r0),
            u = w0 / (rho2 * d1) * (coshr0 * zoom_tanh(rho * s + r0) - zoom_sinh(r0));
        return [
          ux0 + u * dx,
          uy0 + u * dy,
          w0 * coshr0 / zoom_cosh(rho * s + r0)
        ];
      }
    }

    i.duration = S * 1000 * rho / Math.SQRT2;

    return i;
  }

  zoom.rho = function(_) {
    var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2;
    return zoomRho(_1, _2, _4);
  };

  return zoom;
})(Math.SQRT2, 2, 4));

;// ../../node_modules/d3-interpolate/src/hsl.js



function hsl_hsl(hue) {
  return function(start, end) {
    var h = hue((start = hsl(start)).h, (end = hsl(end)).h),
        s = nogamma(start.s, end.s),
        l = nogamma(start.l, end.l),
        opacity = nogamma(start.opacity, end.opacity);
    return function(t) {
      start.h = h(t);
      start.s = s(t);
      start.l = l(t);
      start.opacity = opacity(t);
      return start + "";
    };
  }
}

/* harmony default export */ const src_hsl = (hsl_hsl(hue));
var hslLong = hsl_hsl(nogamma);

;// ../../node_modules/d3-color/src/math.js
const src_math_radians = Math.PI / 180;
const src_math_degrees = 180 / Math.PI;

;// ../../node_modules/d3-color/src/lab.js




// https://observablehq.com/@mbostock/lab-and-rgb
const K = 18,
    Xn = 0.96422,
    Yn = 1,
    Zn = 0.82521,
    lab_t0 = 4 / 29,
    lab_t1 = 6 / 29,
    t2 = 3 * lab_t1 * lab_t1,
    t3 = lab_t1 * lab_t1 * lab_t1;

function labConvert(o) {
  if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
  if (o instanceof Hcl) return hcl2lab(o);
  if (!(o instanceof Rgb)) o = rgbConvert(o);
  var r = rgb2lrgb(o.r),
      g = rgb2lrgb(o.g),
      b = rgb2lrgb(o.b),
      y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z;
  if (r === g && g === b) x = z = y; else {
    x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);
    z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);
  }
  return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
}

function gray(l, opacity) {
  return new Lab(l, 0, 0, opacity == null ? 1 : opacity);
}

function lab(l, a, b, opacity) {
  return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
}

function Lab(l, a, b, opacity) {
  this.l = +l;
  this.a = +a;
  this.b = +b;
  this.opacity = +opacity;
}

src_define(Lab, lab, define_extend(Color, {
  brighter(k) {
    return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
  },
  darker(k) {
    return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
  },
  rgb() {
    var y = (this.l + 16) / 116,
        x = isNaN(this.a) ? y : y + this.a / 500,
        z = isNaN(this.b) ? y : y - this.b / 200;
    x = Xn * lab2xyz(x);
    y = Yn * lab2xyz(y);
    z = Zn * lab2xyz(z);
    return new Rgb(
      lrgb2rgb( 3.1338561 * x - 1.6168667 * y - 0.4906146 * z),
      lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z),
      lrgb2rgb( 0.0719453 * x - 0.2289914 * y + 1.4052427 * z),
      this.opacity
    );
  }
}));

function xyz2lab(t) {
  return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + lab_t0;
}

function lab2xyz(t) {
  return t > lab_t1 ? t * t * t : t2 * (t - lab_t0);
}

function lrgb2rgb(x) {
  return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
}

function rgb2lrgb(x) {
  return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}

function hclConvert(o) {
  if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
  if (!(o instanceof Lab)) o = labConvert(o);
  if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity);
  var h = Math.atan2(o.b, o.a) * src_math_degrees;
  return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
}

function lch(l, c, h, opacity) {
  return arguments.length === 1 ? hclConvert(l) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
}

function hcl(h, c, l, opacity) {
  return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
}

function Hcl(h, c, l, opacity) {
  this.h = +h;
  this.c = +c;
  this.l = +l;
  this.opacity = +opacity;
}

function hcl2lab(o) {
  if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);
  var h = o.h * src_math_radians;
  return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
}

src_define(Hcl, hcl, define_extend(Color, {
  brighter(k) {
    return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
  },
  darker(k) {
    return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
  },
  rgb() {
    return hcl2lab(this).rgb();
  }
}));

;// ../../node_modules/d3-interpolate/src/lab.js



function lab_lab(start, end) {
  var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
      a = nogamma(start.a, end.a),
      b = nogamma(start.b, end.b),
      opacity = nogamma(start.opacity, end.opacity);
  return function(t) {
    start.l = l(t);
    start.a = a(t);
    start.b = b(t);
    start.opacity = opacity(t);
    return start + "";
  };
}

;// ../../node_modules/d3-interpolate/src/hcl.js



function hcl_hcl(hue) {
  return function(start, end) {
    var h = hue((start = hcl(start)).h, (end = hcl(end)).h),
        c = nogamma(start.c, end.c),
        l = nogamma(start.l, end.l),
        opacity = nogamma(start.opacity, end.opacity);
    return function(t) {
      start.h = h(t);
      start.c = c(t);
      start.l = l(t);
      start.opacity = opacity(t);
      return start + "";
    };
  }
}

/* harmony default export */ const src_hcl = (hcl_hcl(hue));
var hclLong = hcl_hcl(nogamma);

;// ../../node_modules/d3-color/src/cubehelix.js




var A = -0.14861,
    B = +1.78277,
    C = -0.29227,
    D = -0.90649,
    E = +1.97294,
    ED = E * D,
    EB = E * B,
    BC_DA = B * C - D * A;

function cubehelixConvert(o) {
  if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
  if (!(o instanceof Rgb)) o = rgbConvert(o);
  var r = o.r / 255,
      g = o.g / 255,
      b = o.b / 255,
      l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
      bl = b - l,
      k = (E * (g - l) - C * bl) / D,
      s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
      h = s ? Math.atan2(k, bl) * src_math_degrees - 120 : NaN;
  return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
}

function cubehelix_cubehelix(h, s, l, opacity) {
  return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
}

function Cubehelix(h, s, l, opacity) {
  this.h = +h;
  this.s = +s;
  this.l = +l;
  this.opacity = +opacity;
}

src_define(Cubehelix, cubehelix_cubehelix, define_extend(Color, {
  brighter(k) {
    k = k == null ? brighter : Math.pow(brighter, k);
    return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
  },
  darker(k) {
    k = k == null ? darker : Math.pow(darker, k);
    return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
  },
  rgb() {
    var h = isNaN(this.h) ? 0 : (this.h + 120) * src_math_radians,
        l = +this.l,
        a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
        cosh = Math.cos(h),
        sinh = Math.sin(h);
    return new Rgb(
      255 * (l + a * (A * cosh + B * sinh)),
      255 * (l + a * (C * cosh + D * sinh)),
      255 * (l + a * (E * cosh)),
      this.opacity
    );
  }
}));

;// ../../node_modules/d3-interpolate/src/cubehelix.js



function cubehelix(hue) {
  return (function cubehelixGamma(y) {
    y = +y;

    function cubehelix(start, end) {
      var h = hue((start = cubehelix_cubehelix(start)).h, (end = cubehelix_cubehelix(end)).h),
          s = nogamma(start.s, end.s),
          l = nogamma(start.l, end.l),
          opacity = nogamma(start.opacity, end.opacity);
      return function(t) {
        start.h = h(t);
        start.s = s(t);
        start.l = l(Math.pow(t, y));
        start.opacity = opacity(t);
        return start + "";
      };
    }

    cubehelix.gamma = cubehelixGamma;

    return cubehelix;
  })(1);
}

/* harmony default export */ const src_cubehelix = (cubehelix(hue));
var cubehelixLong = cubehelix(nogamma);

;// ../../node_modules/d3-interpolate/src/quantize.js
/* harmony default export */ function src_quantize(interpolator, n) {
  var samples = new Array(n);
  for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
  return samples;
}

;// ../../node_modules/d3-interpolate/src/index.js






















;// ../../node_modules/d3-scale-chromatic/src/colors.js
/* harmony default export */ function colors(specifier) {
  var n = specifier.length / 6 | 0, colors = new Array(n), i = 0;
  while (i < n) colors[i] = "#" + specifier.slice(i * 6, ++i * 6);
  return colors;
}

;// ../../node_modules/d3-scale-chromatic/src/categorical/Accent.js


/* harmony default export */ const Accent = (colors("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/category10.js


/* harmony default export */ const category10 = (colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Dark2.js


/* harmony default export */ const Dark2 = (colors("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/observable10.js


/* harmony default export */ const observable10 = (colors("4269d0efb118ff725c6cc5b03ca951ff8ab7a463f297bbf59c6b4e9498a0"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Paired.js


/* harmony default export */ const Paired = (colors("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel1.js


/* harmony default export */ const Pastel1 = (colors("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel2.js


/* harmony default export */ const Pastel2 = (colors("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Set1.js


/* harmony default export */ const Set1 = (colors("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Set2.js


/* harmony default export */ const Set2 = (colors("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"));

;// ../../node_modules/d3-scale-chromatic/src/categorical/Set3.js


/* harmony default export */ const Set3 = (colors("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"));

;// ../../node_modules/vega-scale/build/vega-scale.module.js









function bandSpace (count, paddingInner, paddingOuter) {
  const space = count - paddingInner + paddingOuter * 2;
  return count ? space > 0 ? space : 1 : 0;
}

const Identity = 'identity';
const vega_scale_module_Linear = 'linear';
const Log = 'log';
const Pow = 'pow';
const Sqrt = 'sqrt';
const Symlog = 'symlog';
const Time = 'time';
const UTC = 'utc';
const Sequential = 'sequential';
const Diverging = 'diverging';
const vega_scale_module_Quantile = 'quantile';
const Quantize = 'quantize';
const Threshold = 'threshold';
const Ordinal = 'ordinal';
const Point = 'point';
const Band = 'band';
const BinOrdinal = 'bin-ordinal';

// categories
const Continuous = 'continuous';
const Discrete = 'discrete';
const Discretizing = 'discretizing';
const Interpolating = 'interpolating';
const Temporal = 'temporal';

function invertRange (scale) {
  return function (_) {
    let lo = _[0],
      hi = _[1],
      t;
    if (hi < lo) {
      t = lo;
      lo = hi;
      hi = t;
    }
    return [scale.invert(lo), scale.invert(hi)];
  };
}

function invertRangeExtent (scale) {
  return function (_) {
    const range = scale.range();
    let lo = _[0],
      hi = _[1],
      min = -1,
      max,
      t,
      i,
      n;
    if (hi < lo) {
      t = lo;
      lo = hi;
      hi = t;
    }
    for (i = 0, n = range.length; i < n; ++i) {
      if (range[i] >= lo && range[i] <= hi) {
        if (min < 0) min = i;
        max = i;
      }
    }
    if (min < 0) return undefined;
    lo = scale.invertExtent(range[min]);
    hi = scale.invertExtent(range[max]);
    return [lo[0] === undefined ? lo[1] : lo[0], hi[1] === undefined ? hi[0] : hi[1]];
  };
}

function band() {
  const scale = ordinal().unknown(undefined),
    domain = scale.domain,
    ordinalRange = scale.range;
  let range$1 = [0, 1],
    step,
    bandwidth,
    round = false,
    paddingInner = 0,
    paddingOuter = 0,
    align = 0.5;
  delete scale.unknown;
  function rescale() {
    const n = domain().length,
      reverse = range$1[1] < range$1[0],
      stop = range$1[1 - reverse],
      space = bandSpace(n, paddingInner, paddingOuter);
    let start = range$1[reverse - 0];
    step = (stop - start) / (space || 1);
    if (round) {
      step = Math.floor(step);
    }
    start += (stop - start - step * (n - paddingInner)) * align;
    bandwidth = step * (1 - paddingInner);
    if (round) {
      start = Math.round(start);
      bandwidth = Math.round(bandwidth);
    }
    const values = range_range(n).map(i => start + step * i);
    return ordinalRange(reverse ? values.reverse() : values);
  }
  scale.domain = function (_) {
    if (arguments.length) {
      domain(_);
      return rescale();
    } else {
      return domain();
    }
  };
  scale.range = function (_) {
    if (arguments.length) {
      range$1 = [+_[0], +_[1]];
      return rescale();
    } else {
      return range$1.slice();
    }
  };
  scale.rangeRound = function (_) {
    range$1 = [+_[0], +_[1]];
    round = true;
    return rescale();
  };
  scale.bandwidth = function () {
    return bandwidth;
  };
  scale.step = function () {
    return step;
  };
  scale.round = function (_) {
    if (arguments.length) {
      round = !!_;
      return rescale();
    } else {
      return round;
    }
  };
  scale.padding = function (_) {
    if (arguments.length) {
      paddingOuter = Math.max(0, Math.min(1, _));
      paddingInner = paddingOuter;
      return rescale();
    } else {
      return paddingInner;
    }
  };
  scale.paddingInner = function (_) {
    if (arguments.length) {
      paddingInner = Math.max(0, Math.min(1, _));
      return rescale();
    } else {
      return paddingInner;
    }
  };
  scale.paddingOuter = function (_) {
    if (arguments.length) {
      paddingOuter = Math.max(0, Math.min(1, _));
      return rescale();
    } else {
      return paddingOuter;
    }
  };
  scale.align = function (_) {
    if (arguments.length) {
      align = Math.max(0, Math.min(1, _));
      return rescale();
    } else {
      return align;
    }
  };
  scale.invertRange = function (_) {
    // bail if range has null or undefined values
    if (_[0] == null || _[1] == null) return;
    const reverse = range$1[1] < range$1[0],
      values = reverse ? ordinalRange().reverse() : ordinalRange(),
      n = values.length - 1;
    let lo = +_[0],
      hi = +_[1],
      a,
      b,
      t;

    // bail if either range endpoint is invalid
    if (lo !== lo || hi !== hi) return;

    // order range inputs, bail if outside of scale range
    if (hi < lo) {
      t = lo;
      lo = hi;
      hi = t;
    }
    if (hi < values[0] || lo > range$1[1 - reverse]) return;

    // binary search to index into scale range
    a = Math.max(0, bisectRight(values, lo) - 1);
    b = lo === hi ? a : bisectRight(values, hi) - 1;

    // increment index a if lo is within padding gap
    if (lo - values[a] > bandwidth + 1e-10) ++a;
    if (reverse) {
      // map + swap
      t = a;
      a = n - b;
      b = n - t;
    }
    return a > b ? undefined : domain().slice(a, b + 1);
  };
  scale.invert = function (_) {
    const value = scale.invertRange([_, _]);
    return value ? value[0] : value;
  };
  scale.copy = function () {
    return band().domain(domain()).range(range$1).round(round).paddingInner(paddingInner).paddingOuter(paddingOuter).align(align);
  };
  return rescale();
}
function pointish(scale) {
  const copy = scale.copy;
  scale.padding = scale.paddingOuter;
  delete scale.paddingInner;
  scale.copy = function () {
    return pointish(copy());
  };
  return scale;
}
function vega_scale_module_point() {
  return pointish(band().paddingInner(1));
}

var vega_scale_module_map = Array.prototype.map;
function vega_scale_module_numbers(_) {
  return vega_scale_module_map.call(_, vega_util_module_toNumber);
}

const vega_scale_module_slice = Array.prototype.slice;

function scaleBinOrdinal() {
  let domain = [],
    range = [];
  function scale(x) {
    return x == null || x !== x ? undefined : range[(src_bisect(domain, x) - 1) % range.length];
  }
  scale.domain = function (_) {
    if (arguments.length) {
      domain = vega_scale_module_numbers(_);
      return scale;
    } else {
      return domain.slice();
    }
  };
  scale.range = function (_) {
    if (arguments.length) {
      range = vega_scale_module_slice.call(_);
      return scale;
    } else {
      return range.slice();
    }
  };
  scale.tickFormat = function (count, specifier) {
    return tickFormat(domain[0], peek(domain), count == null ? 10 : count, specifier);
  };
  scale.copy = function () {
    return scaleBinOrdinal().domain(scale.domain()).range(scale.range());
  };
  return scale;
}

/** Private scale registry: should not be exported */
const scales = new Map();
const VEGA_SCALE = Symbol('vega_scale');
function registerScale(scale) {
  scale[VEGA_SCALE] = true;
  return scale;
}

/**
 * Return true if object was created by a constructor from the vega-scale `scale` function.
 */
function isRegisteredScale(scale) {
  return scale && scale[VEGA_SCALE] === true;
}

/**
 * Augment scales with their type and needed inverse methods.
 */
function create(type, constructor, metadata) {
  const ctr = function scale() {
    const s = constructor();
    if (!s.invertRange) {
      s.invertRange = s.invert ? invertRange(s) : s.invertExtent ? invertRangeExtent(s) : undefined;
    }
    s.type = type;
    return registerScale(s);
  };
  ctr.metadata = vega_util_module_toSet(vega_util_module_array(metadata));
  return ctr;
}

/**
 * Registry function for adding and accessing scale constructor functions.
 * The *type* argument is a String indicating the name of the scale type.
 *
 * If the *scale* argument is not specified, this method returns the matching scale constructor in the registry, or `null` if not found.
 * If the *scale* argument is provided, it must be a scale constructor function to add to the registry under the given *type* name.
 * The *metadata* argument provides additional information to guide appropriate use of scales within Vega.
 *
 *  *metadata* can be either a string or string array. The valid string values are:
 * - `"continuous"` - the scale is defined over a continuous-valued domain.
 * - `"discrete"` - the scale is defined over a discrete domain and range.
 * - `"discretizing"` - the scale discretizes a continuous domain to a discrete range.
 * - `"interpolating"` - the scale range is defined using a color interpolator.
 * - `"log"` - the scale performs a logarithmic transform of the continuous domain.
 * - `"temporal"` - the scale domain is defined over date-time values.
 */
function vega_scale_module_scale(type, scale, metadata) {
  if (arguments.length > 1) {
    scales.set(type, create(type, scale, metadata));
    return this;
  } else {
    return isValidScaleType(type) ? scales.get(type) : undefined;
  }
}

// identity scale
vega_scale_module_scale(Identity, src_identity_identity);

// continuous scales
vega_scale_module_scale(vega_scale_module_Linear, linear_linear, Continuous);
vega_scale_module_scale(Log, log_log, [Continuous, Log]);
vega_scale_module_scale(Pow, pow_pow, Continuous);
vega_scale_module_scale(Sqrt, pow_sqrt, Continuous);
vega_scale_module_scale(Symlog, symlog_symlog, Continuous);
vega_scale_module_scale(Time, time_time, [Continuous, Temporal]);
vega_scale_module_scale(UTC, utcTime, [Continuous, Temporal]);

// sequential scales
vega_scale_module_scale(Sequential, sequential, [Continuous, Interpolating]); // backwards compat
vega_scale_module_scale(`${Sequential}-${vega_scale_module_Linear}`, sequential, [Continuous, Interpolating]);
vega_scale_module_scale(`${Sequential}-${Log}`, sequentialLog, [Continuous, Interpolating, Log]);
vega_scale_module_scale(`${Sequential}-${Pow}`, sequentialPow, [Continuous, Interpolating]);
vega_scale_module_scale(`${Sequential}-${Sqrt}`, sequentialSqrt, [Continuous, Interpolating]);
vega_scale_module_scale(`${Sequential}-${Symlog}`, sequentialSymlog, [Continuous, Interpolating]);

// diverging scales
vega_scale_module_scale(`${Diverging}-${vega_scale_module_Linear}`, diverging, [Continuous, Interpolating]);
vega_scale_module_scale(`${Diverging}-${Log}`, divergingLog, [Continuous, Interpolating, Log]);
vega_scale_module_scale(`${Diverging}-${Pow}`, divergingPow, [Continuous, Interpolating]);
vega_scale_module_scale(`${Diverging}-${Sqrt}`, divergingSqrt, [Continuous, Interpolating]);
vega_scale_module_scale(`${Diverging}-${Symlog}`, divergingSymlog, [Continuous, Interpolating]);

// discretizing scales
vega_scale_module_scale(vega_scale_module_Quantile, src_quantile_quantile, [Discretizing, vega_scale_module_Quantile]);
vega_scale_module_scale(Quantize, quantize, Discretizing);
vega_scale_module_scale(Threshold, threshold, Discretizing);

// discrete scales
vega_scale_module_scale(BinOrdinal, scaleBinOrdinal, [Discrete, Discretizing]);
vega_scale_module_scale(Ordinal, ordinal, Discrete);
vega_scale_module_scale(Band, band, Discrete);
vega_scale_module_scale(Point, vega_scale_module_point, Discrete);
function isValidScaleType(type) {
  return scales.has(type);
}
function hasType(key, type) {
  const s = scales.get(key);
  return s && s.metadata[type];
}
function isContinuous(key) {
  return hasType(key, Continuous);
}
function isDiscrete(key) {
  return hasType(key, Discrete);
}
function isDiscretizing(key) {
  return hasType(key, Discretizing);
}
function isLogarithmic(key) {
  return hasType(key, Log);
}
function isTemporal(key) {
  return hasType(key, Temporal);
}
function isInterpolating(key) {
  return hasType(key, Interpolating);
}
function isQuantile(key) {
  return hasType(key, vega_scale_module_Quantile);
}

const scaleProps = ['clamp', 'base', 'constant', 'exponent'];
function interpolateRange(interpolator, range) {
  const start = range[0],
    span = peek(range) - start;
  return function (i) {
    return interpolator(start + i * span);
  };
}
function interpolateColors(colors, type, gamma) {
  return piecewise(interpolate(type || 'rgb', gamma), colors);
}
function quantizeInterpolator(interpolator, count) {
  const samples = new Array(count),
    n = count + 1;
  for (let i = 0; i < count;) samples[i] = interpolator(++i / n);
  return samples;
}
function scaleCopy(scale) {
  const t = scale.type,
    s = scale.copy();
  s.type = t;
  return s;
}
function scaleFraction(scale$1, min, max) {
  const delta = max - min;
  let i, t, s;
  if (!delta || !Number.isFinite(delta)) {
    return vega_util_module_constant(0.5);
  } else {
    i = (t = scale$1.type).indexOf('-');
    t = i < 0 ? t : t.slice(i + 1);
    s = vega_scale_module_scale(t)().domain([min, max]).range([0, 1]);
    scaleProps.forEach(m => scale$1[m] ? s[m](scale$1[m]()) : 0);
    return s;
  }
}
function interpolate(type, gamma) {
  const interp = d3_interpolate_src_namespaceObject[method(type)];
  return gamma != null && interp && interp.gamma ? interp.gamma(gamma) : interp;
}
function method(type) {
  return 'interpolate' + type.toLowerCase().split('-').map(s => s[0].toUpperCase() + s.slice(1)).join('');
}

const vega_scale_module_continuous = {
  blues: 'cfe1f2bed8eca8cee58fc1de74b2d75ba3cf4592c63181bd206fb2125ca40a4a90',
  greens: 'd3eecdc0e6baabdda594d3917bc77d60ba6c46ab5e329a512089430e7735036429',
  greys: 'e2e2e2d4d4d4c4c4c4b1b1b19d9d9d8888887575756262624d4d4d3535351e1e1e',
  oranges: 'fdd8b3fdc998fdb87bfda55efc9244f87f2cf06b18e4580bd14904b93d029f3303',
  purples: 'e2e1efd4d4e8c4c5e0b4b3d6a3a0cc928ec3827cb97566ae684ea25c3696501f8c',
  reds: 'fdc9b4fcb49afc9e80fc8767fa7051f6573fec3f2fdc2a25c81b1db21218970b13',
  blueGreen: 'd5efedc1e8e0a7ddd18bd2be70c6a958ba9144ad77319c5d2089460e7736036429',
  bluePurple: 'ccddecbad0e4a8c2dd9ab0d4919cc98d85be8b6db28a55a6873c99822287730f71',
  greenBlue: 'd3eecec5e8c3b1e1bb9bd8bb82cec269c2ca51b2cd3c9fc7288abd1675b10b60a1',
  orangeRed: 'fddcaffdcf9bfdc18afdad77fb9562f67d53ee6545e24932d32d1ebf130da70403',
  purpleBlue: 'dbdaebc8cee4b1c3de97b7d87bacd15b9fc93a90c01e7fb70b70ab056199045281',
  purpleBlueGreen: 'dbd8eac8cee4b0c3de93b7d872acd1549fc83892bb1c88a3097f8702736b016353',
  purpleRed: 'dcc9e2d3b3d7ce9eccd186c0da6bb2e14da0e23189d91e6fc61159ab07498f023a',
  redPurple: 'fccfccfcbec0faa9b8f98faff571a5ec539ddb3695c41b8aa908808d0179700174',
  yellowGreen: 'e4f4acd1eca0b9e2949ed68880c97c62bb6e47aa5e3297502083440e723b036034',
  yellowOrangeBrown: 'feeaa1fedd84fecc63feb746fca031f68921eb7215db5e0bc54c05ab3d038f3204',
  yellowOrangeRed: 'fee087fed16ffebd59fea849fd903efc7335f9522bee3423de1b20ca0b22af0225',
  blueOrange: '134b852f78b35da2cb9dcae1d2e5eff2f0ebfce0bafbbf74e8932fc5690d994a07',
  brownBlueGreen: '704108a0651ac79548e3c78af3e6c6eef1eac9e9e48ed1c74da79e187a72025147',
  purpleGreen: '5b1667834792a67fb6c9aed3e6d6e8eff0efd9efd5aedda971bb75368e490e5e29',
  purpleOrange: '4114696647968f83b7b9b4d6dadbebf3eeeafce0bafbbf74e8932fc5690d994a07',
  redBlue: '8c0d25bf363adf745ef4ae91fbdbc9f2efeed2e5ef9dcae15da2cb2f78b3134b85',
  redGrey: '8c0d25bf363adf745ef4ae91fcdccbfaf4f1e2e2e2c0c0c0969696646464343434',
  yellowGreenBlue: 'eff9bddbf1b4bde5b594d5b969c5be45b4c22c9ec02182b82163aa23479c1c3185',
  redYellowBlue: 'a50026d4322cf16e43fcac64fedd90faf8c1dcf1ecabd6e875abd04a74b4313695',
  redYellowGreen: 'a50026d4322cf16e43fcac63fedd8df9f7aed7ee8ea4d86e64bc6122964f006837',
  pinkYellowGreen: '8e0152c0267edd72adf0b3d6faddedf5f3efe1f2cab6de8780bb474f9125276419',
  spectral: '9e0142d13c4bf0704afcac63fedd8dfbf8b0e0f3a1a9dda269bda94288b55e4fa2',
  viridis: '440154470e61481a6c482575472f7d443a834144873d4e8a39568c35608d31688e2d708e2a788e27818e23888e21918d1f988b1fa08822a8842ab07f35b77943bf7154c56866cc5d7ad1518fd744a5db36bcdf27d2e21be9e51afde725',
  magma: '0000040404130b0924150e3720114b2c11603b0f704a107957157e651a80721f817f24828c29819a2e80a8327db6377ac43c75d1426fde4968e95462f1605df76f5cfa7f5efc8f65fe9f6dfeaf78febf84fece91fddea0fcedaffcfdbf',
  inferno: '0000040403130c0826170c3b240c4f330a5f420a68500d6c5d126e6b176e781c6d86216b932667a12b62ae305cbb3755c73e4cd24644dd513ae65c30ed6925f3771af8850ffb9506fca50afcb519fac62df6d645f2e661f3f484fcffa4',
  plasma: '0d088723069033059742039d5002a25d01a66a00a87801a88405a7900da49c179ea72198b12a90ba3488c33d80cb4779d35171da5a69e16462e76e5bed7953f2834cf68f44fa9a3dfca636fdb32ffec029fcce25f9dc24f5ea27f0f921',
  cividis: '00205100235800265d002961012b65042e670831690d346b11366c16396d1c3c6e213f6e26426e2c456e31476e374a6e3c4d6e42506e47536d4c566d51586e555b6e5a5e6e5e616e62646f66676f6a6a706e6d717270717573727976737c79747f7c75827f758682768985778c8877908b78938e789691789a94789e9778a19b78a59e77a9a177aea575b2a874b6ab73bbaf71c0b26fc5b66dc9b96acebd68d3c065d8c462ddc85fe2cb5ce7cf58ebd355f0d652f3da4ff7de4cfae249fce647',
  rainbow: '6e40aa883eb1a43db3bf3cafd83fa4ee4395fe4b83ff576eff6659ff7847ff8c38f3a130e2b72fcfcc36bee044aff05b8ff4576ff65b52f6673af27828ea8d1ddfa319d0b81cbecb23abd82f96e03d82e14c6edb5a5dd0664dbf6e40aa',
  sinebow: 'ff4040fc582af47218e78d0bd5a703bfbf00a7d5038de70b72f41858fc2a40ff402afc5818f4720be78d03d5a700bfbf03a7d50b8de71872f42a58fc4040ff582afc7218f48d0be7a703d5bf00bfd503a7e70b8df41872fc2a58ff4040',
  turbo: '23171b32204a3e2a71453493493eae4b49c54a53d7485ee44569ee4074f53c7ff8378af93295f72e9ff42ba9ef28b3e926bce125c5d925cdcf27d5c629dcbc2de3b232e9a738ee9d3ff39347f68950f9805afc7765fd6e70fe667cfd5e88fc5795fb51a1f84badf545b9f140c5ec3cd0e637dae034e4d931ecd12ef4c92bfac029ffb626ffad24ffa223ff9821ff8d1fff821dff771cfd6c1af76118f05616e84b14df4111d5380fcb2f0dc0260ab61f07ac1805a313029b0f00950c00910b00',
  browns: 'eedbbdecca96e9b97ae4a865dc9856d18954c7784cc0673fb85536ad44339f3632',
  tealBlues: 'bce4d89dd3d181c3cb65b3c245a2b9368fae347da0306a932c5985',
  teals: 'bbdfdfa2d4d58ac9c975bcbb61b0af4da5a43799982b8b8c1e7f7f127273006667',
  warmGreys: 'dcd4d0cec5c1c0b8b4b3aaa7a59c9998908c8b827f7e7673726866665c5a59504e',
  goldGreen: 'f4d166d5ca60b6c35c98bb597cb25760a6564b9c533f8f4f33834a257740146c36',
  goldOrange: 'f4d166f8be5cf8aa4cf5983bf3852aef701be2621fd65322c54923b142239e3a26',
  goldRed: 'f4d166f6be59f9aa51fc964ef6834bee734ae56249db5247cf4244c43141b71d3e',
  lightGreyRed: 'efe9e6e1dad7d5cbc8c8bdb9bbaea9cd967ddc7b43e15f19df4011dc000b',
  lightGreyTeal: 'e4eaead6dcddc8ced2b7c2c7a6b4bc64b0bf22a6c32295c11f85be1876bc',
  lightMulti: 'e0f1f2c4e9d0b0de9fd0e181f6e072f6c053f3993ef77440ef4a3c',
  lightOrange: 'f2e7daf7d5baf9c499fab184fa9c73f68967ef7860e8645bde515bd43d5b',
  lightTealBlue: 'e3e9e0c0dccf9aceca7abfc859afc0389fb9328dad2f7ca0276b95255988',
  darkBlue: '3232322d46681a5c930074af008cbf05a7ce25c0dd38daed50f3faffffff',
  darkGold: '3c3c3c584b37725e348c7631ae8b2bcfa424ecc31ef9de30fff184ffffff',
  darkGreen: '3a3a3a215748006f4d048942489e4276b340a6c63dd2d836ffeb2cffffaa',
  darkMulti: '3737371f5287197d8c29a86995ce3fffe800ffffff',
  darkRed: '3434347036339e3c38cc4037e75d1eec8620eeab29f0ce32ffeb2c'
};
const vega_scale_module_discrete = {
  accent: Accent,
  category10: category10,
  category20: '1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5',
  category20b: '393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6',
  category20c: '3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9',
  dark2: Dark2,
  observable10: observable10,
  paired: Paired,
  pastel1: Pastel1,
  pastel2: Pastel2,
  set1: Set1,
  set2: Set2,
  set3: Set3,
  tableau10: '4c78a8f58518e4575672b7b254a24beeca3bb279a2ff9da69d755dbab0ac',
  tableau20: '4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5'
};

function vega_scale_module_colors(palette) {
  if (vega_util_module_isArray(palette)) return palette;
  const n = palette.length / 6 | 0,
    c = new Array(n);
  for (let i = 0; i < n;) {
    c[i] = '#' + palette.slice(i * 6, ++i * 6);
  }
  return c;
}
function apply(_, f) {
  for (const k in _) scheme(k, f(_[k]));
}
const schemes = {};
apply(vega_scale_module_discrete, vega_scale_module_colors);
apply(vega_scale_module_continuous, _ => interpolateColors(vega_scale_module_colors(_)));
function scheme(name, scheme) {
  name = name && name.toLowerCase();
  if (arguments.length > 1) {
    schemes[name] = scheme;
    return this;
  } else {
    return schemes[name];
  }
}

const SymbolLegend = 'symbol';
const DiscreteLegend = 'discrete';
const GradientLegend = 'gradient';

const vega_scale_module_defaultFormatter = value => vega_util_module_isArray(value) ? value.map(v => String(v)) : String(value);
const vega_scale_module_ascending = (a, b) => a[1] - b[1];
const vega_scale_module_descending = (a, b) => b[1] - a[1];

/**
 * Determine the tick count or interval function.
 * @param {Scale} scale - The scale for which to generate tick values.
 * @param {*} count - The desired tick count or interval specifier.
 * @param {number} minStep - The desired minimum step between tick values.
 * @return {*} - The tick count or interval function.
 */
function tickCount(scale, count, minStep) {
  let step;
  if (vega_util_module_isNumber(count)) {
    if (scale.bins) {
      count = Math.max(count, scale.bins.length);
    }
    if (minStep != null) {
      count = Math.min(count, Math.floor(span(scale.domain()) / minStep || 1) + 1);
    }
  }
  if (vega_util_module_isObject(count)) {
    step = count.step;
    count = count.interval;
  }
  if (vega_util_module_isString(count)) {
    count = scale.type === Time ? vega_time_module_timeInterval(count) : scale.type == UTC ? utcInterval(count) : vega_util_module_error('Only time and utc scales accept interval strings.');
    if (step) count = count.every(step);
  }
  return count;
}

/**
 * Filter a set of candidate tick values, ensuring that only tick values
 * that lie within the scale range are included.
 * @param {Scale} scale - The scale for which to generate tick values.
 * @param {Array<*>} ticks - The candidate tick values.
 * @param {*} count - The tick count or interval function.
 * @return {Array<*>} - The filtered tick values.
 */
function validTicks(scale, ticks, count) {
  let range = scale.range(),
    lo = range[0],
    hi = peek(range),
    cmp = vega_scale_module_ascending;
  if (lo > hi) {
    range = hi;
    hi = lo;
    lo = range;
    cmp = vega_scale_module_descending;
  }
  lo = Math.floor(lo);
  hi = Math.ceil(hi);

  // filter ticks to valid values within the range
  // additionally sort ticks in range order (#2579)
  ticks = ticks.map(v => [v, scale(v)]).filter(_ => lo <= _[1] && _[1] <= hi).sort(cmp).map(_ => _[0]);
  if (count > 0 && ticks.length > 1) {
    const endpoints = [ticks[0], peek(ticks)];
    while (ticks.length > count && ticks.length >= 3) {
      ticks = ticks.filter((_, i) => !(i % 2));
    }
    if (ticks.length < 3) {
      ticks = endpoints;
    }
  }
  return ticks;
}

/**
 * Generate tick values for the given scale and approximate tick count or
 * interval value. If the scale has a 'ticks' method, it will be used to
 * generate the ticks, with the count argument passed as a parameter. If the
 * scale lacks a 'ticks' method, the full scale domain will be returned.
 * @param {Scale} scale - The scale for which to generate tick values.
 * @param {*} [count] - The approximate number of desired ticks.
 * @return {Array<*>} - The generated tick values.
 */
function tickValues(scale, count) {
  return scale.bins ? validTicks(scale, scale.bins, count) : scale.ticks ? scale.ticks(count) : scale.domain();
}

/**
 * Generate a label format function for a scale. If the scale has a
 * 'tickFormat' method, it will be used to generate the formatter, with the
 * count and specifier arguments passed as parameters. If the scale lacks a
 * 'tickFormat' method, the returned formatter performs simple string coercion.
 * If the input scale is a logarithmic scale and the format specifier does not
 * indicate a desired decimal precision, a special variable precision formatter
 * that automatically trims trailing zeroes will be generated.
 * @param {Scale} scale - The scale for which to generate the label formatter.
 * @param {*} [count] - The approximate number of desired ticks.
 * @param {string} [specifier] - The format specifier. Must be a legal d3
 *   specifier string (see https://github.com/d3/d3-format#formatSpecifier) or
 *   time multi-format specifier object.
 * @return {function(*):string} - The generated label formatter.
 */
function vega_scale_module_tickFormat(locale, scale, count, specifier, formatType, noSkip) {
  const type = scale.type;
  let format = vega_scale_module_defaultFormatter;
  if (type === Time || formatType === Time) {
    format = locale.timeFormat(specifier);
  } else if (type === UTC || formatType === UTC) {
    format = locale.utcFormat(specifier);
  } else if (isLogarithmic(type)) {
    const varfmt = locale.formatFloat(specifier);
    if (noSkip || scale.bins) {
      format = varfmt;
    } else {
      const test = tickLog(scale, count, false);
      format = _ => test(_) ? varfmt(_) : '';
    }
  } else if (scale.tickFormat) {
    // if d3 scale has tickFormat, it must be continuous
    const d = scale.domain();
    format = locale.formatSpan(d[0], d[d.length - 1], count, specifier);
  } else if (specifier) {
    format = locale.format(specifier);
  }
  return format;
}
function tickLog(scale, count, values) {
  const ticks = tickValues(scale, count),
    base = scale.base(),
    logb = Math.log(base),
    k = Math.max(1, base * count / ticks.length);

  // apply d3-scale's log format filter criteria
  const test = d => {
    let i = d / Math.pow(base, Math.round(Math.log(d) / logb));
    if (i * base < base - 0.5) i *= base;
    return i <= k;
  };
  return values ? ticks.filter(test) : test;
}

const symbols = {
  [vega_scale_module_Quantile]: 'quantiles',
  [Quantize]: 'thresholds',
  [Threshold]: 'domain'
};
const vega_scale_module_formats = {
  [vega_scale_module_Quantile]: 'quantiles',
  [Quantize]: 'domain'
};
function labelValues(scale, count) {
  return scale.bins ? binValues(scale.bins) : scale.type === Log ? tickLog(scale, count, true) : symbols[scale.type] ? thresholdValues(scale[symbols[scale.type]]()) : tickValues(scale, count);
}
function thresholdFormat(locale, scale, specifier) {
  const _ = scale[vega_scale_module_formats[scale.type]](),
    n = _.length;
  let d = n > 1 ? _[1] - _[0] : _[0],
    i;
  for (i = 1; i < n; ++i) {
    d = Math.min(d, _[i] - _[i - 1]);
  }

  // tickCount = 3 ticks times 10 for increased resolution
  return locale.formatSpan(0, d, 3 * 10, specifier);
}
function thresholdValues(thresholds) {
  const values = [-Infinity].concat(thresholds);
  values.max = +Infinity;
  return values;
}
function binValues(bins) {
  const values = bins.slice(0, -1);
  values.max = peek(bins);
  return values;
}
const isDiscreteRange = scale => symbols[scale.type] || scale.bins;
function labelFormat(locale, scale, count, type, specifier, formatType, noSkip) {
  const format = vega_scale_module_formats[scale.type] && formatType !== Time && formatType !== UTC ? thresholdFormat(locale, scale, specifier) : vega_scale_module_tickFormat(locale, scale, count, specifier, formatType, noSkip);
  return type === SymbolLegend && isDiscreteRange(scale) ? formatRange(format) : type === DiscreteLegend ? formatDiscrete(format) : formatPoint(format);
}
const formatRange = format => (value, index, array) => {
  const limit = vega_scale_module_get(array[index + 1], vega_scale_module_get(array.max, +Infinity)),
    lo = vega_scale_module_formatValue(value, format),
    hi = vega_scale_module_formatValue(limit, format);
  return lo && hi ? lo + ' \u2013 ' + hi : hi ? '< ' + hi : '\u2265 ' + lo;
};
const vega_scale_module_get = (value, dflt) => value != null ? value : dflt;
const formatDiscrete = format => (value, index) => index ? format(value) : null;
const formatPoint = format => value => format(value);
const vega_scale_module_formatValue = (value, format) => Number.isFinite(value) ? format(value) : null;
function labelFraction(scale) {
  const domain = scale.domain(),
    count = domain.length - 1;
  let lo = +domain[0],
    hi = +peek(domain),
    span = hi - lo;
  if (scale.type === Threshold) {
    const adjust = count ? span / count : 0.1;
    lo -= adjust;
    hi += adjust;
    span = hi - lo;
  }
  return value => (value - lo) / span;
}

function vega_scale_module_format(locale, scale, specifier, formatType) {
  const type = formatType || scale.type;

  // replace abbreviated time specifiers to improve screen reader experience
  if (vega_util_module_isString(specifier) && isTemporal(type)) {
    specifier = specifier.replace(/%a/g, '%A').replace(/%b/g, '%B');
  }
  return !specifier && type === Time ? locale.timeFormat('%A, %d %B %Y, %X') : !specifier && type === UTC ? locale.utcFormat('%A, %d %B %Y, %X UTC') : labelFormat(locale, scale, 5, null, specifier, formatType, true);
}
function domainCaption(locale, scale, opt) {
  opt = opt || {};
  const max = Math.max(3, opt.maxlen || 7),
    fmt = vega_scale_module_format(locale, scale, opt.format, opt.formatType);

  // if scale breaks domain into bins, describe boundaries
  if (isDiscretizing(scale.type)) {
    const v = labelValues(scale).slice(1).map(fmt),
      n = v.length;
    return `${n} boundar${n === 1 ? 'y' : 'ies'}: ${v.join(', ')}`;
  }

  // if scale domain is discrete, list values
  else if (isDiscrete(scale.type)) {
    const d = scale.domain(),
      n = d.length,
      v = n > max ? d.slice(0, max - 2).map(fmt).join(', ') + ', ending with ' + d.slice(-1).map(fmt) : d.map(fmt).join(', ');
    return `${n} value${n === 1 ? '' : 's'}: ${v}`;
  }

  // if scale domain is continuous, describe value range
  else {
    const d = scale.domain();
    return `values from ${fmt(d[0])} to ${fmt(peek(d))}`;
  }
}



;// ../../node_modules/vega-scenegraph/build/vega-scenegraph.module.js








let gradient_id = 0;
function resetSVGGradientId() {
  gradient_id = 0;
}
const patternPrefix = 'p_';
function isGradient(value) {
  return value && value.gradient;
}
function gradientRef(g, defs, base) {
  const type = g.gradient;
  let id = g.id,
    prefix = type === 'radial' ? patternPrefix : '';

  // check id, assign default values as needed
  if (!id) {
    id = g.id = 'gradient_' + gradient_id++;
    if (type === 'radial') {
      g.x1 = vega_scenegraph_module_get(g.x1, 0.5);
      g.y1 = vega_scenegraph_module_get(g.y1, 0.5);
      g.r1 = vega_scenegraph_module_get(g.r1, 0);
      g.x2 = vega_scenegraph_module_get(g.x2, 0.5);
      g.y2 = vega_scenegraph_module_get(g.y2, 0.5);
      g.r2 = vega_scenegraph_module_get(g.r2, 0.5);
      prefix = patternPrefix;
    } else {
      g.x1 = vega_scenegraph_module_get(g.x1, 0);
      g.y1 = vega_scenegraph_module_get(g.y1, 0);
      g.x2 = vega_scenegraph_module_get(g.x2, 1);
      g.y2 = vega_scenegraph_module_get(g.y2, 0);
    }
  }

  // register definition
  defs[id] = g;

  // return url reference
  return 'url(' + (base || '') + '#' + prefix + id + ')';
}
function vega_scenegraph_module_get(val, def) {
  return val != null ? val : def;
}
function Gradient (p0, p1) {
  var stops = [],
    gradient;
  return gradient = {
    gradient: 'linear',
    x1: p0 ? p0[0] : 0,
    y1: p0 ? p0[1] : 0,
    x2: p1 ? p1[0] : 1,
    y2: p1 ? p1[1] : 0,
    stops: stops,
    stop: function (offset, color) {
      stops.push({
        offset: offset,
        color: color
      });
      return gradient;
    }
  };
}

const vega_scenegraph_module_lookup = {
  'basis': {
    curve: basis
  },
  'basis-closed': {
    curve: basisClosed
  },
  'basis-open': {
    curve: basisOpen
  },
  'bundle': {
    curve: bundle,
    tension: 'beta',
    value: 0.85
  },
  'cardinal': {
    curve: cardinal,
    tension: 'tension',
    value: 0
  },
  'cardinal-open': {
    curve: cardinalOpen,
    tension: 'tension',
    value: 0
  },
  'cardinal-closed': {
    curve: cardinalClosed,
    tension: 'tension',
    value: 0
  },
  'catmull-rom': {
    curve: catmullRom,
    tension: 'alpha',
    value: 0.5
  },
  'catmull-rom-closed': {
    curve: catmullRomClosed,
    tension: 'alpha',
    value: 0.5
  },
  'catmull-rom-open': {
    curve: catmullRomOpen,
    tension: 'alpha',
    value: 0.5
  },
  'linear': {
    curve: curve_linear
  },
  'linear-closed': {
    curve: linearClosed
  },
  'monotone': {
    horizontal: monotoneY,
    vertical: monotoneX
  },
  'natural': {
    curve: natural
  },
  'step': {
    curve: step
  },
  'step-after': {
    curve: stepAfter
  },
  'step-before': {
    curve: stepBefore
  }
};
function curves(type, orientation, tension) {
  var entry = vega_util_module_has(vega_scenegraph_module_lookup, type) && vega_scenegraph_module_lookup[type],
    curve = null;
  if (entry) {
    curve = entry.curve || entry[orientation || 'vertical'];
    if (entry.tension && tension != null) {
      curve = curve[entry.tension](tension);
    }
  }
  return curve;
}

const paramCounts = {
  m: 2,
  l: 2,
  h: 1,
  v: 1,
  z: 0,
  c: 6,
  s: 4,
  q: 4,
  t: 2,
  a: 7
};
const commandPattern = /[mlhvzcsqta]([^mlhvzcsqta]+|$)/gi;
const numberPattern = /^[+-]?(([0-9]*\.[0-9]+)|([0-9]+\.)|([0-9]+))([eE][+-]?[0-9]+)?/;
const spacePattern = /^((\s+,?\s*)|(,\s*))/;
const flagPattern = /^[01]/;
function vega_scenegraph_module_parse(path) {
  const commands = [];
  const matches = path.match(commandPattern) || [];
  matches.forEach(str => {
    let cmd = str[0];
    const type = cmd.toLowerCase();

    // parse parameters
    const paramCount = paramCounts[type];
    const params = parseParams(type, paramCount, str.slice(1).trim());
    const count = params.length;

    // error checking based on parameter count
    if (count < paramCount || count && count % paramCount !== 0) {
      throw Error('Invalid SVG path, incorrect parameter count');
    }

    // register the command
    commands.push([cmd, ...params.slice(0, paramCount)]);

    // exit now if we're done, also handles zero-param 'z'
    if (count === paramCount) {
      return;
    }

    // handle implicit line-to
    if (type === 'm') {
      cmd = cmd === 'M' ? 'L' : 'l';
    }

    // repeat command when given extended param list
    for (let i = paramCount; i < count; i += paramCount) {
      commands.push([cmd, ...params.slice(i, i + paramCount)]);
    }
  });
  return commands;
}
function parseParams(type, paramCount, segment) {
  const params = [];
  for (let index = 0; paramCount && index < segment.length;) {
    for (let i = 0; i < paramCount; ++i) {
      const pattern = type === 'a' && (i === 3 || i === 4) ? flagPattern : numberPattern;
      const match = segment.slice(index).match(pattern);
      if (match === null) {
        throw Error('Invalid SVG path, incorrect parameter type');
      }
      index += match[0].length;
      params.push(+match[0]);
      const ws = segment.slice(index).match(spacePattern);
      if (ws !== null) {
        index += ws[0].length;
      }
    }
  }
  return params;
}

const DegToRad = Math.PI / 180;
const Epsilon = 1e-14;
const HalfPi = Math.PI / 2;
const Tau = Math.PI * 2;
const HalfSqrt3 = Math.sqrt(3) / 2;

var segmentCache = {};
var bezierCache = {};
var vega_scenegraph_module_join = [].join;

// Copied from Inkscape svgtopdf, thanks!
function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
  const key = vega_scenegraph_module_join.call(arguments);
  if (segmentCache[key]) {
    return segmentCache[key];
  }
  const th = rotateX * DegToRad;
  const sin_th = Math.sin(th);
  const cos_th = Math.cos(th);
  rx = Math.abs(rx);
  ry = Math.abs(ry);
  const px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
  const py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
  let pl = px * px / (rx * rx) + py * py / (ry * ry);
  if (pl > 1) {
    pl = Math.sqrt(pl);
    rx *= pl;
    ry *= pl;
  }
  const a00 = cos_th / rx;
  const a01 = sin_th / rx;
  const a10 = -sin_th / ry;
  const a11 = cos_th / ry;
  const x0 = a00 * ox + a01 * oy;
  const y0 = a10 * ox + a11 * oy;
  const x1 = a00 * x + a01 * y;
  const y1 = a10 * x + a11 * y;
  const d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
  let sfactor_sq = 1 / d - 0.25;
  if (sfactor_sq < 0) sfactor_sq = 0;
  let sfactor = Math.sqrt(sfactor_sq);
  if (sweep == large) sfactor = -sfactor;
  const xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
  const yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
  const th0 = Math.atan2(y0 - yc, x0 - xc);
  const th1 = Math.atan2(y1 - yc, x1 - xc);
  let th_arc = th1 - th0;
  if (th_arc < 0 && sweep === 1) {
    th_arc += Tau;
  } else if (th_arc > 0 && sweep === 0) {
    th_arc -= Tau;
  }
  const segs = Math.ceil(Math.abs(th_arc / (HalfPi + 0.001)));
  const result = [];
  for (let i = 0; i < segs; ++i) {
    const th2 = th0 + i * th_arc / segs;
    const th3 = th0 + (i + 1) * th_arc / segs;
    result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
  }
  return segmentCache[key] = result;
}
function bezier(params) {
  const key = vega_scenegraph_module_join.call(params);
  if (bezierCache[key]) {
    return bezierCache[key];
  }
  var cx = params[0],
    cy = params[1],
    th0 = params[2],
    th1 = params[3],
    rx = params[4],
    ry = params[5],
    sin_th = params[6],
    cos_th = params[7];
  const a00 = cos_th * rx;
  const a01 = -sin_th * ry;
  const a10 = sin_th * rx;
  const a11 = cos_th * ry;
  const cos_th0 = Math.cos(th0);
  const sin_th0 = Math.sin(th0);
  const cos_th1 = Math.cos(th1);
  const sin_th1 = Math.sin(th1);
  const th_half = 0.5 * (th1 - th0);
  const sin_th_h2 = Math.sin(th_half * 0.5);
  const t = 8 / 3 * sin_th_h2 * sin_th_h2 / Math.sin(th_half);
  const x1 = cx + cos_th0 - t * sin_th0;
  const y1 = cy + sin_th0 + t * cos_th0;
  const x3 = cx + cos_th1;
  const y3 = cy + sin_th1;
  const x2 = x3 + t * sin_th1;
  const y2 = y3 - t * cos_th1;
  return bezierCache[key] = [a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3];
}

const temp = ['l', 0, 0, 0, 0, 0, 0, 0];
function scale$1(current, sX, sY) {
  const c = temp[0] = current[0];
  if (c === 'a' || c === 'A') {
    temp[1] = sX * current[1];
    temp[2] = sY * current[2];
    temp[3] = current[3];
    temp[4] = current[4];
    temp[5] = current[5];
    temp[6] = sX * current[6];
    temp[7] = sY * current[7];
  } else if (c === 'h' || c === 'H') {
    temp[1] = sX * current[1];
  } else if (c === 'v' || c === 'V') {
    temp[1] = sY * current[1];
  } else {
    for (var i = 1, n = current.length; i < n; ++i) {
      temp[i] = (i % 2 == 1 ? sX : sY) * current[i];
    }
  }
  return temp;
}
function pathRender (context, path, l, t, sX, sY) {
  var current,
    // current instruction
    previous = null,
    x = 0,
    // current x
    y = 0,
    // current y
    controlX = 0,
    // current control point x
    controlY = 0,
    // current control point y
    tempX,
    tempY,
    tempControlX,
    tempControlY,
    anchorX = 0,
    anchorY = 0;
  if (l == null) l = 0;
  if (t == null) t = 0;
  if (sX == null) sX = 1;
  if (sY == null) sY = sX;
  if (context.beginPath) context.beginPath();
  for (var i = 0, len = path.length; i < len; ++i) {
    current = path[i];
    if (sX !== 1 || sY !== 1) {
      current = scale$1(current, sX, sY);
    }
    switch (current[0]) {
      // first letter

      case 'l':
        // lineto, relative
        x += current[1];
        y += current[2];
        context.lineTo(x + l, y + t);
        break;
      case 'L':
        // lineto, absolute
        x = current[1];
        y = current[2];
        context.lineTo(x + l, y + t);
        break;
      case 'h':
        // horizontal lineto, relative
        x += current[1];
        context.lineTo(x + l, y + t);
        break;
      case 'H':
        // horizontal lineto, absolute
        x = current[1];
        context.lineTo(x + l, y + t);
        break;
      case 'v':
        // vertical lineto, relative
        y += current[1];
        context.lineTo(x + l, y + t);
        break;
      case 'V':
        // verical lineto, absolute
        y = current[1];
        context.lineTo(x + l, y + t);
        break;
      case 'm':
        // moveTo, relative
        x += current[1];
        y += current[2];
        anchorX = x;
        anchorY = y;
        context.moveTo(x + l, y + t);
        break;
      case 'M':
        // moveTo, absolute
        x = current[1];
        y = current[2];
        anchorX = x;
        anchorY = y;
        context.moveTo(x + l, y + t);
        break;
      case 'c':
        // bezierCurveTo, relative
        tempX = x + current[5];
        tempY = y + current[6];
        controlX = x + current[3];
        controlY = y + current[4];
        context.bezierCurveTo(x + current[1] + l,
        // x1
        y + current[2] + t,
        // y1
        controlX + l,
        // x2
        controlY + t,
        // y2
        tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        break;
      case 'C':
        // bezierCurveTo, absolute
        x = current[5];
        y = current[6];
        controlX = current[3];
        controlY = current[4];
        context.bezierCurveTo(current[1] + l, current[2] + t, controlX + l, controlY + t, x + l, y + t);
        break;
      case 's':
        // shorthand cubic bezierCurveTo, relative
        // transform to absolute x,y
        tempX = x + current[3];
        tempY = y + current[4];
        // calculate reflection of previous control points
        controlX = 2 * x - controlX;
        controlY = 2 * y - controlY;
        context.bezierCurveTo(controlX + l, controlY + t, x + current[1] + l, y + current[2] + t, tempX + l, tempY + t);

        // set control point to 2nd one of this command
        // the first control point is assumed to be the reflection of
        // the second control point on the previous command relative
        // to the current point.
        controlX = x + current[1];
        controlY = y + current[2];
        x = tempX;
        y = tempY;
        break;
      case 'S':
        // shorthand cubic bezierCurveTo, absolute
        tempX = current[3];
        tempY = current[4];
        // calculate reflection of previous control points
        controlX = 2 * x - controlX;
        controlY = 2 * y - controlY;
        context.bezierCurveTo(controlX + l, controlY + t, current[1] + l, current[2] + t, tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        // set control point to 2nd one of this command
        // the first control point is assumed to be the reflection of
        // the second control point on the previous command relative
        // to the current point.
        controlX = current[1];
        controlY = current[2];
        break;
      case 'q':
        // quadraticCurveTo, relative
        // transform to absolute x,y
        tempX = x + current[3];
        tempY = y + current[4];
        controlX = x + current[1];
        controlY = y + current[2];
        context.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        break;
      case 'Q':
        // quadraticCurveTo, absolute
        tempX = current[3];
        tempY = current[4];
        context.quadraticCurveTo(current[1] + l, current[2] + t, tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        controlX = current[1];
        controlY = current[2];
        break;
      case 't':
        // shorthand quadraticCurveTo, relative

        // transform to absolute x,y
        tempX = x + current[1];
        tempY = y + current[2];
        if (previous[0].match(/[QqTt]/) === null) {
          // If there is no previous command or if the previous command was not a Q, q, T or t,
          // assume the control point is coincident with the current point
          controlX = x;
          controlY = y;
        } else if (previous[0] === 't') {
          // calculate reflection of previous control points for t
          controlX = 2 * x - tempControlX;
          controlY = 2 * y - tempControlY;
        } else if (previous[0] === 'q') {
          // calculate reflection of previous control points for q
          controlX = 2 * x - controlX;
          controlY = 2 * y - controlY;
        }
        tempControlX = controlX;
        tempControlY = controlY;
        context.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        controlX = x + current[1];
        controlY = y + current[2];
        break;
      case 'T':
        tempX = current[1];
        tempY = current[2];

        // calculate reflection of previous control points
        controlX = 2 * x - controlX;
        controlY = 2 * y - controlY;
        context.quadraticCurveTo(controlX + l, controlY + t, tempX + l, tempY + t);
        x = tempX;
        y = tempY;
        break;
      case 'a':
        drawArc(context, x + l, y + t, [current[1], current[2], current[3], current[4], current[5], current[6] + x + l, current[7] + y + t]);
        x += current[6];
        y += current[7];
        break;
      case 'A':
        drawArc(context, x + l, y + t, [current[1], current[2], current[3], current[4], current[5], current[6] + l, current[7] + t]);
        x = current[6];
        y = current[7];
        break;
      case 'z':
      case 'Z':
        x = anchorX;
        y = anchorY;
        context.closePath();
        break;
    }
    previous = current;
  }
}
function drawArc(context, x, y, coords) {
  const seg = segments(coords[5],
  // end x
  coords[6],
  // end y
  coords[0],
  // radius x
  coords[1],
  // radius y
  coords[3],
  // large flag
  coords[4],
  // sweep flag
  coords[2],
  // rotation
  x, y);
  for (let i = 0; i < seg.length; ++i) {
    const bez = bezier(seg[i]);
    context.bezierCurveTo(bez[0], bez[1], bez[2], bez[3], bez[4], bez[5]);
  }
}

const Tan30 = 0.5773502691896257;
const builtins = {
  'circle': {
    draw: function (context, size) {
      const r = Math.sqrt(size) / 2;
      context.moveTo(r, 0);
      context.arc(0, 0, r, 0, Tau);
    }
  },
  'cross': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        s = r / 2.5;
      context.moveTo(-r, -s);
      context.lineTo(-r, s);
      context.lineTo(-s, s);
      context.lineTo(-s, r);
      context.lineTo(s, r);
      context.lineTo(s, s);
      context.lineTo(r, s);
      context.lineTo(r, -s);
      context.lineTo(s, -s);
      context.lineTo(s, -r);
      context.lineTo(-s, -r);
      context.lineTo(-s, -s);
      context.closePath();
    }
  },
  'diamond': {
    draw: function (context, size) {
      const r = Math.sqrt(size) / 2;
      context.moveTo(-r, 0);
      context.lineTo(0, -r);
      context.lineTo(r, 0);
      context.lineTo(0, r);
      context.closePath();
    }
  },
  'square': {
    draw: function (context, size) {
      var w = Math.sqrt(size),
        x = -w / 2;
      context.rect(x, x, w, w);
    }
  },
  'arrow': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        s = r / 7,
        t = r / 2.5,
        v = r / 8;
      context.moveTo(-s, r);
      context.lineTo(s, r);
      context.lineTo(s, -v);
      context.lineTo(t, -v);
      context.lineTo(0, -r);
      context.lineTo(-t, -v);
      context.lineTo(-s, -v);
      context.closePath();
    }
  },
  'wedge': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r,
        o = h - r * Tan30,
        b = r / 4;
      context.moveTo(0, -h - o);
      context.lineTo(-b, h - o);
      context.lineTo(b, h - o);
      context.closePath();
    }
  },
  'triangle': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r,
        o = h - r * Tan30;
      context.moveTo(0, -h - o);
      context.lineTo(-r, h - o);
      context.lineTo(r, h - o);
      context.closePath();
    }
  },
  'triangle-up': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r;
      context.moveTo(0, -h);
      context.lineTo(-r, h);
      context.lineTo(r, h);
      context.closePath();
    }
  },
  'triangle-down': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r;
      context.moveTo(0, h);
      context.lineTo(-r, -h);
      context.lineTo(r, -h);
      context.closePath();
    }
  },
  'triangle-right': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r;
      context.moveTo(h, 0);
      context.lineTo(-h, -r);
      context.lineTo(-h, r);
      context.closePath();
    }
  },
  'triangle-left': {
    draw: function (context, size) {
      var r = Math.sqrt(size) / 2,
        h = HalfSqrt3 * r;
      context.moveTo(-h, 0);
      context.lineTo(h, -r);
      context.lineTo(h, r);
      context.closePath();
    }
  },
  'stroke': {
    draw: function (context, size) {
      const r = Math.sqrt(size) / 2;
      context.moveTo(-r, 0);
      context.lineTo(r, 0);
    }
  }
};
function vega_scenegraph_module_symbols(_) {
  return vega_util_module_has(builtins, _) ? builtins[_] : customSymbol(_);
}
var custom = {};
function customSymbol(path) {
  if (!vega_util_module_has(custom, path)) {
    const parsed = vega_scenegraph_module_parse(path);
    custom[path] = {
      draw: function (context, size) {
        pathRender(context, parsed, 0, 0, Math.sqrt(size) / 2);
      }
    };
  }
  return custom[path];
}

// See http://spencermortensen.com/articles/bezier-circle/
const vega_scenegraph_module_C = 0.448084975506; // C = 1 - c

function rectangleX(d) {
  return d.x;
}
function rectangleY(d) {
  return d.y;
}
function rectangleWidth(d) {
  return d.width;
}
function rectangleHeight(d) {
  return d.height;
}
function vega_scenegraph_module_number(_) {
  return typeof _ === 'function' ? _ : () => +_;
}
function clamp(value, min, max) {
  return Math.max(min, Math.min(value, max));
}
function vg_rect () {
  var x = rectangleX,
    y = rectangleY,
    width = rectangleWidth,
    height = rectangleHeight,
    crTL = vega_scenegraph_module_number(0),
    crTR = crTL,
    crBL = crTL,
    crBR = crTL,
    context = null;
  function rectangle(_, x0, y0) {
    var buffer,
      x1 = x0 != null ? x0 : +x.call(this, _),
      y1 = y0 != null ? y0 : +y.call(this, _),
      w = +width.call(this, _),
      h = +height.call(this, _),
      s = Math.min(w, h) / 2,
      tl = clamp(+crTL.call(this, _), 0, s),
      tr = clamp(+crTR.call(this, _), 0, s),
      bl = clamp(+crBL.call(this, _), 0, s),
      br = clamp(+crBR.call(this, _), 0, s);
    if (!context) context = buffer = path();
    if (tl <= 0 && tr <= 0 && bl <= 0 && br <= 0) {
      context.rect(x1, y1, w, h);
    } else {
      var x2 = x1 + w,
        y2 = y1 + h;
      context.moveTo(x1 + tl, y1);
      context.lineTo(x2 - tr, y1);
      context.bezierCurveTo(x2 - vega_scenegraph_module_C * tr, y1, x2, y1 + vega_scenegraph_module_C * tr, x2, y1 + tr);
      context.lineTo(x2, y2 - br);
      context.bezierCurveTo(x2, y2 - vega_scenegraph_module_C * br, x2 - vega_scenegraph_module_C * br, y2, x2 - br, y2);
      context.lineTo(x1 + bl, y2);
      context.bezierCurveTo(x1 + vega_scenegraph_module_C * bl, y2, x1, y2 - vega_scenegraph_module_C * bl, x1, y2 - bl);
      context.lineTo(x1, y1 + tl);
      context.bezierCurveTo(x1, y1 + vega_scenegraph_module_C * tl, x1 + vega_scenegraph_module_C * tl, y1, x1 + tl, y1);
      context.closePath();
    }
    if (buffer) {
      context = null;
      return buffer + '' || null;
    }
  }
  rectangle.x = function (_) {
    if (arguments.length) {
      x = vega_scenegraph_module_number(_);
      return rectangle;
    } else {
      return x;
    }
  };
  rectangle.y = function (_) {
    if (arguments.length) {
      y = vega_scenegraph_module_number(_);
      return rectangle;
    } else {
      return y;
    }
  };
  rectangle.width = function (_) {
    if (arguments.length) {
      width = vega_scenegraph_module_number(_);
      return rectangle;
    } else {
      return width;
    }
  };
  rectangle.height = function (_) {
    if (arguments.length) {
      height = vega_scenegraph_module_number(_);
      return rectangle;
    } else {
      return height;
    }
  };
  rectangle.cornerRadius = function (tl, tr, br, bl) {
    if (arguments.length) {
      crTL = vega_scenegraph_module_number(tl);
      crTR = tr != null ? vega_scenegraph_module_number(tr) : crTL;
      crBR = br != null ? vega_scenegraph_module_number(br) : crTL;
      crBL = bl != null ? vega_scenegraph_module_number(bl) : crTR;
      return rectangle;
    } else {
      return crTL;
    }
  };
  rectangle.context = function (_) {
    if (arguments.length) {
      context = _ == null ? null : _;
      return rectangle;
    } else {
      return context;
    }
  };
  return rectangle;
}

function vg_trail () {
  var x,
    y,
    size,
    defined,
    context = null,
    ready,
    x1,
    y1,
    r1;
  function point(x2, y2, w2) {
    const r2 = w2 / 2;
    if (ready) {
      var ux = y1 - y2,
        uy = x2 - x1;
      if (ux || uy) {
        // get normal vector
        var ud = Math.hypot(ux, uy),
          rx = (ux /= ud) * r1,
          ry = (uy /= ud) * r1,
          t = Math.atan2(uy, ux);

        // draw segment
        context.moveTo(x1 - rx, y1 - ry);
        context.lineTo(x2 - ux * r2, y2 - uy * r2);
        context.arc(x2, y2, r2, t - Math.PI, t);
        context.lineTo(x1 + rx, y1 + ry);
        context.arc(x1, y1, r1, t, t + Math.PI);
      } else {
        context.arc(x2, y2, r2, 0, Tau);
      }
      context.closePath();
    } else {
      ready = 1;
    }
    x1 = x2;
    y1 = y2;
    r1 = r2;
  }
  function trail(data) {
    var i,
      n = data.length,
      d,
      defined0 = false,
      buffer;
    if (context == null) context = buffer = path();
    for (i = 0; i <= n; ++i) {
      if (!(i < n && defined(d = data[i], i, data)) === defined0) {
        if (defined0 = !defined0) ready = 0;
      }
      if (defined0) point(+x(d, i, data), +y(d, i, data), +size(d, i, data));
    }
    if (buffer) {
      context = null;
      return buffer + '' || null;
    }
  }
  trail.x = function (_) {
    if (arguments.length) {
      x = _;
      return trail;
    } else {
      return x;
    }
  };
  trail.y = function (_) {
    if (arguments.length) {
      y = _;
      return trail;
    } else {
      return y;
    }
  };
  trail.size = function (_) {
    if (arguments.length) {
      size = _;
      return trail;
    } else {
      return size;
    }
  };
  trail.defined = function (_) {
    if (arguments.length) {
      defined = _;
      return trail;
    } else {
      return defined;
    }
  };
  trail.context = function (_) {
    if (arguments.length) {
      if (_ == null) {
        context = null;
      } else {
        context = _;
      }
      return trail;
    } else {
      return context;
    }
  };
  return trail;
}

function value$1(a, b) {
  return a != null ? a : b;
}
const x = item => item.x || 0,
  y = item => item.y || 0,
  w = item => item.width || 0,
  h = item => item.height || 0,
  xw = item => (item.x || 0) + (item.width || 0),
  yh = item => (item.y || 0) + (item.height || 0),
  sa = item => item.startAngle || 0,
  ea = item => item.endAngle || 0,
  pa = item => item.padAngle || 0,
  ir = item => item.innerRadius || 0,
  or = item => item.outerRadius || 0,
  cr = item => item.cornerRadius || 0,
  tl = item => value$1(item.cornerRadiusTopLeft, item.cornerRadius) || 0,
  tr = item => value$1(item.cornerRadiusTopRight, item.cornerRadius) || 0,
  br = item => value$1(item.cornerRadiusBottomRight, item.cornerRadius) || 0,
  bl = item => value$1(item.cornerRadiusBottomLeft, item.cornerRadius) || 0,
  sz = item => value$1(item.size, 64),
  ts = item => item.size || 1,
  def = item => !(item.defined === false),
  type = item => vega_scenegraph_module_symbols(item.shape || 'circle');
const arcShape = arc().startAngle(sa).endAngle(ea).padAngle(pa).innerRadius(ir).outerRadius(or).cornerRadius(cr),
  areavShape = src_area().x(x).y1(y).y0(yh).defined(def),
  areahShape = src_area().y(y).x1(x).x0(xw).defined(def),
  lineShape = line().x(x).y(y).defined(def),
  rectShape = vg_rect().x(x).y(y).width(w).height(h).cornerRadius(tl, tr, br, bl),
  symbolShape = symbol_Symbol().type(type).size(sz),
  trailShape = vg_trail().x(x).y(y).defined(def).size(ts);
function hasCornerRadius(item) {
  return item.cornerRadius || item.cornerRadiusTopLeft || item.cornerRadiusTopRight || item.cornerRadiusBottomRight || item.cornerRadiusBottomLeft;
}
function arc$1(context, item) {
  return arcShape.context(context)(item);
}
function area$1(context, items) {
  const item = items[0],
    interp = item.interpolate || 'linear';
  return (item.orient === 'horizontal' ? areahShape : areavShape).curve(curves(interp, item.orient, item.tension)).context(context)(items);
}
function line$1(context, items) {
  const item = items[0],
    interp = item.interpolate || 'linear';
  return lineShape.curve(curves(interp, item.orient, item.tension)).context(context)(items);
}
function rectangle(context, item, x, y) {
  return rectShape.context(context)(item, x, y);
}
function shape$1(context, item) {
  return (item.mark.shape || item.shape).context(context)(item);
}
function symbol$1(context, item) {
  return symbolShape.context(context)(item);
}
function trail$1(context, items) {
  return trailShape.context(context)(items);
}

var clip_id = 1;
function resetSVGClipId() {
  clip_id = 1;
}
function clip$1 (renderer, item, size) {
  var clip = item.clip,
    defs = renderer._defs,
    id = item.clip_id || (item.clip_id = 'clip' + clip_id++),
    c = defs.clipping[id] || (defs.clipping[id] = {
      id: id
    });
  if (vega_util_module_isFunction(clip)) {
    c.path = clip(null);
  } else if (hasCornerRadius(size)) {
    c.path = rectangle(null, size, 0, 0);
  } else {
    c.width = size.width || 0;
    c.height = size.height || 0;
  }
  return 'url(#' + id + ')';
}

function Bounds(b) {
  this.clear();
  if (b) this.union(b);
}
Bounds.prototype = {
  clone() {
    return new Bounds(this);
  },
  clear() {
    this.x1 = +Number.MAX_VALUE;
    this.y1 = +Number.MAX_VALUE;
    this.x2 = -Number.MAX_VALUE;
    this.y2 = -Number.MAX_VALUE;
    return this;
  },
  empty() {
    return this.x1 === +Number.MAX_VALUE && this.y1 === +Number.MAX_VALUE && this.x2 === -Number.MAX_VALUE && this.y2 === -Number.MAX_VALUE;
  },
  equals(b) {
    return this.x1 === b.x1 && this.y1 === b.y1 && this.x2 === b.x2 && this.y2 === b.y2;
  },
  set(x1, y1, x2, y2) {
    if (x2 < x1) {
      this.x2 = x1;
      this.x1 = x2;
    } else {
      this.x1 = x1;
      this.x2 = x2;
    }
    if (y2 < y1) {
      this.y2 = y1;
      this.y1 = y2;
    } else {
      this.y1 = y1;
      this.y2 = y2;
    }
    return this;
  },
  add(x, y) {
    if (x < this.x1) this.x1 = x;
    if (y < this.y1) this.y1 = y;
    if (x > this.x2) this.x2 = x;
    if (y > this.y2) this.y2 = y;
    return this;
  },
  expand(d) {
    this.x1 -= d;
    this.y1 -= d;
    this.x2 += d;
    this.y2 += d;
    return this;
  },
  round() {
    this.x1 = Math.floor(this.x1);
    this.y1 = Math.floor(this.y1);
    this.x2 = Math.ceil(this.x2);
    this.y2 = Math.ceil(this.y2);
    return this;
  },
  scale(s) {
    this.x1 *= s;
    this.y1 *= s;
    this.x2 *= s;
    this.y2 *= s;
    return this;
  },
  translate(dx, dy) {
    this.x1 += dx;
    this.x2 += dx;
    this.y1 += dy;
    this.y2 += dy;
    return this;
  },
  rotate(angle, x, y) {
    const p = this.rotatedPoints(angle, x, y);
    return this.clear().add(p[0], p[1]).add(p[2], p[3]).add(p[4], p[5]).add(p[6], p[7]);
  },
  rotatedPoints(angle, x, y) {
    var {
        x1,
        y1,
        x2,
        y2
      } = this,
      cos = Math.cos(angle),
      sin = Math.sin(angle),
      cx = x - x * cos + y * sin,
      cy = y - x * sin - y * cos;
    return [cos * x1 - sin * y1 + cx, sin * x1 + cos * y1 + cy, cos * x1 - sin * y2 + cx, sin * x1 + cos * y2 + cy, cos * x2 - sin * y1 + cx, sin * x2 + cos * y1 + cy, cos * x2 - sin * y2 + cx, sin * x2 + cos * y2 + cy];
  },
  union(b) {
    if (b.x1 < this.x1) this.x1 = b.x1;
    if (b.y1 < this.y1) this.y1 = b.y1;
    if (b.x2 > this.x2) this.x2 = b.x2;
    if (b.y2 > this.y2) this.y2 = b.y2;
    return this;
  },
  intersect(b) {
    if (b.x1 > this.x1) this.x1 = b.x1;
    if (b.y1 > this.y1) this.y1 = b.y1;
    if (b.x2 < this.x2) this.x2 = b.x2;
    if (b.y2 < this.y2) this.y2 = b.y2;
    return this;
  },
  encloses(b) {
    return b && this.x1 <= b.x1 && this.x2 >= b.x2 && this.y1 <= b.y1 && this.y2 >= b.y2;
  },
  alignsWith(b) {
    return b && (this.x1 == b.x1 || this.x2 == b.x2 || this.y1 == b.y1 || this.y2 == b.y2);
  },
  intersects(b) {
    return b && !(this.x2 < b.x1 || this.x1 > b.x2 || this.y2 < b.y1 || this.y1 > b.y2);
  },
  contains(x, y) {
    return !(x < this.x1 || x > this.x2 || y < this.y1 || y > this.y2);
  },
  width() {
    return this.x2 - this.x1;
  },
  height() {
    return this.y2 - this.y1;
  }
};

function Item(mark) {
  this.mark = mark;
  this.bounds = this.bounds || new Bounds();
}

function GroupItem(mark) {
  Item.call(this, mark);
  this.items = this.items || [];
}
inherits(GroupItem, Item);

class ResourceLoader {
  constructor(customLoader) {
    this._pending = 0;
    this._loader = customLoader || loader();
  }
  pending() {
    return this._pending;
  }
  sanitizeURL(uri) {
    const loader = this;
    increment(loader);
    return loader._loader.sanitize(uri, {
      context: 'href'
    }).then(opt => {
      decrement(loader);
      return opt;
    }).catch(() => {
      decrement(loader);
      return null;
    });
  }
  loadImage(uri) {
    const loader = this,
      Image = domImage();
    increment(loader);
    return loader._loader.sanitize(uri, {
      context: 'image'
    }).then(opt => {
      const url = opt.href;
      if (!url || !Image) throw {
        url: url
      };
      const img = new Image();

      // set crossOrigin only if cors is defined; empty string sets anonymous mode
      // https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/crossOrigin
      const cors = vega_util_module_has(opt, 'crossOrigin') ? opt.crossOrigin : 'anonymous';
      if (cors != null) img.crossOrigin = cors;

      // attempt to load image resource
      img.onload = () => decrement(loader);
      img.onerror = () => decrement(loader);
      img.src = url;
      return img;
    }).catch(e => {
      decrement(loader);
      return {
        complete: false,
        width: 0,
        height: 0,
        src: e && e.url || ''
      };
    });
  }
  ready() {
    const loader = this;
    return new Promise(accept => {
      function poll(value) {
        if (!loader.pending()) accept(value);else setTimeout(() => {
          poll(true);
        }, 10);
      }
      poll(false);
    });
  }
}
function increment(loader) {
  loader._pending += 1;
}
function decrement(loader) {
  loader._pending -= 1;
}

function boundStroke (bounds, item, miter) {
  if (item.stroke && item.opacity !== 0 && item.strokeOpacity !== 0) {
    const sw = item.strokeWidth != null ? +item.strokeWidth : 1;
    bounds.expand(sw + (miter ? miterAdjustment(item, sw) : 0));
  }
  return bounds;
}
function miterAdjustment(item, strokeWidth) {
  // TODO: more sophisticated adjustment? Or miter support in boundContext?
  return item.strokeJoin && item.strokeJoin !== 'miter' ? 0 : strokeWidth;
}

const circleThreshold = Tau - 1e-8;
let bounds, lx, ly, rot, ma, mb, mc, md;
const vega_scenegraph_module_add = (x, y) => bounds.add(x, y);
const addL = (x, y) => vega_scenegraph_module_add(lx = x, ly = y);
const addX = x => vega_scenegraph_module_add(x, bounds.y1);
const addY = y => vega_scenegraph_module_add(bounds.x1, y);
const px = (x, y) => ma * x + mc * y;
const py = (x, y) => mb * x + md * y;
const addp = (x, y) => vega_scenegraph_module_add(px(x, y), py(x, y));
const addpL = (x, y) => addL(px(x, y), py(x, y));
function boundContext (_, deg) {
  bounds = _;
  if (deg) {
    rot = deg * DegToRad;
    ma = md = Math.cos(rot);
    mb = Math.sin(rot);
    mc = -mb;
  } else {
    ma = md = 1;
    rot = mb = mc = 0;
  }
  return context$1;
}
const context$1 = {
  beginPath() {},
  closePath() {},
  moveTo: addpL,
  lineTo: addpL,
  rect(x, y, w, h) {
    if (rot) {
      addp(x + w, y);
      addp(x + w, y + h);
      addp(x, y + h);
      addpL(x, y);
    } else {
      vega_scenegraph_module_add(x + w, y + h);
      addL(x, y);
    }
  },
  quadraticCurveTo(x1, y1, x2, y2) {
    const px1 = px(x1, y1),
      py1 = py(x1, y1),
      px2 = px(x2, y2),
      py2 = py(x2, y2);
    quadExtrema(lx, px1, px2, addX);
    quadExtrema(ly, py1, py2, addY);
    addL(px2, py2);
  },
  bezierCurveTo(x1, y1, x2, y2, x3, y3) {
    const px1 = px(x1, y1),
      py1 = py(x1, y1),
      px2 = px(x2, y2),
      py2 = py(x2, y2),
      px3 = px(x3, y3),
      py3 = py(x3, y3);
    cubicExtrema(lx, px1, px2, px3, addX);
    cubicExtrema(ly, py1, py2, py3, addY);
    addL(px3, py3);
  },
  arc(cx, cy, r, sa, ea, ccw) {
    sa += rot;
    ea += rot;

    // store last point on path
    lx = r * Math.cos(ea) + cx;
    ly = r * Math.sin(ea) + cy;
    if (Math.abs(ea - sa) > circleThreshold) {
      // treat as full circle
      vega_scenegraph_module_add(cx - r, cy - r);
      vega_scenegraph_module_add(cx + r, cy + r);
    } else {
      const update = a => vega_scenegraph_module_add(r * Math.cos(a) + cx, r * Math.sin(a) + cy);
      let s, i;

      // sample end points
      update(sa);
      update(ea);

      // sample interior points aligned with 90 degrees
      if (ea !== sa) {
        sa = sa % Tau;
        if (sa < 0) sa += Tau;
        ea = ea % Tau;
        if (ea < 0) ea += Tau;
        if (ea < sa) {
          ccw = !ccw; // flip direction
          s = sa;
          sa = ea;
          ea = s; // swap end-points
        }
        if (ccw) {
          ea -= Tau;
          s = sa - sa % HalfPi;
          for (i = 0; i < 4 && s > ea; ++i, s -= HalfPi) update(s);
        } else {
          s = sa - sa % HalfPi + HalfPi;
          for (i = 0; i < 4 && s < ea; ++i, s = s + HalfPi) update(s);
        }
      }
    }
  }
};
function quadExtrema(x0, x1, x2, cb) {
  const t = (x0 - x1) / (x0 + x2 - 2 * x1);
  if (0 < t && t < 1) cb(x0 + (x1 - x0) * t);
}
function cubicExtrema(x0, x1, x2, x3, cb) {
  const a = x3 - x0 + 3 * x1 - 3 * x2,
    b = x0 + x2 - 2 * x1,
    c = x0 - x1;
  let t0 = 0,
    t1 = 0,
    r;

  // solve for parameter t
  if (Math.abs(a) > Epsilon) {
    // quadratic equation
    r = b * b + c * a;
    if (r >= 0) {
      r = Math.sqrt(r);
      t0 = (-b + r) / a;
      t1 = (-b - r) / a;
    }
  } else {
    // linear equation
    t0 = 0.5 * c / b;
  }

  // calculate position
  if (0 < t0 && t0 < 1) cb(cubic(t0, x0, x1, x2, x3));
  if (0 < t1 && t1 < 1) cb(cubic(t1, x0, x1, x2, x3));
}
function cubic(t, x0, x1, x2, x3) {
  const s = 1 - t,
    s2 = s * s,
    t2 = t * t;
  return s2 * s * x0 + 3 * s2 * t * x1 + 3 * s * t2 * x2 + t2 * t * x3;
}

var context = (context = domCanvas(1, 1)) ? context.getContext('2d') : null;

const b = new Bounds();
function intersectPath(draw) {
  return function (item, brush) {
    // rely on (inaccurate) bounds intersection if no context
    if (!context) return true;

    // add path to offscreen graphics context
    draw(context, item);

    // get bounds intersection region
    b.clear().union(item.bounds).intersect(brush).round();
    const {
      x1,
      y1,
      x2,
      y2
    } = b;

    // iterate over intersection region
    // perform fine grained inclusion test
    for (let y = y1; y <= y2; ++y) {
      for (let x = x1; x <= x2; ++x) {
        if (context.isPointInPath(x, y)) {
          return true;
        }
      }
    }

    // false if no hits in intersection region
    return false;
  };
}
function intersectPoint(item, box) {
  return box.contains(item.x || 0, item.y || 0);
}
function intersectRect(item, box) {
  const x = item.x || 0,
    y = item.y || 0,
    w = item.width || 0,
    h = item.height || 0;
  return box.intersects(b.set(x, y, x + w, y + h));
}
function intersectRule(item, box) {
  const x = item.x || 0,
    y = item.y || 0,
    x2 = item.x2 != null ? item.x2 : x,
    y2 = item.y2 != null ? item.y2 : y;
  return intersectBoxLine(box, x, y, x2, y2);
}
function intersectBoxLine(box, x, y, u, v) {
  const {
      x1,
      y1,
      x2,
      y2
    } = box,
    dx = u - x,
    dy = v - y;
  let t0 = 0,
    t1 = 1,
    p,
    q,
    r,
    e;
  for (e = 0; e < 4; ++e) {
    if (e === 0) {
      p = -dx;
      q = -(x1 - x);
    }
    if (e === 1) {
      p = dx;
      q = x2 - x;
    }
    if (e === 2) {
      p = -dy;
      q = -(y1 - y);
    }
    if (e === 3) {
      p = dy;
      q = y2 - y;
    }
    if (Math.abs(p) < 1e-10 && q < 0) return false;
    r = q / p;
    if (p < 0) {
      if (r > t1) return false;else if (r > t0) t0 = r;
    } else if (p > 0) {
      if (r < t0) return false;else if (r < t1) t1 = r;
    }
  }
  return true;
}

function blend (context, item) {
  context.globalCompositeOperation = item.blend || 'source-over';
}

function vega_scenegraph_module_value (value, dflt) {
  return value == null ? dflt : value;
}

function addStops(gradient, stops) {
  const n = stops.length;
  for (let i = 0; i < n; ++i) {
    gradient.addColorStop(stops[i].offset, stops[i].color);
  }
  return gradient;
}
function gradient (context, spec, bounds) {
  const w = bounds.width(),
    h = bounds.height();
  let gradient;
  if (spec.gradient === 'radial') {
    gradient = context.createRadialGradient(bounds.x1 + vega_scenegraph_module_value(spec.x1, 0.5) * w, bounds.y1 + vega_scenegraph_module_value(spec.y1, 0.5) * h, Math.max(w, h) * vega_scenegraph_module_value(spec.r1, 0), bounds.x1 + vega_scenegraph_module_value(spec.x2, 0.5) * w, bounds.y1 + vega_scenegraph_module_value(spec.y2, 0.5) * h, Math.max(w, h) * vega_scenegraph_module_value(spec.r2, 0.5));
  } else {
    // linear gradient
    const x1 = vega_scenegraph_module_value(spec.x1, 0),
      y1 = vega_scenegraph_module_value(spec.y1, 0),
      x2 = vega_scenegraph_module_value(spec.x2, 1),
      y2 = vega_scenegraph_module_value(spec.y2, 0);
    if (x1 === x2 || y1 === y2 || w === h) {
      // axis aligned: use normal gradient
      gradient = context.createLinearGradient(bounds.x1 + x1 * w, bounds.y1 + y1 * h, bounds.x1 + x2 * w, bounds.y1 + y2 * h);
    } else {
      // not axis aligned: render gradient into a pattern (#2365)
      // this allows us to use normalized bounding box coordinates
      const image = domCanvas(Math.ceil(w), Math.ceil(h)),
        ictx = image.getContext('2d');
      ictx.scale(w, h);
      ictx.fillStyle = addStops(ictx.createLinearGradient(x1, y1, x2, y2), spec.stops);
      ictx.fillRect(0, 0, w, h);
      return context.createPattern(image, 'no-repeat');
    }
  }
  return addStops(gradient, spec.stops);
}

function vega_scenegraph_module_color (context, item, value) {
  return isGradient(value) ? gradient(context, value, item.bounds) : value;
}

function fill (context, item, opacity) {
  opacity *= item.fillOpacity == null ? 1 : item.fillOpacity;
  if (opacity > 0) {
    context.globalAlpha = opacity;
    context.fillStyle = vega_scenegraph_module_color(context, item, item.fill);
    return true;
  } else {
    return false;
  }
}

var vega_scenegraph_module_Empty = [];
function stroke (context, item, opacity) {
  var lw = (lw = item.strokeWidth) != null ? lw : 1;
  if (lw <= 0) return false;
  opacity *= item.strokeOpacity == null ? 1 : item.strokeOpacity;
  if (opacity > 0) {
    context.globalAlpha = opacity;
    context.strokeStyle = vega_scenegraph_module_color(context, item, item.stroke);
    context.lineWidth = lw;
    context.lineCap = item.strokeCap || 'butt';
    context.lineJoin = item.strokeJoin || 'miter';
    context.miterLimit = item.strokeMiterLimit || 10;
    if (context.setLineDash) {
      context.setLineDash(item.strokeDash || vega_scenegraph_module_Empty);
      context.lineDashOffset = item.strokeDashOffset || 0;
    }
    return true;
  } else {
    return false;
  }
}

function vega_scenegraph_module_compare(a, b) {
  return a.zindex - b.zindex || a.index - b.index;
}
function zorder(scene) {
  if (!scene.zdirty) return scene.zitems;
  var items = scene.items,
    output = [],
    item,
    i,
    n;
  for (i = 0, n = items.length; i < n; ++i) {
    item = items[i];
    item.index = i;
    if (item.zindex) output.push(item);
  }
  scene.zdirty = false;
  return scene.zitems = output.sort(vega_scenegraph_module_compare);
}
function vega_scenegraph_module_visit(scene, visitor) {
  var items = scene.items,
    i,
    n;
  if (!items || !items.length) return;
  const zitems = zorder(scene);
  if (zitems && zitems.length) {
    for (i = 0, n = items.length; i < n; ++i) {
      if (!items[i].zindex) visitor(items[i]);
    }
    items = zitems;
  }
  for (i = 0, n = items.length; i < n; ++i) {
    visitor(items[i]);
  }
}
function pickVisit(scene, visitor) {
  var items = scene.items,
    hit,
    i;
  if (!items || !items.length) return null;
  const zitems = zorder(scene);
  if (zitems && zitems.length) items = zitems;
  for (i = items.length; --i >= 0;) {
    if (hit = visitor(items[i])) return hit;
  }
  if (items === zitems) {
    for (items = scene.items, i = items.length; --i >= 0;) {
      if (!items[i].zindex) {
        if (hit = visitor(items[i])) return hit;
      }
    }
  }
  return null;
}

function drawAll(path) {
  return function (context, scene, bounds) {
    vega_scenegraph_module_visit(scene, item => {
      if (!bounds || bounds.intersects(item.bounds)) {
        drawPath(path, context, item, item);
      }
    });
  };
}
function drawOne(path) {
  return function (context, scene, bounds) {
    if (scene.items.length && (!bounds || bounds.intersects(scene.bounds))) {
      drawPath(path, context, scene.items[0], scene.items);
    }
  };
}
function drawPath(path, context, item, items) {
  var opacity = item.opacity == null ? 1 : item.opacity;
  if (opacity === 0) return;
  if (path(context, items)) return;
  blend(context, item);
  if (item.fill && fill(context, item, opacity)) {
    context.fill();
  }
  if (item.stroke && stroke(context, item, opacity)) {
    context.stroke();
  }
}

function pick$1(test) {
  test = test || truthy;
  return function (context, scene, x, y, gx, gy) {
    x *= context.pixelRatio;
    y *= context.pixelRatio;
    return pickVisit(scene, item => {
      const b = item.bounds;
      // first hit test against bounding box
      if (b && !b.contains(gx, gy) || !b) return;
      // if in bounding box, perform more careful test
      if (test(context, item, x, y, gx, gy)) return item;
    });
  };
}
function hitPath(path, filled) {
  return function (context, o, x, y) {
    var item = Array.isArray(o) ? o[0] : o,
      fill = filled == null ? item.fill : filled,
      stroke = item.stroke && context.isPointInStroke,
      lw,
      lc;
    if (stroke) {
      lw = item.strokeWidth;
      lc = item.strokeCap;
      context.lineWidth = lw != null ? lw : 1;
      context.lineCap = lc != null ? lc : 'butt';
    }
    return path(context, o) ? false : fill && context.isPointInPath(x, y) || stroke && context.isPointInStroke(x, y);
  };
}
function pickPath(path) {
  return pick$1(hitPath(path));
}

function translate(x, y) {
  return 'translate(' + x + ',' + y + ')';
}
function rotate(a) {
  return 'rotate(' + a + ')';
}
function vega_scenegraph_module_scale(scaleX, scaleY) {
  return 'scale(' + scaleX + ',' + scaleY + ')';
}
function translateItem(item) {
  return translate(item.x || 0, item.y || 0);
}
function rotateItem(item) {
  return translate(item.x || 0, item.y || 0) + (item.angle ? ' ' + rotate(item.angle) : '');
}
function transformItem(item) {
  return translate(item.x || 0, item.y || 0) + (item.angle ? ' ' + rotate(item.angle) : '') + (item.scaleX || item.scaleY ? ' ' + vega_scenegraph_module_scale(item.scaleX || 1, item.scaleY || 1) : '');
}

function markItemPath (type, shape, isect) {
  function attr(emit, item) {
    emit('transform', rotateItem(item));
    emit('d', shape(null, item));
  }
  function bound(bounds, item) {
    shape(boundContext(bounds, item.angle), item);
    return boundStroke(bounds, item).translate(item.x || 0, item.y || 0);
  }
  function draw(context, item) {
    var x = item.x || 0,
      y = item.y || 0,
      a = item.angle || 0;
    context.translate(x, y);
    if (a) context.rotate(a *= DegToRad);
    context.beginPath();
    shape(context, item);
    if (a) context.rotate(-a);
    context.translate(-x, -y);
  }
  return {
    type: type,
    tag: 'path',
    nested: false,
    attr: attr,
    bound: bound,
    draw: drawAll(draw),
    pick: pickPath(draw),
    isect: isect || intersectPath(draw)
  };
}

var vega_scenegraph_module_arc = markItemPath('arc', arc$1);

function pickArea(a, p) {
  var v = a[0].orient === 'horizontal' ? p[1] : p[0],
    z = a[0].orient === 'horizontal' ? 'y' : 'x',
    i = a.length,
    min = +Infinity,
    hit,
    d;
  while (--i >= 0) {
    if (a[i].defined === false) continue;
    d = Math.abs(a[i][z] - v);
    if (d < min) {
      min = d;
      hit = a[i];
    }
  }
  return hit;
}
function pickLine(a, p) {
  var t = Math.pow(a[0].strokeWidth || 1, 2),
    i = a.length,
    dx,
    dy,
    dd;
  while (--i >= 0) {
    if (a[i].defined === false) continue;
    dx = a[i].x - p[0];
    dy = a[i].y - p[1];
    dd = dx * dx + dy * dy;
    if (dd < t) return a[i];
  }
  return null;
}
function pickTrail(a, p) {
  var i = a.length,
    dx,
    dy,
    dd;
  while (--i >= 0) {
    if (a[i].defined === false) continue;
    dx = a[i].x - p[0];
    dy = a[i].y - p[1];
    dd = dx * dx + dy * dy;
    dx = a[i].size || 1;
    if (dd < dx * dx) return a[i];
  }
  return null;
}

function markMultiItemPath (type, shape, tip) {
  function attr(emit, item) {
    var items = item.mark.items;
    if (items.length) emit('d', shape(null, items));
  }
  function bound(bounds, mark) {
    var items = mark.items;
    if (items.length === 0) {
      return bounds;
    } else {
      shape(boundContext(bounds), items);
      return boundStroke(bounds, items[0]);
    }
  }
  function draw(context, items) {
    context.beginPath();
    shape(context, items);
  }
  const hit = hitPath(draw);
  function pick(context, scene, x, y, gx, gy) {
    var items = scene.items,
      b = scene.bounds;
    if (!items || !items.length || b && !b.contains(gx, gy)) {
      return null;
    }
    x *= context.pixelRatio;
    y *= context.pixelRatio;
    return hit(context, items, x, y) ? items[0] : null;
  }
  return {
    type: type,
    tag: 'path',
    nested: true,
    attr: attr,
    bound: bound,
    draw: drawOne(draw),
    pick: pick,
    isect: intersectPoint,
    tip: tip
  };
}

var vega_scenegraph_module_area = markMultiItemPath('area', area$1, pickArea);

function clip (context, scene) {
  var clip = scene.clip;
  context.save();
  if (vega_util_module_isFunction(clip)) {
    context.beginPath();
    clip(context);
    context.clip();
  } else {
    clipGroup(context, scene.group);
  }
}
function clipGroup(context, group) {
  context.beginPath();
  hasCornerRadius(group) ? rectangle(context, group, 0, 0) : context.rect(0, 0, group.width || 0, group.height || 0);
  context.clip();
}

function offset$1(item) {
  const sw = vega_scenegraph_module_value(item.strokeWidth, 1);
  return item.strokeOffset != null ? item.strokeOffset : item.stroke && sw > 0.5 && sw < 1.5 ? 0.5 - Math.abs(sw - 1) : 0;
}
function attr$5(emit, item) {
  emit('transform', translateItem(item));
}
function emitRectangle(emit, item) {
  const off = offset$1(item);
  emit('d', rectangle(null, item, off, off));
}
function background(emit, item) {
  emit('class', 'background');
  emit('aria-hidden', true);
  emitRectangle(emit, item);
}
function foreground(emit, item) {
  emit('class', 'foreground');
  emit('aria-hidden', true);
  if (item.strokeForeground) {
    emitRectangle(emit, item);
  } else {
    emit('d', '');
  }
}
function content(emit, item, renderer) {
  const url = item.clip ? clip$1(renderer, item, item) : null;
  emit('clip-path', url);
}
function bound$5(bounds, group) {
  if (!group.clip && group.items) {
    const items = group.items,
      m = items.length;
    for (let j = 0; j < m; ++j) {
      bounds.union(items[j].bounds);
    }
  }
  if ((group.clip || group.width || group.height) && !group.noBound) {
    bounds.add(0, 0).add(group.width || 0, group.height || 0);
  }
  boundStroke(bounds, group);
  return bounds.translate(group.x || 0, group.y || 0);
}
function rectanglePath(context, group, x, y) {
  const off = offset$1(group);
  context.beginPath();
  rectangle(context, group, (x || 0) + off, (y || 0) + off);
}
const hitBackground = hitPath(rectanglePath);
const hitForeground = hitPath(rectanglePath, false);
const hitCorner = hitPath(rectanglePath, true);
function draw$4(context, scene, bounds, markTypes) {
  vega_scenegraph_module_visit(scene, group => {
    const gx = group.x || 0,
      gy = group.y || 0,
      fore = group.strokeForeground,
      opacity = group.opacity == null ? 1 : group.opacity;

    // draw group background
    if ((group.stroke || group.fill) && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (group.fill && fill(context, group, opacity)) {
        context.fill();
      }
      if (group.stroke && !fore && stroke(context, group, opacity)) {
        context.stroke();
      }
    }

    // setup graphics context, set clip and bounds
    context.save();
    context.translate(gx, gy);
    if (group.clip) clipGroup(context, group);
    if (bounds) bounds.translate(-gx, -gy);

    // draw group contents
    vega_scenegraph_module_visit(group, item => {
      if (item.marktype === 'group' || markTypes == null || markTypes.includes(item.marktype)) {
        this.draw(context, item, bounds, markTypes);
      }
    });

    // restore graphics context
    if (bounds) bounds.translate(gx, gy);
    context.restore();

    // draw group foreground
    if (fore && group.stroke && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (stroke(context, group, opacity)) {
        context.stroke();
      }
    }
  });
}
function pick(context, scene, x, y, gx, gy) {
  if (scene.bounds && !scene.bounds.contains(gx, gy) || !scene.items) {
    return null;
  }
  const cx = x * context.pixelRatio,
    cy = y * context.pixelRatio;
  return pickVisit(scene, group => {
    let hit, dx, dy;

    // first hit test bounding box
    const b = group.bounds;
    if (b && !b.contains(gx, gy)) return;

    // passed bounds check, test rectangular clip
    dx = group.x || 0;
    dy = group.y || 0;
    const dw = dx + (group.width || 0),
      dh = dy + (group.height || 0),
      c = group.clip;
    if (c && (gx < dx || gx > dw || gy < dy || gy > dh)) return;

    // adjust coordinate system
    context.save();
    context.translate(dx, dy);
    dx = gx - dx;
    dy = gy - dy;

    // test background for rounded corner clip
    if (c && hasCornerRadius(group) && !hitCorner(context, group, cx, cy)) {
      context.restore();
      return null;
    }
    const fore = group.strokeForeground,
      ix = scene.interactive !== false;

    // hit test against group foreground
    if (ix && fore && group.stroke && hitForeground(context, group, cx, cy)) {
      context.restore();
      return group;
    }

    // hit test against contained marks
    hit = pickVisit(group, mark => pickMark(mark, dx, dy) ? this.pick(mark, x, y, dx, dy) : null);

    // hit test against group background
    if (!hit && ix && (group.fill || !fore && group.stroke) && hitBackground(context, group, cx, cy)) {
      hit = group;
    }

    // restore state and return
    context.restore();
    return hit || null;
  });
}
function pickMark(mark, x, y) {
  return (mark.interactive !== false || mark.marktype === 'group') && mark.bounds && mark.bounds.contains(x, y);
}
var group = {
  type: 'group',
  tag: 'g',
  nested: false,
  attr: attr$5,
  bound: bound$5,
  draw: draw$4,
  pick: pick,
  isect: intersectRect,
  content: content,
  background: background,
  foreground: foreground
};

var metadata = {
  'xmlns': 'http://www.w3.org/2000/svg',
  'xmlns:xlink': 'http://www.w3.org/1999/xlink',
  'version': '1.1'
};

function getImage(item, renderer) {
  var image = item.image;
  if (!image || item.url && item.url !== image.url) {
    image = {
      complete: false,
      width: 0,
      height: 0
    };
    renderer.loadImage(item.url).then(image => {
      item.image = image;
      item.image.url = item.url;
    });
  }
  return image;
}
function imageWidth(item, image) {
  return item.width != null ? item.width : !image || !image.width ? 0 : item.aspect !== false && item.height ? item.height * image.width / image.height : image.width;
}
function imageHeight(item, image) {
  return item.height != null ? item.height : !image || !image.height ? 0 : item.aspect !== false && item.width ? item.width * image.height / image.width : image.height;
}
function imageXOffset(align, w) {
  return align === 'center' ? w / 2 : align === 'right' ? w : 0;
}
function imageYOffset(baseline, h) {
  return baseline === 'middle' ? h / 2 : baseline === 'bottom' ? h : 0;
}
function attr$4(emit, item, renderer) {
  const img = getImage(item, renderer),
    w = imageWidth(item, img),
    h = imageHeight(item, img),
    x = (item.x || 0) - imageXOffset(item.align, w),
    y = (item.y || 0) - imageYOffset(item.baseline, h),
    i = !img.src && img.toDataURL ? img.toDataURL() : img.src || '';
  emit('href', i, metadata['xmlns:xlink'], 'xlink:href');
  emit('transform', translate(x, y));
  emit('width', w);
  emit('height', h);
  emit('preserveAspectRatio', item.aspect === false ? 'none' : 'xMidYMid');
}
function bound$4(bounds, item) {
  const img = item.image,
    w = imageWidth(item, img),
    h = imageHeight(item, img),
    x = (item.x || 0) - imageXOffset(item.align, w),
    y = (item.y || 0) - imageYOffset(item.baseline, h);
  return bounds.set(x, y, x + w, y + h);
}
function draw$3(context, scene, bounds) {
  vega_scenegraph_module_visit(scene, item => {
    if (bounds && !bounds.intersects(item.bounds)) return; // bounds check

    const img = getImage(item, this);
    let w = imageWidth(item, img);
    let h = imageHeight(item, img);
    if (w === 0 || h === 0) return; // early exit

    let x = (item.x || 0) - imageXOffset(item.align, w),
      y = (item.y || 0) - imageYOffset(item.baseline, h),
      opacity,
      ar0,
      ar1,
      t;
    if (item.aspect !== false) {
      ar0 = img.width / img.height;
      ar1 = item.width / item.height;
      if (ar0 === ar0 && ar1 === ar1 && ar0 !== ar1) {
        if (ar1 < ar0) {
          t = w / ar0;
          y += (h - t) / 2;
          h = t;
        } else {
          t = h * ar0;
          x += (w - t) / 2;
          w = t;
        }
      }
    }
    if (img.complete || img.toDataURL) {
      blend(context, item);
      context.globalAlpha = (opacity = item.opacity) != null ? opacity : 1;
      context.imageSmoothingEnabled = item.smooth !== false;
      context.drawImage(img, x, y, w, h);
    }
  });
}
var vega_scenegraph_module_image = {
  type: 'image',
  tag: 'image',
  nested: false,
  attr: attr$4,
  bound: bound$4,
  draw: draw$3,
  pick: pick$1(),
  isect: truthy,
  // bounds check is sufficient
  get: getImage,
  xOffset: imageXOffset,
  yOffset: imageYOffset
};

var vega_scenegraph_module_line = markMultiItemPath('line', line$1, pickLine);

function attr$3(emit, item) {
  var sx = item.scaleX || 1,
    sy = item.scaleY || 1;
  if (sx !== 1 || sy !== 1) {
    emit('vector-effect', 'non-scaling-stroke');
  }
  emit('transform', transformItem(item));
  emit('d', item.path);
}
function path$1(context, item) {
  var path = item.path;
  if (path == null) return true;
  var x = item.x || 0,
    y = item.y || 0,
    sx = item.scaleX || 1,
    sy = item.scaleY || 1,
    a = (item.angle || 0) * DegToRad,
    cache = item.pathCache;
  if (!cache || cache.path !== path) {
    (item.pathCache = cache = vega_scenegraph_module_parse(path)).path = path;
  }
  if (a && context.rotate && context.translate) {
    context.translate(x, y);
    context.rotate(a);
    pathRender(context, cache, 0, 0, sx, sy);
    context.rotate(-a);
    context.translate(-x, -y);
  } else {
    pathRender(context, cache, x, y, sx, sy);
  }
}
function bound$3(bounds, item) {
  return path$1(boundContext(bounds, item.angle), item) ? bounds.set(0, 0, 0, 0) : boundStroke(bounds, item, true);
}
var path$2 = {
  type: 'path',
  tag: 'path',
  nested: false,
  attr: attr$3,
  bound: bound$3,
  draw: drawAll(path$1),
  pick: pickPath(path$1),
  isect: intersectPath(path$1)
};

function attr$2(emit, item) {
  emit('d', rectangle(null, item));
}
function bound$2(bounds, item) {
  var x, y;
  return boundStroke(bounds.set(x = item.x || 0, y = item.y || 0, x + item.width || 0, y + item.height || 0), item);
}
function draw$2(context, item) {
  context.beginPath();
  rectangle(context, item);
}
var rect = {
  type: 'rect',
  tag: 'path',
  nested: false,
  attr: attr$2,
  bound: bound$2,
  draw: drawAll(draw$2),
  pick: pickPath(draw$2),
  isect: intersectRect
};

function attr$1(emit, item) {
  emit('transform', translateItem(item));
  emit('x2', item.x2 != null ? item.x2 - (item.x || 0) : 0);
  emit('y2', item.y2 != null ? item.y2 - (item.y || 0) : 0);
}
function bound$1(bounds, item) {
  var x1, y1;
  return boundStroke(bounds.set(x1 = item.x || 0, y1 = item.y || 0, item.x2 != null ? item.x2 : x1, item.y2 != null ? item.y2 : y1), item);
}
function vega_scenegraph_module_path(context, item, opacity) {
  var x1, y1, x2, y2;
  if (item.stroke && stroke(context, item, opacity)) {
    x1 = item.x || 0;
    y1 = item.y || 0;
    x2 = item.x2 != null ? item.x2 : x1;
    y2 = item.y2 != null ? item.y2 : y1;
    context.beginPath();
    context.moveTo(x1, y1);
    context.lineTo(x2, y2);
    return true;
  }
  return false;
}
function draw$1(context, scene, bounds) {
  vega_scenegraph_module_visit(scene, item => {
    if (bounds && !bounds.intersects(item.bounds)) return; // bounds check
    var opacity = item.opacity == null ? 1 : item.opacity;
    if (opacity && vega_scenegraph_module_path(context, item, opacity)) {
      blend(context, item);
      context.stroke();
    }
  });
}
function hit$1(context, item, x, y) {
  if (!context.isPointInStroke) return false;
  return vega_scenegraph_module_path(context, item, 1) && context.isPointInStroke(x, y);
}
var rule = {
  type: 'rule',
  tag: 'line',
  nested: false,
  attr: attr$1,
  bound: bound$1,
  draw: draw$1,
  pick: pick$1(hit$1),
  isect: intersectRule
};

var shape = markItemPath('shape', shape$1);

var symbol = markItemPath('symbol', symbol$1, intersectPoint);

// memoize text width measurement
const widthCache = lruCache();
var textMetrics = {
  height: fontSize,
  measureWidth: measureWidth,
  estimateWidth: estimateWidth,
  width: estimateWidth,
  canvas: useCanvas
};
useCanvas(true);
function useCanvas(use) {
  textMetrics.width = use && context ? measureWidth : estimateWidth;
}

// make simple estimate if no canvas is available
function estimateWidth(item, text) {
  return _estimateWidth(textValue(item, text), fontSize(item));
}
function _estimateWidth(text, currentFontHeight) {
  return ~~(0.8 * text.length * currentFontHeight);
}

// measure text width if canvas is available
function measureWidth(item, text) {
  return fontSize(item) <= 0 || !(text = textValue(item, text)) ? 0 : _measureWidth(text, font(item));
}
function _measureWidth(text, currentFont) {
  const key = `(${currentFont}) ${text}`;
  let width = widthCache.get(key);
  if (width === undefined) {
    context.font = currentFont;
    width = context.measureText(text).width;
    widthCache.set(key, width);
  }
  return width;
}
function fontSize(item) {
  return item.fontSize != null ? +item.fontSize || 0 : 11;
}
function lineHeight(item) {
  return item.lineHeight != null ? item.lineHeight : fontSize(item) + 2;
}
function lineArray(_) {
  return vega_util_module_isArray(_) ? _.length > 1 ? _ : _[0] : _;
}
function textLines(item) {
  return lineArray(item.lineBreak && item.text && !vega_util_module_isArray(item.text) ? item.text.split(item.lineBreak) : item.text);
}
function multiLineOffset(item) {
  const tl = textLines(item);
  return (vega_util_module_isArray(tl) ? tl.length - 1 : 0) * lineHeight(item);
}
function textValue(item, line) {
  const text = line == null ? '' : (line + '').trim();
  return item.limit > 0 && text.length ? vega_scenegraph_module_truncate(item, text) : text;
}
function widthGetter(item) {
  if (textMetrics.width === measureWidth) {
    // we are using canvas
    const currentFont = font(item);
    return text => _measureWidth(text, currentFont);
  } else if (textMetrics.width === estimateWidth) {
    // we are relying on estimates
    const currentFontHeight = fontSize(item);
    return text => _estimateWidth(text, currentFontHeight);
  } else {
    // User defined textMetrics.width function in use (e.g. vl-convert)
    return text => textMetrics.width(item, text);
  }
}
function vega_scenegraph_module_truncate(item, text) {
  var limit = +item.limit,
    width = widthGetter(item);
  if (width(text) < limit) return text;
  var ellipsis = item.ellipsis || '\u2026',
    rtl = item.dir === 'rtl',
    lo = 0,
    hi = text.length,
    mid;
  limit -= width(ellipsis);
  if (rtl) {
    while (lo < hi) {
      mid = lo + hi >>> 1;
      if (width(text.slice(mid)) > limit) lo = mid + 1;else hi = mid;
    }
    return ellipsis + text.slice(lo);
  } else {
    while (lo < hi) {
      mid = 1 + (lo + hi >>> 1);
      if (width(text.slice(0, mid)) < limit) lo = mid;else hi = mid - 1;
    }
    return text.slice(0, lo) + ellipsis;
  }
}
function fontFamily(item, quote) {
  var font = item.font;
  return (quote && font ? String(font).replace(/"/g, '\'') : font) || 'sans-serif';
}
function font(item, quote) {
  return '' + (item.fontStyle ? item.fontStyle + ' ' : '') + (item.fontVariant ? item.fontVariant + ' ' : '') + (item.fontWeight ? item.fontWeight + ' ' : '') + fontSize(item) + 'px ' + fontFamily(item, quote);
}
function vega_scenegraph_module_offset(item) {
  // perform our own font baseline calculation
  // why? not all browsers support SVG 1.1 'alignment-baseline' :(
  // this also ensures consistent layout across renderers
  var baseline = item.baseline,
    h = fontSize(item);
  return Math.round(baseline === 'top' ? 0.79 * h : baseline === 'middle' ? 0.30 * h : baseline === 'bottom' ? -0.21 * h : baseline === 'line-top' ? 0.29 * h + 0.5 * lineHeight(item) : baseline === 'line-bottom' ? 0.29 * h - 0.5 * lineHeight(item) : 0);
}

const textAlign = {
  'left': 'start',
  'center': 'middle',
  'right': 'end'
};
const tempBounds = new Bounds();
function anchorPoint(item) {
  var x = item.x || 0,
    y = item.y || 0,
    r = item.radius || 0,
    t;
  if (r) {
    t = (item.theta || 0) - HalfPi;
    x += r * Math.cos(t);
    y += r * Math.sin(t);
  }
  tempBounds.x1 = x;
  tempBounds.y1 = y;
  return tempBounds;
}
function vega_scenegraph_module_attr(emit, item) {
  var dx = item.dx || 0,
    dy = (item.dy || 0) + vega_scenegraph_module_offset(item),
    p = anchorPoint(item),
    x = p.x1,
    y = p.y1,
    a = item.angle || 0,
    t;
  emit('text-anchor', textAlign[item.align] || 'start');
  if (a) {
    t = translate(x, y) + ' ' + rotate(a);
    if (dx || dy) t += ' ' + translate(dx, dy);
  } else {
    t = translate(x + dx, y + dy);
  }
  emit('transform', t);
}
function bound(bounds, item, mode) {
  var h = textMetrics.height(item),
    a = item.align,
    p = anchorPoint(item),
    x = p.x1,
    y = p.y1,
    dx = item.dx || 0,
    dy = (item.dy || 0) + vega_scenegraph_module_offset(item) - Math.round(0.8 * h),
    // use 4/5 offset
    tl = textLines(item),
    w;

  // get dimensions
  if (vega_util_module_isArray(tl)) {
    // multi-line text
    h += lineHeight(item) * (tl.length - 1);
    w = tl.reduce((w, t) => Math.max(w, textMetrics.width(item, t)), 0);
  } else {
    // single-line text
    w = textMetrics.width(item, tl);
  }

  // horizontal alignment
  if (a === 'center') {
    dx -= w / 2;
  } else if (a === 'right') {
    dx -= w;
  } else ;
  bounds.set(dx += x, dy += y, dx + w, dy + h);
  if (item.angle && !mode) {
    bounds.rotate(item.angle * DegToRad, x, y);
  } else if (mode === 2) {
    return bounds.rotatedPoints(item.angle * DegToRad, x, y);
  }
  return bounds;
}
function vega_scenegraph_module_draw(context, scene, bounds) {
  vega_scenegraph_module_visit(scene, item => {
    var opacity = item.opacity == null ? 1 : item.opacity,
      p,
      x,
      y,
      i,
      lh,
      tl,
      str;
    if (bounds && !bounds.intersects(item.bounds) ||
    // bounds check
    opacity === 0 || item.fontSize <= 0 || item.text == null || item.text.length === 0) return;
    context.font = font(item);
    context.textAlign = item.align || 'left';
    p = anchorPoint(item);
    x = p.x1, y = p.y1;
    if (item.angle) {
      context.save();
      context.translate(x, y);
      context.rotate(item.angle * DegToRad);
      x = y = 0; // reset x, y
    }
    x += item.dx || 0;
    y += (item.dy || 0) + vega_scenegraph_module_offset(item);
    tl = textLines(item);
    blend(context, item);
    if (vega_util_module_isArray(tl)) {
      lh = lineHeight(item);
      for (i = 0; i < tl.length; ++i) {
        str = textValue(item, tl[i]);
        if (item.fill && fill(context, item, opacity)) {
          context.fillText(str, x, y);
        }
        if (item.stroke && stroke(context, item, opacity)) {
          context.strokeText(str, x, y);
        }
        y += lh;
      }
    } else {
      str = textValue(item, tl);
      if (item.fill && fill(context, item, opacity)) {
        context.fillText(str, x, y);
      }
      if (item.stroke && stroke(context, item, opacity)) {
        context.strokeText(str, x, y);
      }
    }
    if (item.angle) context.restore();
  });
}
function hit(context, item, x, y, gx, gy) {
  if (item.fontSize <= 0) return false;
  if (!item.angle) return true; // bounds sufficient if no rotation

  // project point into space of unrotated bounds
  var p = anchorPoint(item),
    ax = p.x1,
    ay = p.y1,
    b = bound(tempBounds, item, 1),
    a = -item.angle * DegToRad,
    cos = Math.cos(a),
    sin = Math.sin(a),
    px = cos * gx - sin * gy + (ax - cos * ax + sin * ay),
    py = sin * gx + cos * gy + (ay - sin * ax - cos * ay);
  return b.contains(px, py);
}
function intersectText(item, box) {
  const p = bound(tempBounds, item, 2);
  return intersectBoxLine(box, p[0], p[1], p[2], p[3]) || intersectBoxLine(box, p[0], p[1], p[4], p[5]) || intersectBoxLine(box, p[4], p[5], p[6], p[7]) || intersectBoxLine(box, p[2], p[3], p[6], p[7]);
}
var vega_scenegraph_module_text = {
  type: 'text',
  tag: 'text',
  nested: false,
  attr: vega_scenegraph_module_attr,
  bound: bound,
  draw: vega_scenegraph_module_draw,
  pick: pick$1(hit),
  isect: intersectText
};

var trail = markMultiItemPath('trail', trail$1, pickTrail);

var Marks = {
  arc: vega_scenegraph_module_arc,
  area: vega_scenegraph_module_area,
  group: group,
  image: vega_scenegraph_module_image,
  line: vega_scenegraph_module_line,
  path: path$2,
  rect: rect,
  rule: rule,
  shape: shape,
  symbol: symbol,
  text: vega_scenegraph_module_text,
  trail: trail
};

function boundItem (item, func, opt) {
  var type = Marks[item.mark.marktype],
    bound = func || type.bound;
  if (type.nested) item = item.mark;
  return bound(item.bounds || (item.bounds = new Bounds()), item, opt);
}

var DUMMY = {
  mark: null
};
function boundMark (mark, bounds, opt) {
  var type = Marks[mark.marktype],
    bound = type.bound,
    items = mark.items,
    hasItems = items && items.length,
    i,
    n,
    item,
    b;
  if (type.nested) {
    if (hasItems) {
      item = items[0];
    } else {
      // no items, fake it
      DUMMY.mark = mark;
      item = DUMMY;
    }
    b = boundItem(item, bound, opt);
    bounds = bounds && bounds.union(b) || b;
    return bounds;
  }
  bounds = bounds || mark.bounds && mark.bounds.clear() || new Bounds();
  if (hasItems) {
    for (i = 0, n = items.length; i < n; ++i) {
      bounds.union(boundItem(items[i], bound, opt));
    }
  }
  return mark.bounds = bounds;
}

const vega_scenegraph_module_keys = ['marktype', 'name', 'role', 'interactive', 'clip', 'items', 'zindex', 'x', 'y', 'width', 'height', 'align', 'baseline',
// layout
'fill', 'fillOpacity', 'opacity', 'blend',
// fill
'stroke', 'strokeOpacity', 'strokeWidth', 'strokeCap',
// stroke
'strokeDash', 'strokeDashOffset',
// stroke dash
'strokeForeground', 'strokeOffset',
// group
'startAngle', 'endAngle', 'innerRadius', 'outerRadius',
// arc
'cornerRadius', 'padAngle',
// arc, rect
'cornerRadiusTopLeft', 'cornerRadiusTopRight',
// rect, group
'cornerRadiusBottomLeft', 'cornerRadiusBottomRight', 'interpolate', 'tension', 'orient', 'defined',
// area, line
'url', 'aspect', 'smooth',
// image
'path', 'scaleX', 'scaleY',
// path
'x2', 'y2',
// rule
'size', 'shape',
// symbol
'text', 'angle', 'theta', 'radius', 'dir', 'dx', 'dy',
// text
'ellipsis', 'limit', 'lineBreak', 'lineHeight', 'font', 'fontSize', 'fontWeight', 'fontStyle', 'fontVariant',
// font
'description', 'aria', 'ariaRole', 'ariaRoleDescription' // aria
];
function sceneToJSON(scene, indent) {
  return JSON.stringify(scene, vega_scenegraph_module_keys, indent);
}
function sceneFromJSON(json) {
  const scene = typeof json === 'string' ? JSON.parse(json) : json;
  return initialize(scene);
}
function initialize(scene) {
  var type = scene.marktype,
    items = scene.items,
    parent,
    i,
    n;
  if (items) {
    for (i = 0, n = items.length; i < n; ++i) {
      parent = type ? 'mark' : 'group';
      items[i][parent] = scene;
      if (items[i].zindex) items[i][parent].zdirty = true;
      if ('group' === (type || parent)) initialize(items[i]);
    }
  }
  if (type) boundMark(scene);
  return scene;
}

class Scenegraph {
  constructor(scene) {
    if (arguments.length) {
      this.root = sceneFromJSON(scene);
    } else {
      this.root = createMark({
        marktype: 'group',
        name: 'root',
        role: 'frame'
      });
      this.root.items = [new GroupItem(this.root)];
    }
  }
  toJSON(indent) {
    return sceneToJSON(this.root, indent || 0);
  }
  mark(markdef, group, index) {
    group = group || this.root.items[0];
    const mark = createMark(markdef, group);
    group.items[index] = mark;
    if (mark.zindex) mark.group.zdirty = true;
    return mark;
  }
}
function createMark(def, group) {
  const mark = {
    bounds: new Bounds(),
    clip: !!def.clip,
    group: group,
    interactive: def.interactive === false ? false : true,
    items: [],
    marktype: def.marktype,
    name: def.name || undefined,
    role: def.role || undefined,
    zindex: def.zindex || 0
  };

  // add accessibility properties if defined
  if (def.aria != null) {
    mark.aria = def.aria;
  }
  if (def.description) {
    mark.description = def.description;
  }
  return mark;
}

// create a new DOM element
function domCreate(doc, tag, ns) {
  if (!doc && typeof document !== 'undefined' && document.createElement) {
    doc = document;
  }
  return doc ? ns ? doc.createElementNS(ns, tag) : doc.createElement(tag) : null;
}

// find first child element with matching tag
function domFind(el, tag) {
  tag = tag.toLowerCase();
  var nodes = el.childNodes,
    i = 0,
    n = nodes.length;
  for (; i < n; ++i) if (nodes[i].tagName.toLowerCase() === tag) {
    return nodes[i];
  }
}

// retrieve child element at given index
// create & insert if doesn't exist or if tags do not match
function domChild(el, index, tag, ns) {
  var a = el.childNodes[index],
    b;
  if (!a || a.tagName.toLowerCase() !== tag.toLowerCase()) {
    b = a || null;
    a = domCreate(el.ownerDocument, tag, ns);
    el.insertBefore(a, b);
  }
  return a;
}

// remove all child elements at or above the given index
function domClear(el, index) {
  var nodes = el.childNodes,
    curr = nodes.length;
  while (curr > index) el.removeChild(nodes[--curr]);
  return el;
}

// generate css class name for mark
function cssClass(mark) {
  return 'mark-' + mark.marktype + (mark.role ? ' role-' + mark.role : '') + (mark.name ? ' ' + mark.name : '');
}

function vega_scenegraph_module_point (event, el) {
  const rect = el.getBoundingClientRect();
  return [event.clientX - rect.left - (el.clientLeft || 0), event.clientY - rect.top - (el.clientTop || 0)];
}

function resolveItem (item, event, el, origin) {
  var mark = item && item.mark,
    mdef,
    p;
  if (mark && (mdef = Marks[mark.marktype]).tip) {
    p = vega_scenegraph_module_point(event, el);
    p[0] -= origin[0];
    p[1] -= origin[1];
    while (item = item.mark.group) {
      p[0] -= item.x || 0;
      p[1] -= item.y || 0;
    }
    item = mdef.tip(mark.items, p);
  }
  return item;
}

class Handler {
  /**
   * Create a new Handler instance.
   * @param {object} [customLoader] - Optional loader instance for
   *   href URL sanitization. If not specified, a standard loader
   *   instance will be generated.
   * @param {function} [customTooltip] - Optional tooltip handler
   *   function for custom tooltip display.
   * @constructor
   */
  constructor(customLoader, customTooltip) {
    this._active = null;
    this._handlers = {};
    this._loader = customLoader || loader();
    this._tooltip = customTooltip || defaultTooltip;
  }

  /**
   * Initialize a new Handler instance.
   * @param {DOMElement} el - The containing DOM element for the display.
   * @param {Array<number>} origin - The origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {object} [obj] - Optional context object that should serve as
   *   the "this" context for event callbacks.
   * @return {Handler} - This handler instance.
   */
  initialize(el, origin, obj) {
    this._el = el;
    this._obj = obj || null;
    return this.origin(origin);
  }

  /**
   * Returns the parent container element for a visualization.
   * @return {DOMElement} - The containing DOM element.
   */
  element() {
    return this._el;
  }

  /**
   * Returns the scene element (e.g., canvas or SVG) of the visualization
   * Subclasses must override if the first child is not the scene element.
   * @return {DOMElement} - The scene (e.g., canvas or SVG) element.
   */
  canvas() {
    return this._el && this._el.firstChild;
  }

  /**
   * Get / set the origin coordinates of the visualization.
   */
  origin(origin) {
    if (arguments.length) {
      this._origin = origin || [0, 0];
      return this;
    } else {
      return this._origin.slice();
    }
  }

  /**
   * Get / set the scenegraph root.
   */
  scene(scene) {
    if (!arguments.length) return this._scene;
    this._scene = scene;
    return this;
  }

  /**
   * Add an event handler. Subclasses should override this method.
   */
  on(/*type, handler*/) {}

  /**
   * Remove an event handler. Subclasses should override this method.
   */
  off(/*type, handler*/) {}

  /**
   * Utility method for finding the array index of an event handler.
   * @param {Array} h - An array of registered event handlers.
   * @param {string} type - The event type.
   * @param {function} handler - The event handler instance to find.
   * @return {number} - The handler's array index or -1 if not registered.
   */
  _handlerIndex(h, type, handler) {
    for (let i = h ? h.length : 0; --i >= 0;) {
      if (h[i].type === type && (!handler || h[i].handler === handler)) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Returns an array with registered event handlers.
   * @param {string} [type] - The event type to query. Any annotations
   *   are ignored; for example, for the argument "click.foo", ".foo" will
   *   be ignored and the method returns all "click" handlers. If type is
   *   null or unspecified, this method returns handlers for all types.
   * @return {Array} - A new array containing all registered event handlers.
   */
  handlers(type) {
    const h = this._handlers,
      a = [];
    if (type) {
      a.push(...h[this.eventName(type)]);
    } else {
      for (const k in h) {
        a.push(...h[k]);
      }
    }
    return a;
  }

  /**
   * Parses an event name string to return the specific event type.
   * For example, given "click.foo" returns "click"
   * @param {string} name - The input event type string.
   * @return {string} - A string with the event type only.
   */
  eventName(name) {
    const i = name.indexOf('.');
    return i < 0 ? name : name.slice(0, i);
  }

  /**
   * Handle hyperlink navigation in response to an item.href value.
   * @param {Event} event - The event triggering hyperlink navigation.
   * @param {Item} item - The scenegraph item.
   * @param {string} href - The URL to navigate to.
   */
  handleHref(event, item, href) {
    this._loader.sanitize(href, {
      context: 'href'
    }).then(opt => {
      const e = new MouseEvent(event.type, event),
        a = domCreate(null, 'a');
      for (const name in opt) a.setAttribute(name, opt[name]);
      a.dispatchEvent(e);
    }).catch(() => {});
  }

  /**
   * Handle tooltip display in response to an item.tooltip value.
   * @param {Event} event - The event triggering tooltip display.
   * @param {Item} item - The scenegraph item.
   * @param {boolean} show - A boolean flag indicating whether
   *   to show or hide a tooltip for the given item.
   */
  handleTooltip(event, item, show) {
    if (item && item.tooltip != null) {
      item = resolveItem(item, event, this.canvas(), this._origin);
      const value = show && item && item.tooltip || null;
      this._tooltip.call(this._obj, this, event, item, value);
    }
  }

  /**
   * Returns the size of a scenegraph item and its position relative
   * to the viewport.
   * @param {Item} item - The scenegraph item.
   * @return {object} - A bounding box object (compatible with the
   *   DOMRect type) consisting of x, y, width, heigh, top, left,
   *   right, and bottom properties.
   */
  getItemBoundingClientRect(item) {
    const el = this.canvas();
    if (!el) return;
    const rect = el.getBoundingClientRect(),
      origin = this._origin,
      bounds = item.bounds,
      width = bounds.width(),
      height = bounds.height();
    let x = bounds.x1 + origin[0] + rect.left,
      y = bounds.y1 + origin[1] + rect.top;

    // translate coordinate for each parent group
    while (item.mark && (item = item.mark.group)) {
      x += item.x || 0;
      y += item.y || 0;
    }

    // return DOMRect-compatible bounding box
    return {
      x,
      y,
      width,
      height,
      left: x,
      top: y,
      right: x + width,
      bottom: y + height
    };
  }
}

// The default tooltip display handler.
// Sets the HTML title attribute on the visualization container.
function defaultTooltip(handler, event, item, value) {
  handler.element().setAttribute('title', value || '');
}

class Renderer {
  /**
   * Create a new Renderer instance.
   * @param {object} [loader] - Optional loader instance for
   *   image and href URL sanitization. If not specified, a
   *   standard loader instance will be generated.
   * @constructor
   */
  constructor(loader) {
    this._el = null;
    this._bgcolor = null;
    this._loader = new ResourceLoader(loader);
  }

  /**
   * Initialize a new Renderer instance.
   * @param {DOMElement} el - The containing DOM element for the display.
   * @param {number} width - The coordinate width of the display, in pixels.
   * @param {number} height - The coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {Renderer} - This renderer instance.
   */
  initialize(el, width, height, origin, scaleFactor) {
    this._el = el;
    return this.resize(width, height, origin, scaleFactor);
  }

  /**
   * Returns the parent container element for a visualization.
   * @return {DOMElement} - The containing DOM element.
   */
  element() {
    return this._el;
  }

  /**
   * Returns the scene element (e.g., canvas or SVG) of the visualization
   * Subclasses must override if the first child is not the scene element.
   * @return {DOMElement} - The scene (e.g., canvas or SVG) element.
   */
  canvas() {
    return this._el && this._el.firstChild;
  }

  /**
   * Get / set the background color.
   */
  background(bgcolor) {
    if (arguments.length === 0) return this._bgcolor;
    this._bgcolor = bgcolor;
    return this;
  }

  /**
   * Resize the display.
   * @param {number} width - The new coordinate width of the display, in pixels.
   * @param {number} height - The new coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The new origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {Renderer} - This renderer instance;
   */
  resize(width, height, origin, scaleFactor) {
    this._width = width;
    this._height = height;
    this._origin = origin || [0, 0];
    this._scale = scaleFactor || 1;
    return this;
  }

  /**
   * Report a dirty item whose bounds should be redrawn.
   * This base class method does nothing. Subclasses that perform
   * incremental should implement this method.
   * @param {Item} item - The dirty item whose bounds should be redrawn.
   */
  dirty(/*item*/) {}

  /**
   * Render an input scenegraph, potentially with a set of dirty items.
   * This method will perform an immediate rendering with available resources.
   * The renderer may also need to perform image loading to perform a complete
   * render. This process can lead to asynchronous re-rendering of the scene
   * after this method returns. To receive notification when rendering is
   * complete, use the renderAsync method instead.
   * @param {object} scene - The root mark of a scenegraph to render.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   * @return {Renderer} - This renderer instance.
   */
  render(scene, markTypes) {
    const r = this;

    // bind arguments into a render call, and cache it
    // this function may be subsequently called for async redraw
    r._call = function () {
      r._render(scene, markTypes);
    };

    // invoke the renderer
    r._call();

    // clear the cached call for garbage collection
    // async redraws will stash their own copy
    r._call = null;
    return r;
  }

  /**
   * Internal rendering method. Renderer subclasses should override this
   * method to actually perform rendering.
   * @param {object} scene - The root mark of a scenegraph to render.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   */
  _render(/*scene, markTypes*/
  ) {
    // subclasses to override
  }

  /**
   * Asynchronous rendering method. Similar to render, but returns a Promise
   * that resolves when all rendering is completed. Sometimes a renderer must
   * perform image loading to get a complete rendering. The returned
   * Promise will not resolve until this process completes.
   * @param {object} scene - The root mark of a scenegraph to render.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   * @return {Promise} - A Promise that resolves when rendering is complete.
   */
  renderAsync(scene, markTypes) {
    const r = this.render(scene, markTypes);
    return this._ready ? this._ready.then(() => r) : Promise.resolve(r);
  }

  /**
   * Internal method for asynchronous resource loading.
   * Proxies method calls to the ImageLoader, and tracks loading
   * progress to invoke a re-render once complete.
   * @param {string} method - The method name to invoke on the ImageLoader.
   * @param {string} uri - The URI for the requested resource.
   * @return {Promise} - A Promise that resolves to the requested resource.
   */
  _load(method, uri) {
    var r = this,
      p = r._loader[method](uri);
    if (!r._ready) {
      // re-render the scene when loading completes
      const call = r._call;
      r._ready = r._loader.ready().then(redraw => {
        if (redraw) call();
        r._ready = null;
      });
    }
    return p;
  }

  /**
   * Sanitize a URL to include as a hyperlink in the rendered scene.
   * This method proxies a call to ImageLoader.sanitizeURL, but also tracks
   * image loading progress and invokes a re-render once complete.
   * @param {string} uri - The URI string to sanitize.
   * @return {Promise} - A Promise that resolves to the sanitized URL.
   */
  sanitizeURL(uri) {
    return this._load('sanitizeURL', uri);
  }

  /**
   * Requests an image to include in the rendered scene.
   * This method proxies a call to ImageLoader.loadImage, but also tracks
   * image loading progress and invokes a re-render once complete.
   * @param {string} uri - The URI string of the image.
   * @return {Promise} - A Promise that resolves to the loaded Image.
   */
  loadImage(uri) {
    return this._load('loadImage', uri);
  }
}

const KeyDownEvent = 'keydown';
const KeyPressEvent = 'keypress';
const KeyUpEvent = 'keyup';
const DragEnterEvent = 'dragenter';
const DragLeaveEvent = 'dragleave';
const DragOverEvent = 'dragover';
const PointerDownEvent = 'pointerdown';
const PointerUpEvent = 'pointerup';
const PointerMoveEvent = 'pointermove';
const PointerOutEvent = 'pointerout';
const PointerOverEvent = 'pointerover';
const MouseDownEvent = 'mousedown';
const MouseUpEvent = 'mouseup';
const MouseMoveEvent = 'mousemove';
const MouseOutEvent = 'mouseout';
const MouseOverEvent = 'mouseover';
const ClickEvent = 'click';
const DoubleClickEvent = 'dblclick';
const WheelEvent = 'wheel';
const MouseWheelEvent = 'mousewheel';
const TouchStartEvent = 'touchstart';
const TouchMoveEvent = 'touchmove';
const TouchEndEvent = 'touchend';
const Events = [KeyDownEvent, KeyPressEvent, KeyUpEvent, DragEnterEvent, DragLeaveEvent, DragOverEvent, PointerDownEvent, PointerUpEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, MouseDownEvent, MouseUpEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent, ClickEvent, DoubleClickEvent, WheelEvent, MouseWheelEvent, TouchStartEvent, TouchMoveEvent, TouchEndEvent];
const TooltipShowEvent = PointerMoveEvent;
const TooltipHideEvent = MouseOutEvent;
const HrefEvent = ClickEvent;

class CanvasHandler extends Handler {
  constructor(loader, tooltip) {
    super(loader, tooltip);
    this._down = null;
    this._touch = null;
    this._first = true;
    this._events = {};

    // supported events
    this.events = Events;
    this.pointermove = move([PointerMoveEvent, MouseMoveEvent], [PointerOverEvent, MouseOverEvent], [PointerOutEvent, MouseOutEvent]);
    this.dragover = move([DragOverEvent], [DragEnterEvent], [DragLeaveEvent]), this.pointerout = inactive([PointerOutEvent, MouseOutEvent]);
    this.dragleave = inactive([DragLeaveEvent]);
  }
  initialize(el, origin, obj) {
    this._canvas = el && domFind(el, 'canvas');

    // add minimal events required for proper state management
    [ClickEvent, MouseDownEvent, PointerDownEvent, PointerMoveEvent, PointerOutEvent, DragLeaveEvent].forEach(type => eventListenerCheck(this, type));
    return super.initialize(el, origin, obj);
  }

  // return the backing canvas instance
  canvas() {
    return this._canvas;
  }

  // retrieve the current canvas context
  context() {
    return this._canvas.getContext('2d');
  }

  // to keep old versions of firefox happy
  DOMMouseScroll(evt) {
    this.fire(MouseWheelEvent, evt);
  }
  pointerdown(evt) {
    this._down = this._active;
    this.fire(PointerDownEvent, evt);
  }
  mousedown(evt) {
    this._down = this._active;
    this.fire(MouseDownEvent, evt);
  }
  click(evt) {
    if (this._down === this._active) {
      this.fire(ClickEvent, evt);
      this._down = null;
    }
  }
  touchstart(evt) {
    this._touch = this.pickEvent(evt.changedTouches[0]);
    if (this._first) {
      this._active = this._touch;
      this._first = false;
    }
    this.fire(TouchStartEvent, evt, true);
  }
  touchmove(evt) {
    this.fire(TouchMoveEvent, evt, true);
  }
  touchend(evt) {
    this.fire(TouchEndEvent, evt, true);
    this._touch = null;
  }

  // fire an event
  fire(type, evt, touch) {
    const a = touch ? this._touch : this._active,
      h = this._handlers[type];

    // set event type relative to scenegraph items
    evt.vegaType = type;

    // handle hyperlinks and tooltips first
    if (type === HrefEvent && a && a.href) {
      this.handleHref(evt, a, a.href);
    } else if (type === TooltipShowEvent || type === TooltipHideEvent) {
      this.handleTooltip(evt, a, type !== TooltipHideEvent);
    }

    // invoke all registered handlers
    if (h) {
      for (let i = 0, len = h.length; i < len; ++i) {
        h[i].handler.call(this._obj, evt, a);
      }
    }
  }

  // add an event handler
  on(type, handler) {
    const name = this.eventName(type),
      h = this._handlers,
      i = this._handlerIndex(h[name], type, handler);
    if (i < 0) {
      eventListenerCheck(this, type);
      (h[name] || (h[name] = [])).push({
        type: type,
        handler: handler
      });
    }
    return this;
  }

  // remove an event handler
  off(type, handler) {
    const name = this.eventName(type),
      h = this._handlers[name],
      i = this._handlerIndex(h, type, handler);
    if (i >= 0) {
      h.splice(i, 1);
    }
    return this;
  }
  pickEvent(evt) {
    const p = vega_scenegraph_module_point(evt, this._canvas),
      o = this._origin;
    return this.pick(this._scene, p[0], p[1], p[0] - o[0], p[1] - o[1]);
  }

  // find the scenegraph item at the current pointer position
  // x, y -- the absolute x, y pointer coordinates on the canvas element
  // gx, gy -- the relative coordinates within the current group
  pick(scene, x, y, gx, gy) {
    const g = this.context(),
      mark = Marks[scene.marktype];
    return mark.pick.call(this, g, scene, x, y, gx, gy);
  }
}
const eventBundle = type => type === TouchStartEvent || type === TouchMoveEvent || type === TouchEndEvent ? [TouchStartEvent, TouchMoveEvent, TouchEndEvent] : [type];

// lazily add listeners to the canvas as needed
function eventListenerCheck(handler, type) {
  eventBundle(type).forEach(_ => addEventListener(handler, _));
}
function addEventListener(handler, type) {
  const canvas = handler.canvas();
  if (canvas && !handler._events[type]) {
    handler._events[type] = 1;
    canvas.addEventListener(type, handler[type] ? evt => handler[type](evt) : evt => handler.fire(type, evt));
  }
}
function fireAll(handler, types, event) {
  types.forEach(type => handler.fire(type, event));
}
function move(moveEvents, overEvents, outEvents) {
  return function (evt) {
    const a = this._active,
      p = this.pickEvent(evt);
    if (p === a) {
      // active item and picked item are the same
      fireAll(this, moveEvents, evt); // fire move
    } else {
      // active item and picked item are different
      if (!a || !a.exit) {
        // fire out for prior active item
        // suppress if active item was removed from scene
        fireAll(this, outEvents, evt);
      }
      this._active = p; // set new active item
      fireAll(this, overEvents, evt); // fire over for new active item
      fireAll(this, moveEvents, evt); // fire move for new active item
    }
  };
}
function inactive(types) {
  return function (evt) {
    fireAll(this, types, evt);
    this._active = null;
  };
}

function devicePixelRatio() {
  return typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
}
function vega_scenegraph_module_resize (canvas, width, height, origin, scaleFactor, opt) {
  const inDOM = typeof HTMLElement !== 'undefined' && canvas instanceof HTMLElement && canvas.parentNode != null,
    context = canvas.getContext('2d'),
    ratio = inDOM ? devicePixelRatio() : scaleFactor;
  canvas.width = width * ratio;
  canvas.height = height * ratio;
  for (const key in opt) {
    context[key] = opt[key];
  }
  if (inDOM && ratio !== 1) {
    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
  }
  context.pixelRatio = ratio;
  context.setTransform(ratio, 0, 0, ratio, ratio * origin[0], ratio * origin[1]);
  return canvas;
}

class CanvasRenderer extends Renderer {
  constructor(loader) {
    super(loader);
    this._options = {};
    this._redraw = false;
    this._dirty = new Bounds();
    this._tempb = new Bounds();
  }
  initialize(el, width, height, origin, scaleFactor, options) {
    this._options = options || {};
    this._canvas = this._options.externalContext ? null : domCanvas(1, 1, this._options.type); // instantiate a small canvas

    if (el && this._canvas) {
      domClear(el, 0).appendChild(this._canvas);
      this._canvas.setAttribute('class', 'marks');
    }

    // this method will invoke resize to size the canvas appropriately
    return super.initialize(el, width, height, origin, scaleFactor);
  }
  resize(width, height, origin, scaleFactor) {
    super.resize(width, height, origin, scaleFactor);
    if (this._canvas) {
      // configure canvas size and transform
      vega_scenegraph_module_resize(this._canvas, this._width, this._height, this._origin, this._scale, this._options.context);
    } else {
      // external context needs to be scaled and positioned to origin
      const ctx = this._options.externalContext;
      if (!ctx) vega_util_module_error('CanvasRenderer is missing a valid canvas or context');
      ctx.scale(this._scale, this._scale);
      ctx.translate(this._origin[0], this._origin[1]);
    }
    this._redraw = true;
    return this;
  }
  canvas() {
    return this._canvas;
  }
  context() {
    return this._options.externalContext || (this._canvas ? this._canvas.getContext('2d') : null);
  }
  dirty(item) {
    const b = this._tempb.clear().union(item.bounds);
    let g = item.mark.group;
    while (g) {
      b.translate(g.x || 0, g.y || 0);
      g = g.mark.group;
    }
    this._dirty.union(b);
  }
  _render(scene, markTypes) {
    const g = this.context(),
      o = this._origin,
      w = this._width,
      h = this._height,
      db = this._dirty,
      vb = viewBounds(o, w, h);

    // setup
    g.save();
    const b = this._redraw || db.empty() ? (this._redraw = false, vb.expand(1)) : clipToBounds(g, vb.intersect(db), o);
    this.clear(-o[0], -o[1], w, h);

    // render
    this.draw(g, scene, b, markTypes);

    // takedown
    g.restore();
    db.clear();
    return this;
  }
  draw(ctx, scene, bounds, markTypes) {
    if (scene.marktype !== 'group' && markTypes != null && !markTypes.includes(scene.marktype)) {
      return;
    }
    const mark = Marks[scene.marktype];
    if (scene.clip) clip(ctx, scene);
    mark.draw.call(this, ctx, scene, bounds, markTypes);
    if (scene.clip) ctx.restore();
  }
  clear(x, y, w, h) {
    const opt = this._options,
      g = this.context();
    if (opt.type !== 'pdf' && !opt.externalContext) {
      // calling clear rect voids vector output in pdf mode
      // and could remove external context content (#2615)
      g.clearRect(x, y, w, h);
    }
    if (this._bgcolor != null) {
      g.fillStyle = this._bgcolor;
      g.fillRect(x, y, w, h);
    }
  }
}
const viewBounds = (origin, width, height) => new Bounds().set(0, 0, width, height).translate(-origin[0], -origin[1]);
function clipToBounds(g, b, origin) {
  // expand bounds by 1 pixel, then round to pixel boundaries
  b.expand(1).round();

  // align to base pixel grid in case of non-integer scaling (#2425)
  if (g.pixelRatio % 1) {
    b.scale(g.pixelRatio).round().scale(1 / g.pixelRatio);
  }

  // to avoid artifacts translate if origin has fractional pixels
  b.translate(-(origin[0] % 1), -(origin[1] % 1));

  // set clip path
  g.beginPath();
  g.rect(b.x1, b.y1, b.width(), b.height());
  g.clip();
  return b;
}

class SVGHandler extends Handler {
  constructor(loader, tooltip) {
    super(loader, tooltip);
    const h = this;
    h._hrefHandler = listener(h, (evt, item) => {
      if (item && item.href) h.handleHref(evt, item, item.href);
    });
    h._tooltipHandler = listener(h, (evt, item) => {
      h.handleTooltip(evt, item, evt.type !== TooltipHideEvent);
    });
  }
  initialize(el, origin, obj) {
    let svg = this._svg;
    if (svg) {
      svg.removeEventListener(HrefEvent, this._hrefHandler);
      svg.removeEventListener(TooltipShowEvent, this._tooltipHandler);
      svg.removeEventListener(TooltipHideEvent, this._tooltipHandler);
    }
    this._svg = svg = el && domFind(el, 'svg');
    if (svg) {
      svg.addEventListener(HrefEvent, this._hrefHandler);
      svg.addEventListener(TooltipShowEvent, this._tooltipHandler);
      svg.addEventListener(TooltipHideEvent, this._tooltipHandler);
    }
    return super.initialize(el, origin, obj);
  }
  canvas() {
    return this._svg;
  }

  // add an event handler
  on(type, handler) {
    const name = this.eventName(type),
      h = this._handlers,
      i = this._handlerIndex(h[name], type, handler);
    if (i < 0) {
      const x = {
        type,
        handler,
        listener: listener(this, handler)
      };
      (h[name] || (h[name] = [])).push(x);
      if (this._svg) {
        this._svg.addEventListener(name, x.listener);
      }
    }
    return this;
  }

  // remove an event handler
  off(type, handler) {
    const name = this.eventName(type),
      h = this._handlers[name],
      i = this._handlerIndex(h, type, handler);
    if (i >= 0) {
      if (this._svg) {
        this._svg.removeEventListener(name, h[i].listener);
      }
      h.splice(i, 1);
    }
    return this;
  }
}

// wrap an event listener for the SVG DOM
const listener = (context, handler) => evt => {
  let item = evt.target.__data__;
  item = Array.isArray(item) ? item[0] : item;
  evt.vegaType = evt.type;
  handler.call(context._obj, evt, item);
};

const ARIA_HIDDEN = 'aria-hidden';
const ARIA_LABEL = 'aria-label';
const ARIA_ROLE = 'role';
const ARIA_ROLEDESCRIPTION = 'aria-roledescription';
const GRAPHICS_OBJECT = 'graphics-object';
const GRAPHICS_SYMBOL = 'graphics-symbol';
const vega_scenegraph_module_bundle = (role, roledesc, label) => ({
  [ARIA_ROLE]: role,
  [ARIA_ROLEDESCRIPTION]: roledesc,
  [ARIA_LABEL]: label || undefined
});

// these roles are covered by related roles
// we can ignore them, no need to generate attributes
const AriaIgnore = vega_util_module_toSet(['axis-domain', 'axis-grid', 'axis-label', 'axis-tick', 'axis-title', 'legend-band', 'legend-entry', 'legend-gradient', 'legend-label', 'legend-title', 'legend-symbol', 'title']);

// aria attribute generators for guide roles
const AriaGuides = {
  'axis': {
    desc: 'axis',
    caption: axisCaption
  },
  'legend': {
    desc: 'legend',
    caption: legendCaption
  },
  'title-text': {
    desc: 'title',
    caption: item => `Title text '${titleCaption(item)}'`
  },
  'title-subtitle': {
    desc: 'subtitle',
    caption: item => `Subtitle text '${titleCaption(item)}'`
  }
};

// aria properties generated for mark item encoding channels
const AriaEncode = {
  ariaRole: ARIA_ROLE,
  ariaRoleDescription: ARIA_ROLEDESCRIPTION,
  description: ARIA_LABEL
};
function ariaItemAttributes(emit, item) {
  const hide = item.aria === false;
  emit(ARIA_HIDDEN, hide || undefined);
  if (hide || item.description == null) {
    for (const prop in AriaEncode) {
      emit(AriaEncode[prop], undefined);
    }
  } else {
    const type = item.mark.marktype;
    emit(ARIA_LABEL, item.description);
    emit(ARIA_ROLE, item.ariaRole || (type === 'group' ? GRAPHICS_OBJECT : GRAPHICS_SYMBOL));
    emit(ARIA_ROLEDESCRIPTION, item.ariaRoleDescription || `${type} mark`);
  }
}
function ariaMarkAttributes(mark) {
  return mark.aria === false ? {
    [ARIA_HIDDEN]: true
  } : AriaIgnore[mark.role] ? null : AriaGuides[mark.role] ? ariaGuide(mark, AriaGuides[mark.role]) : ariaMark(mark);
}
function ariaMark(mark) {
  const type = mark.marktype;
  const recurse = type === 'group' || type === 'text' || mark.items.some(_ => _.description != null && _.aria !== false);
  return vega_scenegraph_module_bundle(recurse ? GRAPHICS_OBJECT : GRAPHICS_SYMBOL, `${type} mark container`, mark.description);
}
function ariaGuide(mark, opt) {
  try {
    const item = mark.items[0],
      caption = opt.caption || (() => '');
    return vega_scenegraph_module_bundle(opt.role || GRAPHICS_SYMBOL, opt.desc, item.description || caption(item));
  } catch (err) {
    return null;
  }
}
function titleCaption(item) {
  return vega_util_module_array(item.text).join(' ');
}
function axisCaption(item) {
  const datum = item.datum,
    orient = item.orient,
    title = datum.title ? extractTitle(item) : null,
    ctx = item.context,
    scale = ctx.scales[datum.scale].value,
    locale = ctx.dataflow.locale(),
    type = scale.type,
    xy = orient === 'left' || orient === 'right' ? 'Y' : 'X';
  return `${xy}-axis` + (title ? ` titled '${title}'` : '') + ` for a ${isDiscrete(type) ? 'discrete' : type} scale` + ` with ${domainCaption(locale, scale, item)}`;
}
function legendCaption(item) {
  const datum = item.datum,
    title = datum.title ? extractTitle(item) : null,
    type = `${datum.type || ''} legend`.trim(),
    scales = datum.scales,
    props = Object.keys(scales),
    ctx = item.context,
    scale = ctx.scales[scales[props[0]]].value,
    locale = ctx.dataflow.locale();
  return capitalize(type) + (title ? ` titled '${title}'` : '') + ` for ${channelCaption(props)}` + ` with ${domainCaption(locale, scale, item)}`;
}
function extractTitle(item) {
  try {
    return vega_util_module_array(peek(item.items).items[0].text).join(' ');
  } catch (err) {
    return null;
  }
}
function channelCaption(props) {
  props = props.map(p => p + (p === 'fill' || p === 'stroke' ? ' color' : ''));
  return props.length < 2 ? props[0] : props.slice(0, -1).join(', ') + ' and ' + peek(props);
}
function capitalize(s) {
  return s.length ? s[0].toUpperCase() + s.slice(1) : s;
}

const innerText = val => (val + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
const attrText = val => innerText(val).replace(/"/g, '&quot;').replace(/\t/g, '&#x9;').replace(/\n/g, '&#xA;').replace(/\r/g, '&#xD;');
function markup() {
  let buf = '',
    outer = '',
    inner = '';
  const stack = [],
    clear = () => outer = inner = '',
    push = tag => {
      if (outer) {
        buf += `${outer}>${inner}`;
        clear();
      }
      stack.push(tag);
    },
    attr = (name, value) => {
      if (value != null) outer += ` ${name}="${attrText(value)}"`;
      return m;
    },
    m = {
      open(tag) {
        push(tag);
        outer = '<' + tag;
        for (var _len = arguments.length, attrs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          attrs[_key - 1] = arguments[_key];
        }
        for (const set of attrs) {
          for (const key in set) attr(key, set[key]);
        }
        return m;
      },
      close() {
        const tag = stack.pop();
        if (outer) {
          buf += outer + (inner ? `>${inner}</${tag}>` : '/>');
        } else {
          buf += `</${tag}>`;
        }
        clear();
        return m;
      },
      attr,
      text: t => (inner += innerText(t), m),
      toString: () => buf
    };
  return m;
}
const serializeXML = node => _serialize(markup(), node) + '';
function _serialize(m, node) {
  m.open(node.tagName);
  if (node.hasAttributes()) {
    const attrs = node.attributes,
      n = attrs.length;
    for (let i = 0; i < n; ++i) {
      m.attr(attrs[i].name, attrs[i].value);
    }
  }
  if (node.hasChildNodes()) {
    const children = node.childNodes;
    for (const child of children) {
      child.nodeType === 3 // text node
      ? m.text(child.nodeValue) : _serialize(m, child);
    }
  }
  return m.close();
}

const stylesAttr = {
  fill: 'fill',
  fillOpacity: 'fill-opacity',
  stroke: 'stroke',
  strokeOpacity: 'stroke-opacity',
  strokeWidth: 'stroke-width',
  strokeCap: 'stroke-linecap',
  strokeJoin: 'stroke-linejoin',
  strokeDash: 'stroke-dasharray',
  strokeDashOffset: 'stroke-dashoffset',
  strokeMiterLimit: 'stroke-miterlimit',
  opacity: 'opacity'
};
const stylesCss = {
  blend: 'mix-blend-mode'
};

// ensure miter limit default is consistent with canvas (#2498)
const rootAttributes = {
  'fill': 'none',
  'stroke-miterlimit': 10
};

const RootIndex = 0,
  xmlns = 'http://www.w3.org/2000/xmlns/',
  svgns = metadata.xmlns;
class SVGRenderer extends Renderer {
  constructor(loader) {
    super(loader);
    this._dirtyID = 0;
    this._dirty = [];
    this._svg = null;
    this._root = null;
    this._defs = null;
  }

  /**
   * Initialize a new SVGRenderer instance.
   * @param {DOMElement} el - The containing DOM element for the display.
   * @param {number} width - The coordinate width of the display, in pixels.
   * @param {number} height - The coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {SVGRenderer} - This renderer instance.
   */
  initialize(el, width, height, origin, scaleFactor) {
    // create the svg definitions cache
    this._defs = {};
    this._clearDefs();
    if (el) {
      this._svg = domChild(el, 0, 'svg', svgns);
      this._svg.setAttributeNS(xmlns, 'xmlns', svgns);
      this._svg.setAttributeNS(xmlns, 'xmlns:xlink', metadata['xmlns:xlink']);
      this._svg.setAttribute('version', metadata['version']);
      this._svg.setAttribute('class', 'marks');
      domClear(el, 1);

      // set the svg root group
      this._root = domChild(this._svg, RootIndex, 'g', svgns);
      setAttributes(this._root, rootAttributes);

      // ensure no additional child elements
      domClear(this._svg, RootIndex + 1);
    }

    // set background color if defined
    this.background(this._bgcolor);
    return super.initialize(el, width, height, origin, scaleFactor);
  }

  /**
   * Get / set the background color.
   */
  background(bgcolor) {
    if (arguments.length && this._svg) {
      this._svg.style.setProperty('background-color', bgcolor);
    }
    return super.background(...arguments);
  }

  /**
   * Resize the display.
   * @param {number} width - The new coordinate width of the display, in pixels.
   * @param {number} height - The new coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The new origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {SVGRenderer} - This renderer instance;
   */
  resize(width, height, origin, scaleFactor) {
    super.resize(width, height, origin, scaleFactor);
    if (this._svg) {
      setAttributes(this._svg, {
        width: this._width * this._scale,
        height: this._height * this._scale,
        viewBox: `0 0 ${this._width} ${this._height}`
      });
      this._root.setAttribute('transform', `translate(${this._origin})`);
    }
    this._dirty = [];
    return this;
  }

  /**
   * Returns the SVG element of the visualization.
   * @return {DOMElement} - The SVG element.
   */
  canvas() {
    return this._svg;
  }

  /**
   * Returns an SVG text string for the rendered content,
   * or null if this renderer is currently headless.
   */
  svg() {
    const svg = this._svg,
      bg = this._bgcolor;
    if (!svg) return null;
    let node;
    if (bg) {
      svg.removeAttribute('style');
      node = domChild(svg, RootIndex, 'rect', svgns);
      setAttributes(node, {
        width: this._width,
        height: this._height,
        fill: bg
      });
    }
    const text = serializeXML(svg);
    if (bg) {
      svg.removeChild(node);
      this._svg.style.setProperty('background-color', bg);
    }
    return text;
  }

  /**
   * Internal rendering method.
   * @param {object} scene - The root mark of a scenegraph to render.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   */
  _render(scene, markTypes) {
    // perform spot updates and re-render markup
    if (this._dirtyCheck()) {
      if (this._dirtyAll) this._clearDefs();
      this.mark(this._root, scene, undefined, markTypes);
      domClear(this._root, 1);
    }
    this.defs();
    this._dirty = [];
    ++this._dirtyID;
    return this;
  }

  // -- Manage rendering of items marked as dirty --

  /**
   * Flag a mark item as dirty.
   * @param {Item} item - The mark item.
   */
  dirty(item) {
    if (item.dirty !== this._dirtyID) {
      item.dirty = this._dirtyID;
      this._dirty.push(item);
    }
  }

  /**
   * Check if a mark item is considered dirty.
   * @param {Item} item - The mark item.
   */
  isDirty(item) {
    return this._dirtyAll || !item._svg || !item._svg.ownerSVGElement || item.dirty === this._dirtyID;
  }

  /**
   * Internal method to check dirty status and, if possible,
   * make targetted updates without a full rendering pass.
   */
  _dirtyCheck() {
    this._dirtyAll = true;
    const items = this._dirty;
    if (!items.length || !this._dirtyID) return true;
    const id = ++this._dirtyID;
    let item, mark, type, mdef, i, n, o;
    for (i = 0, n = items.length; i < n; ++i) {
      item = items[i];
      mark = item.mark;
      if (mark.marktype !== type) {
        // memoize mark instance lookup
        type = mark.marktype;
        mdef = Marks[type];
      }
      if (mark.zdirty && mark.dirty !== id) {
        this._dirtyAll = false;
        dirtyParents(item, id);
        mark.items.forEach(i => {
          i.dirty = id;
        });
      }
      if (mark.zdirty) continue; // handle in standard drawing pass

      if (item.exit) {
        // EXIT
        if (mdef.nested && mark.items.length) {
          // if nested mark with remaining points, update instead
          o = mark.items[0];
          if (o._svg) this._update(mdef, o._svg, o);
        } else if (item._svg) {
          // otherwise remove from DOM
          o = item._svg.parentNode;
          if (o) o.removeChild(item._svg);
        }
        item._svg = null;
        continue;
      }
      item = mdef.nested ? mark.items[0] : item;
      if (item._update === id) continue; // already visited

      if (!item._svg || !item._svg.ownerSVGElement) {
        // ENTER
        this._dirtyAll = false;
        dirtyParents(item, id);
      } else {
        // IN-PLACE UPDATE
        this._update(mdef, item._svg, item);
      }
      item._update = id;
    }
    return !this._dirtyAll;
  }

  // -- Construct & maintain scenegraph to SVG mapping ---

  /**
   * Render a set of mark items.
   * @param {SVGElement} el - The parent element in the SVG tree.
   * @param {object} scene - The mark parent to render.
   * @param {SVGElement} prev - The previous sibling in the SVG tree.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   */
  mark(el, scene, prev, markTypes) {
    if (!this.isDirty(scene)) {
      return scene._svg;
    }
    const svg = this._svg,
      markType = scene.marktype,
      mdef = Marks[markType],
      events = scene.interactive === false ? 'none' : null,
      isGroup = mdef.tag === 'g';
    const parent = vega_scenegraph_module_bind(scene, el, prev, 'g', svg);
    if (markType !== 'group' && markTypes != null && !markTypes.includes(markType)) {
      domClear(parent, 0);
      return scene._svg;
    }
    parent.setAttribute('class', cssClass(scene));

    // apply aria attributes to parent container element
    const aria = ariaMarkAttributes(scene);
    for (const key in aria) setAttribute(parent, key, aria[key]);
    if (!isGroup) {
      setAttribute(parent, 'pointer-events', events);
    }
    setAttribute(parent, 'clip-path', scene.clip ? clip$1(this, scene, scene.group) : null);
    let sibling = null,
      i = 0;
    const process = item => {
      const dirty = this.isDirty(item),
        node = vega_scenegraph_module_bind(item, parent, sibling, mdef.tag, svg);
      if (dirty) {
        this._update(mdef, node, item);
        if (isGroup) recurse(this, node, item, markTypes);
      }
      sibling = node;
      ++i;
    };
    if (mdef.nested) {
      if (scene.items.length) process(scene.items[0]);
    } else {
      vega_scenegraph_module_visit(scene, process);
    }
    domClear(parent, i);
    return parent;
  }

  /**
   * Update the attributes of an SVG element for a mark item.
   * @param {object} mdef - The mark definition object
   * @param {SVGElement} el - The SVG element.
   * @param {Item} item - The mark item.
   */
  _update(mdef, el, item) {
    // set dom element and values cache
    // provides access to emit method
    vega_scenegraph_module_element = el;
    vega_scenegraph_module_values = el.__values__;

    // apply aria-specific properties
    ariaItemAttributes(emit, item);

    // apply svg attributes
    mdef.attr(emit, item, this);

    // some marks need special treatment
    const extra = mark_extras[mdef.type];
    if (extra) extra.call(this, mdef, el, item);

    // apply svg style attributes
    // note: element state may have been modified by 'extra' method
    if (vega_scenegraph_module_element) this.style(vega_scenegraph_module_element, item);
  }

  /**
   * Update the presentation attributes of an SVG element for a mark item.
   * @param {SVGElement} el - The SVG element.
   * @param {Item} item - The mark item.
   */
  style(el, item) {
    if (item == null) return;
    for (const prop in stylesAttr) {
      let value = prop === 'font' ? fontFamily(item) : item[prop];
      if (value === vega_scenegraph_module_values[prop]) continue;
      const name = stylesAttr[prop];
      if (value == null) {
        el.removeAttribute(name);
      } else {
        if (isGradient(value)) {
          value = gradientRef(value, this._defs.gradient, href());
        }
        el.setAttribute(name, value + '');
      }
      vega_scenegraph_module_values[prop] = value;
    }
    for (const prop in stylesCss) {
      setStyle(el, stylesCss[prop], item[prop]);
    }
  }

  /**
   * Render SVG defs, as needed.
   * Must be called *after* marks have been processed to ensure the
   * collected state is current and accurate.
   */
  defs() {
    const svg = this._svg,
      defs = this._defs;
    let el = defs.el,
      index = 0;
    for (const id in defs.gradient) {
      if (!el) defs.el = el = domChild(svg, RootIndex + 1, 'defs', svgns);
      index = updateGradient(el, defs.gradient[id], index);
    }
    for (const id in defs.clipping) {
      if (!el) defs.el = el = domChild(svg, RootIndex + 1, 'defs', svgns);
      index = updateClipping(el, defs.clipping[id], index);
    }

    // clean-up
    if (el) {
      index === 0 ? (svg.removeChild(el), defs.el = null) : domClear(el, index);
    }
  }

  /**
   * Clear defs caches.
   */
  _clearDefs() {
    const def = this._defs;
    def.gradient = {};
    def.clipping = {};
  }
}

// mark ancestor chain with a dirty id
function dirtyParents(item, id) {
  for (; item && item.dirty !== id; item = item.mark.group) {
    item.dirty = id;
    if (item.mark && item.mark.dirty !== id) {
      item.mark.dirty = id;
    } else return;
  }
}

// update gradient definitions
function updateGradient(el, grad, index) {
  let i, n, stop;
  if (grad.gradient === 'radial') {
    // SVG radial gradients automatically transform to normalized bbox
    // coordinates, in a way that is cumbersome to replicate in canvas.
    // We wrap the radial gradient in a pattern element, allowing us to
    // maintain a circular gradient that matches what canvas provides.
    let pt = domChild(el, index++, 'pattern', svgns);
    setAttributes(pt, {
      id: patternPrefix + grad.id,
      viewBox: '0,0,1,1',
      width: '100%',
      height: '100%',
      preserveAspectRatio: 'xMidYMid slice'
    });
    pt = domChild(pt, 0, 'rect', svgns);
    setAttributes(pt, {
      width: 1,
      height: 1,
      fill: `url(${href()}#${grad.id})`
    });
    el = domChild(el, index++, 'radialGradient', svgns);
    setAttributes(el, {
      id: grad.id,
      fx: grad.x1,
      fy: grad.y1,
      fr: grad.r1,
      cx: grad.x2,
      cy: grad.y2,
      r: grad.r2
    });
  } else {
    el = domChild(el, index++, 'linearGradient', svgns);
    setAttributes(el, {
      id: grad.id,
      x1: grad.x1,
      x2: grad.x2,
      y1: grad.y1,
      y2: grad.y2
    });
  }
  for (i = 0, n = grad.stops.length; i < n; ++i) {
    stop = domChild(el, i, 'stop', svgns);
    stop.setAttribute('offset', grad.stops[i].offset);
    stop.setAttribute('stop-color', grad.stops[i].color);
  }
  domClear(el, i);
  return index;
}

// update clipping path definitions
function updateClipping(el, clip, index) {
  let mask;
  el = domChild(el, index, 'clipPath', svgns);
  el.setAttribute('id', clip.id);
  if (clip.path) {
    mask = domChild(el, 0, 'path', svgns);
    mask.setAttribute('d', clip.path);
  } else {
    mask = domChild(el, 0, 'rect', svgns);
    setAttributes(mask, {
      x: 0,
      y: 0,
      width: clip.width,
      height: clip.height
    });
  }
  domClear(el, 1);
  return index + 1;
}

// Recursively process group contents.
function recurse(renderer, el, group, markTypes) {
  // child 'g' element is second to last among children (path, g, path)
  // other children here are foreground and background path elements
  el = el.lastChild.previousSibling;
  let prev,
    idx = 0;
  vega_scenegraph_module_visit(group, item => {
    prev = renderer.mark(el, item, prev, markTypes);
    ++idx;
  });

  // remove any extraneous DOM elements
  domClear(el, 1 + idx);
}

// Bind a scenegraph item to an SVG DOM element.
// Create new SVG elements as needed.
function vega_scenegraph_module_bind(item, el, sibling, tag, svg) {
  let node = item._svg,
    doc;

  // create a new dom node if needed
  if (!node) {
    doc = el.ownerDocument;
    node = domCreate(doc, tag, svgns);
    item._svg = node;
    if (item.mark) {
      node.__data__ = item;
      node.__values__ = {
        fill: 'default'
      };

      // if group, create background, content, and foreground elements
      if (tag === 'g') {
        const bg = domCreate(doc, 'path', svgns);
        node.appendChild(bg);
        bg.__data__ = item;
        const cg = domCreate(doc, 'g', svgns);
        node.appendChild(cg);
        cg.__data__ = item;
        const fg = domCreate(doc, 'path', svgns);
        node.appendChild(fg);
        fg.__data__ = item;
        fg.__values__ = {
          fill: 'default'
        };
      }
    }
  }

  // (re-)insert if (a) not contained in SVG or (b) sibling order has changed
  if (node.ownerSVGElement !== svg || siblingCheck(node, sibling)) {
    el.insertBefore(node, sibling ? sibling.nextSibling : el.firstChild);
  }
  return node;
}

// check if two nodes are ordered siblings
function siblingCheck(node, sibling) {
  return node.parentNode && node.parentNode.childNodes.length > 1 && node.previousSibling != sibling; // treat null/undefined the same
}

// -- Set attributes & styles on SVG elements ---

let vega_scenegraph_module_element = null,
  // temp var for current SVG element
  vega_scenegraph_module_values = null; // temp var for current values hash

// Extra configuration for certain mark types
const mark_extras = {
  group(mdef, el, item) {
    const fg = vega_scenegraph_module_element = el.childNodes[2];
    vega_scenegraph_module_values = fg.__values__;
    mdef.foreground(emit, item, this);
    vega_scenegraph_module_values = el.__values__; // use parent's values hash
    vega_scenegraph_module_element = el.childNodes[1];
    mdef.content(emit, item, this);
    const bg = vega_scenegraph_module_element = el.childNodes[0];
    mdef.background(emit, item, this);
    const value = item.mark.interactive === false ? 'none' : null;
    if (value !== vega_scenegraph_module_values.events) {
      setAttribute(fg, 'pointer-events', value);
      setAttribute(bg, 'pointer-events', value);
      vega_scenegraph_module_values.events = value;
    }
    if (item.strokeForeground && item.stroke) {
      const fill = item.fill;
      setAttribute(fg, 'display', null);

      // set style of background
      this.style(bg, item);
      setAttribute(bg, 'stroke', null);

      // set style of foreground
      if (fill) item.fill = null;
      vega_scenegraph_module_values = fg.__values__;
      this.style(fg, item);
      if (fill) item.fill = fill;

      // leave element null to prevent downstream styling
      vega_scenegraph_module_element = null;
    } else {
      // ensure foreground is ignored
      setAttribute(fg, 'display', 'none');
    }
  },
  image(mdef, el, item) {
    if (item.smooth === false) {
      setStyle(el, 'image-rendering', 'optimizeSpeed');
      setStyle(el, 'image-rendering', 'pixelated');
    } else {
      setStyle(el, 'image-rendering', null);
    }
  },
  text(mdef, el, item) {
    const tl = textLines(item);
    let key, value, doc, lh;
    if (vega_util_module_isArray(tl)) {
      // multi-line text
      value = tl.map(_ => textValue(item, _));
      key = value.join('\n'); // content cache key

      if (key !== vega_scenegraph_module_values.text) {
        domClear(el, 0);
        doc = el.ownerDocument;
        lh = lineHeight(item);
        value.forEach((t, i) => {
          const ts = domCreate(doc, 'tspan', svgns);
          ts.__data__ = item; // data binding
          ts.textContent = t;
          if (i) {
            ts.setAttribute('x', 0);
            ts.setAttribute('dy', lh);
          }
          el.appendChild(ts);
        });
        vega_scenegraph_module_values.text = key;
      }
    } else {
      // single-line text
      value = textValue(item, tl);
      if (value !== vega_scenegraph_module_values.text) {
        el.textContent = value;
        vega_scenegraph_module_values.text = value;
      }
    }
    setAttribute(el, 'font-family', fontFamily(item));
    setAttribute(el, 'font-size', fontSize(item) + 'px');
    setAttribute(el, 'font-style', item.fontStyle);
    setAttribute(el, 'font-variant', item.fontVariant);
    setAttribute(el, 'font-weight', item.fontWeight);
  }
};
function emit(name, value, ns) {
  // early exit if value is unchanged
  if (value === vega_scenegraph_module_values[name]) return;

  // use appropriate method given namespace (ns)
  if (ns) {
    setAttributeNS(vega_scenegraph_module_element, name, value, ns);
  } else {
    setAttribute(vega_scenegraph_module_element, name, value);
  }

  // note current value for future comparison
  vega_scenegraph_module_values[name] = value;
}
function setStyle(el, name, value) {
  if (value !== vega_scenegraph_module_values[name]) {
    if (value == null) {
      el.style.removeProperty(name);
    } else {
      el.style.setProperty(name, value + '');
    }
    vega_scenegraph_module_values[name] = value;
  }
}
function setAttributes(el, attrs) {
  for (const key in attrs) {
    setAttribute(el, key, attrs[key]);
  }
}
function setAttribute(el, name, value) {
  if (value != null) {
    // if value is provided, update DOM attribute
    el.setAttribute(name, value);
  } else {
    // else remove DOM attribute
    el.removeAttribute(name);
  }
}
function setAttributeNS(el, name, value, ns) {
  if (value != null) {
    // if value is provided, update DOM attribute
    el.setAttributeNS(ns, name, value);
  } else {
    // else remove DOM attribute
    el.removeAttributeNS(ns, name);
  }
}
function href() {
  let loc;
  return typeof window === 'undefined' ? '' : (loc = window.location).hash ? loc.href.slice(0, -loc.hash.length) : loc.href;
}

class SVGStringRenderer extends Renderer {
  constructor(loader) {
    super(loader);
    this._text = null;
    this._defs = {
      gradient: {},
      clipping: {}
    };
  }

  /**
   * Returns the rendered SVG text string,
   * or null if rendering has not yet occurred.
   */
  svg() {
    return this._text;
  }

  /**
   * Internal rendering method.
   * @param {object} scene - The root mark of a scenegraph to render.
   */
  _render(scene) {
    const m = markup();

    // svg tag
    m.open('svg', extend({}, metadata, {
      class: 'marks',
      width: this._width * this._scale,
      height: this._height * this._scale,
      viewBox: `0 0 ${this._width} ${this._height}`
    }));

    // background, if defined
    const bg = this._bgcolor;
    if (bg && bg !== 'transparent' && bg !== 'none') {
      m.open('rect', {
        width: this._width,
        height: this._height,
        fill: bg
      }).close();
    }

    // root content group
    m.open('g', rootAttributes, {
      transform: 'translate(' + this._origin + ')'
    });
    this.mark(m, scene);
    m.close(); // </g>

    // defs
    this.defs(m);

    // get SVG text string
    this._text = m.close() + '';
    return this;
  }

  /**
   * Render a set of mark items.
   * @param {object} m - The markup context.
   * @param {object} scene - The mark parent to render.
   */
  mark(m, scene) {
    const mdef = Marks[scene.marktype],
      tag = mdef.tag,
      attrList = [ariaItemAttributes, mdef.attr];

    // render opening group tag
    m.open('g', {
      'class': cssClass(scene),
      'clip-path': scene.clip ? clip$1(this, scene, scene.group) : null
    }, ariaMarkAttributes(scene), {
      'pointer-events': tag !== 'g' && scene.interactive === false ? 'none' : null
    });

    // render contained elements
    const process = item => {
      const href = this.href(item);
      if (href) m.open('a', href);
      m.open(tag, this.attr(scene, item, attrList, tag !== 'g' ? tag : null));
      if (tag === 'text') {
        const tl = textLines(item);
        if (vega_util_module_isArray(tl)) {
          // multi-line text
          const attrs = {
            x: 0,
            dy: lineHeight(item)
          };
          for (let i = 0; i < tl.length; ++i) {
            m.open('tspan', i ? attrs : null).text(textValue(item, tl[i])).close();
          }
        } else {
          // single-line text
          m.text(textValue(item, tl));
        }
      } else if (tag === 'g') {
        const fore = item.strokeForeground,
          fill = item.fill,
          stroke = item.stroke;
        if (fore && stroke) {
          item.stroke = null;
        }
        m.open('path', this.attr(scene, item, mdef.background, 'bgrect')).close();

        // recurse for group content
        m.open('g', this.attr(scene, item, mdef.content));
        vega_scenegraph_module_visit(item, scene => this.mark(m, scene));
        m.close();
        if (fore && stroke) {
          if (fill) item.fill = null;
          item.stroke = stroke;
          m.open('path', this.attr(scene, item, mdef.foreground, 'bgrect')).close();
          if (fill) item.fill = fill;
        } else {
          m.open('path', this.attr(scene, item, mdef.foreground, 'bgfore')).close();
        }
      }
      m.close(); // </tag>
      if (href) m.close(); // </a>
    };
    if (mdef.nested) {
      if (scene.items && scene.items.length) process(scene.items[0]);
    } else {
      vega_scenegraph_module_visit(scene, process);
    }

    // render closing group tag
    return m.close(); // </g>
  }

  /**
   * Get href attributes for a hyperlinked mark item.
   * @param {Item} item - The mark item.
   */
  href(item) {
    const href = item.href;
    let attr;
    if (href) {
      if (attr = this._hrefs && this._hrefs[href]) {
        return attr;
      } else {
        this.sanitizeURL(href).then(attr => {
          // rewrite to use xlink namespace
          attr['xlink:href'] = attr.href;
          attr.href = null;
          (this._hrefs || (this._hrefs = {}))[href] = attr;
        });
      }
    }
    return null;
  }

  /**
   * Get an object of SVG attributes for a mark item.
   * @param {object} scene - The mark parent.
   * @param {Item} item - The mark item.
   * @param {array|function} attrs - One or more attribute emitters.
   * @param {string} tag - The tag being rendered.
   */
  attr(scene, item, attrs, tag) {
    const object = {},
      emit = (name, value, ns, prefixed) => {
        object[prefixed || name] = value;
      };

    // apply mark specific attributes
    if (Array.isArray(attrs)) {
      attrs.forEach(fn => fn(emit, item, this));
    } else {
      attrs(emit, item, this);
    }

    // apply style attributes
    if (tag) {
      style(object, item, scene, tag, this._defs);
    }
    return object;
  }

  /**
   * Render SVG defs, as needed.
   * Must be called *after* marks have been processed to ensure the
   * collected state is current and accurate.
   * @param {object} m - The markup context.
   */
  defs(m) {
    const gradient = this._defs.gradient,
      clipping = this._defs.clipping,
      count = Object.keys(gradient).length + Object.keys(clipping).length;
    if (count === 0) return; // nothing to do

    m.open('defs');
    for (const id in gradient) {
      const def = gradient[id],
        stops = def.stops;
      if (def.gradient === 'radial') {
        // SVG radial gradients automatically transform to normalized bbox
        // coordinates, in a way that is cumbersome to replicate in canvas.
        // We wrap the radial gradient in a pattern element, allowing us to
        // maintain a circular gradient that matches what canvas provides.

        m.open('pattern', {
          id: patternPrefix + id,
          viewBox: '0,0,1,1',
          width: '100%',
          height: '100%',
          preserveAspectRatio: 'xMidYMid slice'
        });
        m.open('rect', {
          width: '1',
          height: '1',
          fill: 'url(#' + id + ')'
        }).close();
        m.close(); // </pattern>

        m.open('radialGradient', {
          id: id,
          fx: def.x1,
          fy: def.y1,
          fr: def.r1,
          cx: def.x2,
          cy: def.y2,
          r: def.r2
        });
      } else {
        m.open('linearGradient', {
          id: id,
          x1: def.x1,
          x2: def.x2,
          y1: def.y1,
          y2: def.y2
        });
      }
      for (let i = 0; i < stops.length; ++i) {
        m.open('stop', {
          offset: stops[i].offset,
          'stop-color': stops[i].color
        }).close();
      }
      m.close();
    }
    for (const id in clipping) {
      const def = clipping[id];
      m.open('clipPath', {
        id: id
      });
      if (def.path) {
        m.open('path', {
          d: def.path
        }).close();
      } else {
        m.open('rect', {
          x: 0,
          y: 0,
          width: def.width,
          height: def.height
        }).close();
      }
      m.close();
    }
    m.close();
  }
}

// Helper function for attr for style presentation attributes
function style(s, item, scene, tag, defs) {
  let styleList;
  if (item == null) return s;
  if (tag === 'bgrect' && scene.interactive === false) {
    s['pointer-events'] = 'none';
  }
  if (tag === 'bgfore') {
    if (scene.interactive === false) {
      s['pointer-events'] = 'none';
    }
    s.display = 'none';
    if (item.fill !== null) return s;
  }
  if (tag === 'image' && item.smooth === false) {
    styleList = ['image-rendering: optimizeSpeed;', 'image-rendering: pixelated;'];
  }
  if (tag === 'text') {
    s['font-family'] = fontFamily(item);
    s['font-size'] = fontSize(item) + 'px';
    s['font-style'] = item.fontStyle;
    s['font-variant'] = item.fontVariant;
    s['font-weight'] = item.fontWeight;
  }
  for (const prop in stylesAttr) {
    let value = item[prop];
    const name = stylesAttr[prop];
    if (value === 'transparent' && (name === 'fill' || name === 'stroke')) ; else if (value != null) {
      if (isGradient(value)) {
        value = gradientRef(value, defs.gradient, '');
      }
      s[name] = value;
    }
  }
  for (const prop in stylesCss) {
    const value = item[prop];
    if (value != null) {
      styleList = styleList || [];
      styleList.push(`${stylesCss[prop]}: ${value};`);
    }
  }
  if (styleList) {
    s.style = styleList.join(' ');
  }
  return s;
}

/**
 * @typedef {Object} HybridRendererOptions
 *
 * @property {string[]} [svgMarkTypes=['text']] - An array of SVG mark types to render
 *                                                in the SVG layer. All other mark types
 *                                                will be rendered in the Canvas layer.
 * @property {boolean} [svgOnTop=true] - Flag to determine if SVG should be rendered on top.
 * @property {boolean} [debug=false] - Flag to enable or disable debugging mode. When true,
 *                                     the top layer will be stacked below the bottom layer
 *                                     rather than overlaid on top.
 */

/** @type {HybridRendererOptions} */
const OPTS = {
  svgMarkTypes: ['text'],
  svgOnTop: true,
  debug: false
};

/**
 * Configure the HybridRenderer
 *
 * @param {HybridRendererOptions} options - HybridRenderer configuration options.
 */
function setHybridRendererOptions(options) {
  OPTS['svgMarkTypes'] = options.svgMarkTypes ?? ['text'];
  OPTS['svgOnTop'] = options.svgOnTop ?? true;
  OPTS['debug'] = options.debug ?? false;
}
class HybridRenderer extends Renderer {
  constructor(loader) {
    super(loader);
    this._svgRenderer = new SVGRenderer(loader);
    this._canvasRenderer = new CanvasRenderer(loader);
  }

  /**
   * Initialize a new HybridRenderer instance.
   * @param {DOMElement} el - The containing DOM element for the display.
   * @param {number} width - The coordinate width of the display, in pixels.
   * @param {number} height - The coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {HybridRenderer} - This renderer instance.
   */
  initialize(el, width, height, origin, scaleFactor) {
    this._root_el = domChild(el, 0, 'div');
    const bottomEl = domChild(this._root_el, 0, 'div');
    const topEl = domChild(this._root_el, 1, 'div');
    this._root_el.style.position = 'relative';

    // Set position absolute to overlay svg on top of canvas
    if (!OPTS.debug) {
      bottomEl.style.height = '100%';
      topEl.style.position = 'absolute';
      topEl.style.top = '0';
      topEl.style.left = '0';
      topEl.style.height = '100%';
      topEl.style.width = '100%';
    }
    this._svgEl = OPTS.svgOnTop ? topEl : bottomEl;
    this._canvasEl = OPTS.svgOnTop ? bottomEl : topEl;

    // pointer-events to none on SVG layer so that canvas gets all events
    this._svgEl.style.pointerEvents = 'none';
    this._canvasRenderer.initialize(this._canvasEl, width, height, origin, scaleFactor);
    this._svgRenderer.initialize(this._svgEl, width, height, origin, scaleFactor);
    return super.initialize(el, width, height, origin, scaleFactor);
  }

  /**
   * Flag a mark item as dirty.
   * @param {Item} item - The mark item.
   */
  dirty(item) {
    if (OPTS.svgMarkTypes.includes(item.mark.marktype)) {
      this._svgRenderer.dirty(item);
    } else {
      this._canvasRenderer.dirty(item);
    }
    return this;
  }

  /**
   * Internal rendering method.
   * @param {object} scene - The root mark of a scenegraph to render.
   * @param {Array} markTypes - Array of the mark types to render.
   *                            If undefined, render all mark types
   */
  _render(scene, markTypes) {
    const allMarkTypes = markTypes ?? ['arc', 'area', 'image', 'line', 'path', 'rect', 'rule', 'shape', 'symbol', 'text', 'trail'];
    const canvasMarkTypes = allMarkTypes.filter(m => !OPTS.svgMarkTypes.includes(m));
    this._svgRenderer.render(scene, OPTS.svgMarkTypes);
    this._canvasRenderer.render(scene, canvasMarkTypes);
  }

  /**
   * Resize the display.
   * @param {number} width - The new coordinate width of the display, in pixels.
   * @param {number} height - The new coordinate height of the display, in pixels.
   * @param {Array<number>} origin - The new origin of the display, in pixels.
   *   The coordinate system will be translated to this point.
   * @param {number} [scaleFactor=1] - Optional scaleFactor by which to multiply
   *   the width and height to determine the final pixel size.
   * @return {SVGRenderer} - This renderer instance;
   */
  resize(width, height, origin, scaleFactor) {
    super.resize(width, height, origin, scaleFactor);
    this._svgRenderer.resize(width, height, origin, scaleFactor);
    this._canvasRenderer.resize(width, height, origin, scaleFactor);
    return this;
  }
  background(bgcolor) {
    // Propagate background color to lower canvas renderer
    if (OPTS.svgOnTop) {
      this._canvasRenderer.background(bgcolor);
    } else {
      this._svgRenderer.background(bgcolor);
    }
    return this;
  }
}

class HybridHandler extends CanvasHandler {
  constructor(loader, tooltip) {
    super(loader, tooltip);
  }
  initialize(el, origin, obj) {
    const canvas = domChild(domChild(el, 0, 'div'), OPTS.svgOnTop ? 0 : 1, 'div');
    return super.initialize(canvas, origin, obj);
  }
}

const Canvas = 'canvas';
const Hybrid = 'hybrid';
const PNG = 'png';
const SVG = 'svg';
const vega_scenegraph_module_None = 'none';
const RenderType = {
  Canvas: Canvas,
  PNG: PNG,
  SVG: SVG,
  Hybrid: Hybrid,
  None: vega_scenegraph_module_None
};
const modules = {};
modules[Canvas] = modules[PNG] = {
  renderer: CanvasRenderer,
  headless: CanvasRenderer,
  handler: CanvasHandler
};
modules[SVG] = {
  renderer: SVGRenderer,
  headless: SVGStringRenderer,
  handler: SVGHandler
};
modules[Hybrid] = {
  renderer: HybridRenderer,
  headless: HybridRenderer,
  handler: HybridHandler
};
modules[vega_scenegraph_module_None] = {};
function renderModule(name, _) {
  name = String(name || '').toLowerCase();
  if (arguments.length > 1) {
    modules[name] = _;
    return this;
  } else {
    return modules[name];
  }
}

function vega_scenegraph_module_intersect(scene, bounds, filter) {
  const hits = [],
    // intersection results
    box = new Bounds().union(bounds),
    // defensive copy
    type = scene.marktype;
  return type ? intersectMark(scene, box, filter, hits) : type === 'group' ? intersectGroup(scene, box, filter, hits) : vega_util_module_error('Intersect scene must be mark node or group item.');
}
function intersectMark(mark, box, filter, hits) {
  if (visitMark(mark, box, filter)) {
    const items = mark.items,
      type = mark.marktype,
      n = items.length;
    let i = 0;
    if (type === 'group') {
      for (; i < n; ++i) {
        intersectGroup(items[i], box, filter, hits);
      }
    } else {
      for (const test = Marks[type].isect; i < n; ++i) {
        const item = items[i];
        if (intersectItem(item, box, test)) hits.push(item);
      }
    }
  }
  return hits;
}
function visitMark(mark, box, filter) {
  // process if bounds intersect and if
  // (1) mark is a group mark (so we must recurse), or
  // (2) mark is interactive and passes filter
  return mark.bounds && box.intersects(mark.bounds) && (mark.marktype === 'group' || mark.interactive !== false && (!filter || filter(mark)));
}
function intersectGroup(group, box, filter, hits) {
  // test intersect against group
  // skip groups by default unless filter says otherwise
  if (filter && filter(group.mark) && intersectItem(group, box, Marks.group.isect)) {
    hits.push(group);
  }

  // recursively test children marks
  // translate box to group coordinate space
  const marks = group.items,
    n = marks && marks.length;
  if (n) {
    const x = group.x || 0,
      y = group.y || 0;
    box.translate(-x, -y);
    for (let i = 0; i < n; ++i) {
      intersectMark(marks[i], box, filter, hits);
    }
    box.translate(x, y);
  }
  return hits;
}
function intersectItem(item, box, test) {
  // test bounds enclosure, bounds intersection, then detailed test
  const bounds = item.bounds;
  return box.encloses(bounds) || box.intersects(bounds) && test(item, box);
}

const clipBounds = new Bounds();
function boundClip (mark) {
  const clip = mark.clip;
  if (vega_util_module_isFunction(clip)) {
    clip(boundContext(clipBounds.clear()));
  } else if (clip) {
    clipBounds.set(0, 0, mark.group.width, mark.group.height);
  } else return;
  mark.bounds.intersect(clipBounds);
}

const TOLERANCE = 1e-9;
function sceneEqual(a, b, key) {
  return a === b ? true : key === 'path' ? pathEqual(a, b) : a instanceof Date && b instanceof Date ? +a === +b : vega_util_module_isNumber(a) && vega_util_module_isNumber(b) ? Math.abs(a - b) <= TOLERANCE : !a || !b || !vega_util_module_isObject(a) && !vega_util_module_isObject(b) ? a == b : objectEqual(a, b);
}
function pathEqual(a, b) {
  return sceneEqual(vega_scenegraph_module_parse(a), vega_scenegraph_module_parse(b));
}
function objectEqual(a, b) {
  var ka = Object.keys(a),
    kb = Object.keys(b),
    key,
    i;
  if (ka.length !== kb.length) return false;
  ka.sort();
  kb.sort();
  for (i = ka.length - 1; i >= 0; i--) {
    if (ka[i] != kb[i]) return false;
  }
  for (i = ka.length - 1; i >= 0; i--) {
    key = ka[i];
    if (!sceneEqual(a[key], b[key], key)) return false;
  }
  return typeof a === typeof b;
}

function resetSVGDefIds() {
  resetSVGClipId();
  resetSVGGradientId();
}



;// ../../node_modules/vega-view-transforms/build/vega-view-transforms.module.js




const Top = 'top';
const Left = 'left';
const Right = 'right';
const Bottom = 'bottom';
const TopLeft = 'top-left';
const TopRight = 'top-right';
const BottomLeft = 'bottom-left';
const BottomRight = 'bottom-right';
const Start = 'start';
const Middle = 'middle';
const End = 'end';
const X = 'x';
const Y = 'y';
const Group = 'group';
const AxisRole = 'axis';
const TitleRole = 'title';
const FrameRole = 'frame';
const ScopeRole = 'scope';
const LegendRole = 'legend';
const RowHeader = 'row-header';
const RowFooter = 'row-footer';
const RowTitle = 'row-title';
const ColHeader = 'column-header';
const ColFooter = 'column-footer';
const ColTitle = 'column-title';
const Padding = 'padding';
const Symbols = 'symbol';
const Fit = 'fit';
const FitX = 'fit-x';
const FitY = 'fit-y';
const Pad = 'pad';
const vega_view_transforms_module_None = 'none';
const All = 'all';
const Each = 'each';
const Flush = 'flush';
const vega_view_transforms_module_Column = 'column';
const Row = 'row';

/**
 * Calculate bounding boxes for scenegraph items.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {object} params.mark - The scenegraph mark instance to bound.
 */
function Bound(params) {
  Transform.call(this, null, params);
}
inherits(Bound, Transform, {
  transform(_, pulse) {
    const view = pulse.dataflow,
      mark = _.mark,
      type = mark.marktype,
      entry = Marks[type],
      bound = entry.bound;
    let markBounds = mark.bounds,
      rebound;
    if (entry.nested) {
      // multi-item marks have a single bounds instance
      if (mark.items.length) view.dirty(mark.items[0]);
      markBounds = vega_view_transforms_module_boundItem(mark, bound);
      mark.items.forEach(item => {
        item.bounds.clear().union(markBounds);
      });
    } else if (type === Group || _.modified()) {
      // operator parameters modified -> re-bound all items
      // updates group bounds in response to modified group content
      pulse.visit(pulse.MOD, item => view.dirty(item));
      markBounds.clear();
      mark.items.forEach(item => markBounds.union(vega_view_transforms_module_boundItem(item, bound)));

      // force reflow for axes/legends/titles to propagate any layout changes
      switch (mark.role) {
        case AxisRole:
        case LegendRole:
        case TitleRole:
          pulse.reflow();
      }
    } else {
      // incrementally update bounds, re-bound mark as needed
      rebound = pulse.changed(pulse.REM);
      pulse.visit(pulse.ADD, item => {
        markBounds.union(vega_view_transforms_module_boundItem(item, bound));
      });
      pulse.visit(pulse.MOD, item => {
        rebound = rebound || markBounds.alignsWith(item.bounds);
        view.dirty(item);
        markBounds.union(vega_view_transforms_module_boundItem(item, bound));
      });
      if (rebound) {
        markBounds.clear();
        mark.items.forEach(item => markBounds.union(item.bounds));
      }
    }

    // ensure mark bounds do not exceed any clipping region
    boundClip(mark);
    return pulse.modifies('bounds');
  }
});
function vega_view_transforms_module_boundItem(item, bound, opt) {
  return bound(item.bounds.clear(), item, opt);
}

const COUNTER_NAME = ':vega_identifier:';

/**
 * Adds a unique identifier to all added tuples.
 * This transform creates a new signal that serves as an id counter.
 * As a result, the id counter is shared across all instances of this
 * transform, generating unique ids across multiple data streams. In
 * addition, this signal value can be included in a snapshot of the
 * dataflow state, enabling correct resumption of id allocation.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {string} params.as - The field name for the generated identifier.
 */
function vega_view_transforms_module_Identifier(params) {
  Transform.call(this, 0, params);
}
vega_view_transforms_module_Identifier.Definition = {
  'type': 'Identifier',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'as',
    'type': 'string',
    'required': true
  }]
};
inherits(vega_view_transforms_module_Identifier, Transform, {
  transform(_, pulse) {
    const counter = getCounter(pulse.dataflow),
      as = _.as;
    let id = counter.value;
    pulse.visit(pulse.ADD, t => t[as] = t[as] || ++id);
    counter.set(this.value = id);
    return pulse;
  }
});
function getCounter(view) {
  return view._signals[COUNTER_NAME] || (view._signals[COUNTER_NAME] = view.add(0));
}

/**
 * Bind scenegraph items to a scenegraph mark instance.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {object} params.markdef - The mark definition for creating the mark.
 *   This is an object of legal scenegraph mark properties which *must* include
 *   the 'marktype' property.
 */
function Mark(params) {
  Transform.call(this, null, params);
}
inherits(Mark, Transform, {
  transform(_, pulse) {
    let mark = this.value;

    // acquire mark on first invocation, bind context and group
    if (!mark) {
      mark = pulse.dataflow.scenegraph().mark(_.markdef, lookup$1(_), _.index);
      mark.group.context = _.context;
      if (!_.context.group) _.context.group = mark.group;
      mark.source = this.source; // point to upstream collector
      mark.clip = _.clip;
      mark.interactive = _.interactive;
      this.value = mark;
    }

    // initialize entering items
    const Init = mark.marktype === Group ? GroupItem : Item;
    pulse.visit(pulse.ADD, item => Init.call(item, mark));

    // update clipping and/or interactive status
    if (_.modified('clip') || _.modified('interactive')) {
      mark.clip = _.clip;
      mark.interactive = !!_.interactive;
      mark.zdirty = true; // force scenegraph re-eval
      pulse.reflow();
    }

    // bind items array to scenegraph mark
    mark.items = pulse.source;
    return pulse;
  }
});
function lookup$1(_) {
  const g = _.groups,
    p = _.parent;
  return g && g.size === 1 ? g.get(Object.keys(g.object)[0]) : g && p ? g.lookup(p) : null;
}

/**
 * Analyze items for overlap, changing opacity to hide items with
 * overlapping bounding boxes. This transform will preserve at least
 * two items (e.g., first and last) even if overlap persists.
 * @param {object} params - The parameters for this operator.
 * @param {function(*,*): number} [params.sort] - A comparator
 *   function for sorting items.
 * @param {object} [params.method] - The overlap removal method to apply.
 *   One of 'parity' (default, hide every other item until there is no
 *   more overlap) or 'greedy' (sequentially scan and hide and items that
 *   overlap with the last visible item).
 * @param {object} [params.boundScale] - A scale whose range should be used
 *   to bound the items. Items exceeding the bounds of the scale range
 *   will be treated as overlapping. If null or undefined, no bounds check
 *   will be applied.
 * @param {object} [params.boundOrient] - The orientation of the scale
 *   (top, bottom, left, or right) used to bound items. This parameter is
 *   ignored if boundScale is null or undefined.
 * @param {object} [params.boundTolerance] - The tolerance in pixels for
 *   bound inclusion testing (default 1). This specifies by how many pixels
 *   an item's bounds may exceed the scale range bounds and not be culled.
 * @constructor
 */
function Overlap(params) {
  Transform.call(this, null, params);
}
const methods = {
  parity: items => items.filter((item, i) => i % 2 ? item.opacity = 0 : 1),
  greedy: (items, sep) => {
    let a;
    return items.filter((b, i) => !i || !vega_view_transforms_module_intersect(a.bounds, b.bounds, sep) ? (a = b, 1) : b.opacity = 0);
  }
};

// compute bounding box intersection
// including padding pixels of separation
const vega_view_transforms_module_intersect = (a, b, sep) => sep > Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2);
const hasOverlap = (items, pad) => {
  for (var i = 1, n = items.length, a = items[0].bounds, b; i < n; a = b, ++i) {
    if (vega_view_transforms_module_intersect(a, b = items[i].bounds, pad)) return true;
  }
};
const hasBounds = item => {
  const b = item.bounds;
  return b.width() > 1 && b.height() > 1;
};
const boundTest = (scale, orient, tolerance) => {
  var range = scale.range(),
    b = new Bounds();
  if (orient === Top || orient === Bottom) {
    b.set(range[0], -Infinity, range[1], +Infinity);
  } else {
    b.set(-Infinity, range[0], +Infinity, range[1]);
  }
  b.expand(tolerance || 1);
  return item => b.encloses(item.bounds);
};

// reset all items to be fully opaque
const vega_view_transforms_module_reset = source => {
  source.forEach(item => item.opacity = 1);
  return source;
};

// add all tuples to mod, fork pulse if parameters were modified
// fork prevents cross-stream tuple pollution (e.g., pulse from scale)
const reflow = (pulse, _) => pulse.reflow(_.modified()).modifies('opacity');
inherits(Overlap, Transform, {
  transform(_, pulse) {
    const reduce = methods[_.method] || methods.parity,
      sep = _.separation || 0;
    let source = pulse.materialize(pulse.SOURCE).source,
      items,
      test;
    if (!source || !source.length) return;
    if (!_.method) {
      // early exit if method is falsy
      if (_.modified('method')) {
        vega_view_transforms_module_reset(source);
        pulse = reflow(pulse, _);
      }
      return pulse;
    }

    // skip labels with no content
    source = source.filter(hasBounds);

    // early exit, nothing to do
    if (!source.length) return;
    if (_.sort) {
      source = source.slice().sort(_.sort);
    }
    items = vega_view_transforms_module_reset(source);
    pulse = reflow(pulse, _);
    if (items.length >= 3 && hasOverlap(items, sep)) {
      do {
        items = reduce(items, sep);
      } while (items.length >= 3 && hasOverlap(items, sep));
      if (items.length < 3 && !peek(source).opacity) {
        if (items.length > 1) peek(items).opacity = 0;
        peek(source).opacity = 1;
      }
    }
    if (_.boundScale && _.boundTolerance >= 0) {
      test = boundTest(_.boundScale, _.boundOrient, +_.boundTolerance);
      source.forEach(item => {
        if (!test(item)) item.opacity = 0;
      });
    }

    // re-calculate mark bounds
    const bounds = items[0].mark.bounds.clear();
    source.forEach(item => {
      if (item.opacity) bounds.union(item.bounds);
    });
    return pulse;
  }
});

/**
 * Queue modified scenegraph items for rendering.
 * @constructor
 */
function Render(params) {
  Transform.call(this, null, params);
}
inherits(Render, Transform, {
  transform(_, pulse) {
    const view = pulse.dataflow;
    pulse.visit(pulse.ALL, item => view.dirty(item));

    // set z-index dirty flag as needed
    if (pulse.fields && pulse.fields['zindex']) {
      const item = pulse.source && pulse.source[0];
      if (item) item.mark.zdirty = true;
    }
  }
});

const vega_view_transforms_module_tempBounds = new Bounds();
function vega_view_transforms_module_set(item, property, value) {
  return item[property] === value ? 0 : (item[property] = value, 1);
}

function isYAxis(mark) {
  var orient = mark.items[0].orient;
  return orient === Left || orient === Right;
}
function axisIndices(datum) {
  let index = +datum.grid;
  return [datum.ticks ? index++ : -1,
  // ticks index
  datum.labels ? index++ : -1,
  // labels index
  index + +datum.domain // title index
  ];
}
function axisLayout(view, axis, width, height) {
  var item = axis.items[0],
    datum = item.datum,
    delta = item.translate != null ? item.translate : 0.5,
    orient = item.orient,
    indices = axisIndices(datum),
    range = item.range,
    offset = item.offset,
    position = item.position,
    minExtent = item.minExtent,
    maxExtent = item.maxExtent,
    title = datum.title && item.items[indices[2]].items[0],
    titlePadding = item.titlePadding,
    bounds = item.bounds,
    dl = title && multiLineOffset(title),
    x = 0,
    y = 0,
    i,
    s;
  vega_view_transforms_module_tempBounds.clear().union(bounds);
  bounds.clear();
  if ((i = indices[0]) > -1) bounds.union(item.items[i].bounds);
  if ((i = indices[1]) > -1) bounds.union(item.items[i].bounds);

  // position axis group and title
  switch (orient) {
    case Top:
      x = position || 0;
      y = -offset;
      s = Math.max(minExtent, Math.min(maxExtent, -bounds.y1));
      bounds.add(0, -s).add(range, 0);
      if (title) axisTitleLayout(view, title, s, titlePadding, dl, 0, -1, bounds);
      break;
    case Left:
      x = -offset;
      y = position || 0;
      s = Math.max(minExtent, Math.min(maxExtent, -bounds.x1));
      bounds.add(-s, 0).add(0, range);
      if (title) axisTitleLayout(view, title, s, titlePadding, dl, 1, -1, bounds);
      break;
    case Right:
      x = width + offset;
      y = position || 0;
      s = Math.max(minExtent, Math.min(maxExtent, bounds.x2));
      bounds.add(0, 0).add(s, range);
      if (title) axisTitleLayout(view, title, s, titlePadding, dl, 1, 1, bounds);
      break;
    case Bottom:
      x = position || 0;
      y = height + offset;
      s = Math.max(minExtent, Math.min(maxExtent, bounds.y2));
      bounds.add(0, 0).add(range, s);
      if (title) axisTitleLayout(view, title, s, titlePadding, 0, 0, 1, bounds);
      break;
    default:
      x = item.x;
      y = item.y;
  }

  // update bounds
  boundStroke(bounds.translate(x, y), item);
  if (vega_view_transforms_module_set(item, 'x', x + delta) | vega_view_transforms_module_set(item, 'y', y + delta)) {
    item.bounds = vega_view_transforms_module_tempBounds;
    view.dirty(item);
    item.bounds = bounds;
    view.dirty(item);
  }
  return item.mark.bounds.clear().union(bounds);
}
function axisTitleLayout(view, title, offset, pad, dl, isYAxis, sign, bounds) {
  const b = title.bounds;
  if (title.auto) {
    const v = sign * (offset + dl + pad);
    let dx = 0,
      dy = 0;
    view.dirty(title);
    isYAxis ? dx = (title.x || 0) - (title.x = v) : dy = (title.y || 0) - (title.y = v);
    title.mark.bounds.clear().union(b.translate(-dx, -dy));
    view.dirty(title);
  }
  bounds.union(b);
}

// aggregation functions for grid margin determination
const vega_view_transforms_module_min = (a, b) => Math.floor(Math.min(a, b));
const vega_view_transforms_module_max = (a, b) => Math.ceil(Math.max(a, b));
function gridLayoutGroups(group) {
  var groups = group.items,
    n = groups.length,
    i = 0,
    mark,
    items;
  const views = {
    marks: [],
    rowheaders: [],
    rowfooters: [],
    colheaders: [],
    colfooters: [],
    rowtitle: null,
    coltitle: null
  };

  // layout axes, gather legends, collect bounds
  for (; i < n; ++i) {
    mark = groups[i];
    items = mark.items;
    if (mark.marktype === Group) {
      switch (mark.role) {
        case AxisRole:
        case LegendRole:
        case TitleRole:
          break;
        case RowHeader:
          views.rowheaders.push(...items);
          break;
        case RowFooter:
          views.rowfooters.push(...items);
          break;
        case ColHeader:
          views.colheaders.push(...items);
          break;
        case ColFooter:
          views.colfooters.push(...items);
          break;
        case RowTitle:
          views.rowtitle = items[0];
          break;
        case ColTitle:
          views.coltitle = items[0];
          break;
        default:
          views.marks.push(...items);
      }
    }
  }
  return views;
}
function bboxFlush(item) {
  return new Bounds().set(0, 0, item.width || 0, item.height || 0);
}
function bboxFull(item) {
  const b = item.bounds.clone();
  return b.empty() ? b.set(0, 0, 0, 0) : b.translate(-(item.x || 0), -(item.y || 0));
}
function vega_view_transforms_module_get(opt, key, d) {
  const v = vega_util_module_isObject(opt) ? opt[key] : opt;
  return v != null ? v : d !== undefined ? d : 0;
}
function offsetValue(v) {
  return v < 0 ? Math.ceil(-v) : 0;
}
function gridLayout(view, groups, opt) {
  var dirty = !opt.nodirty,
    bbox = opt.bounds === Flush ? bboxFlush : bboxFull,
    bounds = vega_view_transforms_module_tempBounds.set(0, 0, 0, 0),
    alignCol = vega_view_transforms_module_get(opt.align, vega_view_transforms_module_Column),
    alignRow = vega_view_transforms_module_get(opt.align, Row),
    padCol = vega_view_transforms_module_get(opt.padding, vega_view_transforms_module_Column),
    padRow = vega_view_transforms_module_get(opt.padding, Row),
    ncols = opt.columns || groups.length,
    nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols),
    n = groups.length,
    xOffset = Array(n),
    xExtent = Array(ncols),
    xMax = 0,
    yOffset = Array(n),
    yExtent = Array(nrows),
    yMax = 0,
    dx = Array(n),
    dy = Array(n),
    boxes = Array(n),
    m,
    i,
    c,
    r,
    b,
    g,
    px,
    py,
    x,
    y,
    offset;
  for (i = 0; i < ncols; ++i) xExtent[i] = 0;
  for (i = 0; i < nrows; ++i) yExtent[i] = 0;

  // determine offsets for each group
  for (i = 0; i < n; ++i) {
    g = groups[i];
    b = boxes[i] = bbox(g);
    g.x = g.x || 0;
    dx[i] = 0;
    g.y = g.y || 0;
    dy[i] = 0;
    c = i % ncols;
    r = ~~(i / ncols);
    xMax = Math.max(xMax, px = Math.ceil(b.x2));
    yMax = Math.max(yMax, py = Math.ceil(b.y2));
    xExtent[c] = Math.max(xExtent[c], px);
    yExtent[r] = Math.max(yExtent[r], py);
    xOffset[i] = padCol + offsetValue(b.x1);
    yOffset[i] = padRow + offsetValue(b.y1);
    if (dirty) view.dirty(groups[i]);
  }

  // set initial alignment offsets
  for (i = 0; i < n; ++i) {
    if (i % ncols === 0) xOffset[i] = 0;
    if (i < ncols) yOffset[i] = 0;
  }

  // enforce column alignment constraints
  if (alignCol === Each) {
    for (c = 1; c < ncols; ++c) {
      for (offset = 0, i = c; i < n; i += ncols) {
        if (offset < xOffset[i]) offset = xOffset[i];
      }
      for (i = c; i < n; i += ncols) {
        xOffset[i] = offset + xExtent[c - 1];
      }
    }
  } else if (alignCol === All) {
    for (offset = 0, i = 0; i < n; ++i) {
      if (i % ncols && offset < xOffset[i]) offset = xOffset[i];
    }
    for (i = 0; i < n; ++i) {
      if (i % ncols) xOffset[i] = offset + xMax;
    }
  } else {
    for (alignCol = false, c = 1; c < ncols; ++c) {
      for (i = c; i < n; i += ncols) {
        xOffset[i] += xExtent[c - 1];
      }
    }
  }

  // enforce row alignment constraints
  if (alignRow === Each) {
    for (r = 1; r < nrows; ++r) {
      for (offset = 0, i = r * ncols, m = i + ncols; i < m; ++i) {
        if (offset < yOffset[i]) offset = yOffset[i];
      }
      for (i = r * ncols; i < m; ++i) {
        yOffset[i] = offset + yExtent[r - 1];
      }
    }
  } else if (alignRow === All) {
    for (offset = 0, i = ncols; i < n; ++i) {
      if (offset < yOffset[i]) offset = yOffset[i];
    }
    for (i = ncols; i < n; ++i) {
      yOffset[i] = offset + yMax;
    }
  } else {
    for (alignRow = false, r = 1; r < nrows; ++r) {
      for (i = r * ncols, m = i + ncols; i < m; ++i) {
        yOffset[i] += yExtent[r - 1];
      }
    }
  }

  // perform horizontal grid layout
  for (x = 0, i = 0; i < n; ++i) {
    x = xOffset[i] + (i % ncols ? x : 0);
    dx[i] += x - groups[i].x;
  }

  // perform vertical grid layout
  for (c = 0; c < ncols; ++c) {
    for (y = 0, i = c; i < n; i += ncols) {
      y += yOffset[i];
      dy[i] += y - groups[i].y;
    }
  }

  // perform horizontal centering
  if (alignCol && vega_view_transforms_module_get(opt.center, vega_view_transforms_module_Column) && nrows > 1) {
    for (i = 0; i < n; ++i) {
      b = alignCol === All ? xMax : xExtent[i % ncols];
      x = b - boxes[i].x2 - groups[i].x - dx[i];
      if (x > 0) dx[i] += x / 2;
    }
  }

  // perform vertical centering
  if (alignRow && vega_view_transforms_module_get(opt.center, Row) && ncols !== 1) {
    for (i = 0; i < n; ++i) {
      b = alignRow === All ? yMax : yExtent[~~(i / ncols)];
      y = b - boxes[i].y2 - groups[i].y - dy[i];
      if (y > 0) dy[i] += y / 2;
    }
  }

  // position grid relative to anchor
  for (i = 0; i < n; ++i) {
    bounds.union(boxes[i].translate(dx[i], dy[i]));
  }
  x = vega_view_transforms_module_get(opt.anchor, X);
  y = vega_view_transforms_module_get(opt.anchor, Y);
  switch (vega_view_transforms_module_get(opt.anchor, vega_view_transforms_module_Column)) {
    case End:
      x -= bounds.width();
      break;
    case Middle:
      x -= bounds.width() / 2;
  }
  switch (vega_view_transforms_module_get(opt.anchor, Row)) {
    case End:
      y -= bounds.height();
      break;
    case Middle:
      y -= bounds.height() / 2;
  }
  x = Math.round(x);
  y = Math.round(y);

  // update mark positions, bounds, dirty
  bounds.clear();
  for (i = 0; i < n; ++i) {
    groups[i].mark.bounds.clear();
  }
  for (i = 0; i < n; ++i) {
    g = groups[i];
    g.x += dx[i] += x;
    g.y += dy[i] += y;
    bounds.union(g.mark.bounds.union(g.bounds.translate(dx[i], dy[i])));
    if (dirty) view.dirty(g);
  }
  return bounds;
}
function trellisLayout(view, group, opt) {
  var views = gridLayoutGroups(group),
    groups = views.marks,
    bbox = opt.bounds === Flush ? boundFlush : boundFull,
    off = opt.offset,
    ncols = opt.columns || groups.length,
    nrows = ncols <= 0 ? 1 : Math.ceil(groups.length / ncols),
    cells = nrows * ncols,
    x,
    y,
    x2,
    y2,
    anchor,
    band,
    offset;

  // -- initial grid layout
  const bounds = gridLayout(view, groups, opt);
  if (bounds.empty()) bounds.set(0, 0, 0, 0); // empty grid

  // -- layout grid headers and footers --

  // perform row header layout
  if (views.rowheaders) {
    band = vega_view_transforms_module_get(opt.headerBand, Row, null);
    x = layoutHeaders(view, views.rowheaders, groups, ncols, nrows, -vega_view_transforms_module_get(off, 'rowHeader'), vega_view_transforms_module_min, 0, bbox, 'x1', 0, ncols, 1, band);
  }

  // perform column header layout
  if (views.colheaders) {
    band = vega_view_transforms_module_get(opt.headerBand, vega_view_transforms_module_Column, null);
    y = layoutHeaders(view, views.colheaders, groups, ncols, ncols, -vega_view_transforms_module_get(off, 'columnHeader'), vega_view_transforms_module_min, 1, bbox, 'y1', 0, 1, ncols, band);
  }

  // perform row footer layout
  if (views.rowfooters) {
    band = vega_view_transforms_module_get(opt.footerBand, Row, null);
    x2 = layoutHeaders(view, views.rowfooters, groups, ncols, nrows, vega_view_transforms_module_get(off, 'rowFooter'), vega_view_transforms_module_max, 0, bbox, 'x2', ncols - 1, ncols, 1, band);
  }

  // perform column footer layout
  if (views.colfooters) {
    band = vega_view_transforms_module_get(opt.footerBand, vega_view_transforms_module_Column, null);
    y2 = layoutHeaders(view, views.colfooters, groups, ncols, ncols, vega_view_transforms_module_get(off, 'columnFooter'), vega_view_transforms_module_max, 1, bbox, 'y2', cells - ncols, 1, ncols, band);
  }

  // perform row title layout
  if (views.rowtitle) {
    anchor = vega_view_transforms_module_get(opt.titleAnchor, Row);
    offset = vega_view_transforms_module_get(off, 'rowTitle');
    offset = anchor === End ? x2 + offset : x - offset;
    band = vega_view_transforms_module_get(opt.titleBand, Row, 0.5);
    layoutTitle(view, views.rowtitle, offset, 0, bounds, band);
  }

  // perform column title layout
  if (views.coltitle) {
    anchor = vega_view_transforms_module_get(opt.titleAnchor, vega_view_transforms_module_Column);
    offset = vega_view_transforms_module_get(off, 'columnTitle');
    offset = anchor === End ? y2 + offset : y - offset;
    band = vega_view_transforms_module_get(opt.titleBand, vega_view_transforms_module_Column, 0.5);
    layoutTitle(view, views.coltitle, offset, 1, bounds, band);
  }
}
function boundFlush(item, field) {
  return field === 'x1' ? item.x || 0 : field === 'y1' ? item.y || 0 : field === 'x2' ? (item.x || 0) + (item.width || 0) : field === 'y2' ? (item.y || 0) + (item.height || 0) : undefined;
}
function boundFull(item, field) {
  return item.bounds[field];
}
function layoutHeaders(view, headers, groups, ncols, limit, offset, agg, isX, bound, bf, start, stride, back, band) {
  var n = groups.length,
    init = 0,
    edge = 0,
    i,
    j,
    k,
    m,
    b,
    h,
    g,
    x,
    y;

  // if no groups, early exit and return 0
  if (!n) return init;

  // compute margin
  for (i = start; i < n; i += stride) {
    if (groups[i]) init = agg(init, bound(groups[i], bf));
  }

  // if no headers, return margin calculation
  if (!headers.length) return init;

  // check if number of headers exceeds number of rows or columns
  if (headers.length > limit) {
    view.warn('Grid headers exceed limit: ' + limit);
    headers = headers.slice(0, limit);
  }

  // apply offset
  init += offset;

  // clear mark bounds for all headers
  for (j = 0, m = headers.length; j < m; ++j) {
    view.dirty(headers[j]);
    headers[j].mark.bounds.clear();
  }

  // layout each header
  for (i = start, j = 0, m = headers.length; j < m; ++j, i += stride) {
    h = headers[j];
    b = h.mark.bounds;

    // search for nearest group to align to
    // necessary if table has empty cells
    for (k = i; k >= 0 && (g = groups[k]) == null; k -= back);

    // assign coordinates and update bounds
    if (isX) {
      x = band == null ? g.x : Math.round(g.bounds.x1 + band * g.bounds.width());
      y = init;
    } else {
      x = init;
      y = band == null ? g.y : Math.round(g.bounds.y1 + band * g.bounds.height());
    }
    b.union(h.bounds.translate(x - (h.x || 0), y - (h.y || 0)));
    h.x = x;
    h.y = y;
    view.dirty(h);

    // update current edge of layout bounds
    edge = agg(edge, b[bf]);
  }
  return edge;
}
function layoutTitle(view, g, offset, isX, bounds, band) {
  if (!g) return;
  view.dirty(g);

  // compute title coordinates
  var x = offset,
    y = offset;
  isX ? x = Math.round(bounds.x1 + band * bounds.width()) : y = Math.round(bounds.y1 + band * bounds.height());

  // assign coordinates and update bounds
  g.bounds.translate(x - (g.x || 0), y - (g.y || 0));
  g.mark.bounds.clear().union(g.bounds);
  g.x = x;
  g.y = y;

  // queue title for redraw
  view.dirty(g);
}

// utility for looking up legend layout configuration
function vega_view_transforms_module_lookup(config, orient) {
  const opt = config[orient] || {};
  return (key, d) => opt[key] != null ? opt[key] : config[key] != null ? config[key] : d;
}

// if legends specify offset directly, use the maximum specified value
function offsets(legends, value) {
  let max = -Infinity;
  legends.forEach(item => {
    if (item.offset != null) max = Math.max(max, item.offset);
  });
  return max > -Infinity ? max : value;
}
function legendParams(g, orient, config, xb, yb, w, h) {
  const _ = vega_view_transforms_module_lookup(config, orient),
    offset = offsets(g, _('offset', 0)),
    anchor = _('anchor', Start),
    mult = anchor === End ? 1 : anchor === Middle ? 0.5 : 0;
  const p = {
    align: Each,
    bounds: _('bounds', Flush),
    columns: _('direction') === 'vertical' ? 1 : g.length,
    padding: _('margin', 8),
    center: _('center'),
    nodirty: true
  };
  switch (orient) {
    case Left:
      p.anchor = {
        x: Math.floor(xb.x1) - offset,
        column: End,
        y: mult * (h || xb.height() + 2 * xb.y1),
        row: anchor
      };
      break;
    case Right:
      p.anchor = {
        x: Math.ceil(xb.x2) + offset,
        y: mult * (h || xb.height() + 2 * xb.y1),
        row: anchor
      };
      break;
    case Top:
      p.anchor = {
        y: Math.floor(yb.y1) - offset,
        row: End,
        x: mult * (w || yb.width() + 2 * yb.x1),
        column: anchor
      };
      break;
    case Bottom:
      p.anchor = {
        y: Math.ceil(yb.y2) + offset,
        x: mult * (w || yb.width() + 2 * yb.x1),
        column: anchor
      };
      break;
    case TopLeft:
      p.anchor = {
        x: offset,
        y: offset
      };
      break;
    case TopRight:
      p.anchor = {
        x: w - offset,
        y: offset,
        column: End
      };
      break;
    case BottomLeft:
      p.anchor = {
        x: offset,
        y: h - offset,
        row: End
      };
      break;
    case BottomRight:
      p.anchor = {
        x: w - offset,
        y: h - offset,
        column: End,
        row: End
      };
      break;
  }
  return p;
}
function legendLayout(view, legend) {
  var item = legend.items[0],
    datum = item.datum,
    orient = item.orient,
    bounds = item.bounds,
    x = item.x,
    y = item.y,
    w,
    h;

  // cache current bounds for later comparison
  item._bounds ? item._bounds.clear().union(bounds) : item._bounds = bounds.clone();
  bounds.clear();

  // adjust legend to accommodate padding and title
  legendGroupLayout(view, item, item.items[0].items[0]);

  // aggregate bounds to determine size, and include origin
  bounds = legendBounds(item, bounds);
  w = 2 * item.padding;
  h = 2 * item.padding;
  if (!bounds.empty()) {
    w = Math.ceil(bounds.width() + w);
    h = Math.ceil(bounds.height() + h);
  }
  if (datum.type === Symbols) {
    legendEntryLayout(item.items[0].items[0].items[0].items);
  }
  if (orient !== vega_view_transforms_module_None) {
    item.x = x = 0;
    item.y = y = 0;
  }
  item.width = w;
  item.height = h;
  boundStroke(bounds.set(x, y, x + w, y + h), item);
  item.mark.bounds.clear().union(bounds);
  return item;
}
function legendBounds(item, b) {
  // aggregate item bounds
  item.items.forEach(_ => b.union(_.bounds));

  // anchor to legend origin
  b.x1 = item.padding;
  b.y1 = item.padding;
  return b;
}
function legendGroupLayout(view, item, entry) {
  var pad = item.padding,
    ex = pad - entry.x,
    ey = pad - entry.y;
  if (!item.datum.title) {
    if (ex || ey) vega_view_transforms_module_translate(view, entry, ex, ey);
  } else {
    var title = item.items[1].items[0],
      anchor = title.anchor,
      tpad = item.titlePadding || 0,
      tx = pad - title.x,
      ty = pad - title.y;
    switch (title.orient) {
      case Left:
        ex += Math.ceil(title.bounds.width()) + tpad;
        break;
      case Right:
      case Bottom:
        break;
      default:
        ey += title.bounds.height() + tpad;
    }
    if (ex || ey) vega_view_transforms_module_translate(view, entry, ex, ey);
    switch (title.orient) {
      case Left:
        ty += legendTitleOffset(item, entry, title, anchor, 1, 1);
        break;
      case Right:
        tx += legendTitleOffset(item, entry, title, End, 0, 0) + tpad;
        ty += legendTitleOffset(item, entry, title, anchor, 1, 1);
        break;
      case Bottom:
        tx += legendTitleOffset(item, entry, title, anchor, 0, 0);
        ty += legendTitleOffset(item, entry, title, End, -1, 0, 1) + tpad;
        break;
      default:
        tx += legendTitleOffset(item, entry, title, anchor, 0, 0);
    }
    if (tx || ty) vega_view_transforms_module_translate(view, title, tx, ty);

    // translate legend if title pushes into negative coordinates
    if ((tx = Math.round(title.bounds.x1 - pad)) < 0) {
      vega_view_transforms_module_translate(view, entry, -tx, 0);
      vega_view_transforms_module_translate(view, title, -tx, 0);
    }
  }
}
function legendTitleOffset(item, entry, title, anchor, y, lr, noBar) {
  const grad = item.datum.type !== 'symbol',
    vgrad = title.datum.vgrad,
    e = grad && (lr || !vgrad) && !noBar ? entry.items[0] : entry,
    s = e.bounds[y ? 'y2' : 'x2'] - item.padding,
    u = vgrad && lr ? s : 0,
    v = vgrad && lr ? 0 : s,
    o = y <= 0 ? 0 : multiLineOffset(title);
  return Math.round(anchor === Start ? u : anchor === End ? v - o : 0.5 * (s - o));
}
function vega_view_transforms_module_translate(view, item, dx, dy) {
  item.x += dx;
  item.y += dy;
  item.bounds.translate(dx, dy);
  item.mark.bounds.translate(dx, dy);
  view.dirty(item);
}
function legendEntryLayout(entries) {
  // get max widths for each column
  const widths = entries.reduce((w, g) => {
    w[g.column] = Math.max(g.bounds.x2 - g.x, w[g.column] || 0);
    return w;
  }, {});

  // set dimensions of legend entry groups
  entries.forEach(g => {
    g.width = widths[g.column];
    g.height = g.bounds.y2 - g.y;
  });
}

function titleLayout(view, mark, width, height, viewBounds) {
  var group = mark.items[0],
    frame = group.frame,
    orient = group.orient,
    anchor = group.anchor,
    offset = group.offset,
    padding = group.padding,
    title = group.items[0].items[0],
    subtitle = group.items[1] && group.items[1].items[0],
    end = orient === Left || orient === Right ? height : width,
    start = 0,
    x = 0,
    y = 0,
    sx = 0,
    sy = 0,
    pos;
  if (frame !== Group) {
    orient === Left ? (start = viewBounds.y2, end = viewBounds.y1) : orient === Right ? (start = viewBounds.y1, end = viewBounds.y2) : (start = viewBounds.x1, end = viewBounds.x2);
  } else if (orient === Left) {
    start = height, end = 0;
  }
  pos = anchor === Start ? start : anchor === End ? end : (start + end) / 2;
  if (subtitle && subtitle.text) {
    // position subtitle
    switch (orient) {
      case Top:
      case Bottom:
        sy = title.bounds.height() + padding;
        break;
      case Left:
        sx = title.bounds.width() + padding;
        break;
      case Right:
        sx = -title.bounds.width() - padding;
        break;
    }
    vega_view_transforms_module_tempBounds.clear().union(subtitle.bounds);
    vega_view_transforms_module_tempBounds.translate(sx - (subtitle.x || 0), sy - (subtitle.y || 0));
    if (vega_view_transforms_module_set(subtitle, 'x', sx) | vega_view_transforms_module_set(subtitle, 'y', sy)) {
      view.dirty(subtitle);
      subtitle.bounds.clear().union(vega_view_transforms_module_tempBounds);
      subtitle.mark.bounds.clear().union(vega_view_transforms_module_tempBounds);
      view.dirty(subtitle);
    }
    vega_view_transforms_module_tempBounds.clear().union(subtitle.bounds);
  } else {
    vega_view_transforms_module_tempBounds.clear();
  }
  vega_view_transforms_module_tempBounds.union(title.bounds);

  // position title group
  switch (orient) {
    case Top:
      x = pos;
      y = viewBounds.y1 - vega_view_transforms_module_tempBounds.height() - offset;
      break;
    case Left:
      x = viewBounds.x1 - vega_view_transforms_module_tempBounds.width() - offset;
      y = pos;
      break;
    case Right:
      x = viewBounds.x2 + vega_view_transforms_module_tempBounds.width() + offset;
      y = pos;
      break;
    case Bottom:
      x = pos;
      y = viewBounds.y2 + offset;
      break;
    default:
      x = group.x;
      y = group.y;
  }
  if (vega_view_transforms_module_set(group, 'x', x) | vega_view_transforms_module_set(group, 'y', y)) {
    vega_view_transforms_module_tempBounds.translate(x, y);
    view.dirty(group);
    group.bounds.clear().union(vega_view_transforms_module_tempBounds);
    mark.bounds.clear().union(vega_view_transforms_module_tempBounds);
    view.dirty(group);
  }
  return group.bounds;
}

/**
 * Layout view elements such as axes and legends.
 * Also performs size adjustments.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {object} params.mark - Scenegraph mark of groups to layout.
 */
function ViewLayout(params) {
  Transform.call(this, null, params);
}
inherits(ViewLayout, Transform, {
  transform(_, pulse) {
    const view = pulse.dataflow;
    _.mark.items.forEach(group => {
      if (_.layout) trellisLayout(view, group, _.layout);
      layoutGroup(view, group, _);
    });
    return shouldReflow(_.mark.group) ? pulse.reflow() : pulse;
  }
});
function shouldReflow(group) {
  // We typically should reflow if layout is invoked (#2568), as child items
  // may have resized and reflow ensures group bounds are re-calculated.
  // However, legend entries have a special exception to avoid instability.
  // For example, if a selected legend symbol gains a stroke on hover,
  // we don't want to re-position subsequent elements in the legend.
  return group && group.mark.role !== 'legend-entry';
}
function layoutGroup(view, group, _) {
  var items = group.items,
    width = Math.max(0, group.width || 0),
    height = Math.max(0, group.height || 0),
    viewBounds = new Bounds().set(0, 0, width, height),
    xBounds = viewBounds.clone(),
    yBounds = viewBounds.clone(),
    legends = [],
    title,
    mark,
    orient,
    b,
    i,
    n;

  // layout axes, gather legends, collect bounds
  for (i = 0, n = items.length; i < n; ++i) {
    mark = items[i];
    switch (mark.role) {
      case AxisRole:
        b = isYAxis(mark) ? xBounds : yBounds;
        b.union(axisLayout(view, mark, width, height));
        break;
      case TitleRole:
        title = mark;
        break;
      case LegendRole:
        legends.push(legendLayout(view, mark));
        break;
      case FrameRole:
      case ScopeRole:
      case RowHeader:
      case RowFooter:
      case RowTitle:
      case ColHeader:
      case ColFooter:
      case ColTitle:
        xBounds.union(mark.bounds);
        yBounds.union(mark.bounds);
        break;
      default:
        viewBounds.union(mark.bounds);
    }
  }

  // layout legends, adjust viewBounds
  if (legends.length) {
    // group legends by orient
    const l = {};
    legends.forEach(item => {
      orient = item.orient || Right;
      if (orient !== vega_view_transforms_module_None) (l[orient] || (l[orient] = [])).push(item);
    });

    // perform grid layout for each orient group
    for (const orient in l) {
      const g = l[orient];
      gridLayout(view, g, legendParams(g, orient, _.legends, xBounds, yBounds, width, height));
    }

    // update view bounds
    legends.forEach(item => {
      const b = item.bounds;
      if (!b.equals(item._bounds)) {
        item.bounds = item._bounds;
        view.dirty(item); // dirty previous location
        item.bounds = b;
        view.dirty(item);
      }
      if (_.autosize && (_.autosize.type === Fit || _.autosize.type === FitX || _.autosize.type === FitY)) {
        // For autosize fit, incorporate the orthogonal dimension only.
        // Legends that overrun the chart area will then be clipped;
        // otherwise the chart area gets reduced to nothing!
        switch (item.orient) {
          case Left:
          case Right:
            viewBounds.add(b.x1, 0).add(b.x2, 0);
            break;
          case Top:
          case Bottom:
            viewBounds.add(0, b.y1).add(0, b.y2);
        }
      } else {
        viewBounds.union(b);
      }
    });
  }

  // combine bounding boxes
  viewBounds.union(xBounds).union(yBounds);

  // layout title, adjust bounds
  if (title) {
    viewBounds.union(titleLayout(view, title, width, height, viewBounds));
  }

  // override aggregated view bounds if content is clipped
  if (group.clip) {
    viewBounds.set(0, 0, group.width || 0, group.height || 0);
  }

  // perform size adjustment
  viewSizeLayout(view, group, viewBounds, _);
}
function viewSizeLayout(view, group, viewBounds, _) {
  const auto = _.autosize || {},
    type = auto.type;
  if (view._autosize < 1 || !type) return;
  let viewWidth = view._width,
    viewHeight = view._height,
    width = Math.max(0, group.width || 0),
    left = Math.max(0, Math.ceil(-viewBounds.x1)),
    height = Math.max(0, group.height || 0),
    top = Math.max(0, Math.ceil(-viewBounds.y1));
  const right = Math.max(0, Math.ceil(viewBounds.x2 - width)),
    bottom = Math.max(0, Math.ceil(viewBounds.y2 - height));
  if (auto.contains === Padding) {
    const padding = view.padding();
    viewWidth -= padding.left + padding.right;
    viewHeight -= padding.top + padding.bottom;
  }
  if (type === vega_view_transforms_module_None) {
    left = 0;
    top = 0;
    width = viewWidth;
    height = viewHeight;
  } else if (type === Fit) {
    width = Math.max(0, viewWidth - left - right);
    height = Math.max(0, viewHeight - top - bottom);
  } else if (type === FitX) {
    width = Math.max(0, viewWidth - left - right);
    viewHeight = height + top + bottom;
  } else if (type === FitY) {
    viewWidth = width + left + right;
    height = Math.max(0, viewHeight - top - bottom);
  } else if (type === Pad) {
    viewWidth = width + left + right;
    viewHeight = height + top + bottom;
  }
  view._resizeView(viewWidth, viewHeight, width, height, [left, top], auto.resize);
}



;// ../../node_modules/d3-array/src/sum.js
function sum_sum(values, valueof) {
  let sum = 0;
  if (valueof === undefined) {
    for (let value of values) {
      if (value = +value) {
        sum += value;
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if (value = +valueof(value, ++index, values)) {
        sum += value;
      }
    }
  }
  return sum;
}

;// ../../node_modules/vega-encode/build/vega-encode.module.js






/**
 * Generates axis ticks for visualizing a spatial scale.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Scale} params.scale - The scale to generate ticks for.
 * @param {*} [params.count=10] - The approximate number of ticks, or
 *   desired tick interval, to use.
 * @param {Array<*>} [params.values] - The exact tick values to use.
 *   These must be legal domain values for the provided scale.
 *   If provided, the count argument is ignored.
 * @param {function(*):string} [params.formatSpecifier] - A format specifier
 *   to use in conjunction with scale.tickFormat. Legal values are
 *   any valid d3 4.0 format specifier.
 * @param {function(*):string} [params.format] - The format function to use.
 *   If provided, the formatSpecifier argument is ignored.
 */
function AxisTicks(params) {
  Transform.call(this, null, params);
}
inherits(AxisTicks, Transform, {
  transform(_, pulse) {
    if (this.value && !_.modified()) {
      return pulse.StopPropagation;
    }
    var locale = pulse.dataflow.locale(),
      out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      ticks = this.value,
      scale = _.scale,
      tally = _.count == null ? _.values ? _.values.length : 10 : _.count,
      count = tickCount(scale, tally, _.minstep),
      format = _.format || vega_scale_module_tickFormat(locale, scale, count, _.formatSpecifier, _.formatType, !!_.values),
      values = _.values ? validTicks(scale, _.values, count) : tickValues(scale, count);
    if (ticks) out.rem = ticks;
    ticks = values.map((value, i) => ingest$1({
      index: i / (values.length - 1 || 1),
      value: value,
      label: format(value)
    }));
    if (_.extra && ticks.length) {
      // add an extra tick pegged to the initial domain value
      // this is used to generate axes with 'binned' domains
      ticks.push(ingest$1({
        index: -1,
        extra: {
          value: ticks[0].value
        },
        label: ''
      }));
    }
    out.source = ticks;
    out.add = ticks;
    this.value = ticks;
    return out;
  }
});

/**
 * Joins a set of data elements against a set of visual items.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): object} [params.item] - An item generator function.
 * @param {function(object): *} [params.key] - The key field associating data and visual items.
 */
function DataJoin(params) {
  Transform.call(this, null, params);
}
function defaultItemCreate() {
  return ingest$1({});
}
function newMap(key) {
  const map = fastmap().test(t => t.exit);
  map.lookup = t => map.get(key(t));
  return map;
}
inherits(DataJoin, Transform, {
  transform(_, pulse) {
    var df = pulse.dataflow,
      out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      item = _.item || defaultItemCreate,
      key = _.key || tupleid,
      map = this.value;

    // prevent transient (e.g., hover) requests from
    // cascading across marks derived from marks
    if (vega_util_module_isArray(out.encode)) {
      out.encode = null;
    }
    if (map && (_.modified('key') || pulse.modified(key))) {
      vega_util_module_error('DataJoin does not support modified key function or fields.');
    }
    if (!map) {
      pulse = pulse.addAll();
      this.value = map = newMap(key);
    }
    pulse.visit(pulse.ADD, t => {
      const k = key(t);
      let x = map.get(k);
      if (x) {
        if (x.exit) {
          map.empty--;
          out.add.push(x);
        } else {
          out.mod.push(x);
        }
      } else {
        x = item(t);
        map.set(k, x);
        out.add.push(x);
      }
      x.datum = t;
      x.exit = false;
    });
    pulse.visit(pulse.MOD, t => {
      const k = key(t),
        x = map.get(k);
      if (x) {
        x.datum = t;
        out.mod.push(x);
      }
    });
    pulse.visit(pulse.REM, t => {
      const k = key(t),
        x = map.get(k);
      if (t === x.datum && !x.exit) {
        out.rem.push(x);
        x.exit = true;
        ++map.empty;
      }
    });
    if (pulse.changed(pulse.ADD_MOD)) out.modifies('datum');
    if (pulse.clean() || _.clean && map.empty > df.cleanThreshold) {
      df.runAfter(map.clean);
    }
    return out;
  }
});

/**
 * Invokes encoding functions for visual items.
 * @constructor
 * @param {object} params - The parameters to the encoding functions. This
 *   parameter object will be passed through to all invoked encoding functions.
 * @param {object} [params.mod=false] - Flag indicating if tuples in the input
 *   mod set that are unmodified by encoders should be included in the output.
 * @param {object} param.encoders - The encoding functions
 * @param {function(object, object): boolean} [param.encoders.update] - Update encoding set
 * @param {function(object, object): boolean} [param.encoders.enter] - Enter encoding set
 * @param {function(object, object): boolean} [param.encoders.exit] - Exit encoding set
 */
function Encode(params) {
  Transform.call(this, null, params);
}
inherits(Encode, Transform, {
  transform(_, pulse) {
    var out = pulse.fork(pulse.ADD_REM),
      fmod = _.mod || false,
      encoders = _.encoders,
      encode = pulse.encode;

    // if an array, the encode directive includes additional sets
    // that must be defined in order for the primary set to be invoked
    // e.g., only run the update set if the hover set is defined
    if (vega_util_module_isArray(encode)) {
      if (out.changed() || encode.every(e => encoders[e])) {
        encode = encode[0];
        out.encode = null; // consume targeted encode directive
      } else {
        return pulse.StopPropagation;
      }
    }

    // marshall encoder functions
    var reenter = encode === 'enter',
      update = encoders.update || falsy,
      enter = encoders.enter || falsy,
      exit = encoders.exit || falsy,
      set = (encode && !reenter ? encoders[encode] : update) || falsy;
    if (pulse.changed(pulse.ADD)) {
      pulse.visit(pulse.ADD, t => {
        enter(t, _);
        update(t, _);
      });
      out.modifies(enter.output);
      out.modifies(update.output);
      if (set !== falsy && set !== update) {
        pulse.visit(pulse.ADD, t => {
          set(t, _);
        });
        out.modifies(set.output);
      }
    }
    if (pulse.changed(pulse.REM) && exit !== falsy) {
      pulse.visit(pulse.REM, t => {
        exit(t, _);
      });
      out.modifies(exit.output);
    }
    if (reenter || set !== falsy) {
      const flag = pulse.MOD | (_.modified() ? pulse.REFLOW : 0);
      if (reenter) {
        pulse.visit(flag, t => {
          const mod = enter(t, _) || fmod;
          if (set(t, _) || mod) out.mod.push(t);
        });
        if (out.mod.length) out.modifies(enter.output);
      } else {
        pulse.visit(flag, t => {
          if (set(t, _) || fmod) out.mod.push(t);
        });
      }
      if (out.mod.length) out.modifies(set.output);
    }
    return out.changed() ? out : pulse.StopPropagation;
  }
});

/**
 * Generates legend entries for visualizing a scale.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Scale} params.scale - The scale to generate items for.
 * @param {*} [params.count=5] - The approximate number of items, or
 *   desired tick interval, to use.
 * @param {*} [params.limit] - The maximum number of entries to
 *   include in a symbol legend.
 * @param {Array<*>} [params.values] - The exact tick values to use.
 *   These must be legal domain values for the provided scale.
 *   If provided, the count argument is ignored.
 * @param {string} [params.formatSpecifier] - A format specifier
 *   to use in conjunction with scale.tickFormat. Legal values are
 *   any valid D3 format specifier string.
 * @param {function(*):string} [params.format] - The format function to use.
 *   If provided, the formatSpecifier argument is ignored.
 */
function LegendEntries(params) {
  Transform.call(this, [], params);
}
inherits(LegendEntries, Transform, {
  transform(_, pulse) {
    if (this.value != null && !_.modified()) {
      return pulse.StopPropagation;
    }
    var locale = pulse.dataflow.locale(),
      out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      items = this.value,
      type = _.type || SymbolLegend,
      scale = _.scale,
      limit = +_.limit,
      count = tickCount(scale, _.count == null ? 5 : _.count, _.minstep),
      lskip = !!_.values || type === SymbolLegend,
      format = _.format || labelFormat(locale, scale, count, type, _.formatSpecifier, _.formatType, lskip),
      values = _.values || labelValues(scale, count),
      domain,
      fraction,
      size,
      offset,
      ellipsis;
    if (items) out.rem = items;
    if (type === SymbolLegend) {
      if (limit && values.length > limit) {
        pulse.dataflow.warn('Symbol legend count exceeds limit, filtering items.');
        items = values.slice(0, limit - 1);
        ellipsis = true;
      } else {
        items = values;
      }
      if (vega_util_module_isFunction(size = _.size)) {
        // if first value maps to size zero, remove from list (vega#717)
        if (!_.values && scale(items[0]) === 0) {
          items = items.slice(1);
        }
        // compute size offset for legend entries
        offset = items.reduce((max, value) => Math.max(max, size(value, _)), 0);
      } else {
        size = vega_util_module_constant(offset = size || 8);
      }
      items = items.map((value, index) => ingest$1({
        index: index,
        label: format(value, index, items),
        value: value,
        offset: offset,
        size: size(value, _)
      }));
      if (ellipsis) {
        ellipsis = values[items.length];
        items.push(ingest$1({
          index: items.length,
          label: `\u2026${values.length - items.length} entries`,
          value: ellipsis,
          offset: offset,
          size: size(ellipsis, _)
        }));
      }
    } else if (type === GradientLegend) {
      domain = scale.domain(), fraction = scaleFraction(scale, domain[0], peek(domain));

      // if automatic label generation produces 2 or fewer values,
      // use the domain end points instead (fixes vega/vega#1364)
      if (values.length < 3 && !_.values && domain[0] !== peek(domain)) {
        values = [domain[0], peek(domain)];
      }
      items = values.map((value, index) => ingest$1({
        index: index,
        label: format(value, index, values),
        value: value,
        perc: fraction(value)
      }));
    } else {
      size = values.length - 1;
      fraction = labelFraction(scale);
      items = values.map((value, index) => ingest$1({
        index: index,
        label: format(value, index, values),
        value: value,
        perc: index ? fraction(value) : 0,
        perc2: index === size ? 1 : fraction(values[index + 1])
      }));
    }
    out.source = items;
    out.add = items;
    this.value = items;
    return out;
  }
});

const sourceX = t => t.source.x;
const sourceY = t => t.source.y;
const targetX = t => t.target.x;
const targetY = t => t.target.y;

/**
 * Layout paths linking source and target elements.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function LinkPath(params) {
  Transform.call(this, {}, params);
}
LinkPath.Definition = {
  'type': 'LinkPath',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'sourceX',
    'type': 'field',
    'default': 'source.x'
  }, {
    'name': 'sourceY',
    'type': 'field',
    'default': 'source.y'
  }, {
    'name': 'targetX',
    'type': 'field',
    'default': 'target.x'
  }, {
    'name': 'targetY',
    'type': 'field',
    'default': 'target.y'
  }, {
    'name': 'orient',
    'type': 'enum',
    'default': 'vertical',
    'values': ['horizontal', 'vertical', 'radial']
  }, {
    'name': 'shape',
    'type': 'enum',
    'default': 'line',
    'values': ['line', 'arc', 'curve', 'diagonal', 'orthogonal']
  }, {
    'name': 'require',
    'type': 'signal'
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'path'
  }]
};
inherits(LinkPath, Transform, {
  transform(_, pulse) {
    var sx = _.sourceX || sourceX,
      sy = _.sourceY || sourceY,
      tx = _.targetX || targetX,
      ty = _.targetY || targetY,
      as = _.as || 'path',
      orient = _.orient || 'vertical',
      shape = _.shape || 'line',
      path = Paths.get(shape + '-' + orient) || Paths.get(shape);
    if (!path) {
      vega_util_module_error('LinkPath unsupported type: ' + _.shape + (_.orient ? '-' + _.orient : ''));
    }
    pulse.visit(pulse.SOURCE, t => {
      t[as] = path(sx(t), sy(t), tx(t), ty(t));
    });
    return pulse.reflow(_.modified()).modifies(as);
  }
});
const vega_encode_module_line = (sx, sy, tx, ty) => 'M' + sx + ',' + sy + 'L' + tx + ',' + ty;
const lineR = (sa, sr, ta, tr) => vega_encode_module_line(sr * Math.cos(sa), sr * Math.sin(sa), tr * Math.cos(ta), tr * Math.sin(ta));
const vega_encode_module_arc = (sx, sy, tx, ty) => {
  var dx = tx - sx,
    dy = ty - sy,
    rr = Math.hypot(dx, dy) / 2,
    ra = 180 * Math.atan2(dy, dx) / Math.PI;
  return 'M' + sx + ',' + sy + 'A' + rr + ',' + rr + ' ' + ra + ' 0 1' + ' ' + tx + ',' + ty;
};
const arcR = (sa, sr, ta, tr) => vega_encode_module_arc(sr * Math.cos(sa), sr * Math.sin(sa), tr * Math.cos(ta), tr * Math.sin(ta));
const curve = (sx, sy, tx, ty) => {
  const dx = tx - sx,
    dy = ty - sy,
    ix = 0.2 * (dx + dy),
    iy = 0.2 * (dy - dx);
  return 'M' + sx + ',' + sy + 'C' + (sx + ix) + ',' + (sy + iy) + ' ' + (tx + iy) + ',' + (ty - ix) + ' ' + tx + ',' + ty;
};
const curveR = (sa, sr, ta, tr) => curve(sr * Math.cos(sa), sr * Math.sin(sa), tr * Math.cos(ta), tr * Math.sin(ta));
const orthoX = (sx, sy, tx, ty) => 'M' + sx + ',' + sy + 'V' + ty + 'H' + tx;
const orthoY = (sx, sy, tx, ty) => 'M' + sx + ',' + sy + 'H' + tx + 'V' + ty;
const orthoR = (sa, sr, ta, tr) => {
  const sc = Math.cos(sa),
    ss = Math.sin(sa),
    tc = Math.cos(ta),
    ts = Math.sin(ta),
    sf = Math.abs(ta - sa) > Math.PI ? ta <= sa : ta > sa;
  return 'M' + sr * sc + ',' + sr * ss + 'A' + sr + ',' + sr + ' 0 0,' + (sf ? 1 : 0) + ' ' + sr * tc + ',' + sr * ts + 'L' + tr * tc + ',' + tr * ts;
};
const diagonalX = (sx, sy, tx, ty) => {
  const m = (sx + tx) / 2;
  return 'M' + sx + ',' + sy + 'C' + m + ',' + sy + ' ' + m + ',' + ty + ' ' + tx + ',' + ty;
};
const diagonalY = (sx, sy, tx, ty) => {
  const m = (sy + ty) / 2;
  return 'M' + sx + ',' + sy + 'C' + sx + ',' + m + ' ' + tx + ',' + m + ' ' + tx + ',' + ty;
};
const diagonalR = (sa, sr, ta, tr) => {
  const sc = Math.cos(sa),
    ss = Math.sin(sa),
    tc = Math.cos(ta),
    ts = Math.sin(ta),
    mr = (sr + tr) / 2;
  return 'M' + sr * sc + ',' + sr * ss + 'C' + mr * sc + ',' + mr * ss + ' ' + mr * tc + ',' + mr * ts + ' ' + tr * tc + ',' + tr * ts;
};
const Paths = fastmap({
  'line': vega_encode_module_line,
  'line-radial': lineR,
  'arc': vega_encode_module_arc,
  'arc-radial': arcR,
  'curve': curve,
  'curve-radial': curveR,
  'orthogonal-horizontal': orthoX,
  'orthogonal-vertical': orthoY,
  'orthogonal-radial': orthoR,
  'diagonal-horizontal': diagonalX,
  'diagonal-vertical': diagonalY,
  'diagonal-radial': diagonalR
});

/**
 * Pie and donut chart layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to size pie segments.
 * @param {number} [params.startAngle=0] - The start angle (in radians) of the layout.
 * @param {number} [params.endAngle=2π] - The end angle (in radians) of the layout.
 * @param {boolean} [params.sort] - Boolean flag for sorting sectors by value.
 */
function Pie(params) {
  Transform.call(this, null, params);
}
Pie.Definition = {
  'type': 'Pie',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'startAngle',
    'type': 'number',
    'default': 0
  }, {
    'name': 'endAngle',
    'type': 'number',
    'default': 6.283185307179586
  }, {
    'name': 'sort',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['startAngle', 'endAngle']
  }]
};
inherits(Pie, Transform, {
  transform(_, pulse) {
    var as = _.as || ['startAngle', 'endAngle'],
      startAngle = as[0],
      endAngle = as[1],
      field = _.field || one,
      start = _.startAngle || 0,
      stop = _.endAngle != null ? _.endAngle : 2 * Math.PI,
      data = pulse.source,
      values = data.map(field),
      n = values.length,
      a = start,
      k = (stop - start) / sum_sum(values),
      index = range_range(n),
      i,
      t,
      v;
    if (_.sort) {
      index.sort((a, b) => values[a] - values[b]);
    }
    for (i = 0; i < n; ++i) {
      v = values[index[i]];
      t = data[index[i]];
      t[startAngle] = a;
      t[endAngle] = a += v * k;
    }
    this.value = values;
    return pulse.reflow(_.modified()).modifies(as);
  }
});

const DEFAULT_COUNT = 5;
function includeZero(scale) {
  const type = scale.type;
  return !scale.bins && (type === vega_scale_module_Linear || type === Pow || type === Sqrt);
}
function includePad(type) {
  return isContinuous(type) && type !== Sequential;
}
const vega_encode_module_SKIP = vega_util_module_toSet(['set', 'modified', 'clear', 'type', 'scheme', 'schemeExtent', 'schemeCount', 'domain', 'domainMin', 'domainMid', 'domainMax', 'domainRaw', 'domainImplicit', 'nice', 'zero', 'bins', 'range', 'rangeStep', 'round', 'reverse', 'interpolate', 'interpolateGamma']);

/**
 * Maintains a scale function mapping data values to visual channels.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function Scale(params) {
  Transform.call(this, null, params);
  this.modified(true); // always treat as modified
}
inherits(Scale, Transform, {
  transform(_, pulse) {
    var df = pulse.dataflow,
      scale$1 = this.value,
      key = scaleKey(_);
    if (!scale$1 || key !== scale$1.type) {
      this.value = scale$1 = vega_scale_module_scale(key)();
    }
    for (key in _) if (!vega_encode_module_SKIP[key]) {
      // padding is a scale property for band/point but not others
      if (key === 'padding' && includePad(scale$1.type)) continue;
      // invoke scale property setter, raise warning if not found
      vega_util_module_isFunction(scale$1[key]) ? scale$1[key](_[key]) : df.warn('Unsupported scale property: ' + key);
    }
    configureRange(scale$1, _, configureBins(scale$1, _, configureDomain(scale$1, _, df)));
    return pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
  }
});
function scaleKey(_) {
  var t = _.type,
    d = '',
    n;

  // backwards compatibility pre Vega 5.
  if (t === Sequential) return Sequential + '-' + vega_scale_module_Linear;
  if (isContinuousColor(_)) {
    n = _.rawDomain ? _.rawDomain.length : _.domain ? _.domain.length + +(_.domainMid != null) : 0;
    d = n === 2 ? Sequential + '-' : n === 3 ? Diverging + '-' : '';
  }
  return (d + t || vega_scale_module_Linear).toLowerCase();
}
function isContinuousColor(_) {
  const t = _.type;
  return isContinuous(t) && t !== Time && t !== UTC && (_.scheme || _.range && _.range.length && _.range.every(vega_util_module_isString));
}
function configureDomain(scale, _, df) {
  // check raw domain, if provided use that and exit early
  const raw = rawDomain(scale, _.domainRaw, df);
  if (raw > -1) return raw;
  var domain = _.domain,
    type = scale.type,
    zero = _.zero || _.zero === undefined && includeZero(scale),
    n,
    mid;
  if (!domain) return 0;

  // adjust domain based on zero, min, max settings
  if (zero || _.domainMin != null || _.domainMax != null || _.domainMid != null) {
    n = (domain = domain.slice()).length - 1 || 1;
    if (zero) {
      if (domain[0] > 0) domain[0] = 0;
      if (domain[n] < 0) domain[n] = 0;
    }
    if (_.domainMin != null) domain[0] = _.domainMin;
    if (_.domainMax != null) domain[n] = _.domainMax;
    if (_.domainMid != null) {
      mid = _.domainMid;
      const i = mid > domain[n] ? n + 1 : mid < domain[0] ? 0 : n;
      if (i !== n) df.warn('Scale domainMid exceeds domain min or max.', mid);
      domain.splice(i, 0, mid);
    }
  }

  // adjust continuous domain for minimum pixel padding
  if (includePad(type) && _.padding && domain[0] !== peek(domain)) {
    domain = padDomain(type, domain, _.range, _.padding, _.exponent, _.constant);
  }

  // set the scale domain
  scale.domain(domainCheck(type, domain, df));

  // if ordinal scale domain is defined, prevent implicit
  // domain construction as side-effect of scale lookup
  if (type === Ordinal) {
    scale.unknown(_.domainImplicit ? implicit : undefined);
  }

  // perform 'nice' adjustment as requested
  if (_.nice && scale.nice) {
    scale.nice(_.nice !== true && tickCount(scale, _.nice) || null);
  }

  // return the cardinality of the domain
  return domain.length;
}
function rawDomain(scale, raw, df) {
  if (raw) {
    scale.domain(domainCheck(scale.type, raw, df));
    return raw.length;
  } else {
    return -1;
  }
}
function padDomain(type, domain, range, pad, exponent, constant) {
  var span = Math.abs(peek(range) - range[0]),
    frac = span / (span - 2 * pad),
    d = type === Log ? zoomLog(domain, null, frac) : type === Sqrt ? zoomPow(domain, null, frac, 0.5) : type === Pow ? zoomPow(domain, null, frac, exponent || 1) : type === Symlog ? zoomSymlog(domain, null, frac, constant || 1) : zoomLinear(domain, null, frac);
  domain = domain.slice();
  domain[0] = d[0];
  domain[domain.length - 1] = d[1];
  return domain;
}
function domainCheck(type, domain, df) {
  if (isLogarithmic(type)) {
    // sum signs of domain values
    // if all pos or all neg, abs(sum) === domain.length
    var s = Math.abs(domain.reduce((s, v) => s + (v < 0 ? -1 : v > 0 ? 1 : 0), 0));
    if (s !== domain.length) {
      df.warn('Log scale domain includes zero: ' + $(domain));
    }
  }
  return domain;
}
function configureBins(scale, _, count) {
  let bins = _.bins;
  if (bins && !vega_util_module_isArray(bins)) {
    // generate bin boundary array
    const domain = scale.domain(),
      lo = domain[0],
      hi = peek(domain),
      step = bins.step;
    let start = bins.start == null ? lo : bins.start,
      stop = bins.stop == null ? hi : bins.stop;
    if (!step) vega_util_module_error('Scale bins parameter missing step property.');
    if (start < lo) start = step * Math.ceil(lo / step);
    if (stop > hi) stop = step * Math.floor(hi / step);
    bins = range_range(start, stop + step / 2, step);
  }
  if (bins) {
    // assign bin boundaries to scale instance
    scale.bins = bins;
  } else if (scale.bins) {
    // no current bins, remove bins if previously set
    delete scale.bins;
  }

  // special handling for bin-ordinal scales
  if (scale.type === BinOrdinal) {
    if (!bins) {
      // the domain specifies the bins
      scale.bins = scale.domain();
    } else if (!_.domain && !_.domainRaw) {
      // the bins specify the domain
      scale.domain(bins);
      count = bins.length;
    }
  }

  // return domain cardinality
  return count;
}
function configureRange(scale, _, count) {
  var type = scale.type,
    round = _.round || false,
    range = _.range;

  // if range step specified, calculate full range extent
  if (_.rangeStep != null) {
    range = configureRangeStep(type, _, count);
  }

  // else if a range scheme is defined, use that
  else if (_.scheme) {
    range = configureScheme(type, _, count);
    if (vega_util_module_isFunction(range)) {
      if (scale.interpolator) {
        return scale.interpolator(range);
      } else {
        vega_util_module_error(`Scale type ${type} does not support interpolating color schemes.`);
      }
    }
  }

  // given a range array for an interpolating scale, convert to interpolator
  if (range && isInterpolating(type)) {
    return scale.interpolator(interpolateColors(flip(range, _.reverse), _.interpolate, _.interpolateGamma));
  }

  // configure rounding / interpolation
  if (range && _.interpolate && scale.interpolate) {
    scale.interpolate(interpolate(_.interpolate, _.interpolateGamma));
  } else if (vega_util_module_isFunction(scale.round)) {
    scale.round(round);
  } else if (vega_util_module_isFunction(scale.rangeRound)) {
    scale.interpolate(round ? src_round : value);
  }
  if (range) scale.range(flip(range, _.reverse));
}
function configureRangeStep(type, _, count) {
  if (type !== Band && type !== Point) {
    vega_util_module_error('Only band and point scales support rangeStep.');
  }

  // calculate full range based on requested step size and padding
  var outer = (_.paddingOuter != null ? _.paddingOuter : _.padding) || 0,
    inner = type === Point ? 1 : (_.paddingInner != null ? _.paddingInner : _.padding) || 0;
  return [0, _.rangeStep * bandSpace(count, inner, outer)];
}
function configureScheme(type, _, count) {
  var extent = _.schemeExtent,
    name,
    scheme$1;
  if (vega_util_module_isArray(_.scheme)) {
    scheme$1 = interpolateColors(_.scheme, _.interpolate, _.interpolateGamma);
  } else {
    name = _.scheme.toLowerCase();
    scheme$1 = scheme(name);
    if (!scheme$1) vega_util_module_error(`Unrecognized scheme name: ${_.scheme}`);
  }

  // determine size for potential discrete range
  count = type === Threshold ? count + 1 : type === BinOrdinal ? count - 1 : type === vega_scale_module_Quantile || type === Quantize ? +_.schemeCount || DEFAULT_COUNT : count;

  // adjust and/or quantize scheme as appropriate
  return isInterpolating(type) ? adjustScheme(scheme$1, extent, _.reverse) : vega_util_module_isFunction(scheme$1) ? quantizeInterpolator(adjustScheme(scheme$1, extent), count) : type === Ordinal ? scheme$1 : scheme$1.slice(0, count);
}
function adjustScheme(scheme, extent, reverse) {
  return vega_util_module_isFunction(scheme) && (extent || reverse) ? interpolateRange(scheme, flip(extent || [0, 1], reverse)) : scheme;
}
function flip(array, reverse) {
  return reverse ? array.slice().reverse() : array;
}

/**
 * Sorts scenegraph items in the pulse source array.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(*,*): number} [params.sort] - A comparator
 *   function for sorting tuples.
 */
function SortItems(params) {
  Transform.call(this, null, params);
}
inherits(SortItems, Transform, {
  transform(_, pulse) {
    const mod = _.modified('sort') || pulse.changed(pulse.ADD) || pulse.modified(_.sort.fields) || pulse.modified('datum');
    if (mod) pulse.source.sort(stableCompare(_.sort));
    this.modified(mod);
    return pulse;
  }
});

const Zero = 'zero',
  Center = 'center',
  Normalize = 'normalize',
  DefOutput = ['y0', 'y1'];

/**
 * Stack layout for visualization elements.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to stack.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors to groupby.
 * @param {function(object,object): number} [params.sort] - A comparator for stack sorting.
 * @param {string} [offset='zero'] - Stack baseline offset. One of 'zero', 'center', 'normalize'.
 */
function Stack(params) {
  Transform.call(this, null, params);
}
Stack.Definition = {
  'type': 'Stack',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'offset',
    'type': 'enum',
    'default': Zero,
    'values': [Zero, Center, Normalize]
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': DefOutput
  }]
};
inherits(Stack, Transform, {
  transform(_, pulse) {
    var as = _.as || DefOutput,
      y0 = as[0],
      y1 = as[1],
      sort = stableCompare(_.sort),
      field = _.field || one,
      stack = _.offset === Center ? stackCenter : _.offset === Normalize ? stackNormalize : stackZero,
      groups,
      i,
      n,
      max;

    // partition, sum, and sort the stack groups
    groups = vega_encode_module_partition(pulse.source, _.groupby, sort, field);

    // compute stack layouts per group
    for (i = 0, n = groups.length, max = groups.max; i < n; ++i) {
      stack(groups[i], max, field, y0, y1);
    }
    return pulse.reflow(_.modified()).modifies(as);
  }
});
function stackCenter(group, max, field, y0, y1) {
  var last = (max - group.sum) / 2,
    m = group.length,
    j = 0,
    t;
  for (; j < m; ++j) {
    t = group[j];
    t[y0] = last;
    t[y1] = last += Math.abs(field(t));
  }
}
function stackNormalize(group, max, field, y0, y1) {
  var scale = 1 / group.sum,
    last = 0,
    m = group.length,
    j = 0,
    v = 0,
    t;
  for (; j < m; ++j) {
    t = group[j];
    t[y0] = last;
    t[y1] = last = scale * (v += Math.abs(field(t)));
  }
}
function stackZero(group, max, field, y0, y1) {
  var lastPos = 0,
    lastNeg = 0,
    m = group.length,
    j = 0,
    v,
    t;
  for (; j < m; ++j) {
    t = group[j];
    v = +field(t);
    if (v < 0) {
      t[y0] = lastNeg;
      t[y1] = lastNeg += v;
    } else {
      t[y0] = lastPos;
      t[y1] = lastPos += v;
    }
  }
}
function vega_encode_module_partition(data, groupby, sort, field) {
  var groups = [],
    get = f => f(t),
    map,
    i,
    n,
    m,
    t,
    k,
    g,
    s,
    max;

  // partition data points into stack groups
  if (groupby == null) {
    groups.push(data.slice());
  } else {
    for (map = {}, i = 0, n = data.length; i < n; ++i) {
      t = data[i];
      k = groupby.map(get);
      g = map[k];
      if (!g) {
        map[k] = g = [];
        groups.push(g);
      }
      g.push(t);
    }
  }

  // compute sums of groups, sort groups as needed
  for (k = 0, max = 0, m = groups.length; k < m; ++k) {
    g = groups[k];
    for (i = 0, s = 0, n = g.length; i < n; ++i) {
      s += Math.abs(field(g[i]));
    }
    g.sum = s;
    if (s > max) max = s;
    if (sort) g.sort(sort);
  }
  groups.max = max;
  return groups;
}



;// ../../node_modules/d3-geo/src/identity.js
/* harmony default export */ const d3_geo_src_identity = (x => x);

;// ../../node_modules/d3-geo/src/stream.js
function streamGeometry(geometry, stream) {
  if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
    streamGeometryType[geometry.type](geometry, stream);
  }
}

var streamObjectType = {
  Feature: function(object, stream) {
    streamGeometry(object.geometry, stream);
  },
  FeatureCollection: function(object, stream) {
    var features = object.features, i = -1, n = features.length;
    while (++i < n) streamGeometry(features[i].geometry, stream);
  }
};

var streamGeometryType = {
  Sphere: function(object, stream) {
    stream.sphere();
  },
  Point: function(object, stream) {
    object = object.coordinates;
    stream.point(object[0], object[1], object[2]);
  },
  MultiPoint: function(object, stream) {
    var coordinates = object.coordinates, i = -1, n = coordinates.length;
    while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
  },
  LineString: function(object, stream) {
    streamLine(object.coordinates, stream, 0);
  },
  MultiLineString: function(object, stream) {
    var coordinates = object.coordinates, i = -1, n = coordinates.length;
    while (++i < n) streamLine(coordinates[i], stream, 0);
  },
  Polygon: function(object, stream) {
    streamPolygon(object.coordinates, stream);
  },
  MultiPolygon: function(object, stream) {
    var coordinates = object.coordinates, i = -1, n = coordinates.length;
    while (++i < n) streamPolygon(coordinates[i], stream);
  },
  GeometryCollection: function(object, stream) {
    var geometries = object.geometries, i = -1, n = geometries.length;
    while (++i < n) streamGeometry(geometries[i], stream);
  }
};

function streamLine(coordinates, stream, closed) {
  var i = -1, n = coordinates.length - closed, coordinate;
  stream.lineStart();
  while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
  stream.lineEnd();
}

function streamPolygon(coordinates, stream) {
  var i = -1, n = coordinates.length;
  stream.polygonStart();
  while (++i < n) streamLine(coordinates[i], stream, 1);
  stream.polygonEnd();
}

/* harmony default export */ function src_stream(object, stream) {
  if (object && streamObjectType.hasOwnProperty(object.type)) {
    streamObjectType[object.type](object, stream);
  } else {
    streamGeometry(object, stream);
  }
}

;// ../../node_modules/d3-array/src/fsum.js
// https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
class Adder {
  constructor() {
    this._partials = new Float64Array(32);
    this._n = 0;
  }
  add(x) {
    const p = this._partials;
    let i = 0;
    for (let j = 0; j < this._n && j < 32; j++) {
      const y = p[j],
        hi = x + y,
        lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
      if (lo) p[i++] = lo;
      x = hi;
    }
    p[i] = x;
    this._n = i + 1;
    return this;
  }
  valueOf() {
    const p = this._partials;
    let n = this._n, x, y, lo, hi = 0;
    if (n > 0) {
      hi = p[--n];
      while (n > 0) {
        x = hi;
        y = p[--n];
        hi = x + y;
        lo = y - (hi - x);
        if (lo) break;
      }
      if (n > 0 && ((lo < 0 && p[n - 1] < 0) || (lo > 0 && p[n - 1] > 0))) {
        y = lo * 2;
        x = hi + y;
        if (y == x - hi) hi = x;
      }
    }
    return hi;
  }
}

function fsum(values, valueof) {
  const adder = new Adder();
  if (valueof === undefined) {
    for (let value of values) {
      if (value = +value) {
        adder.add(value);
      }
    }
  } else {
    let index = -1;
    for (let value of values) {
      if (value = +valueof(value, ++index, values)) {
        adder.add(value);
      }
    }
  }
  return +adder;
}

function fcumsum(values, valueof) {
  const adder = new Adder();
  let index = -1;
  return Float64Array.from(values, valueof === undefined
      ? v => adder.add(+v || 0)
      : v => adder.add(+valueof(v, ++index, values) || 0)
  );
}

;// ../../node_modules/d3-geo/src/math.js
var src_math_epsilon = 1e-6;
var math_epsilon2 = 1e-12;
var math_pi = Math.PI;
var math_halfPi = math_pi / 2;
var quarterPi = math_pi / 4;
var math_tau = math_pi * 2;

var d3_geo_src_math_degrees = 180 / math_pi;
var d3_geo_src_math_radians = math_pi / 180;

var src_math_abs = Math.abs;
var math_atan = Math.atan;
var src_math_atan2 = Math.atan2;
var src_math_cos = Math.cos;
var math_ceil = Math.ceil;
var math_exp = Math.exp;
var math_floor = Math.floor;
var hypot = Math.hypot;
var math_log = Math.log;
var math_pow = Math.pow;
var src_math_sin = Math.sin;
var math_sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
var src_math_sqrt = Math.sqrt;
var math_tan = Math.tan;

function src_math_acos(x) {
  return x > 1 ? 0 : x < -1 ? math_pi : Math.acos(x);
}

function src_math_asin(x) {
  return x > 1 ? math_halfPi : x < -1 ? -math_halfPi : Math.asin(x);
}

function haversin(x) {
  return (x = src_math_sin(x / 2)) * x;
}

;// ../../node_modules/d3-geo/src/noop.js
function noop_noop() {}

;// ../../node_modules/d3-geo/src/path/area.js




var areaSum = new Adder(),
    areaRingSum = new Adder(),
    x00,
    y00,
    x0,
    y0;

var areaStream = {
  point: noop_noop,
  lineStart: noop_noop,
  lineEnd: noop_noop,
  polygonStart: function() {
    areaStream.lineStart = areaRingStart;
    areaStream.lineEnd = areaRingEnd;
  },
  polygonEnd: function() {
    areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop_noop;
    areaSum.add(src_math_abs(areaRingSum));
    areaRingSum = new Adder();
  },
  result: function() {
    var area = areaSum / 2;
    areaSum = new Adder();
    return area;
  }
};

function areaRingStart() {
  areaStream.point = areaPointFirst;
}

function areaPointFirst(x, y) {
  areaStream.point = areaPoint;
  x00 = x0 = x, y00 = y0 = y;
}

function areaPoint(x, y) {
  areaRingSum.add(y0 * x - x0 * y);
  x0 = x, y0 = y;
}

function areaRingEnd() {
  areaPoint(x00, y00);
}

/* harmony default export */ const path_area = (areaStream);

;// ../../node_modules/d3-geo/src/path/bounds.js


var bounds_x0 = Infinity,
    bounds_y0 = bounds_x0,
    x1 = -bounds_x0,
    y1 = x1;

var boundsStream = {
  point: boundsPoint,
  lineStart: noop_noop,
  lineEnd: noop_noop,
  polygonStart: noop_noop,
  polygonEnd: noop_noop,
  result: function() {
    var bounds = [[bounds_x0, bounds_y0], [x1, y1]];
    x1 = y1 = -(bounds_y0 = bounds_x0 = Infinity);
    return bounds;
  }
};

function boundsPoint(x, y) {
  if (x < bounds_x0) bounds_x0 = x;
  if (x > x1) x1 = x;
  if (y < bounds_y0) bounds_y0 = y;
  if (y > y1) y1 = y;
}

/* harmony default export */ const path_bounds = (boundsStream);

;// ../../node_modules/d3-geo/src/path/centroid.js


// TODO Enforce positive area for exterior, negative area for interior?

var X0 = 0,
    Y0 = 0,
    Z0 = 0,
    X1 = 0,
    Y1 = 0,
    Z1 = 0,
    X2 = 0,
    Y2 = 0,
    Z2 = 0,
    centroid_x00,
    centroid_y00,
    centroid_x0,
    centroid_y0;

var centroidStream = {
  point: centroidPoint,
  lineStart: centroidLineStart,
  lineEnd: centroidLineEnd,
  polygonStart: function() {
    centroidStream.lineStart = centroidRingStart;
    centroidStream.lineEnd = centroidRingEnd;
  },
  polygonEnd: function() {
    centroidStream.point = centroidPoint;
    centroidStream.lineStart = centroidLineStart;
    centroidStream.lineEnd = centroidLineEnd;
  },
  result: function() {
    var centroid = Z2 ? [X2 / Z2, Y2 / Z2]
        : Z1 ? [X1 / Z1, Y1 / Z1]
        : Z0 ? [X0 / Z0, Y0 / Z0]
        : [NaN, NaN];
    X0 = Y0 = Z0 =
    X1 = Y1 = Z1 =
    X2 = Y2 = Z2 = 0;
    return centroid;
  }
};

function centroidPoint(x, y) {
  X0 += x;
  Y0 += y;
  ++Z0;
}

function centroidLineStart() {
  centroidStream.point = centroidPointFirstLine;
}

function centroidPointFirstLine(x, y) {
  centroidStream.point = centroidPointLine;
  centroidPoint(centroid_x0 = x, centroid_y0 = y);
}

function centroidPointLine(x, y) {
  var dx = x - centroid_x0, dy = y - centroid_y0, z = src_math_sqrt(dx * dx + dy * dy);
  X1 += z * (centroid_x0 + x) / 2;
  Y1 += z * (centroid_y0 + y) / 2;
  Z1 += z;
  centroidPoint(centroid_x0 = x, centroid_y0 = y);
}

function centroidLineEnd() {
  centroidStream.point = centroidPoint;
}

function centroidRingStart() {
  centroidStream.point = centroidPointFirstRing;
}

function centroidRingEnd() {
  centroidPointRing(centroid_x00, centroid_y00);
}

function centroidPointFirstRing(x, y) {
  centroidStream.point = centroidPointRing;
  centroidPoint(centroid_x00 = centroid_x0 = x, centroid_y00 = centroid_y0 = y);
}

function centroidPointRing(x, y) {
  var dx = x - centroid_x0,
      dy = y - centroid_y0,
      z = src_math_sqrt(dx * dx + dy * dy);

  X1 += z * (centroid_x0 + x) / 2;
  Y1 += z * (centroid_y0 + y) / 2;
  Z1 += z;

  z = centroid_y0 * x - centroid_x0 * y;
  X2 += z * (centroid_x0 + x);
  Y2 += z * (centroid_y0 + y);
  Z2 += z * 3;
  centroidPoint(centroid_x0 = x, centroid_y0 = y);
}

/* harmony default export */ const centroid = (centroidStream);

;// ../../node_modules/d3-geo/src/path/context.js



function PathContext(context) {
  this._context = context;
}

PathContext.prototype = {
  _radius: 4.5,
  pointRadius: function(_) {
    return this._radius = _, this;
  },
  polygonStart: function() {
    this._line = 0;
  },
  polygonEnd: function() {
    this._line = NaN;
  },
  lineStart: function() {
    this._point = 0;
  },
  lineEnd: function() {
    if (this._line === 0) this._context.closePath();
    this._point = NaN;
  },
  point: function(x, y) {
    switch (this._point) {
      case 0: {
        this._context.moveTo(x, y);
        this._point = 1;
        break;
      }
      case 1: {
        this._context.lineTo(x, y);
        break;
      }
      default: {
        this._context.moveTo(x + this._radius, y);
        this._context.arc(x, y, this._radius, 0, math_tau);
        break;
      }
    }
  },
  result: noop_noop
};

;// ../../node_modules/d3-geo/src/path/measure.js




var lengthSum = new Adder(),
    lengthRing,
    measure_x00,
    measure_y00,
    measure_x0,
    measure_y0;

var lengthStream = {
  point: noop_noop,
  lineStart: function() {
    lengthStream.point = lengthPointFirst;
  },
  lineEnd: function() {
    if (lengthRing) lengthPoint(measure_x00, measure_y00);
    lengthStream.point = noop_noop;
  },
  polygonStart: function() {
    lengthRing = true;
  },
  polygonEnd: function() {
    lengthRing = null;
  },
  result: function() {
    var length = +lengthSum;
    lengthSum = new Adder();
    return length;
  }
};

function lengthPointFirst(x, y) {
  lengthStream.point = lengthPoint;
  measure_x00 = measure_x0 = x, measure_y00 = measure_y0 = y;
}

function lengthPoint(x, y) {
  measure_x0 -= x, measure_y0 -= y;
  lengthSum.add(src_math_sqrt(measure_x0 * measure_x0 + measure_y0 * measure_y0));
  measure_x0 = x, measure_y0 = y;
}

/* harmony default export */ const path_measure = (lengthStream);

;// ../../node_modules/d3-geo/src/path/string.js
// Simple caching for constant-radius points.
let cacheDigits, cacheAppend, cacheRadius, cacheCircle;

class PathString {
  constructor(digits) {
    this._append = digits == null ? string_append : string_appendRound(digits);
    this._radius = 4.5;
    this._ = "";
  }
  pointRadius(_) {
    this._radius = +_;
    return this;
  }
  polygonStart() {
    this._line = 0;
  }
  polygonEnd() {
    this._line = NaN;
  }
  lineStart() {
    this._point = 0;
  }
  lineEnd() {
    if (this._line === 0) this._ += "Z";
    this._point = NaN;
  }
  point(x, y) {
    switch (this._point) {
      case 0: {
        this._append`M${x},${y}`;
        this._point = 1;
        break;
      }
      case 1: {
        this._append`L${x},${y}`;
        break;
      }
      default: {
        this._append`M${x},${y}`;
        if (this._radius !== cacheRadius || this._append !== cacheAppend) {
          const r = this._radius;
          const s = this._;
          this._ = ""; // stash the old string so we can cache the circle path fragment
          this._append`m0,${r}a${r},${r} 0 1,1 0,${-2 * r}a${r},${r} 0 1,1 0,${2 * r}z`;
          cacheRadius = r;
          cacheAppend = this._append;
          cacheCircle = this._;
          this._ = s;
        }
        this._ += cacheCircle;
        break;
      }
    }
  }
  result() {
    const result = this._;
    this._ = "";
    return result.length ? result : null;
  }
}

function string_append(strings) {
  let i = 1;
  this._ += strings[0];
  for (const j = strings.length; i < j; ++i) {
    this._ += arguments[i] + strings[i];
  }
}

function string_appendRound(digits) {
  const d = Math.floor(digits);
  if (!(d >= 0)) throw new RangeError(`invalid digits: ${digits}`);
  if (d > 15) return string_append;
  if (d !== cacheDigits) {
    const k = 10 ** d;
    cacheDigits = d;
    cacheAppend = function append(strings) {
      let i = 1;
      this._ += strings[0];
      for (const j = strings.length; i < j; ++i) {
        this._ += Math.round(arguments[i] * k) / k + strings[i];
      }
    };
  }
  return cacheAppend;
}

;// ../../node_modules/d3-geo/src/path/index.js









/* harmony default export */ function src_path(projection, context) {
  let digits = 3,
      pointRadius = 4.5,
      projectionStream,
      contextStream;

  function path(object) {
    if (object) {
      if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
      src_stream(object, projectionStream(contextStream));
    }
    return contextStream.result();
  }

  path.area = function(object) {
    src_stream(object, projectionStream(path_area));
    return path_area.result();
  };

  path.measure = function(object) {
    src_stream(object, projectionStream(path_measure));
    return path_measure.result();
  };

  path.bounds = function(object) {
    src_stream(object, projectionStream(path_bounds));
    return path_bounds.result();
  };

  path.centroid = function(object) {
    src_stream(object, projectionStream(centroid));
    return centroid.result();
  };

  path.projection = function(_) {
    if (!arguments.length) return projection;
    projectionStream = _ == null ? (projection = null, d3_geo_src_identity) : (projection = _).stream;
    return path;
  };

  path.context = function(_) {
    if (!arguments.length) return context;
    contextStream = _ == null ? (context = null, new PathString(digits)) : new PathContext(context = _);
    if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
    return path;
  };

  path.pointRadius = function(_) {
    if (!arguments.length) return pointRadius;
    pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
    return path;
  };

  path.digits = function(_) {
    if (!arguments.length) return digits;
    if (_ == null) digits = null;
    else {
      const d = Math.floor(_);
      if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);
      digits = d;
    }
    if (context === null) contextStream = new PathString(digits);
    return path;
  };

  return path.projection(projection).digits(digits).context(context);
}

;// ../../node_modules/d3-geo/src/clip/buffer.js


/* harmony default export */ function clip_buffer() {
  var lines = [],
      line;
  return {
    point: function(x, y, m) {
      line.push([x, y, m]);
    },
    lineStart: function() {
      lines.push(line = []);
    },
    lineEnd: noop_noop,
    rejoin: function() {
      if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
    },
    result: function() {
      var result = lines;
      lines = [];
      line = null;
      return result;
    }
  };
}

;// ../../node_modules/d3-geo/src/pointEqual.js


/* harmony default export */ function pointEqual(a, b) {
  return src_math_abs(a[0] - b[0]) < src_math_epsilon && src_math_abs(a[1] - b[1]) < src_math_epsilon;
}

;// ../../node_modules/d3-geo/src/clip/rejoin.js



function Intersection(point, points, other, entry) {
  this.x = point;
  this.z = points;
  this.o = other; // another intersection
  this.e = entry; // is an entry?
  this.v = false; // visited
  this.n = this.p = null; // next & previous
}

// A generalized polygon clipping algorithm: given a polygon that has been cut
// into its visible line segments, and rejoins the segments by interpolating
// along the clip edge.
/* harmony default export */ function rejoin(segments, compareIntersection, startInside, interpolate, stream) {
  var subject = [],
      clip = [],
      i,
      n;

  segments.forEach(function(segment) {
    if ((n = segment.length - 1) <= 0) return;
    var n, p0 = segment[0], p1 = segment[n], x;

    if (pointEqual(p0, p1)) {
      if (!p0[2] && !p1[2]) {
        stream.lineStart();
        for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
        stream.lineEnd();
        return;
      }
      // handle degenerate cases by moving the point
      p1[0] += 2 * src_math_epsilon;
    }

    subject.push(x = new Intersection(p0, segment, null, true));
    clip.push(x.o = new Intersection(p0, null, x, false));
    subject.push(x = new Intersection(p1, segment, null, false));
    clip.push(x.o = new Intersection(p1, null, x, true));
  });

  if (!subject.length) return;

  clip.sort(compareIntersection);
  rejoin_link(subject);
  rejoin_link(clip);

  for (i = 0, n = clip.length; i < n; ++i) {
    clip[i].e = startInside = !startInside;
  }

  var start = subject[0],
      points,
      point;

  while (1) {
    // Find first unvisited intersection.
    var current = start,
        isSubject = true;
    while (current.v) if ((current = current.n) === start) return;
    points = current.z;
    stream.lineStart();
    do {
      current.v = current.o.v = true;
      if (current.e) {
        if (isSubject) {
          for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
        } else {
          interpolate(current.x, current.n.x, 1, stream);
        }
        current = current.n;
      } else {
        if (isSubject) {
          points = current.p.z;
          for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
        } else {
          interpolate(current.x, current.p.x, -1, stream);
        }
        current = current.p;
      }
      current = current.o;
      points = current.z;
      isSubject = !isSubject;
    } while (!current.v);
    stream.lineEnd();
  }
}

function rejoin_link(array) {
  if (!(n = array.length)) return;
  var n,
      i = 0,
      a = array[0],
      b;
  while (++i < n) {
    a.n = b = array[i];
    b.p = a;
    a = b;
  }
  a.n = b = array[0];
  b.p = a;
}

;// ../../node_modules/d3-geo/src/cartesian.js


function spherical(cartesian) {
  return [src_math_atan2(cartesian[1], cartesian[0]), src_math_asin(cartesian[2])];
}

function cartesian_cartesian(spherical) {
  var lambda = spherical[0], phi = spherical[1], cosPhi = src_math_cos(phi);
  return [cosPhi * src_math_cos(lambda), cosPhi * src_math_sin(lambda), src_math_sin(phi)];
}

function cartesianDot(a, b) {
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}

function cartesianCross(a, b) {
  return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
}

// TODO return a
function cartesianAddInPlace(a, b) {
  a[0] += b[0], a[1] += b[1], a[2] += b[2];
}

function cartesianScale(vector, k) {
  return [vector[0] * k, vector[1] * k, vector[2] * k];
}

// TODO return d
function cartesianNormalizeInPlace(d) {
  var l = src_math_sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
  d[0] /= l, d[1] /= l, d[2] /= l;
}

;// ../../node_modules/d3-geo/src/polygonContains.js




function longitude(point) {
  return src_math_abs(point[0]) <= math_pi ? point[0] : math_sign(point[0]) * ((src_math_abs(point[0]) + math_pi) % math_tau - math_pi);
}

/* harmony default export */ function polygonContains(polygon, point) {
  var lambda = longitude(point),
      phi = point[1],
      sinPhi = src_math_sin(phi),
      normal = [src_math_sin(lambda), -src_math_cos(lambda), 0],
      angle = 0,
      winding = 0;

  var sum = new Adder();

  if (sinPhi === 1) phi = math_halfPi + src_math_epsilon;
  else if (sinPhi === -1) phi = -math_halfPi - src_math_epsilon;

  for (var i = 0, n = polygon.length; i < n; ++i) {
    if (!(m = (ring = polygon[i]).length)) continue;
    var ring,
        m,
        point0 = ring[m - 1],
        lambda0 = longitude(point0),
        phi0 = point0[1] / 2 + quarterPi,
        sinPhi0 = src_math_sin(phi0),
        cosPhi0 = src_math_cos(phi0);

    for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
      var point1 = ring[j],
          lambda1 = longitude(point1),
          phi1 = point1[1] / 2 + quarterPi,
          sinPhi1 = src_math_sin(phi1),
          cosPhi1 = src_math_cos(phi1),
          delta = lambda1 - lambda0,
          sign = delta >= 0 ? 1 : -1,
          absDelta = sign * delta,
          antimeridian = absDelta > math_pi,
          k = sinPhi0 * sinPhi1;

      sum.add(src_math_atan2(k * sign * src_math_sin(absDelta), cosPhi0 * cosPhi1 + k * src_math_cos(absDelta)));
      angle += antimeridian ? delta + sign * math_tau : delta;

      // Are the longitudes either side of the point’s meridian (lambda),
      // and are the latitudes smaller than the parallel (phi)?
      if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
        var arc = cartesianCross(cartesian_cartesian(point0), cartesian_cartesian(point1));
        cartesianNormalizeInPlace(arc);
        var intersection = cartesianCross(normal, arc);
        cartesianNormalizeInPlace(intersection);
        var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * src_math_asin(intersection[2]);
        if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
          winding += antimeridian ^ delta >= 0 ? 1 : -1;
        }
      }
    }
  }

  // First, determine whether the South pole is inside or outside:
  //
  // It is inside if:
  // * the polygon winds around it in a clockwise direction.
  // * the polygon does not (cumulatively) wind around it, but has a negative
  //   (counter-clockwise) area.
  //
  // Second, count the (signed) number of times a segment crosses a lambda
  // from the point to the South pole.  If it is zero, then the point is the
  // same side as the South pole.

  return (angle < -src_math_epsilon || angle < src_math_epsilon && sum < -math_epsilon2) ^ (winding & 1);
}

;// ../../node_modules/d3-array/src/merge.js
function* merge_flatten(arrays) {
  for (const array of arrays) {
    yield* array;
  }
}

function merge_merge(arrays) {
  return Array.from(merge_flatten(arrays));
}

;// ../../node_modules/d3-geo/src/clip/index.js






/* harmony default export */ function src_clip(pointVisible, clipLine, interpolate, start) {
  return function(sink) {
    var line = clipLine(sink),
        ringBuffer = clip_buffer(),
        ringSink = clipLine(ringBuffer),
        polygonStarted = false,
        polygon,
        segments,
        ring;

    var clip = {
      point: point,
      lineStart: lineStart,
      lineEnd: lineEnd,
      polygonStart: function() {
        clip.point = pointRing;
        clip.lineStart = ringStart;
        clip.lineEnd = ringEnd;
        segments = [];
        polygon = [];
      },
      polygonEnd: function() {
        clip.point = point;
        clip.lineStart = lineStart;
        clip.lineEnd = lineEnd;
        segments = merge_merge(segments);
        var startInside = polygonContains(polygon, start);
        if (segments.length) {
          if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
          rejoin(segments, compareIntersection, startInside, interpolate, sink);
        } else if (startInside) {
          if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
          sink.lineStart();
          interpolate(null, null, 1, sink);
          sink.lineEnd();
        }
        if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
        segments = polygon = null;
      },
      sphere: function() {
        sink.polygonStart();
        sink.lineStart();
        interpolate(null, null, 1, sink);
        sink.lineEnd();
        sink.polygonEnd();
      }
    };

    function point(lambda, phi) {
      if (pointVisible(lambda, phi)) sink.point(lambda, phi);
    }

    function pointLine(lambda, phi) {
      line.point(lambda, phi);
    }

    function lineStart() {
      clip.point = pointLine;
      line.lineStart();
    }

    function lineEnd() {
      clip.point = point;
      line.lineEnd();
    }

    function pointRing(lambda, phi) {
      ring.push([lambda, phi]);
      ringSink.point(lambda, phi);
    }

    function ringStart() {
      ringSink.lineStart();
      ring = [];
    }

    function ringEnd() {
      pointRing(ring[0][0], ring[0][1]);
      ringSink.lineEnd();

      var clean = ringSink.clean(),
          ringSegments = ringBuffer.result(),
          i, n = ringSegments.length, m,
          segment,
          point;

      ring.pop();
      polygon.push(ring);
      ring = null;

      if (!n) return;

      // No intersections.
      if (clean & 1) {
        segment = ringSegments[0];
        if ((m = segment.length - 1) > 0) {
          if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
          sink.lineStart();
          for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
          sink.lineEnd();
        }
        return;
      }

      // Rejoin connected segments.
      // TODO reuse ringBuffer.rejoin()?
      if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));

      segments.push(ringSegments.filter(validSegment));
    }

    return clip;
  };
}

function validSegment(segment) {
  return segment.length > 1;
}

// Intersections are sorted along the clip edge. For both antimeridian cutting
// and circle clipping, the same comparison is used.
function compareIntersection(a, b) {
  return ((a = a.x)[0] < 0 ? a[1] - math_halfPi - src_math_epsilon : math_halfPi - a[1])
       - ((b = b.x)[0] < 0 ? b[1] - math_halfPi - src_math_epsilon : math_halfPi - b[1]);
}

;// ../../node_modules/d3-geo/src/clip/antimeridian.js



/* harmony default export */ const antimeridian = (src_clip(
  function() { return true; },
  clipAntimeridianLine,
  clipAntimeridianInterpolate,
  [-math_pi, -math_halfPi]
));

// Takes a line and cuts into visible segments. Return values: 0 - there were
// intersections or the line was empty; 1 - no intersections; 2 - there were
// intersections, and the first and last segments should be rejoined.
function clipAntimeridianLine(stream) {
  var lambda0 = NaN,
      phi0 = NaN,
      sign0 = NaN,
      clean; // no intersections

  return {
    lineStart: function() {
      stream.lineStart();
      clean = 1;
    },
    point: function(lambda1, phi1) {
      var sign1 = lambda1 > 0 ? math_pi : -math_pi,
          delta = src_math_abs(lambda1 - lambda0);
      if (src_math_abs(delta - math_pi) < src_math_epsilon) { // line crosses a pole
        stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? math_halfPi : -math_halfPi);
        stream.point(sign0, phi0);
        stream.lineEnd();
        stream.lineStart();
        stream.point(sign1, phi0);
        stream.point(lambda1, phi0);
        clean = 0;
      } else if (sign0 !== sign1 && delta >= math_pi) { // line crosses antimeridian
        if (src_math_abs(lambda0 - sign0) < src_math_epsilon) lambda0 -= sign0 * src_math_epsilon; // handle degeneracies
        if (src_math_abs(lambda1 - sign1) < src_math_epsilon) lambda1 -= sign1 * src_math_epsilon;
        phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
        stream.point(sign0, phi0);
        stream.lineEnd();
        stream.lineStart();
        stream.point(sign1, phi0);
        clean = 0;
      }
      stream.point(lambda0 = lambda1, phi0 = phi1);
      sign0 = sign1;
    },
    lineEnd: function() {
      stream.lineEnd();
      lambda0 = phi0 = NaN;
    },
    clean: function() {
      return 2 - clean; // if intersections, rejoin first and last segments
    }
  };
}

function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
  var cosPhi0,
      cosPhi1,
      sinLambda0Lambda1 = src_math_sin(lambda0 - lambda1);
  return src_math_abs(sinLambda0Lambda1) > src_math_epsilon
      ? math_atan((src_math_sin(phi0) * (cosPhi1 = src_math_cos(phi1)) * src_math_sin(lambda1)
          - src_math_sin(phi1) * (cosPhi0 = src_math_cos(phi0)) * src_math_sin(lambda0))
          / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
      : (phi0 + phi1) / 2;
}

function clipAntimeridianInterpolate(from, to, direction, stream) {
  var phi;
  if (from == null) {
    phi = direction * math_halfPi;
    stream.point(-math_pi, phi);
    stream.point(0, phi);
    stream.point(math_pi, phi);
    stream.point(math_pi, 0);
    stream.point(math_pi, -phi);
    stream.point(0, -phi);
    stream.point(-math_pi, -phi);
    stream.point(-math_pi, 0);
    stream.point(-math_pi, phi);
  } else if (src_math_abs(from[0] - to[0]) > src_math_epsilon) {
    var lambda = from[0] < to[0] ? math_pi : -math_pi;
    phi = direction * lambda / 2;
    stream.point(-lambda, phi);
    stream.point(0, phi);
    stream.point(lambda, phi);
  } else {
    stream.point(to[0], to[1]);
  }
}

;// ../../node_modules/d3-geo/src/circle.js





// Generates a circle centered at [0°, 0°], with a given radius and precision.
function circleStream(stream, radius, delta, direction, t0, t1) {
  if (!delta) return;
  var cosRadius = src_math_cos(radius),
      sinRadius = src_math_sin(radius),
      step = direction * delta;
  if (t0 == null) {
    t0 = radius + direction * math_tau;
    t1 = radius - step / 2;
  } else {
    t0 = circleRadius(cosRadius, t0);
    t1 = circleRadius(cosRadius, t1);
    if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * math_tau;
  }
  for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
    point = spherical([cosRadius, -sinRadius * src_math_cos(t), -sinRadius * src_math_sin(t)]);
    stream.point(point[0], point[1]);
  }
}

// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
function circleRadius(cosRadius, point) {
  point = cartesian_cartesian(point), point[0] -= cosRadius;
  cartesianNormalizeInPlace(point);
  var radius = src_math_acos(-point[1]);
  return ((-point[2] < 0 ? -radius : radius) + math_tau - src_math_epsilon) % math_tau;
}

/* harmony default export */ function src_circle() {
  var center = constant([0, 0]),
      radius = constant(90),
      precision = constant(2),
      ring,
      rotate,
      stream = {point: point};

  function point(x, y) {
    ring.push(x = rotate(x, y));
    x[0] *= degrees, x[1] *= degrees;
  }

  function circle() {
    var c = center.apply(this, arguments),
        r = radius.apply(this, arguments) * radians,
        p = precision.apply(this, arguments) * radians;
    ring = [];
    rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
    circleStream(stream, r, p, 1);
    c = {type: "Polygon", coordinates: [ring]};
    ring = rotate = null;
    return c;
  }

  circle.center = function(_) {
    return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center;
  };

  circle.radius = function(_) {
    return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius;
  };

  circle.precision = function(_) {
    return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision;
  };

  return circle;
}

;// ../../node_modules/d3-geo/src/clip/circle.js






/* harmony default export */ function clip_circle(radius) {
  var cr = src_math_cos(radius),
      delta = 2 * d3_geo_src_math_radians,
      smallRadius = cr > 0,
      notHemisphere = src_math_abs(cr) > src_math_epsilon; // TODO optimise for this common case

  function interpolate(from, to, direction, stream) {
    circleStream(stream, radius, delta, direction, from, to);
  }

  function visible(lambda, phi) {
    return src_math_cos(lambda) * src_math_cos(phi) > cr;
  }

  // Takes a line and cuts into visible segments. Return values used for polygon
  // clipping: 0 - there were intersections or the line was empty; 1 - no
  // intersections 2 - there were intersections, and the first and last segments
  // should be rejoined.
  function clipLine(stream) {
    var point0, // previous point
        c0, // code for previous point
        v0, // visibility of previous point
        v00, // visibility of first point
        clean; // no intersections
    return {
      lineStart: function() {
        v00 = v0 = false;
        clean = 1;
      },
      point: function(lambda, phi) {
        var point1 = [lambda, phi],
            point2,
            v = visible(lambda, phi),
            c = smallRadius
              ? v ? 0 : code(lambda, phi)
              : v ? code(lambda + (lambda < 0 ? math_pi : -math_pi), phi) : 0;
        if (!point0 && (v00 = v0 = v)) stream.lineStart();
        if (v !== v0) {
          point2 = intersect(point0, point1);
          if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2))
            point1[2] = 1;
        }
        if (v !== v0) {
          clean = 0;
          if (v) {
            // outside going in
            stream.lineStart();
            point2 = intersect(point1, point0);
            stream.point(point2[0], point2[1]);
          } else {
            // inside going out
            point2 = intersect(point0, point1);
            stream.point(point2[0], point2[1], 2);
            stream.lineEnd();
          }
          point0 = point2;
        } else if (notHemisphere && point0 && smallRadius ^ v) {
          var t;
          // If the codes for two points are different, or are both zero,
          // and there this segment intersects with the small circle.
          if (!(c & c0) && (t = intersect(point1, point0, true))) {
            clean = 0;
            if (smallRadius) {
              stream.lineStart();
              stream.point(t[0][0], t[0][1]);
              stream.point(t[1][0], t[1][1]);
              stream.lineEnd();
            } else {
              stream.point(t[1][0], t[1][1]);
              stream.lineEnd();
              stream.lineStart();
              stream.point(t[0][0], t[0][1], 3);
            }
          }
        }
        if (v && (!point0 || !pointEqual(point0, point1))) {
          stream.point(point1[0], point1[1]);
        }
        point0 = point1, v0 = v, c0 = c;
      },
      lineEnd: function() {
        if (v0) stream.lineEnd();
        point0 = null;
      },
      // Rejoin first and last segments if there were intersections and the first
      // and last points were visible.
      clean: function() {
        return clean | ((v00 && v0) << 1);
      }
    };
  }

  // Intersects the great circle between a and b with the clip circle.
  function intersect(a, b, two) {
    var pa = cartesian_cartesian(a),
        pb = cartesian_cartesian(b);

    // We have two planes, n1.p = d1 and n2.p = d2.
    // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
    var n1 = [1, 0, 0], // normal
        n2 = cartesianCross(pa, pb),
        n2n2 = cartesianDot(n2, n2),
        n1n2 = n2[0], // cartesianDot(n1, n2),
        determinant = n2n2 - n1n2 * n1n2;

    // Two polar points.
    if (!determinant) return !two && a;

    var c1 =  cr * n2n2 / determinant,
        c2 = -cr * n1n2 / determinant,
        n1xn2 = cartesianCross(n1, n2),
        A = cartesianScale(n1, c1),
        B = cartesianScale(n2, c2);
    cartesianAddInPlace(A, B);

    // Solve |p(t)|^2 = 1.
    var u = n1xn2,
        w = cartesianDot(A, u),
        uu = cartesianDot(u, u),
        t2 = w * w - uu * (cartesianDot(A, A) - 1);

    if (t2 < 0) return;

    var t = src_math_sqrt(t2),
        q = cartesianScale(u, (-w - t) / uu);
    cartesianAddInPlace(q, A);
    q = spherical(q);

    if (!two) return q;

    // Two intersection points.
    var lambda0 = a[0],
        lambda1 = b[0],
        phi0 = a[1],
        phi1 = b[1],
        z;

    if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;

    var delta = lambda1 - lambda0,
        polar = src_math_abs(delta - math_pi) < src_math_epsilon,
        meridian = polar || delta < src_math_epsilon;

    if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;

    // Check that the first point is between a and b.
    if (meridian
        ? polar
          ? phi0 + phi1 > 0 ^ q[1] < (src_math_abs(q[0] - lambda0) < src_math_epsilon ? phi0 : phi1)
          : phi0 <= q[1] && q[1] <= phi1
        : delta > math_pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
      var q1 = cartesianScale(u, (-w + t) / uu);
      cartesianAddInPlace(q1, A);
      return [q, spherical(q1)];
    }
  }

  // Generates a 4-bit vector representing the location of a point relative to
  // the small circle's bounding box.
  function code(lambda, phi) {
    var r = smallRadius ? radius : math_pi - radius,
        code = 0;
    if (lambda < -r) code |= 1; // left
    else if (lambda > r) code |= 2; // right
    if (phi < -r) code |= 4; // below
    else if (phi > r) code |= 8; // above
    return code;
  }

  return src_clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-math_pi, radius - math_pi]);
}

;// ../../node_modules/d3-geo/src/clip/line.js
/* harmony default export */ function clip_line(a, b, x0, y0, x1, y1) {
  var ax = a[0],
      ay = a[1],
      bx = b[0],
      by = b[1],
      t0 = 0,
      t1 = 1,
      dx = bx - ax,
      dy = by - ay,
      r;

  r = x0 - ax;
  if (!dx && r > 0) return;
  r /= dx;
  if (dx < 0) {
    if (r < t0) return;
    if (r < t1) t1 = r;
  } else if (dx > 0) {
    if (r > t1) return;
    if (r > t0) t0 = r;
  }

  r = x1 - ax;
  if (!dx && r < 0) return;
  r /= dx;
  if (dx < 0) {
    if (r > t1) return;
    if (r > t0) t0 = r;
  } else if (dx > 0) {
    if (r < t0) return;
    if (r < t1) t1 = r;
  }

  r = y0 - ay;
  if (!dy && r > 0) return;
  r /= dy;
  if (dy < 0) {
    if (r < t0) return;
    if (r < t1) t1 = r;
  } else if (dy > 0) {
    if (r > t1) return;
    if (r > t0) t0 = r;
  }

  r = y1 - ay;
  if (!dy && r < 0) return;
  r /= dy;
  if (dy < 0) {
    if (r > t1) return;
    if (r > t0) t0 = r;
  } else if (dy > 0) {
    if (r < t0) return;
    if (r < t1) t1 = r;
  }

  if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
  if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
  return true;
}

;// ../../node_modules/d3-geo/src/clip/rectangle.js






var clipMax = 1e9, clipMin = -clipMax;

// TODO Use d3-polygon’s polygonContains here for the ring check?
// TODO Eliminate duplicate buffering in clipBuffer and polygon.push?

function clipRectangle(x0, y0, x1, y1) {

  function visible(x, y) {
    return x0 <= x && x <= x1 && y0 <= y && y <= y1;
  }

  function interpolate(from, to, direction, stream) {
    var a = 0, a1 = 0;
    if (from == null
        || (a = corner(from, direction)) !== (a1 = corner(to, direction))
        || comparePoint(from, to) < 0 ^ direction > 0) {
      do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
      while ((a = (a + direction + 4) % 4) !== a1);
    } else {
      stream.point(to[0], to[1]);
    }
  }

  function corner(p, direction) {
    return src_math_abs(p[0] - x0) < src_math_epsilon ? direction > 0 ? 0 : 3
        : src_math_abs(p[0] - x1) < src_math_epsilon ? direction > 0 ? 2 : 1
        : src_math_abs(p[1] - y0) < src_math_epsilon ? direction > 0 ? 1 : 0
        : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
  }

  function compareIntersection(a, b) {
    return comparePoint(a.x, b.x);
  }

  function comparePoint(a, b) {
    var ca = corner(a, 1),
        cb = corner(b, 1);
    return ca !== cb ? ca - cb
        : ca === 0 ? b[1] - a[1]
        : ca === 1 ? a[0] - b[0]
        : ca === 2 ? a[1] - b[1]
        : b[0] - a[0];
  }

  return function(stream) {
    var activeStream = stream,
        bufferStream = clip_buffer(),
        segments,
        polygon,
        ring,
        x__, y__, v__, // first point
        x_, y_, v_, // previous point
        first,
        clean;

    var clipStream = {
      point: point,
      lineStart: lineStart,
      lineEnd: lineEnd,
      polygonStart: polygonStart,
      polygonEnd: polygonEnd
    };

    function point(x, y) {
      if (visible(x, y)) activeStream.point(x, y);
    }

    function polygonInside() {
      var winding = 0;

      for (var i = 0, n = polygon.length; i < n; ++i) {
        for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
          a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
          if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
          else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
        }
      }

      return winding;
    }

    // Buffer geometry within a polygon and then clip it en masse.
    function polygonStart() {
      activeStream = bufferStream, segments = [], polygon = [], clean = true;
    }

    function polygonEnd() {
      var startInside = polygonInside(),
          cleanInside = clean && startInside,
          visible = (segments = merge_merge(segments)).length;
      if (cleanInside || visible) {
        stream.polygonStart();
        if (cleanInside) {
          stream.lineStart();
          interpolate(null, null, 1, stream);
          stream.lineEnd();
        }
        if (visible) {
          rejoin(segments, compareIntersection, startInside, interpolate, stream);
        }
        stream.polygonEnd();
      }
      activeStream = stream, segments = polygon = ring = null;
    }

    function lineStart() {
      clipStream.point = linePoint;
      if (polygon) polygon.push(ring = []);
      first = true;
      v_ = false;
      x_ = y_ = NaN;
    }

    // TODO rather than special-case polygons, simply handle them separately.
    // Ideally, coincident intersection points should be jittered to avoid
    // clipping issues.
    function lineEnd() {
      if (segments) {
        linePoint(x__, y__);
        if (v__ && v_) bufferStream.rejoin();
        segments.push(bufferStream.result());
      }
      clipStream.point = point;
      if (v_) activeStream.lineEnd();
    }

    function linePoint(x, y) {
      var v = visible(x, y);
      if (polygon) ring.push([x, y]);
      if (first) {
        x__ = x, y__ = y, v__ = v;
        first = false;
        if (v) {
          activeStream.lineStart();
          activeStream.point(x, y);
        }
      } else {
        if (v && v_) activeStream.point(x, y);
        else {
          var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
              b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
          if (clip_line(a, b, x0, y0, x1, y1)) {
            if (!v_) {
              activeStream.lineStart();
              activeStream.point(a[0], a[1]);
            }
            activeStream.point(b[0], b[1]);
            if (!v) activeStream.lineEnd();
            clean = false;
          } else if (v) {
            activeStream.lineStart();
            activeStream.point(x, y);
            clean = false;
          }
        }
      }
      x_ = x, y_ = y, v_ = v;
    }

    return clipStream;
  };
}

;// ../../node_modules/d3-geo/src/compose.js
/* harmony default export */ function compose(a, b) {

  function compose(x, y) {
    return x = a(x, y), b(x[0], x[1]);
  }

  if (a.invert && b.invert) compose.invert = function(x, y) {
    return x = b.invert(x, y), x && a.invert(x[0], x[1]);
  };

  return compose;
}

;// ../../node_modules/d3-geo/src/rotation.js



function rotationIdentity(lambda, phi) {
  if (src_math_abs(lambda) > math_pi) lambda -= Math.round(lambda / math_tau) * math_tau;
  return [lambda, phi];
}

rotationIdentity.invert = rotationIdentity;

function rotation_rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
  return (deltaLambda %= math_tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
    : rotationLambda(deltaLambda))
    : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
    : rotationIdentity);
}

function forwardRotationLambda(deltaLambda) {
  return function(lambda, phi) {
    lambda += deltaLambda;
    if (src_math_abs(lambda) > math_pi) lambda -= Math.round(lambda / math_tau) * math_tau;
    return [lambda, phi];
  };
}

function rotationLambda(deltaLambda) {
  var rotation = forwardRotationLambda(deltaLambda);
  rotation.invert = forwardRotationLambda(-deltaLambda);
  return rotation;
}

function rotationPhiGamma(deltaPhi, deltaGamma) {
  var cosDeltaPhi = src_math_cos(deltaPhi),
      sinDeltaPhi = src_math_sin(deltaPhi),
      cosDeltaGamma = src_math_cos(deltaGamma),
      sinDeltaGamma = src_math_sin(deltaGamma);

  function rotation(lambda, phi) {
    var cosPhi = src_math_cos(phi),
        x = src_math_cos(lambda) * cosPhi,
        y = src_math_sin(lambda) * cosPhi,
        z = src_math_sin(phi),
        k = z * cosDeltaPhi + x * sinDeltaPhi;
    return [
      src_math_atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
      src_math_asin(k * cosDeltaGamma + y * sinDeltaGamma)
    ];
  }

  rotation.invert = function(lambda, phi) {
    var cosPhi = src_math_cos(phi),
        x = src_math_cos(lambda) * cosPhi,
        y = src_math_sin(lambda) * cosPhi,
        z = src_math_sin(phi),
        k = z * cosDeltaGamma - y * sinDeltaGamma;
    return [
      src_math_atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
      src_math_asin(k * cosDeltaPhi - x * sinDeltaPhi)
    ];
  };

  return rotation;
}

/* harmony default export */ function rotation(rotate) {
  rotate = rotation_rotateRadians(rotate[0] * d3_geo_src_math_radians, rotate[1] * d3_geo_src_math_radians, rotate.length > 2 ? rotate[2] * d3_geo_src_math_radians : 0);

  function forward(coordinates) {
    coordinates = rotate(coordinates[0] * d3_geo_src_math_radians, coordinates[1] * d3_geo_src_math_radians);
    return coordinates[0] *= d3_geo_src_math_degrees, coordinates[1] *= d3_geo_src_math_degrees, coordinates;
  }

  forward.invert = function(coordinates) {
    coordinates = rotate.invert(coordinates[0] * d3_geo_src_math_radians, coordinates[1] * d3_geo_src_math_radians);
    return coordinates[0] *= d3_geo_src_math_degrees, coordinates[1] *= d3_geo_src_math_degrees, coordinates;
  };

  return forward;
}

;// ../../node_modules/d3-geo/src/transform.js
/* harmony default export */ function src_transform(methods) {
  return {
    stream: transform_transformer(methods)
  };
}

function transform_transformer(methods) {
  return function(stream) {
    var s = new TransformStream;
    for (var key in methods) s[key] = methods[key];
    s.stream = stream;
    return s;
  };
}

function TransformStream() {}

TransformStream.prototype = {
  constructor: TransformStream,
  point: function(x, y) { this.stream.point(x, y); },
  sphere: function() { this.stream.sphere(); },
  lineStart: function() { this.stream.lineStart(); },
  lineEnd: function() { this.stream.lineEnd(); },
  polygonStart: function() { this.stream.polygonStart(); },
  polygonEnd: function() { this.stream.polygonEnd(); }
};

;// ../../node_modules/d3-geo/src/projection/fit.js



function fit(projection, fitBounds, object) {
  var clip = projection.clipExtent && projection.clipExtent();
  projection.scale(150).translate([0, 0]);
  if (clip != null) projection.clipExtent(null);
  src_stream(object, projection.stream(path_bounds));
  fitBounds(path_bounds.result());
  if (clip != null) projection.clipExtent(clip);
  return projection;
}

function fitExtent(projection, extent, object) {
  return fit(projection, function(b) {
    var w = extent[1][0] - extent[0][0],
        h = extent[1][1] - extent[0][1],
        k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
        x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
        y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
    projection.scale(150 * k).translate([x, y]);
  }, object);
}

function fitSize(projection, size, object) {
  return fitExtent(projection, [[0, 0], size], object);
}

function fitWidth(projection, width, object) {
  return fit(projection, function(b) {
    var w = +width,
        k = w / (b[1][0] - b[0][0]),
        x = (w - k * (b[1][0] + b[0][0])) / 2,
        y = -k * b[0][1];
    projection.scale(150 * k).translate([x, y]);
  }, object);
}

function fitHeight(projection, height, object) {
  return fit(projection, function(b) {
    var h = +height,
        k = h / (b[1][1] - b[0][1]),
        x = -k * b[0][0],
        y = (h - k * (b[1][1] + b[0][1])) / 2;
    projection.scale(150 * k).translate([x, y]);
  }, object);
}

;// ../../node_modules/d3-geo/src/projection/resample.js




var maxDepth = 16, // maximum depth of subdivision
    cosMinDistance = src_math_cos(30 * d3_geo_src_math_radians); // cos(minimum angular distance)

/* harmony default export */ function resample(project, delta2) {
  return +delta2 ? resample_resample(project, delta2) : resampleNone(project);
}

function resampleNone(project) {
  return transform_transformer({
    point: function(x, y) {
      x = project(x, y);
      this.stream.point(x[0], x[1]);
    }
  });
}

function resample_resample(project, delta2) {

  function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
    var dx = x1 - x0,
        dy = y1 - y0,
        d2 = dx * dx + dy * dy;
    if (d2 > 4 * delta2 && depth--) {
      var a = a0 + a1,
          b = b0 + b1,
          c = c0 + c1,
          m = src_math_sqrt(a * a + b * b + c * c),
          phi2 = src_math_asin(c /= m),
          lambda2 = src_math_abs(src_math_abs(c) - 1) < src_math_epsilon || src_math_abs(lambda0 - lambda1) < src_math_epsilon ? (lambda0 + lambda1) / 2 : src_math_atan2(b, a),
          p = project(lambda2, phi2),
          x2 = p[0],
          y2 = p[1],
          dx2 = x2 - x0,
          dy2 = y2 - y0,
          dz = dy * dx2 - dx * dy2;
      if (dz * dz / d2 > delta2 // perpendicular projected distance
          || src_math_abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
          || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
        resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
        stream.point(x2, y2);
        resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
      }
    }
  }
  return function(stream) {
    var lambda00, x00, y00, a00, b00, c00, // first point
        lambda0, x0, y0, a0, b0, c0; // previous point

    var resampleStream = {
      point: point,
      lineStart: lineStart,
      lineEnd: lineEnd,
      polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
      polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
    };

    function point(x, y) {
      x = project(x, y);
      stream.point(x[0], x[1]);
    }

    function lineStart() {
      x0 = NaN;
      resampleStream.point = linePoint;
      stream.lineStart();
    }

    function linePoint(lambda, phi) {
      var c = cartesian_cartesian([lambda, phi]), p = project(lambda, phi);
      resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
      stream.point(x0, y0);
    }

    function lineEnd() {
      resampleStream.point = point;
      stream.lineEnd();
    }

    function ringStart() {
      lineStart();
      resampleStream.point = ringPoint;
      resampleStream.lineEnd = ringEnd;
    }

    function ringPoint(lambda, phi) {
      linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
      resampleStream.point = linePoint;
    }

    function ringEnd() {
      resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
      resampleStream.lineEnd = lineEnd;
      lineEnd();
    }

    return resampleStream;
  };
}

;// ../../node_modules/d3-geo/src/projection/index.js











var transformRadians = transform_transformer({
  point: function(x, y) {
    this.stream.point(x * d3_geo_src_math_radians, y * d3_geo_src_math_radians);
  }
});

function transformRotate(rotate) {
  return transform_transformer({
    point: function(x, y) {
      var r = rotate(x, y);
      return this.stream.point(r[0], r[1]);
    }
  });
}

function scaleTranslate(k, dx, dy, sx, sy) {
  function transform(x, y) {
    x *= sx; y *= sy;
    return [dx + k * x, dy - k * y];
  }
  transform.invert = function(x, y) {
    return [(x - dx) / k * sx, (dy - y) / k * sy];
  };
  return transform;
}

function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) {
  if (!alpha) return scaleTranslate(k, dx, dy, sx, sy);
  var cosAlpha = src_math_cos(alpha),
      sinAlpha = src_math_sin(alpha),
      a = cosAlpha * k,
      b = sinAlpha * k,
      ai = cosAlpha / k,
      bi = sinAlpha / k,
      ci = (sinAlpha * dy - cosAlpha * dx) / k,
      fi = (sinAlpha * dx + cosAlpha * dy) / k;
  function transform(x, y) {
    x *= sx; y *= sy;
    return [a * x - b * y + dx, dy - b * x - a * y];
  }
  transform.invert = function(x, y) {
    return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)];
  };
  return transform;
}

function projection(project) {
  return projectionMutator(function() { return project; })();
}

function projectionMutator(projectAt) {
  var project,
      k = 150, // scale
      x = 480, y = 250, // translate
      lambda = 0, phi = 0, // center
      deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, // pre-rotate
      alpha = 0, // post-rotate angle
      sx = 1, // reflectX
      sy = 1, // reflectX
      theta = null, preclip = antimeridian, // pre-clip angle
      x0 = null, y0, x1, y1, postclip = d3_geo_src_identity, // post-clip extent
      delta2 = 0.5, // precision
      projectResample,
      projectTransform,
      projectRotateTransform,
      cache,
      cacheStream;

  function projection(point) {
    return projectRotateTransform(point[0] * d3_geo_src_math_radians, point[1] * d3_geo_src_math_radians);
  }

  function invert(point) {
    point = projectRotateTransform.invert(point[0], point[1]);
    return point && [point[0] * d3_geo_src_math_degrees, point[1] * d3_geo_src_math_degrees];
  }

  projection.stream = function(stream) {
    return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));
  };

  projection.preclip = function(_) {
    return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip;
  };

  projection.postclip = function(_) {
    return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
  };

  projection.clipAngle = function(_) {
    return arguments.length ? (preclip = +_ ? clip_circle(theta = _ * d3_geo_src_math_radians) : (theta = null, antimeridian), reset()) : theta * d3_geo_src_math_degrees;
  };

  projection.clipExtent = function(_) {
    return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, d3_geo_src_identity) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  };

  projection.scale = function(_) {
    return arguments.length ? (k = +_, recenter()) : k;
  };

  projection.translate = function(_) {
    return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
  };

  projection.center = function(_) {
    return arguments.length ? (lambda = _[0] % 360 * d3_geo_src_math_radians, phi = _[1] % 360 * d3_geo_src_math_radians, recenter()) : [lambda * d3_geo_src_math_degrees, phi * d3_geo_src_math_degrees];
  };

  projection.rotate = function(_) {
    return arguments.length ? (deltaLambda = _[0] % 360 * d3_geo_src_math_radians, deltaPhi = _[1] % 360 * d3_geo_src_math_radians, deltaGamma = _.length > 2 ? _[2] % 360 * d3_geo_src_math_radians : 0, recenter()) : [deltaLambda * d3_geo_src_math_degrees, deltaPhi * d3_geo_src_math_degrees, deltaGamma * d3_geo_src_math_degrees];
  };

  projection.angle = function(_) {
    return arguments.length ? (alpha = _ % 360 * d3_geo_src_math_radians, recenter()) : alpha * d3_geo_src_math_degrees;
  };

  projection.reflectX = function(_) {
    return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;
  };

  projection.reflectY = function(_) {
    return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;
  };

  projection.precision = function(_) {
    return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : src_math_sqrt(delta2);
  };

  projection.fitExtent = function(extent, object) {
    return fitExtent(projection, extent, object);
  };

  projection.fitSize = function(size, object) {
    return fitSize(projection, size, object);
  };

  projection.fitWidth = function(width, object) {
    return fitWidth(projection, width, object);
  };

  projection.fitHeight = function(height, object) {
    return fitHeight(projection, height, object);
  };

  function recenter() {
    var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)),
        transform = scaleTranslateRotate(k, x - center[0], y - center[1], sx, sy, alpha);
    rotate = rotation_rotateRadians(deltaLambda, deltaPhi, deltaGamma);
    projectTransform = compose(project, transform);
    projectRotateTransform = compose(rotate, projectTransform);
    projectResample = resample(projectTransform, delta2);
    return reset();
  }

  function reset() {
    cache = cacheStream = null;
    return projection;
  }

  return function() {
    project = projectAt.apply(this, arguments);
    projection.invert = project.invert && invert;
    return recenter();
  };
}

;// ../../node_modules/d3-geo/src/projection/conic.js



function conicProjection(projectAt) {
  var phi0 = 0,
      phi1 = math_pi / 3,
      m = projectionMutator(projectAt),
      p = m(phi0, phi1);

  p.parallels = function(_) {
    return arguments.length ? m(phi0 = _[0] * d3_geo_src_math_radians, phi1 = _[1] * d3_geo_src_math_radians) : [phi0 * d3_geo_src_math_degrees, phi1 * d3_geo_src_math_degrees];
  };

  return p;
}

;// ../../node_modules/d3-geo/src/projection/cylindricalEqualArea.js


function cylindricalEqualAreaRaw(phi0) {
  var cosPhi0 = src_math_cos(phi0);

  function forward(lambda, phi) {
    return [lambda * cosPhi0, src_math_sin(phi) / cosPhi0];
  }

  forward.invert = function(x, y) {
    return [x / cosPhi0, src_math_asin(y * cosPhi0)];
  };

  return forward;
}

;// ../../node_modules/d3-geo/src/projection/conicEqualArea.js




function conicEqualAreaRaw(y0, y1) {
  var sy0 = src_math_sin(y0), n = (sy0 + src_math_sin(y1)) / 2;

  // Are the parallels symmetrical around the Equator?
  if (src_math_abs(n) < src_math_epsilon) return cylindricalEqualAreaRaw(y0);

  var c = 1 + sy0 * (2 * n - sy0), r0 = src_math_sqrt(c) / n;

  function project(x, y) {
    var r = src_math_sqrt(c - 2 * n * src_math_sin(y)) / n;
    return [r * src_math_sin(x *= n), r0 - r * src_math_cos(x)];
  }

  project.invert = function(x, y) {
    var r0y = r0 - y,
        l = src_math_atan2(x, src_math_abs(r0y)) * math_sign(r0y);
    if (r0y * n < 0)
      l -= math_pi * math_sign(x) * math_sign(r0y);
    return [l / n, src_math_asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
  };

  return project;
}

/* harmony default export */ function conicEqualArea() {
  return conicProjection(conicEqualAreaRaw)
      .scale(155.424)
      .center([0, 33.6442]);
}

;// ../../node_modules/d3-geo/src/projection/albers.js


/* harmony default export */ function albers() {
  return conicEqualArea()
      .parallels([29.5, 45.5])
      .scale(1070)
      .translate([480, 250])
      .rotate([96, 0])
      .center([-0.6, 38.7]);
}

;// ../../node_modules/d3-geo/src/projection/albersUsa.js





// The projections must have mutually exclusive clip regions on the sphere,
// as this will avoid emitting interleaving lines and polygons.
function multiplex(streams) {
  var n = streams.length;
  return {
    point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
    sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
    lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
    lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
    polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
    polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
  };
}

// A composite projection for the United States, configured by default for
// 960×500. The projection also works quite well at 960×600 if you change the
// scale to 1285 and adjust the translate accordingly. The set of standard
// parallels for each region comes from USGS, which is published here:
// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
/* harmony default export */ function albersUsa() {
  var cache,
      cacheStream,
      lower48 = albers(), lower48Point,
      alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
      hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
      point, pointStream = {point: function(x, y) { point = [x, y]; }};

  function albersUsa(coordinates) {
    var x = coordinates[0], y = coordinates[1];
    return point = null,
        (lower48Point.point(x, y), point)
        || (alaskaPoint.point(x, y), point)
        || (hawaiiPoint.point(x, y), point);
  }

  albersUsa.invert = function(coordinates) {
    var k = lower48.scale(),
        t = lower48.translate(),
        x = (coordinates[0] - t[0]) / k,
        y = (coordinates[1] - t[1]) / k;
    return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
        : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
        : lower48).invert(coordinates);
  };

  albersUsa.stream = function(stream) {
    return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
  };

  albersUsa.precision = function(_) {
    if (!arguments.length) return lower48.precision();
    lower48.precision(_), alaska.precision(_), hawaii.precision(_);
    return reset();
  };

  albersUsa.scale = function(_) {
    if (!arguments.length) return lower48.scale();
    lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
    return albersUsa.translate(lower48.translate());
  };

  albersUsa.translate = function(_) {
    if (!arguments.length) return lower48.translate();
    var k = lower48.scale(), x = +_[0], y = +_[1];

    lower48Point = lower48
        .translate(_)
        .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
        .stream(pointStream);

    alaskaPoint = alaska
        .translate([x - 0.307 * k, y + 0.201 * k])
        .clipExtent([[x - 0.425 * k + src_math_epsilon, y + 0.120 * k + src_math_epsilon], [x - 0.214 * k - src_math_epsilon, y + 0.234 * k - src_math_epsilon]])
        .stream(pointStream);

    hawaiiPoint = hawaii
        .translate([x - 0.205 * k, y + 0.212 * k])
        .clipExtent([[x - 0.214 * k + src_math_epsilon, y + 0.166 * k + src_math_epsilon], [x - 0.115 * k - src_math_epsilon, y + 0.234 * k - src_math_epsilon]])
        .stream(pointStream);

    return reset();
  };

  albersUsa.fitExtent = function(extent, object) {
    return fitExtent(albersUsa, extent, object);
  };

  albersUsa.fitSize = function(size, object) {
    return fitSize(albersUsa, size, object);
  };

  albersUsa.fitWidth = function(width, object) {
    return fitWidth(albersUsa, width, object);
  };

  albersUsa.fitHeight = function(height, object) {
    return fitHeight(albersUsa, height, object);
  };

  function reset() {
    cache = cacheStream = null;
    return albersUsa;
  }

  return albersUsa.scale(1070);
}

;// ../../node_modules/d3-geo/src/projection/azimuthal.js


function azimuthalRaw(scale) {
  return function(x, y) {
    var cx = src_math_cos(x),
        cy = src_math_cos(y),
        k = scale(cx * cy);
        if (k === Infinity) return [2, 0];
    return [
      k * cy * src_math_sin(x),
      k * src_math_sin(y)
    ];
  }
}

function azimuthalInvert(angle) {
  return function(x, y) {
    var z = src_math_sqrt(x * x + y * y),
        c = angle(z),
        sc = src_math_sin(c),
        cc = src_math_cos(c);
    return [
      src_math_atan2(x * sc, z * cc),
      src_math_asin(z && y * sc / z)
    ];
  }
}

;// ../../node_modules/d3-geo/src/projection/azimuthalEqualArea.js




var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
  return src_math_sqrt(2 / (1 + cxcy));
});

azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
  return 2 * src_math_asin(z / 2);
});

/* harmony default export */ function azimuthalEqualArea() {
  return projection(azimuthalEqualAreaRaw)
      .scale(124.75)
      .clipAngle(180 - 1e-3);
}

;// ../../node_modules/d3-geo/src/projection/azimuthalEquidistant.js




var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
  return (c = src_math_acos(c)) && c / src_math_sin(c);
});

azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
  return z;
});

/* harmony default export */ function azimuthalEquidistant() {
  return projection(azimuthalEquidistantRaw)
      .scale(79.4188)
      .clipAngle(180 - 1e-3);
}

;// ../../node_modules/d3-geo/src/projection/mercator.js




function mercatorRaw(lambda, phi) {
  return [lambda, math_log(math_tan((math_halfPi + phi) / 2))];
}

mercatorRaw.invert = function(x, y) {
  return [x, 2 * math_atan(math_exp(y)) - math_halfPi];
};

/* harmony default export */ function mercator() {
  return mercatorProjection(mercatorRaw)
      .scale(961 / math_tau);
}

function mercatorProjection(project) {
  var m = projection(project),
      center = m.center,
      scale = m.scale,
      translate = m.translate,
      clipExtent = m.clipExtent,
      x0 = null, y0, x1, y1; // clip extent

  m.scale = function(_) {
    return arguments.length ? (scale(_), reclip()) : scale();
  };

  m.translate = function(_) {
    return arguments.length ? (translate(_), reclip()) : translate();
  };

  m.center = function(_) {
    return arguments.length ? (center(_), reclip()) : center();
  };

  m.clipExtent = function(_) {
    return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  };

  function reclip() {
    var k = math_pi * scale(),
        t = m(rotation(m.rotate()).invert([0, 0]));
    return clipExtent(x0 == null
        ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
        ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
        : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
  }

  return reclip();
}

;// ../../node_modules/d3-geo/src/projection/conicConformal.js




function tany(y) {
  return math_tan((math_halfPi + y) / 2);
}

function conicConformalRaw(y0, y1) {
  var cy0 = src_math_cos(y0),
      n = y0 === y1 ? src_math_sin(y0) : math_log(cy0 / src_math_cos(y1)) / math_log(tany(y1) / tany(y0)),
      f = cy0 * math_pow(tany(y0), n) / n;

  if (!n) return mercatorRaw;

  function project(x, y) {
    if (f > 0) { if (y < -math_halfPi + src_math_epsilon) y = -math_halfPi + src_math_epsilon; }
    else { if (y > math_halfPi - src_math_epsilon) y = math_halfPi - src_math_epsilon; }
    var r = f / math_pow(tany(y), n);
    return [r * src_math_sin(n * x), f - r * src_math_cos(n * x)];
  }

  project.invert = function(x, y) {
    var fy = f - y, r = math_sign(n) * src_math_sqrt(x * x + fy * fy),
      l = src_math_atan2(x, src_math_abs(fy)) * math_sign(fy);
    if (fy * n < 0)
      l -= math_pi * math_sign(x) * math_sign(fy);
    return [l / n, 2 * math_atan(math_pow(f / r, 1 / n)) - math_halfPi];
  };

  return project;
}

/* harmony default export */ function conicConformal() {
  return conicProjection(conicConformalRaw)
      .scale(109.5)
      .parallels([30, 30]);
}

;// ../../node_modules/d3-geo/src/projection/equirectangular.js


function equirectangularRaw(lambda, phi) {
  return [lambda, phi];
}

equirectangularRaw.invert = equirectangularRaw;

/* harmony default export */ function equirectangular() {
  return projection(equirectangularRaw)
      .scale(152.63);
}

;// ../../node_modules/d3-geo/src/projection/conicEquidistant.js




function conicEquidistantRaw(y0, y1) {
  var cy0 = src_math_cos(y0),
      n = y0 === y1 ? src_math_sin(y0) : (cy0 - src_math_cos(y1)) / (y1 - y0),
      g = cy0 / n + y0;

  if (src_math_abs(n) < src_math_epsilon) return equirectangularRaw;

  function project(x, y) {
    var gy = g - y, nx = n * x;
    return [gy * src_math_sin(nx), g - gy * src_math_cos(nx)];
  }

  project.invert = function(x, y) {
    var gy = g - y,
        l = src_math_atan2(x, src_math_abs(gy)) * math_sign(gy);
    if (gy * n < 0)
      l -= math_pi * math_sign(x) * math_sign(gy);
    return [l / n, g - math_sign(n) * src_math_sqrt(x * x + gy * gy)];
  };

  return project;
}

/* harmony default export */ function conicEquidistant() {
  return conicProjection(conicEquidistantRaw)
      .scale(131.154)
      .center([0, 13.9389]);
}

;// ../../node_modules/d3-geo/src/projection/equalEarth.js



var A1 = 1.340264,
    A2 = -0.081106,
    A3 = 0.000893,
    A4 = 0.003796,
    M = src_math_sqrt(3) / 2,
    iterations = 12;

function equalEarthRaw(lambda, phi) {
  var l = src_math_asin(M * src_math_sin(phi)), l2 = l * l, l6 = l2 * l2 * l2;
  return [
    lambda * src_math_cos(l) / (M * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2))),
    l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2))
  ];
}

equalEarthRaw.invert = function(x, y) {
  var l = y, l2 = l * l, l6 = l2 * l2 * l2;
  for (var i = 0, delta, fy, fpy; i < iterations; ++i) {
    fy = l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) - y;
    fpy = A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2);
    l -= delta = fy / fpy, l2 = l * l, l6 = l2 * l2 * l2;
    if (src_math_abs(delta) < math_epsilon2) break;
  }
  return [
    M * x * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2)) / src_math_cos(l),
    src_math_asin(src_math_sin(l) / M)
  ];
};

/* harmony default export */ function equalEarth() {
  return projection(equalEarthRaw)
      .scale(177.158);
}

;// ../../node_modules/d3-geo/src/projection/gnomonic.js




function gnomonicRaw(x, y) {
  var cy = src_math_cos(y), k = src_math_cos(x) * cy;
  return [cy * src_math_sin(x) / k, src_math_sin(y) / k];
}

gnomonicRaw.invert = azimuthalInvert(math_atan);

/* harmony default export */ function gnomonic() {
  return projection(gnomonicRaw)
      .scale(144.049)
      .clipAngle(60);
}

;// ../../node_modules/d3-geo/src/projection/identity.js






/* harmony default export */ function projection_identity() {
  var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, // scale, translate and reflect
      alpha = 0, ca, sa, // angle
      x0 = null, y0, x1, y1, // clip extent
      kx = 1, ky = 1,
      transform = transform_transformer({
        point: function(x, y) {
          var p = projection([x, y])
          this.stream.point(p[0], p[1]);
        }
      }),
      postclip = d3_geo_src_identity,
      cache,
      cacheStream;

  function reset() {
    kx = k * sx;
    ky = k * sy;
    cache = cacheStream = null;
    return projection;
  }

  function projection (p) {
    var x = p[0] * kx, y = p[1] * ky;
    if (alpha) {
      var t = y * ca - x * sa;
      x = x * ca + y * sa;
      y = t;
    }    
    return [x + tx, y + ty];
  }
  projection.invert = function(p) {
    var x = p[0] - tx, y = p[1] - ty;
    if (alpha) {
      var t = y * ca + x * sa;
      x = x * ca - y * sa;
      y = t;
    }
    return [x / kx, y / ky];
  };
  projection.stream = function(stream) {
    return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
  };
  projection.postclip = function(_) {
    return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
  };
  projection.clipExtent = function(_) {
    return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, d3_geo_src_identity) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  };
  projection.scale = function(_) {
    return arguments.length ? (k = +_, reset()) : k;
  };
  projection.translate = function(_) {
    return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
  }
  projection.angle = function(_) {
    return arguments.length ? (alpha = _ % 360 * d3_geo_src_math_radians, sa = src_math_sin(alpha), ca = src_math_cos(alpha), reset()) : alpha * d3_geo_src_math_degrees;
  };
  projection.reflectX = function(_) {
    return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
  };
  projection.reflectY = function(_) {
    return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
  };
  projection.fitExtent = function(extent, object) {
    return fitExtent(projection, extent, object);
  };
  projection.fitSize = function(size, object) {
    return fitSize(projection, size, object);
  };
  projection.fitWidth = function(width, object) {
    return fitWidth(projection, width, object);
  };
  projection.fitHeight = function(height, object) {
    return fitHeight(projection, height, object);
  };

  return projection;
}

;// ../../node_modules/d3-geo/src/projection/naturalEarth1.js



function naturalEarth1Raw(lambda, phi) {
  var phi2 = phi * phi, phi4 = phi2 * phi2;
  return [
    lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))),
    phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4)))
  ];
}

naturalEarth1Raw.invert = function(x, y) {
  var phi = y, i = 25, delta;
  do {
    var phi2 = phi * phi, phi4 = phi2 * phi2;
    phi -= delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) /
        (1.007226 + phi2 * (0.015085 * 3 + phi4 * (-0.044475 * 7 + 0.028874 * 9 * phi2 - 0.005916 * 11 * phi4)));
  } while (src_math_abs(delta) > src_math_epsilon && --i > 0);
  return [
    x / (0.8707 + (phi2 = phi * phi) * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))),
    phi
  ];
};

/* harmony default export */ function naturalEarth1() {
  return projection(naturalEarth1Raw)
      .scale(175.295);
}

;// ../../node_modules/d3-geo/src/projection/orthographic.js




function orthographicRaw(x, y) {
  return [src_math_cos(y) * src_math_sin(x), src_math_sin(y)];
}

orthographicRaw.invert = azimuthalInvert(src_math_asin);

/* harmony default export */ function orthographic() {
  return projection(orthographicRaw)
      .scale(249.5)
      .clipAngle(90 + src_math_epsilon);
}

;// ../../node_modules/d3-geo/src/projection/stereographic.js




function stereographicRaw(x, y) {
  var cy = src_math_cos(y), k = 1 + src_math_cos(x) * cy;
  return [cy * src_math_sin(x) / k, src_math_sin(y) / k];
}

stereographicRaw.invert = azimuthalInvert(function(z) {
  return 2 * math_atan(z);
});

/* harmony default export */ function stereographic() {
  return projection(stereographicRaw)
      .scale(250)
      .clipAngle(142);
}

;// ../../node_modules/d3-geo/src/projection/transverseMercator.js



function transverseMercatorRaw(lambda, phi) {
  return [math_log(math_tan((math_halfPi + phi) / 2)), -lambda];
}

transverseMercatorRaw.invert = function(x, y) {
  return [-y, 2 * math_atan(math_exp(x)) - math_halfPi];
};

/* harmony default export */ function transverseMercator() {
  var m = mercatorProjection(transverseMercatorRaw),
      center = m.center,
      rotate = m.rotate;

  m.center = function(_) {
    return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
  };

  m.rotate = function(_) {
    return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
  };

  return rotate([0, 0, 90])
      .scale(159.155);
}

;// ../../node_modules/d3-geo-projection/src/math.js
var d3_geo_projection_src_math_abs = Math.abs;
var src_math_atan = Math.atan;
var d3_geo_projection_src_math_atan2 = Math.atan2;
var src_math_ceil = Math.ceil;
var d3_geo_projection_src_math_cos = Math.cos;
var src_math_exp = Math.exp;
var src_math_floor = Math.floor;
var src_math_log = Math.log;
var src_math_max = Math.max;
var src_math_min = Math.min;
var src_math_pow = Math.pow;
var math_round = Math.round;
var src_math_sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
var d3_geo_projection_src_math_sin = Math.sin;
var src_math_tan = Math.tan;

var d3_geo_projection_src_math_epsilon = 1e-6;
var src_math_epsilon2 = 1e-12;
var src_math_pi = Math.PI;
var src_math_halfPi = src_math_pi / 2;
var math_quarterPi = src_math_pi / 4;
var sqrt1_2 = Math.SQRT1_2;
var sqrt2 = d3_geo_projection_src_math_sqrt(2);
var sqrtPi = d3_geo_projection_src_math_sqrt(src_math_pi);
var src_math_tau = src_math_pi * 2;
var d3_geo_projection_src_math_degrees = 180 / src_math_pi;
var d3_geo_projection_src_math_radians = src_math_pi / 180;

function sinci(x) {
  return x ? x / Math.sin(x) : 1;
}

function d3_geo_projection_src_math_asin(x) {
  return x > 1 ? src_math_halfPi : x < -1 ? -src_math_halfPi : Math.asin(x);
}

function d3_geo_projection_src_math_acos(x) {
  return x > 1 ? 0 : x < -1 ? src_math_pi : Math.acos(x);
}

function d3_geo_projection_src_math_sqrt(x) {
  return x > 0 ? Math.sqrt(x) : 0;
}

function math_tanh(x) {
  x = src_math_exp(2 * x);
  return (x - 1) / (x + 1);
}

function math_sinh(x) {
  return (src_math_exp(x) - src_math_exp(-x)) / 2;
}

function math_cosh(x) {
  return (src_math_exp(x) + src_math_exp(-x)) / 2;
}

function arsinh(x) {
  return src_math_log(x + d3_geo_projection_src_math_sqrt(x * x + 1));
}

function arcosh(x) {
  return src_math_log(x + d3_geo_projection_src_math_sqrt(x * x - 1));
}

;// ../../node_modules/d3-geo-projection/src/mollweide.js



function mollweideBromleyTheta(cp, phi) {
  var cpsinPhi = cp * d3_geo_projection_src_math_sin(phi), i = 30, delta;
  do phi -= delta = (phi + d3_geo_projection_src_math_sin(phi) - cpsinPhi) / (1 + d3_geo_projection_src_math_cos(phi));
  while (d3_geo_projection_src_math_abs(delta) > d3_geo_projection_src_math_epsilon && --i > 0);
  return phi / 2;
}

function mollweideBromleyRaw(cx, cy, cp) {

  function forward(lambda, phi) {
    return [cx * lambda * d3_geo_projection_src_math_cos(phi = mollweideBromleyTheta(cp, phi)), cy * d3_geo_projection_src_math_sin(phi)];
  }

  forward.invert = function(x, y) {
    return y = d3_geo_projection_src_math_asin(y / cy), [x / (cx * d3_geo_projection_src_math_cos(y)), d3_geo_projection_src_math_asin((2 * y + d3_geo_projection_src_math_sin(2 * y)) / cp)];
  };

  return forward;
}

var mollweideRaw = mollweideBromleyRaw(sqrt2 / src_math_halfPi, sqrt2, src_math_pi);

/* harmony default export */ function mollweide() {
  return projection(mollweideRaw)
      .scale(169.529);
}

;// ../../node_modules/vega-projection/build/vega-projection.module.js




const defaultPath = src_path();
const projectionProperties = [
// standard properties in d3-geo
'clipAngle', 'clipExtent', 'scale', 'translate', 'center', 'rotate', 'parallels', 'precision', 'reflectX', 'reflectY',
// extended properties in d3-geo-projections
'coefficient', 'distance', 'fraction', 'lobes', 'parallel', 'radius', 'ratio', 'spacing', 'tilt'];

/**
 * Augment projections with their type and a copy method.
 */
function vega_projection_module_create(type, constructor) {
  return function projection() {
    const p = constructor();
    p.type = type;
    p.path = src_path().projection(p);
    p.copy = p.copy || function () {
      const c = projection();
      projectionProperties.forEach(prop => {
        if (p[prop]) c[prop](p[prop]());
      });
      c.path.pointRadius(p.path.pointRadius());
      return c;
    };
    return registerScale(p);
  };
}
function vega_projection_module_projection(type, proj) {
  if (!type || typeof type !== 'string') {
    throw new Error('Projection type must be a name string.');
  }
  type = type.toLowerCase();
  if (arguments.length > 1) {
    projections[type] = vega_projection_module_create(type, proj);
    return this;
  } else {
    return projections[type] || null;
  }
}
function getProjectionPath(proj) {
  return proj && proj.path || defaultPath;
}
const projections = {
  // base d3-geo projection types
  albers: albers,
  albersusa: albersUsa,
  azimuthalequalarea: azimuthalEqualArea,
  azimuthalequidistant: azimuthalEquidistant,
  conicconformal: conicConformal,
  conicequalarea: conicEqualArea,
  conicequidistant: conicEquidistant,
  equalEarth: equalEarth,
  equirectangular: equirectangular,
  gnomonic: gnomonic,
  identity: projection_identity,
  mercator: mercator,
  mollweide: mollweide,
  naturalEarth1: naturalEarth1,
  orthographic: orthographic,
  stereographic: stereographic,
  transversemercator: transverseMercator
};
for (const key in projections) {
  vega_projection_module_projection(key, projections[key]);
}



;// ../../node_modules/d3-geo/src/graticule.js



function graticuleX(y0, y1, dy) {
  var y = range_range(y0, y1 - src_math_epsilon, dy).concat(y1);
  return function(x) { return y.map(function(y) { return [x, y]; }); };
}

function graticuleY(x0, x1, dx) {
  var x = range_range(x0, x1 - src_math_epsilon, dx).concat(x1);
  return function(y) { return x.map(function(x) { return [x, y]; }); };
}

function graticule() {
  var x1, x0, X1, X0,
      y1, y0, Y1, Y0,
      dx = 10, dy = dx, DX = 90, DY = 360,
      x, y, X, Y,
      precision = 2.5;

  function graticule() {
    return {type: "MultiLineString", coordinates: lines()};
  }

  function lines() {
    return range_range(math_ceil(X0 / DX) * DX, X1, DX).map(X)
        .concat(range_range(math_ceil(Y0 / DY) * DY, Y1, DY).map(Y))
        .concat(range_range(math_ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return src_math_abs(x % DX) > src_math_epsilon; }).map(x))
        .concat(range_range(math_ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return src_math_abs(y % DY) > src_math_epsilon; }).map(y));
  }

  graticule.lines = function() {
    return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
  };

  graticule.outline = function() {
    return {
      type: "Polygon",
      coordinates: [
        X(X0).concat(
        Y(Y1).slice(1),
        X(X1).reverse().slice(1),
        Y(Y0).reverse().slice(1))
      ]
    };
  };

  graticule.extent = function(_) {
    if (!arguments.length) return graticule.extentMinor();
    return graticule.extentMajor(_).extentMinor(_);
  };

  graticule.extentMajor = function(_) {
    if (!arguments.length) return [[X0, Y0], [X1, Y1]];
    X0 = +_[0][0], X1 = +_[1][0];
    Y0 = +_[0][1], Y1 = +_[1][1];
    if (X0 > X1) _ = X0, X0 = X1, X1 = _;
    if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
    return graticule.precision(precision);
  };

  graticule.extentMinor = function(_) {
    if (!arguments.length) return [[x0, y0], [x1, y1]];
    x0 = +_[0][0], x1 = +_[1][0];
    y0 = +_[0][1], y1 = +_[1][1];
    if (x0 > x1) _ = x0, x0 = x1, x1 = _;
    if (y0 > y1) _ = y0, y0 = y1, y1 = _;
    return graticule.precision(precision);
  };

  graticule.step = function(_) {
    if (!arguments.length) return graticule.stepMinor();
    return graticule.stepMajor(_).stepMinor(_);
  };

  graticule.stepMajor = function(_) {
    if (!arguments.length) return [DX, DY];
    DX = +_[0], DY = +_[1];
    return graticule;
  };

  graticule.stepMinor = function(_) {
    if (!arguments.length) return [dx, dy];
    dx = +_[0], dy = +_[1];
    return graticule;
  };

  graticule.precision = function(_) {
    if (!arguments.length) return precision;
    precision = +_;
    x = graticuleX(y0, y1, 90);
    y = graticuleY(x0, x1, precision);
    X = graticuleX(Y0, Y1, 90);
    Y = graticuleY(X0, X1, precision);
    return graticule;
  };

  return graticule
      .extentMajor([[-180, -90 + src_math_epsilon], [180, 90 - src_math_epsilon]])
      .extentMinor([[-180, -80 - src_math_epsilon], [180, 80 + src_math_epsilon]]);
}

function graticule10() {
  return graticule()();
}

;// ../../node_modules/vega-geo/build/vega-geo.module.js









function vega_geo_module_noop() {}
const cases = [[], [[[1.0, 1.5], [0.5, 1.0]]], [[[1.5, 1.0], [1.0, 1.5]]], [[[1.5, 1.0], [0.5, 1.0]]], [[[1.0, 0.5], [1.5, 1.0]]], [[[1.0, 1.5], [0.5, 1.0]], [[1.0, 0.5], [1.5, 1.0]]], [[[1.0, 0.5], [1.0, 1.5]]], [[[1.0, 0.5], [0.5, 1.0]]], [[[0.5, 1.0], [1.0, 0.5]]], [[[1.0, 1.5], [1.0, 0.5]]], [[[0.5, 1.0], [1.0, 0.5]], [[1.5, 1.0], [1.0, 1.5]]], [[[1.5, 1.0], [1.0, 0.5]]], [[[0.5, 1.0], [1.5, 1.0]]], [[[1.0, 1.5], [1.5, 1.0]]], [[[0.5, 1.0], [1.0, 1.5]]], []];

// Implementation adapted from d3/d3-contour. Thanks!
function contours () {
  var dx = 1,
    dy = 1,
    smooth = smoothLinear;
  function contours(values, tz) {
    return tz.map(value => contour(values, value));
  }

  // Accumulate, smooth contour rings, assign holes to exterior rings.
  // Based on https://github.com/mbostock/shapefile/blob/v0.6.2/shp/polygon.js
  function contour(values, value) {
    var polygons = [],
      holes = [];
    isorings(values, value, ring => {
      smooth(ring, values, value);
      if (vega_geo_module_area(ring) > 0) polygons.push([ring]);else holes.push(ring);
    });
    holes.forEach(hole => {
      for (var i = 0, n = polygons.length, polygon; i < n; ++i) {
        if (contains((polygon = polygons[i])[0], hole) !== -1) {
          polygon.push(hole);
          return;
        }
      }
    });
    return {
      type: 'MultiPolygon',
      value: value,
      coordinates: polygons
    };
  }

  // Marching squares with isolines stitched into rings.
  // Based on https://github.com/topojson/topojson-client/blob/v3.0.0/src/stitch.js
  function isorings(values, value, callback) {
    var fragmentByStart = [],
      fragmentByEnd = [],
      x,
      y,
      t0,
      t1,
      t2,
      t3;

    // Special case for the first row (y = -1, t2 = t3 = 0).
    x = y = -1;
    t1 = values[0] >= value;
    cases[t1 << 1].forEach(stitch);
    while (++x < dx - 1) {
      t0 = t1, t1 = values[x + 1] >= value;
      cases[t0 | t1 << 1].forEach(stitch);
    }
    cases[t1 << 0].forEach(stitch);

    // General case for the intermediate rows.
    while (++y < dy - 1) {
      x = -1;
      t1 = values[y * dx + dx] >= value;
      t2 = values[y * dx] >= value;
      cases[t1 << 1 | t2 << 2].forEach(stitch);
      while (++x < dx - 1) {
        t0 = t1, t1 = values[y * dx + dx + x + 1] >= value;
        t3 = t2, t2 = values[y * dx + x + 1] >= value;
        cases[t0 | t1 << 1 | t2 << 2 | t3 << 3].forEach(stitch);
      }
      cases[t1 | t2 << 3].forEach(stitch);
    }

    // Special case for the last row (y = dy - 1, t0 = t1 = 0).
    x = -1;
    t2 = values[y * dx] >= value;
    cases[t2 << 2].forEach(stitch);
    while (++x < dx - 1) {
      t3 = t2, t2 = values[y * dx + x + 1] >= value;
      cases[t2 << 2 | t3 << 3].forEach(stitch);
    }
    cases[t2 << 3].forEach(stitch);
    function stitch(line) {
      var start = [line[0][0] + x, line[0][1] + y],
        end = [line[1][0] + x, line[1][1] + y],
        startIndex = index(start),
        endIndex = index(end),
        f,
        g;
      if (f = fragmentByEnd[startIndex]) {
        if (g = fragmentByStart[endIndex]) {
          delete fragmentByEnd[f.end];
          delete fragmentByStart[g.start];
          if (f === g) {
            f.ring.push(end);
            callback(f.ring);
          } else {
            fragmentByStart[f.start] = fragmentByEnd[g.end] = {
              start: f.start,
              end: g.end,
              ring: f.ring.concat(g.ring)
            };
          }
        } else {
          delete fragmentByEnd[f.end];
          f.ring.push(end);
          fragmentByEnd[f.end = endIndex] = f;
        }
      } else if (f = fragmentByStart[endIndex]) {
        if (g = fragmentByEnd[startIndex]) {
          delete fragmentByStart[f.start];
          delete fragmentByEnd[g.end];
          if (f === g) {
            f.ring.push(end);
            callback(f.ring);
          } else {
            fragmentByStart[g.start] = fragmentByEnd[f.end] = {
              start: g.start,
              end: f.end,
              ring: g.ring.concat(f.ring)
            };
          }
        } else {
          delete fragmentByStart[f.start];
          f.ring.unshift(start);
          fragmentByStart[f.start = startIndex] = f;
        }
      } else {
        fragmentByStart[startIndex] = fragmentByEnd[endIndex] = {
          start: startIndex,
          end: endIndex,
          ring: [start, end]
        };
      }
    }
  }
  function index(point) {
    return point[0] * 2 + point[1] * (dx + 1) * 4;
  }
  function smoothLinear(ring, values, value) {
    ring.forEach(point => {
      var x = point[0],
        y = point[1],
        xt = x | 0,
        yt = y | 0,
        v0,
        v1 = values[yt * dx + xt];
      if (x > 0 && x < dx && xt === x) {
        v0 = values[yt * dx + xt - 1];
        point[0] = x + (value - v0) / (v1 - v0) - 0.5;
      }
      if (y > 0 && y < dy && yt === y) {
        v0 = values[(yt - 1) * dx + xt];
        point[1] = y + (value - v0) / (v1 - v0) - 0.5;
      }
    });
  }
  contours.contour = contour;
  contours.size = function (_) {
    if (!arguments.length) return [dx, dy];
    var _0 = Math.floor(_[0]),
      _1 = Math.floor(_[1]);
    if (!(_0 >= 0 && _1 >= 0)) vega_util_module_error('invalid size');
    return dx = _0, dy = _1, contours;
  };
  contours.smooth = function (_) {
    return arguments.length ? (smooth = _ ? smoothLinear : vega_geo_module_noop, contours) : smooth === smoothLinear;
  };
  return contours;
}
function vega_geo_module_area(ring) {
  var i = 0,
    n = ring.length,
    area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];
  while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];
  return area;
}
function contains(ring, hole) {
  var i = -1,
    n = hole.length,
    c;
  while (++i < n) if (c = ringContains(ring, hole[i])) return c;
  return 0;
}
function ringContains(ring, point) {
  var x = point[0],
    y = point[1],
    contains = -1;
  for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) {
    var pi = ring[i],
      xi = pi[0],
      yi = pi[1],
      pj = ring[j],
      xj = pj[0],
      yj = pj[1];
    if (segmentContains(pi, pj, point)) return 0;
    if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) contains = -contains;
  }
  return contains;
}
function segmentContains(a, b, c) {
  var i;
  return collinear(a, b, c) && within(a[i = +(a[0] === b[0])], c[i], b[i]);
}
function collinear(a, b, c) {
  return (b[0] - a[0]) * (c[1] - a[1]) === (c[0] - a[0]) * (b[1] - a[1]);
}
function within(p, q, r) {
  return p <= q && q <= r || r <= q && q <= p;
}

function vega_geo_module_quantize (k, nice, zero) {
  return function (values) {
    var ex = extent(values),
      start = zero ? Math.min(ex[0], 0) : ex[0],
      stop = ex[1],
      span = stop - start,
      step = nice ? tickStep(start, stop, k) : span / (k + 1);
    return range_range(start + step, stop, step);
  };
}

/**
 * Generate isocontours (level sets) based on input raster grid data.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} [params.field] - The field with raster grid
 *   data. If unspecified, the tuple itself is interpreted as a raster grid.
 * @param {Array<number>} [params.thresholds] - Contour threshold array. If
 *   specified, the levels, nice, resolve, and zero parameters are ignored.
 * @param {number} [params.levels] - The desired number of contour levels.
 * @param {boolean} [params.nice] - Boolean flag indicating if the contour
 *   threshold values should be automatically aligned to "nice"
 *   human-friendly values. Setting this flag may cause the number of
 *   thresholds to deviate from the specified levels.
 * @param {string} [params.resolve] - The method for resolving thresholds
 *   across multiple input grids. If 'independent' (the default), threshold
 *   calculation will be performed separately for each grid. If 'shared', a
 *   single set of threshold values will be used for all input grids.
 * @param {boolean} [params.zero] - Boolean flag indicating if the contour
 *   threshold values should include zero.
 * @param {boolean} [params.smooth] - Boolean flag indicating if the contour
 *   polygons should be smoothed using linear interpolation. The default is
 *   true. The parameter is ignored when using density estimation.
 * @param {boolean} [params.scale] - Optional numerical value by which to
 *   scale the output isocontour coordinates. This parameter can be useful
 *   to scale the contours to match a desired output resolution.
 * @param {string} [params.as='contour'] - The output field in which to store
 *   the generated isocontour data (default 'contour').
 */
function Isocontour(params) {
  Transform.call(this, null, params);
}
Isocontour.Definition = {
  'type': 'Isocontour',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'thresholds',
    'type': 'number',
    'array': true
  }, {
    'name': 'levels',
    'type': 'number'
  }, {
    'name': 'nice',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'resolve',
    'type': 'enum',
    'values': ['shared', 'independent'],
    'default': 'independent'
  }, {
    'name': 'zero',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'smooth',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'scale',
    'type': 'number',
    'expr': true
  }, {
    'name': 'translate',
    'type': 'number',
    'array': true,
    'expr': true
  }, {
    'name': 'as',
    'type': 'string',
    'null': true,
    'default': 'contour'
  }]
};
inherits(Isocontour, Transform, {
  transform(_, pulse) {
    if (this.value && !pulse.changed() && !_.modified()) {
      return pulse.StopPropagation;
    }
    var out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      source = pulse.materialize(pulse.SOURCE).source,
      field = _.field || vega_util_module_identity,
      contour = contours().smooth(_.smooth !== false),
      tz = _.thresholds || levels(source, field, _),
      as = _.as === null ? null : _.as || 'contour',
      values = [];
    source.forEach(t => {
      const grid = field(t);

      // generate contour paths in GeoJSON format
      const paths = contour.size([grid.width, grid.height])(grid.values, vega_util_module_isArray(tz) ? tz : tz(grid.values));

      // adjust contour path coordinates as needed
      transformPaths(paths, grid, t, _);

      // ingest; copy source data properties to output
      paths.forEach(p => {
        values.push(rederive(t, ingest$1(as != null ? {
          [as]: p
        } : p)));
      });
    });
    if (this.value) out.rem = this.value;
    this.value = out.source = out.add = values;
    return out;
  }
});
function levels(values, f, _) {
  const q = vega_geo_module_quantize(_.levels || 10, _.nice, _.zero !== false);
  return _.resolve !== 'shared' ? q : q(values.map(t => max_max(f(t).values)));
}
function transformPaths(paths, grid, datum, _) {
  let s = _.scale || grid.scale,
    t = _.translate || grid.translate;
  if (vega_util_module_isFunction(s)) s = s(datum, _);
  if (vega_util_module_isFunction(t)) t = t(datum, _);
  if ((s === 1 || s == null) && !t) return;
  const sx = (vega_util_module_isNumber(s) ? s : s[0]) || 1,
    sy = (vega_util_module_isNumber(s) ? s : s[1]) || 1,
    tx = t && t[0] || 0,
    ty = t && t[1] || 0;
  paths.forEach(vega_geo_module_transform(grid, sx, sy, tx, ty));
}
function vega_geo_module_transform(grid, sx, sy, tx, ty) {
  const x1 = grid.x1 || 0,
    y1 = grid.y1 || 0,
    flip = sx * sy < 0;
  function transformPolygon(coordinates) {
    coordinates.forEach(transformRing);
  }
  function transformRing(coordinates) {
    if (flip) coordinates.reverse(); // maintain winding order
    coordinates.forEach(transformPoint);
  }
  function transformPoint(coordinates) {
    coordinates[0] = (coordinates[0] - x1) * sx + tx;
    coordinates[1] = (coordinates[1] - y1) * sy + ty;
  }
  return function (geometry) {
    geometry.coordinates.forEach(transformPolygon);
    return geometry;
  };
}

function radius(bw, data, f) {
  const v = bw >= 0 ? bw : estimateBandwidth(data, f);
  return Math.round((Math.sqrt(4 * v * v + 1) - 1) / 2);
}
function vega_geo_module_number(_) {
  return vega_util_module_isFunction(_) ? _ : vega_util_module_constant(+_);
}

// Implementation adapted from d3/d3-contour. Thanks!
function density2D () {
  var x = d => d[0],
    y = d => d[1],
    weight = one,
    bandwidth = [-1, -1],
    dx = 960,
    dy = 500,
    k = 2; // log2(cellSize)

  function density(data, counts) {
    const rx = radius(bandwidth[0], data, x) >> k,
      // blur x-radius
      ry = radius(bandwidth[1], data, y) >> k,
      // blur y-radius
      ox = rx ? rx + 2 : 0,
      // x-offset padding for blur
      oy = ry ? ry + 2 : 0,
      // y-offset padding for blur
      n = 2 * ox + (dx >> k),
      // grid width
      m = 2 * oy + (dy >> k),
      // grid height
      values0 = new Float32Array(n * m),
      values1 = new Float32Array(n * m);
    let values = values0;
    data.forEach(d => {
      const xi = ox + (+x(d) >> k),
        yi = oy + (+y(d) >> k);
      if (xi >= 0 && xi < n && yi >= 0 && yi < m) {
        values0[xi + yi * n] += +weight(d);
      }
    });
    if (rx > 0 && ry > 0) {
      blurX(n, m, values0, values1, rx);
      blurY(n, m, values1, values0, ry);
      blurX(n, m, values0, values1, rx);
      blurY(n, m, values1, values0, ry);
      blurX(n, m, values0, values1, rx);
      blurY(n, m, values1, values0, ry);
    } else if (rx > 0) {
      blurX(n, m, values0, values1, rx);
      blurX(n, m, values1, values0, rx);
      blurX(n, m, values0, values1, rx);
      values = values1;
    } else if (ry > 0) {
      blurY(n, m, values0, values1, ry);
      blurY(n, m, values1, values0, ry);
      blurY(n, m, values0, values1, ry);
      values = values1;
    }

    // scale density estimates
    // density in points per square pixel or probability density
    const s = counts ? Math.pow(2, -2 * k) : 1 / sum_sum(values);
    for (let i = 0, sz = n * m; i < sz; ++i) values[i] *= s;
    return {
      values: values,
      scale: 1 << k,
      width: n,
      height: m,
      x1: ox,
      y1: oy,
      x2: ox + (dx >> k),
      y2: oy + (dy >> k)
    };
  }
  density.x = function (_) {
    return arguments.length ? (x = vega_geo_module_number(_), density) : x;
  };
  density.y = function (_) {
    return arguments.length ? (y = vega_geo_module_number(_), density) : y;
  };
  density.weight = function (_) {
    return arguments.length ? (weight = vega_geo_module_number(_), density) : weight;
  };
  density.size = function (_) {
    if (!arguments.length) return [dx, dy];
    var _0 = +_[0],
      _1 = +_[1];
    if (!(_0 >= 0 && _1 >= 0)) vega_util_module_error('invalid size');
    return dx = _0, dy = _1, density;
  };
  density.cellSize = function (_) {
    if (!arguments.length) return 1 << k;
    if (!((_ = +_) >= 1)) vega_util_module_error('invalid cell size');
    k = Math.floor(Math.log(_) / Math.LN2);
    return density;
  };
  density.bandwidth = function (_) {
    if (!arguments.length) return bandwidth;
    _ = vega_util_module_array(_);
    if (_.length === 1) _ = [+_[0], +_[0]];
    if (_.length !== 2) vega_util_module_error('invalid bandwidth');
    return bandwidth = _, density;
  };
  return density;
}
function blurX(n, m, source, target, r) {
  const w = (r << 1) + 1;
  for (let j = 0; j < m; ++j) {
    for (let i = 0, sr = 0; i < n + r; ++i) {
      if (i < n) {
        sr += source[i + j * n];
      }
      if (i >= r) {
        if (i >= w) {
          sr -= source[i - w + j * n];
        }
        target[i - r + j * n] = sr / Math.min(i + 1, n - 1 + w - i, w);
      }
    }
  }
}
function blurY(n, m, source, target, r) {
  const w = (r << 1) + 1;
  for (let i = 0; i < n; ++i) {
    for (let j = 0, sr = 0; j < m + r; ++j) {
      if (j < m) {
        sr += source[i + j * n];
      }
      if (j >= r) {
        if (j >= w) {
          sr -= source[i + (j - w) * n];
        }
        target[i + (j - r) * n] = sr / Math.min(j + 1, m - 1 + w - j, w);
      }
    }
  }
}

/**
 * Perform 2D kernel-density estimation of point data.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<number>} params.size - The [width, height] extent (in
 *   units of input pixels) over which to perform density estimation.
 * @param {function(object): number} params.x - The x-coordinate accessor.
 * @param {function(object): number} params.y - The y-coordinate accessor.
 * @param {function(object): number} [params.weight] - The weight accessor.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors
 *   to groupby.
 * @param {number} [params.cellSize] - Contour density calculation cell size.
 *   This parameter determines the level of spatial approximation. For example,
 *   the default value of 4 maps to 2x reductions in both x- and y- dimensions.
 *   A value of 1 will result in an output raster grid whose dimensions exactly
 *   matches the size parameter.
 * @param {Array<number>} [params.bandwidth] - The KDE kernel bandwidths,
 *   in pixels. The input can be a two-element array specifying separate
 *   x and y bandwidths, or a single-element array specifying both. If the
 *   bandwidth is unspecified or less than zero, the bandwidth will be
 *   automatically determined.
 * @param {boolean} [params.counts=false] - A boolean flag indicating if the
 *   output values should be probability estimates (false, default) or
 *   smoothed counts (true).
 * @param {string} [params.as='grid'] - The output field in which to store
 *   the generated raster grid (default 'grid').
 */
function KDE2D(params) {
  Transform.call(this, null, params);
}
KDE2D.Definition = {
  'type': 'KDE2D',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2,
    'required': true
  }, {
    'name': 'x',
    'type': 'field',
    'required': true
  }, {
    'name': 'y',
    'type': 'field',
    'required': true
  }, {
    'name': 'weight',
    'type': 'field'
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'cellSize',
    'type': 'number'
  }, {
    'name': 'bandwidth',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'counts',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'grid'
  }]
};
const PARAMS = ['x', 'y', 'weight', 'size', 'cellSize', 'bandwidth'];
function params(obj, _) {
  PARAMS.forEach(param => _[param] != null ? obj[param](_[param]) : 0);
  return obj;
}
inherits(KDE2D, Transform, {
  transform(_, pulse) {
    if (this.value && !pulse.changed() && !_.modified()) return pulse.StopPropagation;
    var out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      source = pulse.materialize(pulse.SOURCE).source,
      groups = vega_geo_module_partition(source, _.groupby),
      names = (_.groupby || []).map(accessorName),
      kde = params(density2D(), _),
      as = _.as || 'grid',
      values = [];
    function set(t, vals) {
      for (let i = 0; i < names.length; ++i) t[names[i]] = vals[i];
      return t;
    }

    // generate density raster grids
    values = groups.map(g => ingest$1(set({
      [as]: kde(g, _.counts)
    }, g.dims)));
    if (this.value) out.rem = this.value;
    this.value = out.source = out.add = values;
    return out;
  }
});
function vega_geo_module_partition(data, groupby) {
  var groups = [],
    get = f => f(t),
    map,
    i,
    n,
    t,
    k,
    g;

  // partition data points into groups
  if (groupby == null) {
    groups.push(data);
  } else {
    for (map = {}, i = 0, n = data.length; i < n; ++i) {
      t = data[i];
      k = groupby.map(get);
      g = map[k];
      if (!g) {
        map[k] = g = [];
        g.dims = k;
        groups.push(g);
      }
      g.push(t);
    }
  }
  return groups;
}

/**
 * Generate contours based on kernel-density estimation of point data.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<number>} params.size - The dimensions [width, height] over which to compute contours.
 *  If the values parameter is provided, this must be the dimensions of the input data.
 *  If density estimation is performed, this is the output view dimensions in pixels.
 * @param {Array<number>} [params.values] - An array of numeric values representing an
 *  width x height grid of values over which to compute contours. If unspecified, this
 *  transform will instead attempt to compute contours for the kernel density estimate
 *  using values drawn from data tuples in the input pulse.
 * @param {function(object): number} [params.x] - The pixel x-coordinate accessor for density estimation.
 * @param {function(object): number} [params.y] - The pixel y-coordinate accessor for density estimation.
 * @param {function(object): number} [params.weight] - The data point weight accessor for density estimation.
 * @param {number} [params.cellSize] - Contour density calculation cell size.
 * @param {number} [params.bandwidth] - Kernel density estimation bandwidth.
 * @param {Array<number>} [params.thresholds] - Contour threshold array. If
 *   this parameter is set, the count and nice parameters will be ignored.
 * @param {number} [params.count] - The desired number of contours.
 * @param {boolean} [params.nice] - Boolean flag indicating if the contour
 *   threshold values should be automatically aligned to "nice"
 *   human-friendly values. Setting this flag may cause the number of
 *   thresholds to deviate from the specified count.
 * @param {boolean} [params.smooth] - Boolean flag indicating if the contour
 *   polygons should be smoothed using linear interpolation. The default is
 *   true. The parameter is ignored when using density estimation.
 */
function Contour(params) {
  Transform.call(this, null, params);
}
Contour.Definition = {
  'type': 'Contour',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2,
    'required': true
  }, {
    'name': 'values',
    'type': 'number',
    'array': true
  }, {
    'name': 'x',
    'type': 'field'
  }, {
    'name': 'y',
    'type': 'field'
  }, {
    'name': 'weight',
    'type': 'field'
  }, {
    'name': 'cellSize',
    'type': 'number'
  }, {
    'name': 'bandwidth',
    'type': 'number'
  }, {
    'name': 'count',
    'type': 'number'
  }, {
    'name': 'nice',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'thresholds',
    'type': 'number',
    'array': true
  }, {
    'name': 'smooth',
    'type': 'boolean',
    'default': true
  }]
};
inherits(Contour, Transform, {
  transform(_, pulse) {
    if (this.value && !pulse.changed() && !_.modified()) {
      return pulse.StopPropagation;
    }
    var out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS),
      contour = contours().smooth(_.smooth !== false),
      values = _.values,
      thresh = _.thresholds || vega_geo_module_quantize(_.count || 10, _.nice, !!values),
      size = _.size,
      grid,
      post;
    if (!values) {
      values = pulse.materialize(pulse.SOURCE).source;
      grid = params(density2D(), _)(values, true);
      post = vega_geo_module_transform(grid, grid.scale || 1, grid.scale || 1, 0, 0);
      size = [grid.width, grid.height];
      values = grid.values;
    }
    thresh = vega_util_module_isArray(thresh) ? thresh : thresh(values);
    values = contour.size(size)(values, thresh);
    if (post) values.forEach(post);
    if (this.value) out.rem = this.value;
    this.value = out.source = out.add = (values || []).map(ingest$1);
    return out;
  }
});

const Feature = 'Feature';
const FeatureCollection = 'FeatureCollection';
const MultiPoint = 'MultiPoint';

/**
 * Consolidate an array of [longitude, latitude] points or GeoJSON features
 * into a combined GeoJSON object. This transform is particularly useful for
 * combining geo data for a Projection's fit argument. The resulting GeoJSON
 * data is available as this transform's value. Input pulses are unchanged.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} [params.fields] - A two-element array
 *   of field accessors for the longitude and latitude values.
 * @param {function(object): *} params.geojson - A field accessor for
 *   retrieving GeoJSON feature data.
 */
function GeoJSON(params) {
  Transform.call(this, null, params);
}
GeoJSON.Definition = {
  'type': 'GeoJSON',
  'metadata': {},
  'params': [{
    'name': 'fields',
    'type': 'field',
    'array': true,
    'length': 2
  }, {
    'name': 'geojson',
    'type': 'field'
  }]
};
inherits(GeoJSON, Transform, {
  transform(_, pulse) {
    var features = this._features,
      points = this._points,
      fields = _.fields,
      lon = fields && fields[0],
      lat = fields && fields[1],
      geojson = _.geojson || !fields && vega_util_module_identity,
      flag = pulse.ADD,
      mod;
    mod = _.modified() || pulse.changed(pulse.REM) || pulse.modified(accessorFields(geojson)) || lon && pulse.modified(accessorFields(lon)) || lat && pulse.modified(accessorFields(lat));
    if (!this.value || mod) {
      flag = pulse.SOURCE;
      this._features = features = [];
      this._points = points = [];
    }
    if (geojson) {
      pulse.visit(flag, t => features.push(geojson(t)));
    }
    if (lon && lat) {
      pulse.visit(flag, t => {
        var x = lon(t),
          y = lat(t);
        if (x != null && y != null && (x = +x) === x && (y = +y) === y) {
          points.push([x, y]);
        }
      });
      features = features.concat({
        type: Feature,
        geometry: {
          type: MultiPoint,
          coordinates: points
        }
      });
    }
    this.value = {
      type: FeatureCollection,
      features: features
    };
  }
});

/**
 * Map GeoJSON data to an SVG path string.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(number, number): *} params.projection - The cartographic
 *   projection to apply.
 * @param {function(object): *} [params.field] - The field with GeoJSON data,
 *   or null if the tuple itself is a GeoJSON feature.
 * @param {string} [params.as='path'] - The output field in which to store
 *   the generated path data (default 'path').
 */
function GeoPath(params) {
  Transform.call(this, null, params);
}
GeoPath.Definition = {
  'type': 'GeoPath',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'projection',
    'type': 'projection'
  }, {
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'pointRadius',
    'type': 'number',
    'expr': true
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'path'
  }]
};
inherits(GeoPath, Transform, {
  transform(_, pulse) {
    var out = pulse.fork(pulse.ALL),
      path = this.value,
      field = _.field || vega_util_module_identity,
      as = _.as || 'path',
      flag = out.SOURCE;
    if (!path || _.modified()) {
      // parameters updated, reset and reflow
      this.value = path = getProjectionPath(_.projection);
      out.materialize().reflow();
    } else {
      flag = field === vega_util_module_identity || pulse.modified(field.fields) ? out.ADD_MOD : out.ADD;
    }
    const prev = initPath(path, _.pointRadius);
    out.visit(flag, t => t[as] = path(field(t)));
    path.pointRadius(prev);
    return out.modifies(as);
  }
});
function initPath(path, pointRadius) {
  const prev = path.pointRadius();
  path.context(null);
  if (pointRadius != null) {
    path.pointRadius(pointRadius);
  }
  return prev;
}

/**
 * Geo-code a longitude/latitude point to an x/y coordinate.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(number, number): *} params.projection - The cartographic
 *   projection to apply.
 * @param {Array<function(object): *>} params.fields - A two-element array of
 *   field accessors for the longitude and latitude values.
 * @param {Array<string>} [params.as] - A two-element array of field names
 *   under which to store the result. Defaults to ['x','y'].
 */
function GeoPoint(params) {
  Transform.call(this, null, params);
}
GeoPoint.Definition = {
  'type': 'GeoPoint',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'projection',
    'type': 'projection',
    'required': true
  }, {
    'name': 'fields',
    'type': 'field',
    'array': true,
    'required': true,
    'length': 2
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 2,
    'default': ['x', 'y']
  }]
};
inherits(GeoPoint, Transform, {
  transform(_, pulse) {
    var proj = _.projection,
      lon = _.fields[0],
      lat = _.fields[1],
      as = _.as || ['x', 'y'],
      x = as[0],
      y = as[1],
      mod;
    function set(t) {
      const xy = proj([lon(t), lat(t)]);
      if (xy) {
        t[x] = xy[0];
        t[y] = xy[1];
      } else {
        t[x] = undefined;
        t[y] = undefined;
      }
    }
    if (_.modified()) {
      // parameters updated, reflow
      pulse = pulse.materialize().reflow(true).visit(pulse.SOURCE, set);
    } else {
      mod = pulse.modified(lon.fields) || pulse.modified(lat.fields);
      pulse.visit(mod ? pulse.ADD_MOD : pulse.ADD, set);
    }
    return pulse.modifies(as);
  }
});

/**
 * Annotate items with a geopath shape generator.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(number, number): *} params.projection - The cartographic
 *   projection to apply.
 * @param {function(object): *} [params.field] - The field with GeoJSON data,
 *   or null if the tuple itself is a GeoJSON feature.
 * @param {string} [params.as='shape'] - The output field in which to store
 *   the generated path data (default 'shape').
 */
function GeoShape(params) {
  Transform.call(this, null, params);
}
GeoShape.Definition = {
  'type': 'GeoShape',
  'metadata': {
    'modifies': true,
    'nomod': true
  },
  'params': [{
    'name': 'projection',
    'type': 'projection'
  }, {
    'name': 'field',
    'type': 'field',
    'default': 'datum'
  }, {
    'name': 'pointRadius',
    'type': 'number',
    'expr': true
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'shape'
  }]
};
inherits(GeoShape, Transform, {
  transform(_, pulse) {
    var out = pulse.fork(pulse.ALL),
      shape = this.value,
      as = _.as || 'shape',
      flag = out.ADD;
    if (!shape || _.modified()) {
      // parameters updated, reset and reflow
      this.value = shape = shapeGenerator(getProjectionPath(_.projection), _.field || vega_util_module_field('datum'), _.pointRadius);
      out.materialize().reflow();
      flag = out.SOURCE;
    }
    out.visit(flag, t => t[as] = shape);
    return out.modifies(as);
  }
});
function shapeGenerator(path, field, pointRadius) {
  const shape = pointRadius == null ? _ => path(field(_)) : _ => {
    var prev = path.pointRadius(),
      value = path.pointRadius(pointRadius)(field(_));
    path.pointRadius(prev);
    return value;
  };
  shape.context = _ => {
    path.context(_);
    return shape;
  };
  return shape;
}

/**
 * GeoJSON feature generator for creating graticules.
 * @constructor
 */
function Graticule(params) {
  Transform.call(this, [], params);
  this.generator = graticule();
}
Graticule.Definition = {
  'type': 'Graticule',
  'metadata': {
    'changes': true,
    'generates': true
  },
  'params': [{
    'name': 'extent',
    'type': 'array',
    'array': true,
    'length': 2,
    'content': {
      'type': 'number',
      'array': true,
      'length': 2
    }
  }, {
    'name': 'extentMajor',
    'type': 'array',
    'array': true,
    'length': 2,
    'content': {
      'type': 'number',
      'array': true,
      'length': 2
    }
  }, {
    'name': 'extentMinor',
    'type': 'array',
    'array': true,
    'length': 2,
    'content': {
      'type': 'number',
      'array': true,
      'length': 2
    }
  }, {
    'name': 'step',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'stepMajor',
    'type': 'number',
    'array': true,
    'length': 2,
    'default': [90, 360]
  }, {
    'name': 'stepMinor',
    'type': 'number',
    'array': true,
    'length': 2,
    'default': [10, 10]
  }, {
    'name': 'precision',
    'type': 'number',
    'default': 2.5
  }]
};
inherits(Graticule, Transform, {
  transform(_, pulse) {
    var src = this.value,
      gen = this.generator,
      t;
    if (!src.length || _.modified()) {
      for (const prop in _) {
        if (vega_util_module_isFunction(gen[prop])) {
          gen[prop](_[prop]);
        }
      }
    }
    t = gen();
    if (src.length) {
      pulse.mod.push(vega_dataflow_module_replace(src[0], t));
    } else {
      pulse.add.push(ingest$1(t));
    }
    src[0] = t;
    return pulse;
  }
});

/**
 * Render a heatmap image for input raster grid data.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} [params.field] - The field with raster grid
 *   data. If unspecified, the tuple itself is interpreted as a raster grid.
 * @param {string} [params.color] - A constant color value or function for
 *   individual pixel color. If a function, it will be invoked with an input
 *   object that includes $x, $y, $value, and $max fields for the grid.
 * @param {number} [params.opacity] - A constant opacity value or function for
 *   individual pixel opacity. If a function, it will be invoked with an input
 *   object that includes $x, $y, $value, and $max fields for the grid.
 * @param {string} [params.resolve] - The method for resolving maximum values
 *   across multiple input grids. If 'independent' (the default), maximum
 *   calculation will be performed separately for each grid. If 'shared',
 *   a single global maximum will be used for all input grids.
 * @param {string} [params.as='image'] - The output field in which to store
 *   the generated bitmap canvas images (default 'image').
 */
function Heatmap(params) {
  Transform.call(this, null, params);
}
Heatmap.Definition = {
  'type': 'heatmap',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'color',
    'type': 'string',
    'expr': true
  }, {
    'name': 'opacity',
    'type': 'number',
    'expr': true
  }, {
    'name': 'resolve',
    'type': 'enum',
    'values': ['shared', 'independent'],
    'default': 'independent'
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'image'
  }]
};
inherits(Heatmap, Transform, {
  transform(_, pulse) {
    if (!pulse.changed() && !_.modified()) {
      return pulse.StopPropagation;
    }
    var source = pulse.materialize(pulse.SOURCE).source,
      shared = _.resolve === 'shared',
      field = _.field || vega_util_module_identity,
      opacity = opacity_(_.opacity, _),
      color = color_(_.color, _),
      as = _.as || 'image',
      obj = {
        $x: 0,
        $y: 0,
        $value: 0,
        $max: shared ? max_max(source.map(t => max_max(field(t).values))) : 0
      };
    source.forEach(t => {
      const v = field(t);

      // build proxy data object
      const o = extend({}, t, obj);
      // set maximum value if not globally shared
      if (!shared) o.$max = max_max(v.values || []);

      // generate canvas image
      // optimize color/opacity if not pixel-dependent
      t[as] = toCanvas(v, o, color.dep ? color : vega_util_module_constant(color(o)), opacity.dep ? opacity : vega_util_module_constant(opacity(o)));
    });
    return pulse.reflow(true).modifies(as);
  }
});

// get image color function
function color_(color, _) {
  let f;
  if (vega_util_module_isFunction(color)) {
    f = obj => color_rgb(color(obj, _));
    f.dep = dependency(color);
  } else {
    // default to mid-grey
    f = vega_util_module_constant(color_rgb(color || '#888'));
  }
  return f;
}

// get image opacity function
function opacity_(opacity, _) {
  let f;
  if (vega_util_module_isFunction(opacity)) {
    f = obj => opacity(obj, _);
    f.dep = dependency(opacity);
  } else if (opacity) {
    f = vega_util_module_constant(opacity);
  } else {
    // default to [0, max] opacity gradient
    f = obj => obj.$value / obj.$max || 0;
    f.dep = true;
  }
  return f;
}

// check if function depends on individual pixel data
function dependency(f) {
  if (!vega_util_module_isFunction(f)) return false;
  const set = vega_util_module_toSet(accessorFields(f));
  return set.$x || set.$y || set.$value || set.$max;
}

// render raster grid to canvas
function toCanvas(grid, obj, color, opacity) {
  const n = grid.width,
    m = grid.height,
    x1 = grid.x1 || 0,
    y1 = grid.y1 || 0,
    x2 = grid.x2 || n,
    y2 = grid.y2 || m,
    val = grid.values,
    value = val ? i => val[i] : zero,
    can = domCanvas(x2 - x1, y2 - y1),
    ctx = can.getContext('2d'),
    img = ctx.getImageData(0, 0, x2 - x1, y2 - y1),
    pix = img.data;
  for (let j = y1, k = 0; j < y2; ++j) {
    obj.$y = j - y1;
    for (let i = x1, r = j * n; i < x2; ++i, k += 4) {
      obj.$x = i - x1;
      obj.$value = value(i + r);
      const v = color(obj);
      pix[k + 0] = v.r;
      pix[k + 1] = v.g;
      pix[k + 2] = v.b;
      pix[k + 3] = ~~(255 * opacity(obj));
    }
  }
  ctx.putImageData(img, 0, 0);
  return can;
}

/**
 * Maintains a cartographic projection.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function Projection(params) {
  Transform.call(this, null, params);
  this.modified(true); // always treat as modified
}
inherits(Projection, Transform, {
  transform(_, pulse) {
    let proj = this.value;
    if (!proj || _.modified('type')) {
      this.value = proj = vega_geo_module_create(_.type);
      projectionProperties.forEach(prop => {
        if (_[prop] != null) vega_geo_module_set(proj, prop, _[prop]);
      });
    } else {
      projectionProperties.forEach(prop => {
        if (_.modified(prop)) vega_geo_module_set(proj, prop, _[prop]);
      });
    }
    if (_.pointRadius != null) proj.path.pointRadius(_.pointRadius);
    if (_.fit) vega_geo_module_fit(proj, _);
    return pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
  }
});
function vega_geo_module_fit(proj, _) {
  const data = collectGeoJSON(_.fit);
  _.extent ? proj.fitExtent(_.extent, data) : _.size ? proj.fitSize(_.size, data) : 0;
}
function vega_geo_module_create(type) {
  const constructor = vega_projection_module_projection((type || 'mercator').toLowerCase());
  if (!constructor) vega_util_module_error('Unrecognized projection type: ' + type);
  return constructor();
}
function vega_geo_module_set(proj, key, value) {
  if (vega_util_module_isFunction(proj[key])) proj[key](value);
}
function collectGeoJSON(data) {
  data = vega_util_module_array(data);
  return data.length === 1 ? data[0] : {
    type: FeatureCollection,
    features: data.reduce((a, f) => a.concat(featurize(f)), [])
  };
}
function featurize(f) {
  return f.type === FeatureCollection ? f.features : vega_util_module_array(f).filter(d => d != null).map(d => d.type === Feature ? d : {
    type: Feature,
    geometry: d
  });
}



;// ../../node_modules/d3-force/src/center.js
/* harmony default export */ function center(x, y) {
  var nodes, strength = 1;

  if (x == null) x = 0;
  if (y == null) y = 0;

  function force() {
    var i,
        n = nodes.length,
        node,
        sx = 0,
        sy = 0;

    for (i = 0; i < n; ++i) {
      node = nodes[i], sx += node.x, sy += node.y;
    }

    for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, i = 0; i < n; ++i) {
      node = nodes[i], node.x -= sx, node.y -= sy;
    }
  }

  force.initialize = function(_) {
    nodes = _;
  };

  force.x = function(_) {
    return arguments.length ? (x = +_, force) : x;
  };

  force.y = function(_) {
    return arguments.length ? (y = +_, force) : y;
  };

  force.strength = function(_) {
    return arguments.length ? (strength = +_, force) : strength;
  };

  return force;
}

;// ../../node_modules/d3-quadtree/src/add.js
/* harmony default export */ function src_add(d) {
  const x = +this._x.call(null, d),
      y = +this._y.call(null, d);
  return add_add(this.cover(x, y), x, y, d);
}

function add_add(tree, x, y, d) {
  if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points

  var parent,
      node = tree._root,
      leaf = {data: d},
      x0 = tree._x0,
      y0 = tree._y0,
      x1 = tree._x1,
      y1 = tree._y1,
      xm,
      ym,
      xp,
      yp,
      right,
      bottom,
      i,
      j;

  // If the tree is empty, initialize the root as a leaf.
  if (!node) return tree._root = leaf, tree;

  // Find the existing leaf for the new point, or add it.
  while (node.length) {
    if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
    if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
    if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
  }

  // Is the new point is exactly coincident with the existing point?
  xp = +tree._x.call(null, node.data);
  yp = +tree._y.call(null, node.data);
  if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;

  // Otherwise, split the leaf node until the old and new point are separated.
  do {
    parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
    if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
    if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
  return parent[j] = node, parent[i] = leaf, tree;
}

function addAll(data) {
  var d, i, n = data.length,
      x,
      y,
      xz = new Array(n),
      yz = new Array(n),
      x0 = Infinity,
      y0 = Infinity,
      x1 = -Infinity,
      y1 = -Infinity;

  // Compute the points and their extent.
  for (i = 0; i < n; ++i) {
    if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
    xz[i] = x;
    yz[i] = y;
    if (x < x0) x0 = x;
    if (x > x1) x1 = x;
    if (y < y0) y0 = y;
    if (y > y1) y1 = y;
  }

  // If there were no (valid) points, abort.
  if (x0 > x1 || y0 > y1) return this;

  // Expand the tree to cover the new points.
  this.cover(x0, y0).cover(x1, y1);

  // Add the new points.
  for (i = 0; i < n; ++i) {
    add_add(this, xz[i], yz[i], data[i]);
  }

  return this;
}

;// ../../node_modules/d3-quadtree/src/cover.js
/* harmony default export */ function cover(x, y) {
  if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points

  var x0 = this._x0,
      y0 = this._y0,
      x1 = this._x1,
      y1 = this._y1;

  // If the quadtree has no extent, initialize them.
  // Integer extent are necessary so that if we later double the extent,
  // the existing quadrant boundaries don’t change due to floating point error!
  if (isNaN(x0)) {
    x1 = (x0 = Math.floor(x)) + 1;
    y1 = (y0 = Math.floor(y)) + 1;
  }

  // Otherwise, double repeatedly to cover.
  else {
    var z = x1 - x0 || 1,
        node = this._root,
        parent,
        i;

    while (x0 > x || x >= x1 || y0 > y || y >= y1) {
      i = (y < y0) << 1 | (x < x0);
      parent = new Array(4), parent[i] = node, node = parent, z *= 2;
      switch (i) {
        case 0: x1 = x0 + z, y1 = y0 + z; break;
        case 1: x0 = x1 - z, y1 = y0 + z; break;
        case 2: x1 = x0 + z, y0 = y1 - z; break;
        case 3: x0 = x1 - z, y0 = y1 - z; break;
      }
    }

    if (this._root && this._root.length) this._root = node;
  }

  this._x0 = x0;
  this._y0 = y0;
  this._x1 = x1;
  this._y1 = y1;
  return this;
}

;// ../../node_modules/d3-quadtree/src/data.js
/* harmony default export */ function src_data() {
  var data = [];
  this.visit(function(node) {
    if (!node.length) do data.push(node.data); while (node = node.next)
  });
  return data;
}

;// ../../node_modules/d3-quadtree/src/extent.js
/* harmony default export */ function src_extent(_) {
  return arguments.length
      ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
      : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
}

;// ../../node_modules/d3-quadtree/src/quad.js
/* harmony default export */ function src_quad(node, x0, y0, x1, y1) {
  this.node = node;
  this.x0 = x0;
  this.y0 = y0;
  this.x1 = x1;
  this.y1 = y1;
}

;// ../../node_modules/d3-quadtree/src/find.js


/* harmony default export */ function src_find(x, y, radius) {
  var data,
      x0 = this._x0,
      y0 = this._y0,
      x1,
      y1,
      x2,
      y2,
      x3 = this._x1,
      y3 = this._y1,
      quads = [],
      node = this._root,
      q,
      i;

  if (node) quads.push(new src_quad(node, x0, y0, x3, y3));
  if (radius == null) radius = Infinity;
  else {
    x0 = x - radius, y0 = y - radius;
    x3 = x + radius, y3 = y + radius;
    radius *= radius;
  }

  while (q = quads.pop()) {

    // Stop searching if this quadrant can’t contain a closer node.
    if (!(node = q.node)
        || (x1 = q.x0) > x3
        || (y1 = q.y0) > y3
        || (x2 = q.x1) < x0
        || (y2 = q.y1) < y0) continue;

    // Bisect the current quadrant.
    if (node.length) {
      var xm = (x1 + x2) / 2,
          ym = (y1 + y2) / 2;

      quads.push(
        new src_quad(node[3], xm, ym, x2, y2),
        new src_quad(node[2], x1, ym, xm, y2),
        new src_quad(node[1], xm, y1, x2, ym),
        new src_quad(node[0], x1, y1, xm, ym)
      );

      // Visit the closest quadrant first.
      if (i = (y >= ym) << 1 | (x >= xm)) {
        q = quads[quads.length - 1];
        quads[quads.length - 1] = quads[quads.length - 1 - i];
        quads[quads.length - 1 - i] = q;
      }
    }

    // Visit this point. (Visiting coincident points isn’t necessary!)
    else {
      var dx = x - +this._x.call(null, node.data),
          dy = y - +this._y.call(null, node.data),
          d2 = dx * dx + dy * dy;
      if (d2 < radius) {
        var d = Math.sqrt(radius = d2);
        x0 = x - d, y0 = y - d;
        x3 = x + d, y3 = y + d;
        data = node.data;
      }
    }
  }

  return data;
}

;// ../../node_modules/d3-quadtree/src/remove.js
/* harmony default export */ function remove(d) {
  if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points

  var parent,
      node = this._root,
      retainer,
      previous,
      next,
      x0 = this._x0,
      y0 = this._y0,
      x1 = this._x1,
      y1 = this._y1,
      x,
      y,
      xm,
      ym,
      right,
      bottom,
      i,
      j;

  // If the tree is empty, initialize the root as a leaf.
  if (!node) return this;

  // Find the leaf node for the point.
  // While descending, also retain the deepest parent with a non-removed sibling.
  if (node.length) while (true) {
    if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
    if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
    if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
    if (!node.length) break;
    if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
  }

  // Find the point to remove.
  while (node.data !== d) if (!(previous = node, node = node.next)) return this;
  if (next = node.next) delete node.next;

  // If there are multiple coincident points, remove just the point.
  if (previous) return (next ? previous.next = next : delete previous.next), this;

  // If this is the root point, remove it.
  if (!parent) return this._root = next, this;

  // Remove this leaf.
  next ? parent[i] = next : delete parent[i];

  // If the parent now contains exactly one leaf, collapse superfluous parents.
  if ((node = parent[0] || parent[1] || parent[2] || parent[3])
      && node === (parent[3] || parent[2] || parent[1] || parent[0])
      && !node.length) {
    if (retainer) retainer[j] = node;
    else this._root = node;
  }

  return this;
}

function removeAll(data) {
  for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
  return this;
}

;// ../../node_modules/d3-quadtree/src/root.js
/* harmony default export */ function root() {
  return this._root;
}

;// ../../node_modules/d3-quadtree/src/size.js
/* harmony default export */ function size() {
  var size = 0;
  this.visit(function(node) {
    if (!node.length) do ++size; while (node = node.next)
  });
  return size;
}

;// ../../node_modules/d3-quadtree/src/visit.js


/* harmony default export */ function src_visit(callback) {
  var quads = [], q, node = this._root, child, x0, y0, x1, y1;
  if (node) quads.push(new src_quad(node, this._x0, this._y0, this._x1, this._y1));
  while (q = quads.pop()) {
    if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
      var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
      if (child = node[3]) quads.push(new src_quad(child, xm, ym, x1, y1));
      if (child = node[2]) quads.push(new src_quad(child, x0, ym, xm, y1));
      if (child = node[1]) quads.push(new src_quad(child, xm, y0, x1, ym));
      if (child = node[0]) quads.push(new src_quad(child, x0, y0, xm, ym));
    }
  }
  return this;
}

;// ../../node_modules/d3-quadtree/src/visitAfter.js


/* harmony default export */ function visitAfter(callback) {
  var quads = [], next = [], q;
  if (this._root) quads.push(new src_quad(this._root, this._x0, this._y0, this._x1, this._y1));
  while (q = quads.pop()) {
    var node = q.node;
    if (node.length) {
      var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
      if (child = node[0]) quads.push(new src_quad(child, x0, y0, xm, ym));
      if (child = node[1]) quads.push(new src_quad(child, xm, y0, x1, ym));
      if (child = node[2]) quads.push(new src_quad(child, x0, ym, xm, y1));
      if (child = node[3]) quads.push(new src_quad(child, xm, ym, x1, y1));
    }
    next.push(q);
  }
  while (q = next.pop()) {
    callback(q.node, q.x0, q.y0, q.x1, q.y1);
  }
  return this;
}

;// ../../node_modules/d3-quadtree/src/x.js
function defaultX(d) {
  return d[0];
}

/* harmony default export */ function src_x(_) {
  return arguments.length ? (this._x = _, this) : this._x;
}

;// ../../node_modules/d3-quadtree/src/y.js
function defaultY(d) {
  return d[1];
}

/* harmony default export */ function src_y(_) {
  return arguments.length ? (this._y = _, this) : this._y;
}

;// ../../node_modules/d3-quadtree/src/quadtree.js













function quadtree(nodes, x, y) {
  var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
  return nodes == null ? tree : tree.addAll(nodes);
}

function Quadtree(x, y, x0, y0, x1, y1) {
  this._x = x;
  this._y = y;
  this._x0 = x0;
  this._y0 = y0;
  this._x1 = x1;
  this._y1 = y1;
  this._root = undefined;
}

function leaf_copy(leaf) {
  var copy = {data: leaf.data}, next = copy;
  while (leaf = leaf.next) next = next.next = {data: leaf.data};
  return copy;
}

var treeProto = quadtree.prototype = Quadtree.prototype;

treeProto.copy = function() {
  var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
      node = this._root,
      nodes,
      child;

  if (!node) return copy;

  if (!node.length) return copy._root = leaf_copy(node), copy;

  nodes = [{source: node, target: copy._root = new Array(4)}];
  while (node = nodes.pop()) {
    for (var i = 0; i < 4; ++i) {
      if (child = node.source[i]) {
        if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
        else node.target[i] = leaf_copy(child);
      }
    }
  }

  return copy;
};

treeProto.add = src_add;
treeProto.addAll = addAll;
treeProto.cover = cover;
treeProto.data = src_data;
treeProto.extent = src_extent;
treeProto.find = src_find;
treeProto.remove = remove;
treeProto.removeAll = removeAll;
treeProto.root = root;
treeProto.size = size;
treeProto.visit = src_visit;
treeProto.visitAfter = visitAfter;
treeProto.x = src_x;
treeProto.y = src_y;

;// ../../node_modules/d3-force/src/constant.js
/* harmony default export */ function d3_force_src_constant(x) {
  return function() {
    return x;
  };
}

;// ../../node_modules/d3-force/src/jiggle.js
/* harmony default export */ function jiggle(random) {
  return (random() - 0.5) * 1e-6;
}

;// ../../node_modules/d3-force/src/collide.js




function collide_x(d) {
  return d.x + d.vx;
}

function collide_y(d) {
  return d.y + d.vy;
}

/* harmony default export */ function collide(radius) {
  var nodes,
      radii,
      random,
      strength = 1,
      iterations = 1;

  if (typeof radius !== "function") radius = d3_force_src_constant(radius == null ? 1 : +radius);

  function force() {
    var i, n = nodes.length,
        tree,
        node,
        xi,
        yi,
        ri,
        ri2;

    for (var k = 0; k < iterations; ++k) {
      tree = quadtree(nodes, collide_x, collide_y).visitAfter(prepare);
      for (i = 0; i < n; ++i) {
        node = nodes[i];
        ri = radii[node.index], ri2 = ri * ri;
        xi = node.x + node.vx;
        yi = node.y + node.vy;
        tree.visit(apply);
      }
    }

    function apply(quad, x0, y0, x1, y1) {
      var data = quad.data, rj = quad.r, r = ri + rj;
      if (data) {
        if (data.index > node.index) {
          var x = xi - data.x - data.vx,
              y = yi - data.y - data.vy,
              l = x * x + y * y;
          if (l < r * r) {
            if (x === 0) x = jiggle(random), l += x * x;
            if (y === 0) y = jiggle(random), l += y * y;
            l = (r - (l = Math.sqrt(l))) / l * strength;
            node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
            node.vy += (y *= l) * r;
            data.vx -= x * (r = 1 - r);
            data.vy -= y * r;
          }
        }
        return;
      }
      return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
    }
  }

  function prepare(quad) {
    if (quad.data) return quad.r = radii[quad.data.index];
    for (var i = quad.r = 0; i < 4; ++i) {
      if (quad[i] && quad[i].r > quad.r) {
        quad.r = quad[i].r;
      }
    }
  }

  function initialize() {
    if (!nodes) return;
    var i, n = nodes.length, node;
    radii = new Array(n);
    for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
  }

  force.initialize = function(_nodes, _random) {
    nodes = _nodes;
    random = _random;
    initialize();
  };

  force.iterations = function(_) {
    return arguments.length ? (iterations = +_, force) : iterations;
  };

  force.strength = function(_) {
    return arguments.length ? (strength = +_, force) : strength;
  };

  force.radius = function(_) {
    return arguments.length ? (radius = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : radius;
  };

  return force;
}

;// ../../node_modules/d3-dispatch/src/dispatch.js
var dispatch_noop = {value: () => {}};

function dispatch_dispatch() {
  for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
    if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
    _[t] = [];
  }
  return new Dispatch(_);
}

function Dispatch(_) {
  this._ = _;
}

function parseTypenames(typenames, types) {
  return typenames.trim().split(/^|\s+/).map(function(t) {
    var name = "", i = t.indexOf(".");
    if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
    if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
    return {type: t, name: name};
  });
}

Dispatch.prototype = dispatch_dispatch.prototype = {
  constructor: Dispatch,
  on: function(typename, callback) {
    var _ = this._,
        T = parseTypenames(typename + "", _),
        t,
        i = -1,
        n = T.length;

    // If no callback was specified, return the callback of the given type and name.
    if (arguments.length < 2) {
      while (++i < n) if ((t = (typename = T[i]).type) && (t = dispatch_get(_[t], typename.name))) return t;
      return;
    }

    // If a type was specified, set the callback for the given type and name.
    // Otherwise, if a null callback was specified, remove callbacks of the given name.
    if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
    while (++i < n) {
      if (t = (typename = T[i]).type) _[t] = dispatch_set(_[t], typename.name, callback);
      else if (callback == null) for (t in _) _[t] = dispatch_set(_[t], typename.name, null);
    }

    return this;
  },
  copy: function() {
    var copy = {}, _ = this._;
    for (var t in _) copy[t] = _[t].slice();
    return new Dispatch(copy);
  },
  call: function(type, that) {
    if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
    if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
    for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
  },
  apply: function(type, that, args) {
    if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
    for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
  }
};

function dispatch_get(type, name) {
  for (var i = 0, n = type.length, c; i < n; ++i) {
    if ((c = type[i]).name === name) {
      return c.value;
    }
  }
}

function dispatch_set(type, name, callback) {
  for (var i = 0, n = type.length; i < n; ++i) {
    if (type[i].name === name) {
      type[i] = dispatch_noop, type = type.slice(0, i).concat(type.slice(i + 1));
      break;
    }
  }
  if (callback != null) type.push({name: name, value: callback});
  return type;
}

/* harmony default export */ const src_dispatch = (dispatch_dispatch);

;// ../../node_modules/d3-timer/src/timer.js
var timer_frame = 0, // is an animation frame pending?
    timeout = 0, // is a timeout pending?
    timer_interval = 0, // are any timers active?
    pokeDelay = 1000, // how frequently we check for clock skew
    taskHead,
    taskTail,
    clockLast = 0,
    clockNow = 0,
    clockSkew = 0,
    clock = typeof performance === "object" && performance.now ? performance : Date,
    setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); };

function timer_now() {
  return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
}

function clearNow() {
  clockNow = 0;
}

function Timer() {
  this._call =
  this._time =
  this._next = null;
}

Timer.prototype = timer.prototype = {
  constructor: Timer,
  restart: function(callback, delay, time) {
    if (typeof callback !== "function") throw new TypeError("callback is not a function");
    time = (time == null ? timer_now() : +time) + (delay == null ? 0 : +delay);
    if (!this._next && taskTail !== this) {
      if (taskTail) taskTail._next = this;
      else taskHead = this;
      taskTail = this;
    }
    this._call = callback;
    this._time = time;
    sleep();
  },
  stop: function() {
    if (this._call) {
      this._call = null;
      this._time = Infinity;
      sleep();
    }
  }
};

function timer(callback, delay, time) {
  var t = new Timer;
  t.restart(callback, delay, time);
  return t;
}

function timerFlush() {
  timer_now(); // Get the current time, if not already set.
  ++timer_frame; // Pretend we’ve set an alarm, if we haven’t already.
  var t = taskHead, e;
  while (t) {
    if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e);
    t = t._next;
  }
  --timer_frame;
}

function wake() {
  clockNow = (clockLast = clock.now()) + clockSkew;
  timer_frame = timeout = 0;
  try {
    timerFlush();
  } finally {
    timer_frame = 0;
    nap();
    clockNow = 0;
  }
}

function poke() {
  var now = clock.now(), delay = now - clockLast;
  if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
}

function nap() {
  var t0, t1 = taskHead, t2, time = Infinity;
  while (t1) {
    if (t1._call) {
      if (time > t1._time) time = t1._time;
      t0 = t1, t1 = t1._next;
    } else {
      t2 = t1._next, t1._next = null;
      t1 = t0 ? t0._next = t2 : taskHead = t2;
    }
  }
  taskTail = t0;
  sleep(time);
}

function sleep(time) {
  if (timer_frame) return; // Soonest alarm already set, or will be.
  if (timeout) timeout = clearTimeout(timeout);
  var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
  if (delay > 24) {
    if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
    if (timer_interval) timer_interval = clearInterval(timer_interval);
  } else {
    if (!timer_interval) clockLast = clock.now(), timer_interval = setInterval(poke, pokeDelay);
    timer_frame = 1, setFrame(wake);
  }
}

;// ../../node_modules/d3-force/src/lcg.js
// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
const lcg_a = 1664525;
const lcg_c = 1013904223;
const m = 4294967296; // 2^32

/* harmony default export */ function src_lcg() {
  let s = 1;
  return () => (s = (lcg_a * s + lcg_c) % m) / m;
}

;// ../../node_modules/d3-force/src/simulation.js




function simulation_x(d) {
  return d.x;
}

function simulation_y(d) {
  return d.y;
}

var initialRadius = 10,
    initialAngle = Math.PI * (3 - Math.sqrt(5));

/* harmony default export */ function simulation(nodes) {
  var simulation,
      alpha = 1,
      alphaMin = 0.001,
      alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
      alphaTarget = 0,
      velocityDecay = 0.6,
      forces = new Map(),
      stepper = timer(step),
      event = src_dispatch("tick", "end"),
      random = src_lcg();

  if (nodes == null) nodes = [];

  function step() {
    tick();
    event.call("tick", simulation);
    if (alpha < alphaMin) {
      stepper.stop();
      event.call("end", simulation);
    }
  }

  function tick(iterations) {
    var i, n = nodes.length, node;

    if (iterations === undefined) iterations = 1;

    for (var k = 0; k < iterations; ++k) {
      alpha += (alphaTarget - alpha) * alphaDecay;

      forces.forEach(function(force) {
        force(alpha);
      });

      for (i = 0; i < n; ++i) {
        node = nodes[i];
        if (node.fx == null) node.x += node.vx *= velocityDecay;
        else node.x = node.fx, node.vx = 0;
        if (node.fy == null) node.y += node.vy *= velocityDecay;
        else node.y = node.fy, node.vy = 0;
      }
    }

    return simulation;
  }

  function initializeNodes() {
    for (var i = 0, n = nodes.length, node; i < n; ++i) {
      node = nodes[i], node.index = i;
      if (node.fx != null) node.x = node.fx;
      if (node.fy != null) node.y = node.fy;
      if (isNaN(node.x) || isNaN(node.y)) {
        var radius = initialRadius * Math.sqrt(0.5 + i), angle = i * initialAngle;
        node.x = radius * Math.cos(angle);
        node.y = radius * Math.sin(angle);
      }
      if (isNaN(node.vx) || isNaN(node.vy)) {
        node.vx = node.vy = 0;
      }
    }
  }

  function initializeForce(force) {
    if (force.initialize) force.initialize(nodes, random);
    return force;
  }

  initializeNodes();

  return simulation = {
    tick: tick,

    restart: function() {
      return stepper.restart(step), simulation;
    },

    stop: function() {
      return stepper.stop(), simulation;
    },

    nodes: function(_) {
      return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes;
    },

    alpha: function(_) {
      return arguments.length ? (alpha = +_, simulation) : alpha;
    },

    alphaMin: function(_) {
      return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
    },

    alphaDecay: function(_) {
      return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
    },

    alphaTarget: function(_) {
      return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
    },

    velocityDecay: function(_) {
      return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
    },

    randomSource: function(_) {
      return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random;
    },

    force: function(name, _) {
      return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
    },

    find: function(x, y, radius) {
      var i = 0,
          n = nodes.length,
          dx,
          dy,
          d2,
          node,
          closest;

      if (radius == null) radius = Infinity;
      else radius *= radius;

      for (i = 0; i < n; ++i) {
        node = nodes[i];
        dx = x - node.x;
        dy = y - node.y;
        d2 = dx * dx + dy * dy;
        if (d2 < radius) closest = node, radius = d2;
      }

      return closest;
    },

    on: function(name, _) {
      return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
    }
  };
}

;// ../../node_modules/d3-force/src/manyBody.js





/* harmony default export */ function manyBody() {
  var nodes,
      node,
      random,
      alpha,
      strength = d3_force_src_constant(-30),
      strengths,
      distanceMin2 = 1,
      distanceMax2 = Infinity,
      theta2 = 0.81;

  function force(_) {
    var i, n = nodes.length, tree = quadtree(nodes, simulation_x, simulation_y).visitAfter(accumulate);
    for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
  }

  function initialize() {
    if (!nodes) return;
    var i, n = nodes.length, node;
    strengths = new Array(n);
    for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
  }

  function accumulate(quad) {
    var strength = 0, q, c, weight = 0, x, y, i;

    // For internal nodes, accumulate forces from child quadrants.
    if (quad.length) {
      for (x = y = i = 0; i < 4; ++i) {
        if ((q = quad[i]) && (c = Math.abs(q.value))) {
          strength += q.value, weight += c, x += c * q.x, y += c * q.y;
        }
      }
      quad.x = x / weight;
      quad.y = y / weight;
    }

    // For leaf nodes, accumulate forces from coincident quadrants.
    else {
      q = quad;
      q.x = q.data.x;
      q.y = q.data.y;
      do strength += strengths[q.data.index];
      while (q = q.next);
    }

    quad.value = strength;
  }

  function apply(quad, x1, _, x2) {
    if (!quad.value) return true;

    var x = quad.x - node.x,
        y = quad.y - node.y,
        w = x2 - x1,
        l = x * x + y * y;

    // Apply the Barnes-Hut approximation if possible.
    // Limit forces for very close nodes; randomize direction if coincident.
    if (w * w / theta2 < l) {
      if (l < distanceMax2) {
        if (x === 0) x = jiggle(random), l += x * x;
        if (y === 0) y = jiggle(random), l += y * y;
        if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
        node.vx += x * quad.value * alpha / l;
        node.vy += y * quad.value * alpha / l;
      }
      return true;
    }

    // Otherwise, process points directly.
    else if (quad.length || l >= distanceMax2) return;

    // Limit forces for very close nodes; randomize direction if coincident.
    if (quad.data !== node || quad.next) {
      if (x === 0) x = jiggle(random), l += x * x;
      if (y === 0) y = jiggle(random), l += y * y;
      if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
    }

    do if (quad.data !== node) {
      w = strengths[quad.data.index] * alpha / l;
      node.vx += x * w;
      node.vy += y * w;
    } while (quad = quad.next);
  }

  force.initialize = function(_nodes, _random) {
    nodes = _nodes;
    random = _random;
    initialize();
  };

  force.strength = function(_) {
    return arguments.length ? (strength = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : strength;
  };

  force.distanceMin = function(_) {
    return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
  };

  force.distanceMax = function(_) {
    return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
  };

  force.theta = function(_) {
    return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
  };

  return force;
}

;// ../../node_modules/d3-force/src/link.js



function index(d) {
  return d.index;
}

function link_find(nodeById, nodeId) {
  var node = nodeById.get(nodeId);
  if (!node) throw new Error("node not found: " + nodeId);
  return node;
}

/* harmony default export */ function src_link(links) {
  var id = index,
      strength = defaultStrength,
      strengths,
      distance = d3_force_src_constant(30),
      distances,
      nodes,
      count,
      bias,
      random,
      iterations = 1;

  if (links == null) links = [];

  function defaultStrength(link) {
    return 1 / Math.min(count[link.source.index], count[link.target.index]);
  }

  function force(alpha) {
    for (var k = 0, n = links.length; k < iterations; ++k) {
      for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
        link = links[i], source = link.source, target = link.target;
        x = target.x + target.vx - source.x - source.vx || jiggle(random);
        y = target.y + target.vy - source.y - source.vy || jiggle(random);
        l = Math.sqrt(x * x + y * y);
        l = (l - distances[i]) / l * alpha * strengths[i];
        x *= l, y *= l;
        target.vx -= x * (b = bias[i]);
        target.vy -= y * b;
        source.vx += x * (b = 1 - b);
        source.vy += y * b;
      }
    }
  }

  function initialize() {
    if (!nodes) return;

    var i,
        n = nodes.length,
        m = links.length,
        nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),
        link;

    for (i = 0, count = new Array(n); i < m; ++i) {
      link = links[i], link.index = i;
      if (typeof link.source !== "object") link.source = link_find(nodeById, link.source);
      if (typeof link.target !== "object") link.target = link_find(nodeById, link.target);
      count[link.source.index] = (count[link.source.index] || 0) + 1;
      count[link.target.index] = (count[link.target.index] || 0) + 1;
    }

    for (i = 0, bias = new Array(m); i < m; ++i) {
      link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
    }

    strengths = new Array(m), initializeStrength();
    distances = new Array(m), initializeDistance();
  }

  function initializeStrength() {
    if (!nodes) return;

    for (var i = 0, n = links.length; i < n; ++i) {
      strengths[i] = +strength(links[i], i, links);
    }
  }

  function initializeDistance() {
    if (!nodes) return;

    for (var i = 0, n = links.length; i < n; ++i) {
      distances[i] = +distance(links[i], i, links);
    }
  }

  force.initialize = function(_nodes, _random) {
    nodes = _nodes;
    random = _random;
    initialize();
  };

  force.links = function(_) {
    return arguments.length ? (links = _, initialize(), force) : links;
  };

  force.id = function(_) {
    return arguments.length ? (id = _, force) : id;
  };

  force.iterations = function(_) {
    return arguments.length ? (iterations = +_, force) : iterations;
  };

  force.strength = function(_) {
    return arguments.length ? (strength = typeof _ === "function" ? _ : d3_force_src_constant(+_), initializeStrength(), force) : strength;
  };

  force.distance = function(_) {
    return arguments.length ? (distance = typeof _ === "function" ? _ : d3_force_src_constant(+_), initializeDistance(), force) : distance;
  };

  return force;
}

;// ../../node_modules/d3-force/src/x.js


/* harmony default export */ function d3_force_src_x(x) {
  var strength = d3_force_src_constant(0.1),
      nodes,
      strengths,
      xz;

  if (typeof x !== "function") x = d3_force_src_constant(x == null ? 0 : +x);

  function force(alpha) {
    for (var i = 0, n = nodes.length, node; i < n; ++i) {
      node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
    }
  }

  function initialize() {
    if (!nodes) return;
    var i, n = nodes.length;
    strengths = new Array(n);
    xz = new Array(n);
    for (i = 0; i < n; ++i) {
      strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
    }
  }

  force.initialize = function(_) {
    nodes = _;
    initialize();
  };

  force.strength = function(_) {
    return arguments.length ? (strength = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : strength;
  };

  force.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : x;
  };

  return force;
}

;// ../../node_modules/d3-force/src/y.js


/* harmony default export */ function d3_force_src_y(y) {
  var strength = d3_force_src_constant(0.1),
      nodes,
      strengths,
      yz;

  if (typeof y !== "function") y = d3_force_src_constant(y == null ? 0 : +y);

  function force(alpha) {
    for (var i = 0, n = nodes.length, node; i < n; ++i) {
      node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
    }
  }

  function initialize() {
    if (!nodes) return;
    var i, n = nodes.length;
    strengths = new Array(n);
    yz = new Array(n);
    for (i = 0; i < n; ++i) {
      strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
    }
  }

  force.initialize = function(_) {
    nodes = _;
    initialize();
  };

  force.strength = function(_) {
    return arguments.length ? (strength = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : strength;
  };

  force.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : d3_force_src_constant(+_), initialize(), force) : y;
  };

  return force;
}

;// ../../node_modules/vega-force/build/vega-force.module.js




const ForceMap = {
  center: center,
  collide: collide,
  nbody: manyBody,
  link: src_link,
  x: d3_force_src_x,
  y: d3_force_src_y
};
const Forces = 'forces',
  ForceParams = ['alpha', 'alphaMin', 'alphaTarget', 'velocityDecay', 'forces'],
  ForceConfig = ['static', 'iterations'],
  ForceOutput = ['x', 'y', 'vx', 'vy'];

/**
 * Force simulation layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<object>} params.forces - The forces to apply.
 */
function Force(params) {
  Transform.call(this, null, params);
}
Force.Definition = {
  'type': 'Force',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'static',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'restart',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'iterations',
    'type': 'number',
    'default': 300
  }, {
    'name': 'alpha',
    'type': 'number',
    'default': 1
  }, {
    'name': 'alphaMin',
    'type': 'number',
    'default': 0.001
  }, {
    'name': 'alphaTarget',
    'type': 'number',
    'default': 0
  }, {
    'name': 'velocityDecay',
    'type': 'number',
    'default': 0.4
  }, {
    'name': 'forces',
    'type': 'param',
    'array': true,
    'params': [{
      'key': {
        'force': 'center'
      },
      'params': [{
        'name': 'x',
        'type': 'number',
        'default': 0
      }, {
        'name': 'y',
        'type': 'number',
        'default': 0
      }]
    }, {
      'key': {
        'force': 'collide'
      },
      'params': [{
        'name': 'radius',
        'type': 'number',
        'expr': true
      }, {
        'name': 'strength',
        'type': 'number',
        'default': 0.7
      }, {
        'name': 'iterations',
        'type': 'number',
        'default': 1
      }]
    }, {
      'key': {
        'force': 'nbody'
      },
      'params': [{
        'name': 'strength',
        'type': 'number',
        'default': -30,
        'expr': true
      }, {
        'name': 'theta',
        'type': 'number',
        'default': 0.9
      }, {
        'name': 'distanceMin',
        'type': 'number',
        'default': 1
      }, {
        'name': 'distanceMax',
        'type': 'number'
      }]
    }, {
      'key': {
        'force': 'link'
      },
      'params': [{
        'name': 'links',
        'type': 'data'
      }, {
        'name': 'id',
        'type': 'field'
      }, {
        'name': 'distance',
        'type': 'number',
        'default': 30,
        'expr': true
      }, {
        'name': 'strength',
        'type': 'number',
        'expr': true
      }, {
        'name': 'iterations',
        'type': 'number',
        'default': 1
      }]
    }, {
      'key': {
        'force': 'x'
      },
      'params': [{
        'name': 'strength',
        'type': 'number',
        'default': 0.1
      }, {
        'name': 'x',
        'type': 'field'
      }]
    }, {
      'key': {
        'force': 'y'
      },
      'params': [{
        'name': 'strength',
        'type': 'number',
        'default': 0.1
      }, {
        'name': 'y',
        'type': 'field'
      }]
    }]
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'modify': false,
    'default': ForceOutput
  }]
};
inherits(Force, Transform, {
  transform(_, pulse) {
    var sim = this.value,
      change = pulse.changed(pulse.ADD_REM),
      params = _.modified(ForceParams),
      iters = _.iterations || 300;

    // configure simulation
    if (!sim) {
      this.value = sim = vega_force_module_simulation(pulse.source, _);
      sim.on('tick', rerun(pulse.dataflow, this));
      if (!_.static) {
        change = true;
        sim.tick(); // ensure we run on init
      }
      pulse.modifies('index');
    } else {
      if (change) {
        pulse.modifies('index');
        sim.nodes(pulse.source);
      }
      if (params || pulse.changed(pulse.MOD)) {
        setup(sim, _, 0, pulse);
      }
    }

    // run simulation
    if (params || change || _.modified(ForceConfig) || pulse.changed() && _.restart) {
      sim.alpha(Math.max(sim.alpha(), _.alpha || 1)).alphaDecay(1 - Math.pow(sim.alphaMin(), 1 / iters));
      if (_.static) {
        for (sim.stop(); --iters >= 0;) sim.tick();
      } else {
        if (sim.stopped()) sim.restart();
        if (!change) return pulse.StopPropagation; // defer to sim ticks
      }
    }
    return this.finish(_, pulse);
  },
  finish(_, pulse) {
    const dataflow = pulse.dataflow;

    // inspect dependencies, touch link source data
    for (let args = this._argops, j = 0, m = args.length, arg; j < m; ++j) {
      arg = args[j];
      if (arg.name !== Forces || arg.op._argval.force !== 'link') {
        continue;
      }
      for (var ops = arg.op._argops, i = 0, n = ops.length, op; i < n; ++i) {
        if (ops[i].name === 'links' && (op = ops[i].op.source)) {
          dataflow.pulse(op, dataflow.changeset().reflow());
          break;
        }
      }
    }

    // reflow all nodes
    return pulse.reflow(_.modified()).modifies(ForceOutput);
  }
});
function rerun(df, op) {
  return () => df.touch(op).run();
}
function vega_force_module_simulation(nodes, _) {
  const sim = simulation(nodes),
    stop = sim.stop,
    restart = sim.restart;
  let stopped = false;
  sim.stopped = () => stopped;
  sim.restart = () => (stopped = false, restart());
  sim.stop = () => (stopped = true, stop());
  return setup(sim, _, true).on('end', () => stopped = true);
}
function setup(sim, _, init, pulse) {
  var f = vega_util_module_array(_.forces),
    i,
    n,
    p,
    name;
  for (i = 0, n = ForceParams.length; i < n; ++i) {
    p = ForceParams[i];
    if (p !== Forces && _.modified(p)) sim[p](_[p]);
  }
  for (i = 0, n = f.length; i < n; ++i) {
    name = Forces + i;
    p = init || _.modified(Forces, i) ? getForce(f[i]) : pulse && modified(f[i], pulse) ? sim.force(name) : null;
    if (p) sim.force(name, p);
  }
  for (n = sim.numForces || 0; i < n; ++i) {
    sim.force(Forces + i, null); // remove
  }
  sim.numForces = f.length;
  return sim;
}
function modified(f, pulse) {
  var k, v;
  for (k in f) {
    if (vega_util_module_isFunction(v = f[k]) && pulse.modified(accessorFields(v))) return 1;
  }
  return 0;
}
function getForce(_) {
  var f, p;
  if (!vega_util_module_has(ForceMap, _.force)) {
    vega_util_module_error('Unrecognized force: ' + _.force);
  }
  f = ForceMap[_.force]();
  for (p in _) {
    if (vega_util_module_isFunction(f[p])) setForceParam(f[p], _[p], _);
  }
  return f;
}
function setForceParam(f, v, _) {
  f(vega_util_module_isFunction(v) ? d => v(d, _) : v);
}



;// ../../node_modules/d3-hierarchy/src/hierarchy/count.js
function count_count(node) {
  var sum = 0,
      children = node.children,
      i = children && children.length;
  if (!i) sum = 1;
  else while (--i >= 0) sum += children[i].value;
  node.value = sum;
}

/* harmony default export */ function hierarchy_count() {
  return this.eachAfter(count_count);
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/each.js
/* harmony default export */ function hierarchy_each(callback, that) {
  let index = -1;
  for (const node of this) {
    callback.call(that, node, ++index, this);
  }
  return this;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/eachBefore.js
/* harmony default export */ function eachBefore(callback, that) {
  var node = this, nodes = [node], children, i, index = -1;
  while (node = nodes.pop()) {
    callback.call(that, node, ++index, this);
    if (children = node.children) {
      for (i = children.length - 1; i >= 0; --i) {
        nodes.push(children[i]);
      }
    }
  }
  return this;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/eachAfter.js
/* harmony default export */ function eachAfter(callback, that) {
  var node = this, nodes = [node], next = [], children, i, n, index = -1;
  while (node = nodes.pop()) {
    next.push(node);
    if (children = node.children) {
      for (i = 0, n = children.length; i < n; ++i) {
        nodes.push(children[i]);
      }
    }
  }
  while (node = next.pop()) {
    callback.call(that, node, ++index, this);
  }
  return this;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/find.js
/* harmony default export */ function hierarchy_find(callback, that) {
  let index = -1;
  for (const node of this) {
    if (callback.call(that, node, ++index, this)) {
      return node;
    }
  }
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/sum.js
/* harmony default export */ function hierarchy_sum(value) {
  return this.eachAfter(function(node) {
    var sum = +value(node.data) || 0,
        children = node.children,
        i = children && children.length;
    while (--i >= 0) sum += children[i].value;
    node.value = sum;
  });
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/sort.js
/* harmony default export */ function hierarchy_sort(compare) {
  return this.eachBefore(function(node) {
    if (node.children) {
      node.children.sort(compare);
    }
  });
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/path.js
/* harmony default export */ function hierarchy_path(end) {
  var start = this,
      ancestor = leastCommonAncestor(start, end),
      nodes = [start];
  while (start !== ancestor) {
    start = start.parent;
    nodes.push(start);
  }
  var k = nodes.length;
  while (end !== ancestor) {
    nodes.splice(k, 0, end);
    end = end.parent;
  }
  return nodes;
}

function leastCommonAncestor(a, b) {
  if (a === b) return a;
  var aNodes = a.ancestors(),
      bNodes = b.ancestors(),
      c = null;
  a = aNodes.pop();
  b = bNodes.pop();
  while (a === b) {
    c = a;
    a = aNodes.pop();
    b = bNodes.pop();
  }
  return c;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/ancestors.js
/* harmony default export */ function ancestors() {
  var node = this, nodes = [node];
  while (node = node.parent) {
    nodes.push(node);
  }
  return nodes;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/descendants.js
/* harmony default export */ function descendants() {
  return Array.from(this);
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/leaves.js
/* harmony default export */ function leaves() {
  var leaves = [];
  this.eachBefore(function(node) {
    if (!node.children) {
      leaves.push(node);
    }
  });
  return leaves;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/links.js
/* harmony default export */ function links() {
  var root = this, links = [];
  root.each(function(node) {
    if (node !== root) { // Don’t include the root’s parent, if any.
      links.push({source: node.parent, target: node});
    }
  });
  return links;
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/iterator.js
/* harmony default export */ function* iterator() {
  var node = this, current, next = [node], children, i, n;
  do {
    current = next.reverse(), next = [];
    while (node = current.pop()) {
      yield node;
      if (children = node.children) {
        for (i = 0, n = children.length; i < n; ++i) {
          next.push(children[i]);
        }
      }
    }
  } while (next.length);
}

;// ../../node_modules/d3-hierarchy/src/hierarchy/index.js














function hierarchy(data, children) {
  if (data instanceof Map) {
    data = [undefined, data];
    if (children === undefined) children = mapChildren;
  } else if (children === undefined) {
    children = objectChildren;
  }

  var root = new hierarchy_Node(data),
      node,
      nodes = [root],
      child,
      childs,
      i,
      n;

  while (node = nodes.pop()) {
    if ((childs = children(node.data)) && (n = (childs = Array.from(childs)).length)) {
      node.children = childs;
      for (i = n - 1; i >= 0; --i) {
        nodes.push(child = childs[i] = new hierarchy_Node(childs[i]));
        child.parent = node;
        child.depth = node.depth + 1;
      }
    }
  }

  return root.eachBefore(computeHeight);
}

function node_copy() {
  return hierarchy(this).eachBefore(copyData);
}

function objectChildren(d) {
  return d.children;
}

function mapChildren(d) {
  return Array.isArray(d) ? d[1] : null;
}

function copyData(node) {
  if (node.data.value !== undefined) node.value = node.data.value;
  node.data = node.data.data;
}

function computeHeight(node) {
  var height = 0;
  do node.height = height;
  while ((node = node.parent) && (node.height < ++height));
}

function hierarchy_Node(data) {
  this.data = data;
  this.depth =
  this.height = 0;
  this.parent = null;
}

hierarchy_Node.prototype = hierarchy.prototype = {
  constructor: hierarchy_Node,
  count: hierarchy_count,
  each: hierarchy_each,
  eachAfter: eachAfter,
  eachBefore: eachBefore,
  find: hierarchy_find,
  sum: hierarchy_sum,
  sort: hierarchy_sort,
  path: hierarchy_path,
  ancestors: ancestors,
  descendants: descendants,
  leaves: leaves,
  links: links,
  copy: node_copy,
  [Symbol.iterator]: iterator
};

;// ../../node_modules/d3-hierarchy/src/accessors.js
function optional(f) {
  return f == null ? null : required(f);
}

function required(f) {
  if (typeof f !== "function") throw new Error;
  return f;
}

;// ../../node_modules/d3-hierarchy/src/constant.js
function constantZero() {
  return 0;
}

/* harmony default export */ function d3_hierarchy_src_constant(x) {
  return function() {
    return x;
  };
}

;// ../../node_modules/d3-hierarchy/src/lcg.js
// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
const src_lcg_a = 1664525;
const src_lcg_c = 1013904223;
const lcg_m = 4294967296; // 2^32

/* harmony default export */ function d3_hierarchy_src_lcg() {
  let s = 1;
  return () => (s = (src_lcg_a * s + src_lcg_c) % lcg_m) / lcg_m;
}

;// ../../node_modules/d3-hierarchy/src/array.js
/* harmony default export */ function d3_hierarchy_src_array(x) {
  return typeof x === "object" && "length" in x
    ? x // Array, TypedArray, NodeList, array-like
    : Array.from(x); // Map, Set, iterable, string, or anything else
}

function shuffle(array, random) {
  let m = array.length,
      t,
      i;

  while (m) {
    i = random() * m-- | 0;
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }

  return array;
}

;// ../../node_modules/d3-hierarchy/src/pack/enclose.js



/* harmony default export */ function enclose(circles) {
  return packEncloseRandom(circles, lcg());
}

function packEncloseRandom(circles, random) {
  var i = 0, n = (circles = shuffle(Array.from(circles), random)).length, B = [], p, e;

  while (i < n) {
    p = circles[i];
    if (e && enclosesWeak(e, p)) ++i;
    else e = encloseBasis(B = extendBasis(B, p)), i = 0;
  }

  return e;
}

function extendBasis(B, p) {
  var i, j;

  if (enclosesWeakAll(p, B)) return [p];

  // If we get here then B must have at least one element.
  for (i = 0; i < B.length; ++i) {
    if (enclosesNot(p, B[i])
        && enclosesWeakAll(encloseBasis2(B[i], p), B)) {
      return [B[i], p];
    }
  }

  // If we get here then B must have at least two elements.
  for (i = 0; i < B.length - 1; ++i) {
    for (j = i + 1; j < B.length; ++j) {
      if (enclosesNot(encloseBasis2(B[i], B[j]), p)
          && enclosesNot(encloseBasis2(B[i], p), B[j])
          && enclosesNot(encloseBasis2(B[j], p), B[i])
          && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) {
        return [B[i], B[j], p];
      }
    }
  }

  // If we get here then something is very wrong.
  throw new Error;
}

function enclosesNot(a, b) {
  var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y;
  return dr < 0 || dr * dr < dx * dx + dy * dy;
}

function enclosesWeak(a, b) {
  var dr = a.r - b.r + Math.max(a.r, b.r, 1) * 1e-9, dx = b.x - a.x, dy = b.y - a.y;
  return dr > 0 && dr * dr > dx * dx + dy * dy;
}

function enclosesWeakAll(a, B) {
  for (var i = 0; i < B.length; ++i) {
    if (!enclosesWeak(a, B[i])) {
      return false;
    }
  }
  return true;
}

function encloseBasis(B) {
  switch (B.length) {
    case 1: return encloseBasis1(B[0]);
    case 2: return encloseBasis2(B[0], B[1]);
    case 3: return encloseBasis3(B[0], B[1], B[2]);
  }
}

function encloseBasis1(a) {
  return {
    x: a.x,
    y: a.y,
    r: a.r
  };
}

function encloseBasis2(a, b) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
      l = Math.sqrt(x21 * x21 + y21 * y21);
  return {
    x: (x1 + x2 + x21 / l * r21) / 2,
    y: (y1 + y2 + y21 / l * r21) / 2,
    r: (l + r1 + r2) / 2
  };
}

function encloseBasis3(a, b, c) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x3 = c.x, y3 = c.y, r3 = c.r,
      a2 = x1 - x2,
      a3 = x1 - x3,
      b2 = y1 - y2,
      b3 = y1 - y3,
      c2 = r2 - r1,
      c3 = r3 - r1,
      d1 = x1 * x1 + y1 * y1 - r1 * r1,
      d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2,
      d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3,
      ab = a3 * b2 - a2 * b3,
      xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1,
      xb = (b3 * c2 - b2 * c3) / ab,
      ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1,
      yb = (a2 * c3 - a3 * c2) / ab,
      A = xb * xb + yb * yb - 1,
      B = 2 * (r1 + xa * xb + ya * yb),
      C = xa * xa + ya * ya - r1 * r1,
      r = -(Math.abs(A) > 1e-6 ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B);
  return {
    x: x1 + xa + xb * r,
    y: y1 + ya + yb * r,
    r: r
  };
}

;// ../../node_modules/d3-hierarchy/src/pack/siblings.js




function place(b, a, c) {
  var dx = b.x - a.x, x, a2,
      dy = b.y - a.y, y, b2,
      d2 = dx * dx + dy * dy;
  if (d2) {
    a2 = a.r + c.r, a2 *= a2;
    b2 = b.r + c.r, b2 *= b2;
    if (a2 > b2) {
      x = (d2 + b2 - a2) / (2 * d2);
      y = Math.sqrt(Math.max(0, b2 / d2 - x * x));
      c.x = b.x - x * dx - y * dy;
      c.y = b.y - x * dy + y * dx;
    } else {
      x = (d2 + a2 - b2) / (2 * d2);
      y = Math.sqrt(Math.max(0, a2 / d2 - x * x));
      c.x = a.x + x * dx - y * dy;
      c.y = a.y + x * dy + y * dx;
    }
  } else {
    c.x = a.x + c.r;
    c.y = a.y;
  }
}

function intersects(a, b) {
  var dr = a.r + b.r - 1e-6, dx = b.x - a.x, dy = b.y - a.y;
  return dr > 0 && dr * dr > dx * dx + dy * dy;
}

function score(node) {
  var a = node._,
      b = node.next._,
      ab = a.r + b.r,
      dx = (a.x * b.r + b.x * a.r) / ab,
      dy = (a.y * b.r + b.y * a.r) / ab;
  return dx * dx + dy * dy;
}

function siblings_Node(circle) {
  this._ = circle;
  this.next = null;
  this.previous = null;
}

function packSiblingsRandom(circles, random) {
  if (!(n = (circles = d3_hierarchy_src_array(circles)).length)) return 0;

  var a, b, c, n, aa, ca, i, j, k, sj, sk;

  // Place the first circle.
  a = circles[0], a.x = 0, a.y = 0;
  if (!(n > 1)) return a.r;

  // Place the second circle.
  b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
  if (!(n > 2)) return a.r + b.r;

  // Place the third circle.
  place(b, a, c = circles[2]);

  // Initialize the front-chain using the first three circles a, b and c.
  a = new siblings_Node(a), b = new siblings_Node(b), c = new siblings_Node(c);
  a.next = c.previous = b;
  b.next = a.previous = c;
  c.next = b.previous = a;

  // Attempt to place each remaining circle…
  pack: for (i = 3; i < n; ++i) {
    place(a._, b._, c = circles[i]), c = new siblings_Node(c);

    // Find the closest intersecting circle on the front-chain, if any.
    // “Closeness” is determined by linear distance along the front-chain.
    // “Ahead” or “behind” is likewise determined by linear distance.
    j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
    do {
      if (sj <= sk) {
        if (intersects(j._, c._)) {
          b = j, a.next = b, b.previous = a, --i;
          continue pack;
        }
        sj += j._.r, j = j.next;
      } else {
        if (intersects(k._, c._)) {
          a = k, a.next = b, b.previous = a, --i;
          continue pack;
        }
        sk += k._.r, k = k.previous;
      }
    } while (j !== k.next);

    // Success! Insert the new circle c between a and b.
    c.previous = a, c.next = b, a.next = b.previous = b = c;

    // Compute the new closest circle pair to the centroid.
    aa = score(a);
    while ((c = c.next) !== b) {
      if ((ca = score(c)) < aa) {
        a = c, aa = ca;
      }
    }
    b = a.next;
  }

  // Compute the enclosing circle of the front chain.
  a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = packEncloseRandom(a, random);

  // Translate the circles to put the enclosing circle around the origin.
  for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;

  return c.r;
}

/* harmony default export */ function siblings(circles) {
  packSiblingsRandom(circles, lcg());
  return circles;
}

;// ../../node_modules/d3-hierarchy/src/pack/index.js





function defaultRadius(d) {
  return Math.sqrt(d.value);
}

/* harmony default export */ function pack() {
  var radius = null,
      dx = 1,
      dy = 1,
      padding = constantZero;

  function pack(root) {
    const random = d3_hierarchy_src_lcg();
    root.x = dx / 2, root.y = dy / 2;
    if (radius) {
      root.eachBefore(radiusLeaf(radius))
          .eachAfter(packChildrenRandom(padding, 0.5, random))
          .eachBefore(translateChild(1));
    } else {
      root.eachBefore(radiusLeaf(defaultRadius))
          .eachAfter(packChildrenRandom(constantZero, 1, random))
          .eachAfter(packChildrenRandom(padding, root.r / Math.min(dx, dy), random))
          .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
    }
    return root;
  }

  pack.radius = function(x) {
    return arguments.length ? (radius = optional(x), pack) : radius;
  };

  pack.size = function(x) {
    return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
  };

  pack.padding = function(x) {
    return arguments.length ? (padding = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), pack) : padding;
  };

  return pack;
}

function radiusLeaf(radius) {
  return function(node) {
    if (!node.children) {
      node.r = Math.max(0, +radius(node) || 0);
    }
  };
}

function packChildrenRandom(padding, k, random) {
  return function(node) {
    if (children = node.children) {
      var children,
          i,
          n = children.length,
          r = padding(node) * k || 0,
          e;

      if (r) for (i = 0; i < n; ++i) children[i].r += r;
      e = packSiblingsRandom(children, random);
      if (r) for (i = 0; i < n; ++i) children[i].r -= r;
      node.r = e + r;
    }
  };
}

function translateChild(k) {
  return function(node) {
    var parent = node.parent;
    node.r *= k;
    if (parent) {
      node.x = parent.x + k * node.x;
      node.y = parent.y + k * node.y;
    }
  };
}

;// ../../node_modules/d3-hierarchy/src/treemap/round.js
/* harmony default export */ function treemap_round(node) {
  node.x0 = Math.round(node.x0);
  node.y0 = Math.round(node.y0);
  node.x1 = Math.round(node.x1);
  node.y1 = Math.round(node.y1);
}

;// ../../node_modules/d3-hierarchy/src/treemap/dice.js
/* harmony default export */ function dice(parent, x0, y0, x1, y1) {
  var nodes = parent.children,
      node,
      i = -1,
      n = nodes.length,
      k = parent.value && (x1 - x0) / parent.value;

  while (++i < n) {
    node = nodes[i], node.y0 = y0, node.y1 = y1;
    node.x0 = x0, node.x1 = x0 += node.value * k;
  }
}

;// ../../node_modules/d3-hierarchy/src/partition.js



/* harmony default export */ function src_partition() {
  var dx = 1,
      dy = 1,
      padding = 0,
      round = false;

  function partition(root) {
    var n = root.height + 1;
    root.x0 =
    root.y0 = padding;
    root.x1 = dx;
    root.y1 = dy / n;
    root.eachBefore(positionNode(dy, n));
    if (round) root.eachBefore(treemap_round);
    return root;
  }

  function positionNode(dy, n) {
    return function(node) {
      if (node.children) {
        dice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
      }
      var x0 = node.x0,
          y0 = node.y0,
          x1 = node.x1 - padding,
          y1 = node.y1 - padding;
      if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
      if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
      node.x0 = x0;
      node.y0 = y0;
      node.x1 = x1;
      node.y1 = y1;
    };
  }

  partition.round = function(x) {
    return arguments.length ? (round = !!x, partition) : round;
  };

  partition.size = function(x) {
    return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
  };

  partition.padding = function(x) {
    return arguments.length ? (padding = +x, partition) : padding;
  };

  return partition;
}

;// ../../node_modules/d3-hierarchy/src/stratify.js



var preroot = {depth: -1},
    ambiguous = {},
    imputed = {};

function defaultId(d) {
  return d.id;
}

function defaultParentId(d) {
  return d.parentId;
}

/* harmony default export */ function stratify() {
  var id = defaultId,
      parentId = defaultParentId,
      path;

  function stratify(data) {
    var nodes = Array.from(data),
        currentId = id,
        currentParentId = parentId,
        n,
        d,
        i,
        root,
        parent,
        node,
        nodeId,
        nodeKey,
        nodeByKey = new Map;

    if (path != null) {
      const I = nodes.map((d, i) => stratify_normalize(path(d, i, data)));
      const P = I.map(parentof);
      const S = new Set(I).add("");
      for (const i of P) {
        if (!S.has(i)) {
          S.add(i);
          I.push(i);
          P.push(parentof(i));
          nodes.push(imputed);
        }
      }
      currentId = (_, i) => I[i];
      currentParentId = (_, i) => P[i];
    }

    for (i = 0, n = nodes.length; i < n; ++i) {
      d = nodes[i], node = nodes[i] = new hierarchy_Node(d);
      if ((nodeId = currentId(d, i, data)) != null && (nodeId += "")) {
        nodeKey = node.id = nodeId;
        nodeByKey.set(nodeKey, nodeByKey.has(nodeKey) ? ambiguous : node);
      }
      if ((nodeId = currentParentId(d, i, data)) != null && (nodeId += "")) {
        node.parent = nodeId;
      }
    }

    for (i = 0; i < n; ++i) {
      node = nodes[i];
      if (nodeId = node.parent) {
        parent = nodeByKey.get(nodeId);
        if (!parent) throw new Error("missing: " + nodeId);
        if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
        if (parent.children) parent.children.push(node);
        else parent.children = [node];
        node.parent = parent;
      } else {
        if (root) throw new Error("multiple roots");
        root = node;
      }
    }

    if (!root) throw new Error("no root");

    // When imputing internal nodes, only introduce roots if needed.
    // Then replace the imputed marker data with null.
    if (path != null) {
      while (root.data === imputed && root.children.length === 1) {
        root = root.children[0], --n;
      }
      for (let i = nodes.length - 1; i >= 0; --i) {
        node = nodes[i];
        if (node.data !== imputed) break;
        node.data = null;
      }
    }

    root.parent = preroot;
    root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
    root.parent = null;
    if (n > 0) throw new Error("cycle");

    return root;
  }

  stratify.id = function(x) {
    return arguments.length ? (id = optional(x), stratify) : id;
  };

  stratify.parentId = function(x) {
    return arguments.length ? (parentId = optional(x), stratify) : parentId;
  };

  stratify.path = function(x) {
    return arguments.length ? (path = optional(x), stratify) : path;
  };

  return stratify;
}

// To normalize a path, we coerce to a string, strip the trailing slash if any
// (as long as the trailing slash is not immediately preceded by another slash),
// and add leading slash if missing.
function stratify_normalize(path) {
  path = `${path}`;
  let i = path.length;
  if (slash(path, i - 1) && !slash(path, i - 2)) path = path.slice(0, -1);
  return path[0] === "/" ? path : `/${path}`;
}

// Walk backwards to find the first slash that is not the leading slash, e.g.:
// "/foo/bar" ⇥ "/foo", "/foo" ⇥ "/", "/" ↦ "". (The root is special-cased
// because the id of the root must be a truthy value.)
function parentof(path) {
  let i = path.length;
  if (i < 2) return "";
  while (--i > 1) if (slash(path, i)) break;
  return path.slice(0, i);
}

// Slashes can be escaped; to determine whether a slash is a path delimiter, we
// count the number of preceding backslashes escaping the forward slash: an odd
// number indicates an escaped forward slash.
function slash(path, i) {
  if (path[i] === "/") {
    let k = 0;
    while (i > 0 && path[--i] === "\\") ++k;
    if ((k & 1) === 0) return true;
  }
  return false;
}

;// ../../node_modules/d3-hierarchy/src/tree.js


function defaultSeparation(a, b) {
  return a.parent === b.parent ? 1 : 2;
}

// function radialSeparation(a, b) {
//   return (a.parent === b.parent ? 1 : 2) / a.depth;
// }

// This function is used to traverse the left contour of a subtree (or
// subforest). It returns the successor of v on this contour. This successor is
// either given by the leftmost child of v or by the thread of v. The function
// returns null if and only if v is on the highest level of its subtree.
function nextLeft(v) {
  var children = v.children;
  return children ? children[0] : v.t;
}

// This function works analogously to nextLeft.
function nextRight(v) {
  var children = v.children;
  return children ? children[children.length - 1] : v.t;
}

// Shifts the current subtree rooted at w+. This is done by increasing
// prelim(w+) and mod(w+) by shift.
function moveSubtree(wm, wp, shift) {
  var change = shift / (wp.i - wm.i);
  wp.c -= change;
  wp.s += shift;
  wm.c += change;
  wp.z += shift;
  wp.m += shift;
}

// All other shifts, applied to the smaller subtrees between w- and w+, are
// performed by this function. To prepare the shifts, we have to adjust
// change(w+), shift(w+), and change(w-).
function executeShifts(v) {
  var shift = 0,
      change = 0,
      children = v.children,
      i = children.length,
      w;
  while (--i >= 0) {
    w = children[i];
    w.z += shift;
    w.m += shift;
    shift += w.s + (change += w.c);
  }
}

// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
// returns the specified (default) ancestor.
function nextAncestor(vim, v, ancestor) {
  return vim.a.parent === v.parent ? vim.a : ancestor;
}

function TreeNode(node, i) {
  this._ = node;
  this.parent = null;
  this.children = null;
  this.A = null; // default ancestor
  this.a = this; // ancestor
  this.z = 0; // prelim
  this.m = 0; // mod
  this.c = 0; // change
  this.s = 0; // shift
  this.t = null; // thread
  this.i = i; // number
}

TreeNode.prototype = Object.create(hierarchy_Node.prototype);

function treeRoot(root) {
  var tree = new TreeNode(root, 0),
      node,
      nodes = [tree],
      child,
      children,
      i,
      n;

  while (node = nodes.pop()) {
    if (children = node._.children) {
      node.children = new Array(n = children.length);
      for (i = n - 1; i >= 0; --i) {
        nodes.push(child = node.children[i] = new TreeNode(children[i], i));
        child.parent = node;
      }
    }
  }

  (tree.parent = new TreeNode(null, 0)).children = [tree];
  return tree;
}

// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
/* harmony default export */ function tree() {
  var separation = defaultSeparation,
      dx = 1,
      dy = 1,
      nodeSize = null;

  function tree(root) {
    var t = treeRoot(root);

    // Compute the layout using Buchheim et al.’s algorithm.
    t.eachAfter(firstWalk), t.parent.m = -t.z;
    t.eachBefore(secondWalk);

    // If a fixed node size is specified, scale x and y.
    if (nodeSize) root.eachBefore(sizeNode);

    // If a fixed tree size is specified, scale x and y based on the extent.
    // Compute the left-most, right-most, and depth-most nodes for extents.
    else {
      var left = root,
          right = root,
          bottom = root;
      root.eachBefore(function(node) {
        if (node.x < left.x) left = node;
        if (node.x > right.x) right = node;
        if (node.depth > bottom.depth) bottom = node;
      });
      var s = left === right ? 1 : separation(left, right) / 2,
          tx = s - left.x,
          kx = dx / (right.x + s + tx),
          ky = dy / (bottom.depth || 1);
      root.eachBefore(function(node) {
        node.x = (node.x + tx) * kx;
        node.y = node.depth * ky;
      });
    }

    return root;
  }

  // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
  // applied recursively to the children of v, as well as the function
  // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
  // node v is placed to the midpoint of its outermost children.
  function firstWalk(v) {
    var children = v.children,
        siblings = v.parent.children,
        w = v.i ? siblings[v.i - 1] : null;
    if (children) {
      executeShifts(v);
      var midpoint = (children[0].z + children[children.length - 1].z) / 2;
      if (w) {
        v.z = w.z + separation(v._, w._);
        v.m = v.z - midpoint;
      } else {
        v.z = midpoint;
      }
    } else if (w) {
      v.z = w.z + separation(v._, w._);
    }
    v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
  }

  // Computes all real x-coordinates by summing up the modifiers recursively.
  function secondWalk(v) {
    v._.x = v.z + v.parent.m;
    v.m += v.parent.m;
  }

  // The core of the algorithm. Here, a new subtree is combined with the
  // previous subtrees. Threads are used to traverse the inside and outside
  // contours of the left and right subtree up to the highest common level. The
  // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
  // superscript o means outside and i means inside, the subscript - means left
  // subtree and + means right subtree. For summing up the modifiers along the
  // contour, we use respective variables si+, si-, so-, and so+. Whenever two
  // nodes of the inside contours conflict, we compute the left one of the
  // greatest uncommon ancestors using the function ANCESTOR and call MOVE
  // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
  // Finally, we add a new thread (if necessary).
  function apportion(v, w, ancestor) {
    if (w) {
      var vip = v,
          vop = v,
          vim = w,
          vom = vip.parent.children[0],
          sip = vip.m,
          sop = vop.m,
          sim = vim.m,
          som = vom.m,
          shift;
      while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
        vom = nextLeft(vom);
        vop = nextRight(vop);
        vop.a = v;
        shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
        if (shift > 0) {
          moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
          sip += shift;
          sop += shift;
        }
        sim += vim.m;
        sip += vip.m;
        som += vom.m;
        sop += vop.m;
      }
      if (vim && !nextRight(vop)) {
        vop.t = vim;
        vop.m += sim - sop;
      }
      if (vip && !nextLeft(vom)) {
        vom.t = vip;
        vom.m += sip - som;
        ancestor = v;
      }
    }
    return ancestor;
  }

  function sizeNode(node) {
    node.x *= dx;
    node.y = node.depth * dy;
  }

  tree.separation = function(x) {
    return arguments.length ? (separation = x, tree) : separation;
  };

  tree.size = function(x) {
    return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
  };

  tree.nodeSize = function(x) {
    return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
  };

  return tree;
}

;// ../../node_modules/d3-hierarchy/src/cluster.js
function cluster_defaultSeparation(a, b) {
  return a.parent === b.parent ? 1 : 2;
}

function meanX(children) {
  return children.reduce(meanXReduce, 0) / children.length;
}

function meanXReduce(x, c) {
  return x + c.x;
}

function maxY(children) {
  return 1 + children.reduce(maxYReduce, 0);
}

function maxYReduce(y, c) {
  return Math.max(y, c.y);
}

function leafLeft(node) {
  var children;
  while (children = node.children) node = children[0];
  return node;
}

function leafRight(node) {
  var children;
  while (children = node.children) node = children[children.length - 1];
  return node;
}

/* harmony default export */ function cluster() {
  var separation = cluster_defaultSeparation,
      dx = 1,
      dy = 1,
      nodeSize = false;

  function cluster(root) {
    var previousNode,
        x = 0;

    // First walk, computing the initial x & y values.
    root.eachAfter(function(node) {
      var children = node.children;
      if (children) {
        node.x = meanX(children);
        node.y = maxY(children);
      } else {
        node.x = previousNode ? x += separation(node, previousNode) : 0;
        node.y = 0;
        previousNode = node;
      }
    });

    var left = leafLeft(root),
        right = leafRight(root),
        x0 = left.x - separation(left, right) / 2,
        x1 = right.x + separation(right, left) / 2;

    // Second walk, normalizing x & y to the desired size.
    return root.eachAfter(nodeSize ? function(node) {
      node.x = (node.x - root.x) * dx;
      node.y = (root.y - node.y) * dy;
    } : function(node) {
      node.x = (node.x - x0) / (x1 - x0) * dx;
      node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
    });
  }

  cluster.separation = function(x) {
    return arguments.length ? (separation = x, cluster) : separation;
  };

  cluster.size = function(x) {
    return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
  };

  cluster.nodeSize = function(x) {
    return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
  };

  return cluster;
}

;// ../../node_modules/d3-hierarchy/src/treemap/binary.js
/* harmony default export */ function treemap_binary(parent, x0, y0, x1, y1) {
  var nodes = parent.children,
      i, n = nodes.length,
      sum, sums = new Array(n + 1);

  for (sums[0] = sum = i = 0; i < n; ++i) {
    sums[i + 1] = sum += nodes[i].value;
  }

  partition(0, n, parent.value, x0, y0, x1, y1);

  function partition(i, j, value, x0, y0, x1, y1) {
    if (i >= j - 1) {
      var node = nodes[i];
      node.x0 = x0, node.y0 = y0;
      node.x1 = x1, node.y1 = y1;
      return;
    }

    var valueOffset = sums[i],
        valueTarget = (value / 2) + valueOffset,
        k = i + 1,
        hi = j - 1;

    while (k < hi) {
      var mid = k + hi >>> 1;
      if (sums[mid] < valueTarget) k = mid + 1;
      else hi = mid;
    }

    if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k;

    var valueLeft = sums[k] - valueOffset,
        valueRight = value - valueLeft;

    if ((x1 - x0) > (y1 - y0)) {
      var xk = value ? (x0 * valueRight + x1 * valueLeft) / value : x1;
      partition(i, k, valueLeft, x0, y0, xk, y1);
      partition(k, j, valueRight, xk, y0, x1, y1);
    } else {
      var yk = value ? (y0 * valueRight + y1 * valueLeft) / value : y1;
      partition(i, k, valueLeft, x0, y0, x1, yk);
      partition(k, j, valueRight, x0, yk, x1, y1);
    }
  }
}

;// ../../node_modules/d3-hierarchy/src/treemap/slice.js
/* harmony default export */ function treemap_slice(parent, x0, y0, x1, y1) {
  var nodes = parent.children,
      node,
      i = -1,
      n = nodes.length,
      k = parent.value && (y1 - y0) / parent.value;

  while (++i < n) {
    node = nodes[i], node.x0 = x0, node.x1 = x1;
    node.y0 = y0, node.y1 = y0 += node.value * k;
  }
}

;// ../../node_modules/d3-hierarchy/src/treemap/sliceDice.js



/* harmony default export */ function sliceDice(parent, x0, y0, x1, y1) {
  (parent.depth & 1 ? treemap_slice : dice)(parent, x0, y0, x1, y1);
}

;// ../../node_modules/d3-hierarchy/src/treemap/squarify.js



var phi = (1 + Math.sqrt(5)) / 2;

function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
  var rows = [],
      nodes = parent.children,
      row,
      nodeValue,
      i0 = 0,
      i1 = 0,
      n = nodes.length,
      dx, dy,
      value = parent.value,
      sumValue,
      minValue,
      maxValue,
      newRatio,
      minRatio,
      alpha,
      beta;

  while (i0 < n) {
    dx = x1 - x0, dy = y1 - y0;

    // Find the next non-empty node.
    do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
    minValue = maxValue = sumValue;
    alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
    beta = sumValue * sumValue * alpha;
    minRatio = Math.max(maxValue / beta, beta / minValue);

    // Keep adding nodes while the aspect ratio maintains or improves.
    for (; i1 < n; ++i1) {
      sumValue += nodeValue = nodes[i1].value;
      if (nodeValue < minValue) minValue = nodeValue;
      if (nodeValue > maxValue) maxValue = nodeValue;
      beta = sumValue * sumValue * alpha;
      newRatio = Math.max(maxValue / beta, beta / minValue);
      if (newRatio > minRatio) { sumValue -= nodeValue; break; }
      minRatio = newRatio;
    }

    // Position and record the row orientation.
    rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
    if (row.dice) dice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
    else treemap_slice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
    value -= sumValue, i0 = i1;
  }

  return rows;
}

/* harmony default export */ const squarify = ((function custom(ratio) {

  function squarify(parent, x0, y0, x1, y1) {
    squarifyRatio(ratio, parent, x0, y0, x1, y1);
  }

  squarify.ratio = function(x) {
    return custom((x = +x) > 1 ? x : 1);
  };

  return squarify;
})(phi));

;// ../../node_modules/d3-hierarchy/src/treemap/resquarify.js




/* harmony default export */ const resquarify = ((function custom(ratio) {

  function resquarify(parent, x0, y0, x1, y1) {
    if ((rows = parent._squarify) && (rows.ratio === ratio)) {
      var rows,
          row,
          nodes,
          i,
          j = -1,
          n,
          m = rows.length,
          value = parent.value;

      while (++j < m) {
        row = rows[j], nodes = row.children;
        for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
        if (row.dice) dice(row, x0, y0, x1, value ? y0 += (y1 - y0) * row.value / value : y1);
        else treemap_slice(row, x0, y0, value ? x0 += (x1 - x0) * row.value / value : x1, y1);
        value -= row.value;
      }
    } else {
      parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
      rows.ratio = ratio;
    }
  }

  resquarify.ratio = function(x) {
    return custom((x = +x) > 1 ? x : 1);
  };

  return resquarify;
})(phi));

;// ../../node_modules/d3-hierarchy/src/treemap/index.js





/* harmony default export */ function treemap() {
  var tile = squarify,
      round = false,
      dx = 1,
      dy = 1,
      paddingStack = [0],
      paddingInner = constantZero,
      paddingTop = constantZero,
      paddingRight = constantZero,
      paddingBottom = constantZero,
      paddingLeft = constantZero;

  function treemap(root) {
    root.x0 =
    root.y0 = 0;
    root.x1 = dx;
    root.y1 = dy;
    root.eachBefore(positionNode);
    paddingStack = [0];
    if (round) root.eachBefore(treemap_round);
    return root;
  }

  function positionNode(node) {
    var p = paddingStack[node.depth],
        x0 = node.x0 + p,
        y0 = node.y0 + p,
        x1 = node.x1 - p,
        y1 = node.y1 - p;
    if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
    if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
    node.x0 = x0;
    node.y0 = y0;
    node.x1 = x1;
    node.y1 = y1;
    if (node.children) {
      p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
      x0 += paddingLeft(node) - p;
      y0 += paddingTop(node) - p;
      x1 -= paddingRight(node) - p;
      y1 -= paddingBottom(node) - p;
      if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
      if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
      tile(node, x0, y0, x1, y1);
    }
  }

  treemap.round = function(x) {
    return arguments.length ? (round = !!x, treemap) : round;
  };

  treemap.size = function(x) {
    return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
  };

  treemap.tile = function(x) {
    return arguments.length ? (tile = required(x), treemap) : tile;
  };

  treemap.padding = function(x) {
    return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
  };

  treemap.paddingInner = function(x) {
    return arguments.length ? (paddingInner = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), treemap) : paddingInner;
  };

  treemap.paddingOuter = function(x) {
    return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
  };

  treemap.paddingTop = function(x) {
    return arguments.length ? (paddingTop = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), treemap) : paddingTop;
  };

  treemap.paddingRight = function(x) {
    return arguments.length ? (paddingRight = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), treemap) : paddingRight;
  };

  treemap.paddingBottom = function(x) {
    return arguments.length ? (paddingBottom = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), treemap) : paddingBottom;
  };

  treemap.paddingLeft = function(x) {
    return arguments.length ? (paddingLeft = typeof x === "function" ? x : d3_hierarchy_src_constant(+x), treemap) : paddingLeft;
  };

  return treemap;
}

;// ../../node_modules/vega-hierarchy/build/vega-hierarchy.module.js




// Build lookup table mapping tuple keys to tree node instances
function vega_hierarchy_module_lookup (tree, key, filter) {
  const map = {};
  tree.each(node => {
    const t = node.data;
    if (filter(t)) map[key(t)] = node;
  });
  tree.lookup = map;
  return tree;
}

/**
 * Nest tuples into a tree structure, grouped by key values.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} params.keys - The key fields to nest by, in order.
 * @param {boolean} [params.generate=false] - A boolean flag indicating if
 *   non-leaf nodes generated by this transform should be included in the
 *   output. The default (false) includes only the input data (leaf nodes)
 *   in the data stream.
 */
function Nest(params) {
  Transform.call(this, null, params);
}
Nest.Definition = {
  'type': 'Nest',
  'metadata': {
    'treesource': true,
    'changes': true
  },
  'params': [{
    'name': 'keys',
    'type': 'field',
    'array': true
  }, {
    'name': 'generate',
    'type': 'boolean'
  }]
};
const vega_hierarchy_module_children = n => n.values;
inherits(Nest, Transform, {
  transform(_, pulse) {
    if (!pulse.source) {
      vega_util_module_error('Nest transform requires an upstream data source.');
    }
    var gen = _.generate,
      mod = _.modified(),
      out = pulse.clone(),
      tree = this.value;
    if (!tree || mod || pulse.changed()) {
      // collect nodes to remove
      if (tree) {
        tree.each(node => {
          if (node.children && isTuple(node.data)) {
            out.rem.push(node.data);
          }
        });
      }

      // generate new tree structure
      this.value = tree = hierarchy({
        values: vega_util_module_array(_.keys).reduce((n, k) => {
          n.key(k);
          return n;
        }, vega_hierarchy_module_nest()).entries(out.source)
      }, vega_hierarchy_module_children);

      // collect nodes to add
      if (gen) {
        tree.each(node => {
          if (node.children) {
            node = ingest$1(node.data);
            out.add.push(node);
            out.source.push(node);
          }
        });
      }

      // build lookup table
      vega_hierarchy_module_lookup(tree, tupleid, tupleid);
    }
    out.source.root = tree;
    return out;
  }
});
function vega_hierarchy_module_nest() {
  const keys = [],
    nest = {
      entries: array => entries(apply(array, 0), 0),
      key: d => (keys.push(d), nest)
    };
  function apply(array, depth) {
    if (depth >= keys.length) {
      return array;
    }
    const n = array.length,
      key = keys[depth++],
      valuesByKey = {},
      result = {};
    let i = -1,
      keyValue,
      value,
      values;
    while (++i < n) {
      keyValue = key(value = array[i]) + '';
      if (values = valuesByKey[keyValue]) {
        values.push(value);
      } else {
        valuesByKey[keyValue] = [value];
      }
    }
    for (keyValue in valuesByKey) {
      result[keyValue] = apply(valuesByKey[keyValue], depth);
    }
    return result;
  }
  function entries(map, depth) {
    if (++depth > keys.length) return map;
    const array = [];
    for (const key in map) {
      array.push({
        key,
        values: entries(map[key], depth)
      });
    }
    return array;
  }
  return nest;
}

/**
 * Abstract class for tree layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function HierarchyLayout(params) {
  Transform.call(this, null, params);
}
const vega_hierarchy_module_defaultSeparation = (a, b) => a.parent === b.parent ? 1 : 2;
inherits(HierarchyLayout, Transform, {
  transform(_, pulse) {
    if (!pulse.source || !pulse.source.root) {
      vega_util_module_error(this.constructor.name + ' transform requires a backing tree data source.');
    }
    const layout = this.layout(_.method),
      fields = this.fields,
      root = pulse.source.root,
      as = _.as || fields;
    if (_.field) root.sum(_.field);else root.count();
    if (_.sort) root.sort(stableCompare(_.sort, d => d.data));
    setParams(layout, this.params, _);
    if (layout.separation) {
      layout.separation(_.separation !== false ? vega_hierarchy_module_defaultSeparation : one);
    }
    try {
      this.value = layout(root);
    } catch (err) {
      vega_util_module_error(err);
    }
    root.each(node => setFields(node, fields, as));
    return pulse.reflow(_.modified()).modifies(as).modifies('leaf');
  }
});
function setParams(layout, params, _) {
  for (let p, i = 0, n = params.length; i < n; ++i) {
    p = params[i];
    if (p in _) layout[p](_[p]);
  }
}
function setFields(node, fields, as) {
  const t = node.data,
    n = fields.length - 1;
  for (let i = 0; i < n; ++i) {
    t[as[i]] = node[fields[i]];
  }
  t[as[n]] = node.children ? node.children.length : 0;
}

const Output$3 = ['x', 'y', 'r', 'depth', 'children'];

/**
 * Packed circle tree layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to size nodes.
 */
function Pack(params) {
  HierarchyLayout.call(this, params);
}
Pack.Definition = {
  'type': 'Pack',
  'metadata': {
    'tree': true,
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'padding',
    'type': 'number',
    'default': 0
  }, {
    'name': 'radius',
    'type': 'field',
    'default': null
  }, {
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': Output$3.length,
    'default': Output$3
  }]
};
inherits(Pack, HierarchyLayout, {
  layout: pack,
  params: ['radius', 'size', 'padding'],
  fields: Output$3
});

const Output$2 = ['x0', 'y0', 'x1', 'y1', 'depth', 'children'];

/**
 * Partition tree layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to size nodes.
 */
function Partition(params) {
  HierarchyLayout.call(this, params);
}
Partition.Definition = {
  'type': 'Partition',
  'metadata': {
    'tree': true,
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'padding',
    'type': 'number',
    'default': 0
  }, {
    'name': 'round',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': Output$2.length,
    'default': Output$2
  }]
};
inherits(Partition, HierarchyLayout, {
  layout: src_partition,
  params: ['size', 'round', 'padding'],
  fields: Output$2
});

/**
 * Stratify a collection of tuples into a tree structure based on
 * id and parent id fields.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.key - Unique key field for each tuple.
 * @param {function(object): *} params.parentKey - Field with key for parent tuple.
 */
function Stratify(params) {
  Transform.call(this, null, params);
}
Stratify.Definition = {
  'type': 'Stratify',
  'metadata': {
    'treesource': true
  },
  'params': [{
    'name': 'key',
    'type': 'field',
    'required': true
  }, {
    'name': 'parentKey',
    'type': 'field',
    'required': true
  }]
};
inherits(Stratify, Transform, {
  transform(_, pulse) {
    if (!pulse.source) {
      vega_util_module_error('Stratify transform requires an upstream data source.');
    }
    let tree = this.value;
    const mod = _.modified(),
      out = pulse.fork(pulse.ALL).materialize(pulse.SOURCE),
      run = !tree || mod || pulse.changed(pulse.ADD_REM) || pulse.modified(_.key.fields) || pulse.modified(_.parentKey.fields);

    // prevent upstream source pollution
    out.source = out.source.slice();
    if (run) {
      tree = out.source.length ? vega_hierarchy_module_lookup(stratify().id(_.key).parentId(_.parentKey)(out.source), _.key, truthy) : vega_hierarchy_module_lookup(stratify()([{}]), _.key, _.key);
    }
    out.source.root = this.value = tree;
    return out;
  }
});

const Layouts = {
  tidy: tree,
  cluster: cluster
};
const Output$1 = ['x', 'y', 'depth', 'children'];

/**
 * Tree layout. Depending on the method parameter, performs either
 * Reingold-Tilford 'tidy' layout or dendrogram 'cluster' layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function Tree(params) {
  HierarchyLayout.call(this, params);
}
Tree.Definition = {
  'type': 'Tree',
  'metadata': {
    'tree': true,
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'method',
    'type': 'enum',
    'default': 'tidy',
    'values': ['tidy', 'cluster']
  }, {
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'nodeSize',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'separation',
    'type': 'boolean',
    'default': true
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': Output$1.length,
    'default': Output$1
  }]
};
inherits(Tree, HierarchyLayout, {
  /**
   * Tree layout generator. Supports both 'tidy' and 'cluster' layouts.
   */
  layout(method) {
    const m = method || 'tidy';
    if (vega_util_module_has(Layouts, m)) return Layouts[m]();else vega_util_module_error('Unrecognized Tree layout method: ' + m);
  },
  params: ['size', 'nodeSize'],
  fields: Output$1
});

/**
 * Generate tuples representing links between tree nodes.
 * The resulting tuples will contain 'source' and 'target' fields,
 * which point to parent and child node tuples, respectively.
 * @constructor
 * @param {object} params - The parameters for this operator.
 */
function TreeLinks(params) {
  Transform.call(this, [], params);
}
TreeLinks.Definition = {
  'type': 'TreeLinks',
  'metadata': {
    'tree': true,
    'generates': true,
    'changes': true
  },
  'params': []
};
inherits(TreeLinks, Transform, {
  transform(_, pulse) {
    const links = this.value,
      tree = pulse.source && pulse.source.root,
      out = pulse.fork(pulse.NO_SOURCE),
      lut = {};
    if (!tree) vega_util_module_error('TreeLinks transform requires a tree data source.');
    if (pulse.changed(pulse.ADD_REM)) {
      // remove previous links
      out.rem = links;

      // build lookup table of valid tuples
      pulse.visit(pulse.SOURCE, t => lut[tupleid(t)] = 1);

      // generate links for all edges incident on valid tuples
      tree.each(node => {
        const t = node.data,
          p = node.parent && node.parent.data;
        if (p && lut[tupleid(t)] && lut[tupleid(p)]) {
          out.add.push(ingest$1({
            source: p,
            target: t
          }));
        }
      });
      this.value = out.add;
    } else if (pulse.changed(pulse.MOD)) {
      // build lookup table of modified tuples
      pulse.visit(pulse.MOD, t => lut[tupleid(t)] = 1);

      // gather links incident on modified tuples
      links.forEach(link => {
        if (lut[tupleid(link.source)] || lut[tupleid(link.target)]) {
          out.mod.push(link);
        }
      });
    }
    return out;
  }
});

const Tiles = {
  binary: treemap_binary,
  dice: dice,
  slice: treemap_slice,
  slicedice: sliceDice,
  squarify: squarify,
  resquarify: resquarify
};
const vega_hierarchy_module_Output = ['x0', 'y0', 'x1', 'y1', 'depth', 'children'];

/**
 * Treemap layout.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.field - The value field to size nodes.
 */
function Treemap(params) {
  HierarchyLayout.call(this, params);
}
Treemap.Definition = {
  'type': 'Treemap',
  'metadata': {
    'tree': true,
    'modifies': true
  },
  'params': [{
    'name': 'field',
    'type': 'field'
  }, {
    'name': 'sort',
    'type': 'compare'
  }, {
    'name': 'method',
    'type': 'enum',
    'default': 'squarify',
    'values': ['squarify', 'resquarify', 'binary', 'dice', 'slice', 'slicedice']
  }, {
    'name': 'padding',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingInner',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingOuter',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingTop',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingRight',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingBottom',
    'type': 'number',
    'default': 0
  }, {
    'name': 'paddingLeft',
    'type': 'number',
    'default': 0
  }, {
    'name': 'ratio',
    'type': 'number',
    'default': 1.618033988749895
  }, {
    'name': 'round',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': vega_hierarchy_module_Output.length,
    'default': vega_hierarchy_module_Output
  }]
};
inherits(Treemap, HierarchyLayout, {
  /**
   * Treemap layout generator. Adds 'method' and 'ratio' parameters
   * to configure the underlying tile method.
   */
  layout() {
    const x = treemap();
    x.ratio = _ => {
      const t = x.tile();
      if (t.ratio) x.tile(t.ratio(_));
    };
    x.method = _ => {
      if (vega_util_module_has(Tiles, _)) x.tile(Tiles[_]);else vega_util_module_error('Unrecognized Treemap layout method: ' + _);
    };
    return x;
  },
  params: ['method', 'ratio', 'size', 'round', 'padding', 'paddingInner', 'paddingOuter', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'],
  fields: vega_hierarchy_module_Output
});



;// ../../node_modules/vega-label/build/vega-label.module.js





// bit mask for getting first 2 bytes of alpha value
const ALPHA_MASK = 0xff000000;
function baseBitmaps($, data) {
  const bitmap = $.bitmap();
  // when there is no base mark but data points are to be avoided
  (data || []).forEach(d => bitmap.set($(d.boundary[0]), $(d.boundary[3])));
  return [bitmap, undefined];
}
function markBitmaps($, baseMark, avoidMarks, labelInside, isGroupArea) {
  // create canvas
  const width = $.width,
    height = $.height,
    border = labelInside || isGroupArea,
    context = domCanvas(width, height).getContext('2d'),
    baseMarkContext = domCanvas(width, height).getContext('2d'),
    strokeContext = border && domCanvas(width, height).getContext('2d');

  // render all marks to be avoided into canvas
  avoidMarks.forEach(items => vega_label_module_draw(context, items, false));
  vega_label_module_draw(baseMarkContext, baseMark, false);
  if (border) {
    vega_label_module_draw(strokeContext, baseMark, true);
  }

  // get canvas buffer, create bitmaps
  const buffer = getBuffer(context, width, height),
    baseMarkBuffer = getBuffer(baseMarkContext, width, height),
    strokeBuffer = border && getBuffer(strokeContext, width, height),
    layer1 = $.bitmap(),
    layer2 = border && $.bitmap();

  // populate bitmap layers
  let x, y, u, v, index, alpha, strokeAlpha, baseMarkAlpha;
  for (y = 0; y < height; ++y) {
    for (x = 0; x < width; ++x) {
      index = y * width + x;
      alpha = buffer[index] & ALPHA_MASK;
      baseMarkAlpha = baseMarkBuffer[index] & ALPHA_MASK;
      strokeAlpha = border && strokeBuffer[index] & ALPHA_MASK;
      if (alpha || strokeAlpha || baseMarkAlpha) {
        u = $(x);
        v = $(y);
        if (!isGroupArea && (alpha || baseMarkAlpha)) layer1.set(u, v); // update interior bitmap
        if (border && (alpha || strokeAlpha)) layer2.set(u, v); // update border bitmap
      }
    }
  }
  return [layer1, layer2];
}
function getBuffer(context, width, height) {
  return new Uint32Array(context.getImageData(0, 0, width, height).data.buffer);
}
function vega_label_module_draw(context, items, interior) {
  if (!items.length) return;
  const type = items[0].mark.marktype;
  if (type === 'group') {
    items.forEach(group => {
      group.items.forEach(mark => vega_label_module_draw(context, mark.items, interior));
    });
  } else {
    Marks[type].draw(context, {
      items: interior ? items.map(prepare) : items
    });
  }
}

/**
 * Prepare item before drawing into canvas (setting stroke and opacity)
 * @param {object} source item to be prepared
 * @returns prepared item
 */
function prepare(source) {
  const item = rederive(source, {});
  if (item.stroke && item.strokeOpacity !== 0 || item.fill && item.fillOpacity !== 0) {
    return {
      ...item,
      strokeOpacity: 1,
      stroke: '#000',
      fillOpacity: 0
    };
  }
  return item;
}

const DIV = 5,
  // bit shift from x, y index to bit vector array index
  vega_label_module_MOD = 31,
  // bit mask for index lookup within a bit vector
  SIZE = 32,
  // individual bit vector size
  RIGHT0 = new Uint32Array(SIZE + 1),
  // left-anchored bit vectors, full -> 0
  RIGHT1 = new Uint32Array(SIZE + 1); // right-anchored bit vectors, 0 -> full

RIGHT1[0] = 0;
RIGHT0[0] = ~RIGHT1[0];
for (let i = 1; i <= SIZE; ++i) {
  RIGHT1[i] = RIGHT1[i - 1] << 1 | 1;
  RIGHT0[i] = ~RIGHT1[i];
}
function vega_label_module_Bitmap (w, h) {
  const array = new Uint32Array(~~((w * h + SIZE) / SIZE));
  function _set(index, mask) {
    array[index] |= mask;
  }
  function _clear(index, mask) {
    array[index] &= mask;
  }
  return {
    array: array,
    get: (x, y) => {
      const index = y * w + x;
      return array[index >>> DIV] & 1 << (index & vega_label_module_MOD);
    },
    set: (x, y) => {
      const index = y * w + x;
      _set(index >>> DIV, 1 << (index & vega_label_module_MOD));
    },
    clear: (x, y) => {
      const index = y * w + x;
      _clear(index >>> DIV, ~(1 << (index & vega_label_module_MOD)));
    },
    getRange: (x, y, x2, y2) => {
      let r = y2,
        start,
        end,
        indexStart,
        indexEnd;
      for (; r >= y; --r) {
        start = r * w + x;
        end = r * w + x2;
        indexStart = start >>> DIV;
        indexEnd = end >>> DIV;
        if (indexStart === indexEnd) {
          if (array[indexStart] & RIGHT0[start & vega_label_module_MOD] & RIGHT1[(end & vega_label_module_MOD) + 1]) {
            return true;
          }
        } else {
          if (array[indexStart] & RIGHT0[start & vega_label_module_MOD]) return true;
          if (array[indexEnd] & RIGHT1[(end & vega_label_module_MOD) + 1]) return true;
          for (let i = indexStart + 1; i < indexEnd; ++i) {
            if (array[i]) return true;
          }
        }
      }
      return false;
    },
    setRange: (x, y, x2, y2) => {
      let start, end, indexStart, indexEnd, i;
      for (; y <= y2; ++y) {
        start = y * w + x;
        end = y * w + x2;
        indexStart = start >>> DIV;
        indexEnd = end >>> DIV;
        if (indexStart === indexEnd) {
          _set(indexStart, RIGHT0[start & vega_label_module_MOD] & RIGHT1[(end & vega_label_module_MOD) + 1]);
        } else {
          _set(indexStart, RIGHT0[start & vega_label_module_MOD]);
          _set(indexEnd, RIGHT1[(end & vega_label_module_MOD) + 1]);
          for (i = indexStart + 1; i < indexEnd; ++i) _set(i, 0xffffffff);
        }
      }
    },
    clearRange: (x, y, x2, y2) => {
      let start, end, indexStart, indexEnd, i;
      for (; y <= y2; ++y) {
        start = y * w + x;
        end = y * w + x2;
        indexStart = start >>> DIV;
        indexEnd = end >>> DIV;
        if (indexStart === indexEnd) {
          _clear(indexStart, RIGHT1[start & vega_label_module_MOD] | RIGHT0[(end & vega_label_module_MOD) + 1]);
        } else {
          _clear(indexStart, RIGHT1[start & vega_label_module_MOD]);
          _clear(indexEnd, RIGHT0[(end & vega_label_module_MOD) + 1]);
          for (i = indexStart + 1; i < indexEnd; ++i) _clear(i, 0);
        }
      }
    },
    outOfBounds: (x, y, x2, y2) => x < 0 || y < 0 || y2 >= h || x2 >= w
  };
}

function scaler (width, height, padding) {
  const ratio = Math.max(1, Math.sqrt(width * height / 1e6)),
    w = ~~((width + 2 * padding + ratio) / ratio),
    h = ~~((height + 2 * padding + ratio) / ratio),
    scale = _ => ~~((_ + padding) / ratio);
  scale.invert = _ => _ * ratio - padding;
  scale.bitmap = () => vega_label_module_Bitmap(w, h);
  scale.ratio = ratio;
  scale.padding = padding;
  scale.width = width;
  scale.height = height;
  return scale;
}

function placeAreaLabelNaive ($, bitmaps, avoidBaseMark, markIndex) {
  const width = $.width,
    height = $.height;

  // try to place a label within an input area mark
  return function (d) {
    const items = d.datum.datum.items[markIndex].items,
      // area points
      n = items.length,
      // number of points
      textHeight = d.datum.fontSize,
      // label width
      textWidth = textMetrics.width(d.datum, d.datum.text); // label height

    let maxAreaWidth = 0,
      x1,
      x2,
      y1,
      y2,
      x,
      y,
      areaWidth;

    // for each area sample point
    for (let i = 0; i < n; ++i) {
      x1 = items[i].x;
      y1 = items[i].y;
      x2 = items[i].x2 === undefined ? x1 : items[i].x2;
      y2 = items[i].y2 === undefined ? y1 : items[i].y2;
      x = (x1 + x2) / 2;
      y = (y1 + y2) / 2;
      areaWidth = Math.abs(x2 - x1 + y2 - y1);
      if (areaWidth >= maxAreaWidth) {
        maxAreaWidth = areaWidth;
        d.x = x;
        d.y = y;
      }
    }
    x = textWidth / 2;
    y = textHeight / 2;
    x1 = d.x - x;
    x2 = d.x + x;
    y1 = d.y - y;
    y2 = d.y + y;
    d.align = 'center';
    if (x1 < 0 && x2 <= width) {
      d.align = 'left';
    } else if (0 <= x1 && width < x2) {
      d.align = 'right';
    }
    d.baseline = 'middle';
    if (y1 < 0 && y2 <= height) {
      d.baseline = 'top';
    } else if (0 <= y1 && height < y2) {
      d.baseline = 'bottom';
    }
    return true;
  };
}

function outOfBounds(x, y, textWidth, textHeight, width, height) {
  let r = textWidth / 2;
  return x - r < 0 || x + r > width || y - (r = textHeight / 2) < 0 || y + r > height;
}
function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
  const w = textWidth * h / (textHeight * 2),
    x1 = $(x - w),
    x2 = $(x + w),
    y1 = $(y - (h = h / 2)),
    y2 = $(y + h);
  return bm0.outOfBounds(x1, y1, x2, y2) || bm0.getRange(x1, y1, x2, y2) || bm1 && bm1.getRange(x1, y1, x2, y2);
}

function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex) {
  const width = $.width,
    height = $.height,
    bm0 = bitmaps[0],
    // where labels have been placed
    bm1 = bitmaps[1]; // area outlines

  function tryLabel(_x, _y, maxSize, textWidth, textHeight) {
    const x = $.invert(_x),
      y = $.invert(_y);
    let lo = maxSize,
      hi = height,
      mid;
    if (!outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, lo, bm0, bm1) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
      // if the label fits at the current sample point,
      // perform binary search to find the largest font size that fits
      while (hi - lo >= 1) {
        mid = (lo + hi) / 2;
        if (collision($, x, y, textHeight, textWidth, mid, bm0, bm1)) {
          hi = mid;
        } else {
          lo = mid;
        }
      }
      // place label if current lower bound exceeds prior max font size
      if (lo > maxSize) {
        return [x, y, lo, true];
      }
    }
  }

  // try to place a label within an input area mark
  return function (d) {
    const items = d.datum.datum.items[markIndex].items,
      // area points
      n = items.length,
      // number of points
      textHeight = d.datum.fontSize,
      // label width
      textWidth = textMetrics.width(d.datum, d.datum.text); // label height

    let maxSize = avoidBaseMark ? textHeight : 0,
      labelPlaced = false,
      labelPlaced2 = false,
      maxAreaWidth = 0,
      x1,
      x2,
      y1,
      y2,
      x,
      y,
      _x,
      _y,
      _x1,
      _xMid,
      _x2,
      _y1,
      _yMid,
      _y2,
      areaWidth,
      result,
      swapTmp;

    // for each area sample point
    for (let i = 0; i < n; ++i) {
      x1 = items[i].x;
      y1 = items[i].y;
      x2 = items[i].x2 === undefined ? x1 : items[i].x2;
      y2 = items[i].y2 === undefined ? y1 : items[i].y2;
      if (x1 > x2) {
        swapTmp = x1;
        x1 = x2;
        x2 = swapTmp;
      }
      if (y1 > y2) {
        swapTmp = y1;
        y1 = y2;
        y2 = swapTmp;
      }
      _x1 = $(x1);
      _x2 = $(x2);
      _xMid = ~~((_x1 + _x2) / 2);
      _y1 = $(y1);
      _y2 = $(y2);
      _yMid = ~~((_y1 + _y2) / 2);

      // search along the line from mid point between the 2 border to lower border
      for (_x = _xMid; _x >= _x1; --_x) {
        for (_y = _yMid; _y >= _y1; --_y) {
          result = tryLabel(_x, _y, maxSize, textWidth, textHeight);
          if (result) {
            [d.x, d.y, maxSize, labelPlaced] = result;
          }
        }
      }

      // search along the line from mid point between the 2 border to upper border
      for (_x = _xMid; _x <= _x2; ++_x) {
        for (_y = _yMid; _y <= _y2; ++_y) {
          result = tryLabel(_x, _y, maxSize, textWidth, textHeight);
          if (result) {
            [d.x, d.y, maxSize, labelPlaced] = result;
          }
        }
      }

      // place label at slice center if not placed through other means
      // and if we're not avoiding overlap with other areas
      if (!labelPlaced && !avoidBaseMark) {
        // one span is zero, hence we can add
        areaWidth = Math.abs(x2 - x1 + y2 - y1);
        x = (x1 + x2) / 2;
        y = (y1 + y2) / 2;

        // place label if it fits and improves the max area width
        if (areaWidth >= maxAreaWidth && !outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
          maxAreaWidth = areaWidth;
          d.x = x;
          d.y = y;
          labelPlaced2 = true;
        }
      }
    }

    // record current label placement information, update label bitmap
    if (labelPlaced || labelPlaced2) {
      x = textWidth / 2;
      y = textHeight / 2;
      bm0.setRange($(d.x - x), $(d.y - y), $(d.x + x), $(d.y + y));
      d.align = 'center';
      d.baseline = 'middle';
      return true;
    } else {
      return false;
    }
  };
}

// pixel direction offsets for flood fill search
const X_DIR = [-1, -1, 1, 1];
const Y_DIR = [-1, 1, -1, 1];
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex) {
  const width = $.width,
    height = $.height,
    bm0 = bitmaps[0],
    // where labels have been placed
    bm1 = bitmaps[1],
    // area outlines
    bm2 = $.bitmap(); // flood-fill visitations

  // try to place a label within an input area mark
  return function (d) {
    const items = d.datum.datum.items[markIndex].items,
      // area points
      n = items.length,
      // number of points
      textHeight = d.datum.fontSize,
      // label width
      textWidth = textMetrics.width(d.datum, d.datum.text),
      // label height
      stack = []; // flood fill stack

    let maxSize = avoidBaseMark ? textHeight : 0,
      labelPlaced = false,
      labelPlaced2 = false,
      maxAreaWidth = 0,
      x1,
      x2,
      y1,
      y2,
      x,
      y,
      _x,
      _y,
      lo,
      hi,
      mid,
      areaWidth;

    // for each area sample point
    for (let i = 0; i < n; ++i) {
      x1 = items[i].x;
      y1 = items[i].y;
      x2 = items[i].x2 === undefined ? x1 : items[i].x2;
      y2 = items[i].y2 === undefined ? y1 : items[i].y2;

      // add scaled center point to stack
      stack.push([$((x1 + x2) / 2), $((y1 + y2) / 2)]);

      // perform flood fill, visit points
      while (stack.length) {
        [_x, _y] = stack.pop();

        // exit if point already marked
        if (bm0.get(_x, _y) || bm1.get(_x, _y) || bm2.get(_x, _y)) continue;

        // mark point in flood fill bitmap
        // add search points for all (in bound) directions
        bm2.set(_x, _y);
        for (let j = 0; j < 4; ++j) {
          x = _x + X_DIR[j];
          y = _y + Y_DIR[j];
          if (!bm2.outOfBounds(x, y, x, y)) stack.push([x, y]);
        }

        // unscale point back to x, y space
        x = $.invert(_x);
        y = $.invert(_y);
        lo = maxSize;
        hi = height; // TODO: make this bound smaller

        if (!outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, lo, bm0, bm1) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
          // if the label fits at the current sample point,
          // perform binary search to find the largest font size that fits
          while (hi - lo >= 1) {
            mid = (lo + hi) / 2;
            if (collision($, x, y, textHeight, textWidth, mid, bm0, bm1)) {
              hi = mid;
            } else {
              lo = mid;
            }
          }
          // place label if current lower bound exceeds prior max font size
          if (lo > maxSize) {
            d.x = x;
            d.y = y;
            maxSize = lo;
            labelPlaced = true;
          }
        }
      }

      // place label at slice center if not placed through other means
      // and if we're not avoiding overlap with other areas
      if (!labelPlaced && !avoidBaseMark) {
        // one span is zero, hence we can add
        areaWidth = Math.abs(x2 - x1 + y2 - y1);
        x = (x1 + x2) / 2;
        y = (y1 + y2) / 2;

        // place label if it fits and improves the max area width
        if (areaWidth >= maxAreaWidth && !outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
          maxAreaWidth = areaWidth;
          d.x = x;
          d.y = y;
          labelPlaced2 = true;
        }
      }
    }

    // record current label placement information, update label bitmap
    if (labelPlaced || labelPlaced2) {
      x = textWidth / 2;
      y = textHeight / 2;
      bm0.setRange($(d.x - x), $(d.y - y), $(d.x + x), $(d.y + y));
      d.align = 'center';
      d.baseline = 'middle';
      return true;
    } else {
      return false;
    }
  };
}

const Aligns = ['right', 'center', 'left'],
  Baselines = ['bottom', 'middle', 'top'];
function placeMarkLabel ($, bitmaps, anchors, offsets) {
  const width = $.width,
    height = $.height,
    bm0 = bitmaps[0],
    bm1 = bitmaps[1],
    n = offsets.length;
  return function (d) {
    const boundary = d.boundary,
      textHeight = d.datum.fontSize;

    // can not be placed if the mark is not visible in the graph bound
    if (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height) {
      return false;
    }
    let textWidth = d.textWidth ?? 0,
      dx,
      dy,
      isInside,
      sizeFactor,
      insideFactor,
      x1,
      x2,
      y1,
      y2,
      xc,
      yc,
      _x1,
      _x2,
      _y1,
      _y2;

    // for each anchor and offset
    for (let i = 0; i < n; ++i) {
      dx = (anchors[i] & 0x3) - 1;
      dy = (anchors[i] >>> 0x2 & 0x3) - 1;
      isInside = dx === 0 && dy === 0 || offsets[i] < 0;
      sizeFactor = dx && dy ? Math.SQRT1_2 : 1;
      insideFactor = offsets[i] < 0 ? -1 : 1;
      x1 = boundary[1 + dx] + offsets[i] * dx * sizeFactor;
      yc = boundary[4 + dy] + insideFactor * textHeight * dy / 2 + offsets[i] * dy * sizeFactor;
      y1 = yc - textHeight / 2;
      y2 = yc + textHeight / 2;
      _x1 = $(x1);
      _y1 = $(y1);
      _y2 = $(y2);
      if (!textWidth) {
        // to avoid finding width of text label,
        if (!test(_x1, _x1, _y1, _y2, bm0, bm1, x1, x1, y1, y2, boundary, isInside)) {
          // skip this anchor/offset option if we fail to place a label with 1px width
          continue;
        } else {
          // Otherwise, find the label width
          textWidth = textMetrics.width(d.datum, d.datum.text);
        }
      }
      xc = x1 + insideFactor * textWidth * dx / 2;
      x1 = xc - textWidth / 2;
      x2 = xc + textWidth / 2;
      _x1 = $(x1);
      _x2 = $(x2);
      if (test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside)) {
        // place label if the position is placeable
        d.x = !dx ? xc : dx * insideFactor < 0 ? x2 : x1;
        d.y = !dy ? yc : dy * insideFactor < 0 ? y2 : y1;
        d.align = Aligns[dx * insideFactor + 1];
        d.baseline = Baselines[dy * insideFactor + 1];
        bm0.setRange(_x1, _y1, _x2, _y2);
        return true;
      }
    }
    return false;
  };
}

// Test if a label with the given dimensions can be added without overlap
function test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside) {
  return !(bm0.outOfBounds(_x1, _y1, _x2, _y2) || (isInside && bm1 || bm0).getRange(_x1, _y1, _x2, _y2));
}

// 8-bit representation of anchors
const TOP = 0x0,
  MIDDLE = 0x4,
  BOTTOM = 0x8,
  LEFT = 0x0,
  CENTER = 0x1,
  RIGHT = 0x2;

// Mapping from text anchor to number representation
const anchorCode = {
  'top-left': TOP + LEFT,
  'top': TOP + CENTER,
  'top-right': TOP + RIGHT,
  'left': MIDDLE + LEFT,
  'middle': MIDDLE + CENTER,
  'right': MIDDLE + RIGHT,
  'bottom-left': BOTTOM + LEFT,
  'bottom': BOTTOM + CENTER,
  'bottom-right': BOTTOM + RIGHT
};
const placeAreaLabel = {
  'naive': placeAreaLabelNaive,
  'reduced-search': placeAreaLabelReducedSearch,
  'floodfill': placeAreaLabelFloodFill
};
function labelLayout (texts, size, compare, offset, anchor, avoidMarks, avoidBaseMark, lineAnchor, markIndex, padding, method) {
  // early exit for empty data
  if (!texts.length) return texts;
  const positions = Math.max(offset.length, anchor.length),
    offsets = getOffsets(offset, positions),
    anchors = getAnchors(anchor, positions),
    marktype = markType(texts[0].datum),
    grouptype = marktype === 'group' && texts[0].datum.items[markIndex].marktype,
    isGroupArea = grouptype === 'area',
    boundary = markBoundary(marktype, grouptype, lineAnchor, markIndex),
    infPadding = padding === null || padding === Infinity,
    isNaiveGroupArea = isGroupArea && method === 'naive';
  let maxTextWidth = -1,
    maxTextHeight = -1;

  // prepare text mark data for placing
  const data = texts.map(d => {
    const textWidth = infPadding ? textMetrics.width(d, d.text) : undefined;
    maxTextWidth = Math.max(maxTextWidth, textWidth);
    maxTextHeight = Math.max(maxTextHeight, d.fontSize);
    return {
      datum: d,
      opacity: 0,
      x: undefined,
      y: undefined,
      align: undefined,
      baseline: undefined,
      boundary: boundary(d),
      textWidth
    };
  });
  padding = padding === null || padding === Infinity ? Math.max(maxTextWidth, maxTextHeight) + Math.max(...offset) : padding;
  const $ = scaler(size[0], size[1], padding);
  let bitmaps;
  if (!isNaiveGroupArea) {
    // sort labels in priority order, if comparator is provided
    if (compare) {
      data.sort((a, b) => compare(a.datum, b.datum));
    }

    // flag indicating if label can be placed inside its base mark
    let labelInside = false;
    for (let i = 0; i < anchors.length && !labelInside; ++i) {
      // label inside if anchor is at center
      // label inside if offset to be inside the mark bound
      labelInside = anchors[i] === 0x5 || offsets[i] < 0;
    }

    // extract data information from base mark when base mark is to be avoided
    // base mark is implicitly avoided if it is a group area
    const baseMark = (marktype && avoidBaseMark || isGroupArea) && texts.map(d => d.datum);

    // generate bitmaps for layout calculation
    bitmaps = avoidMarks.length || baseMark ? markBitmaps($, baseMark || [], avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
  }

  // generate label placement function
  const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex) : placeMarkLabel($, bitmaps, anchors, offsets);

  // place all labels
  data.forEach(d => d.opacity = +place(d));
  return data;
}
function getOffsets(_, count) {
  const offsets = new Float64Array(count),
    n = _.length;
  for (let i = 0; i < n; ++i) offsets[i] = _[i] || 0;
  for (let i = n; i < count; ++i) offsets[i] = offsets[n - 1];
  return offsets;
}
function getAnchors(_, count) {
  const anchors = new Int8Array(count),
    n = _.length;
  for (let i = 0; i < n; ++i) anchors[i] |= anchorCode[_[i]];
  for (let i = n; i < count; ++i) anchors[i] = anchors[n - 1];
  return anchors;
}
function markType(item) {
  return item && item.mark && item.mark.marktype;
}

/**
 * Factory function for function for getting base mark boundary, depending
 * on mark and group type. When mark type is undefined, line or area: boundary
 * is the coordinate of each data point. When base mark is grouped line,
 * boundary is either at the start or end of the line depending on the
 * value of lineAnchor. Otherwise, use bounds of base mark.
 */
function markBoundary(marktype, grouptype, lineAnchor, markIndex) {
  const xy = d => [d.x, d.x, d.x, d.y, d.y, d.y];
  if (!marktype) {
    return xy; // no reactive geometry
  } else if (marktype === 'line' || marktype === 'area') {
    return d => xy(d.datum);
  } else if (grouptype === 'line') {
    return d => {
      const items = d.datum.items[markIndex].items;
      return xy(items.length ? items[lineAnchor === 'start' ? 0 : items.length - 1] : {
        x: NaN,
        y: NaN
      });
    };
  } else {
    return d => {
      const b = d.datum.bounds;
      return [b.x1, (b.x1 + b.x2) / 2, b.x2, b.y1, (b.y1 + b.y2) / 2, b.y2];
    };
  }
}

const vega_label_module_Output = ['x', 'y', 'opacity', 'align', 'baseline'];
const Anchors = ['top-left', 'left', 'bottom-left', 'top', 'bottom', 'top-right', 'right', 'bottom-right'];

/**
 * Compute text label layout to annotate marks.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<number>} params.size - The size of the layout, provided as a [width, height] array.
 * @param {function(*,*): number} [params.sort] - An optional
 *   comparator function for sorting label data in priority order.
 * @param {Array<string>} [params.anchor] - Label anchor points relative to the base mark bounding box.
 *   The available options are 'top-left', 'left', 'bottom-left', 'top',
 *   'bottom', 'top-right', 'right', 'bottom-right', 'middle'.
 * @param {Array<number>} [params.offset] - Label offsets (in pixels) from the base mark bounding box.
 *   This parameter is parallel to the list of anchor points.
 * @param {number | null} [params.padding=0] - The amount (in pixels) that a label may exceed the layout size.
 *   If this parameter is null, a label may exceed the layout size without any boundary.
 * @param {string} [params.lineAnchor='end'] - For group line mark labels only, indicates the anchor
 *   position for labels. One of 'start' or 'end'.
 * @param {string} [params.markIndex=0] - For group mark labels only, an index indicating
 *   which mark within the group should be labeled.
 * @param {Array<number>} [params.avoidMarks] - A list of additional mark names for which the label
 *   layout should avoid overlap.
 * @param {boolean} [params.avoidBaseMark=true] - Boolean flag indicating if labels should avoid
 *   overlap with the underlying base mark being labeled.
 * @param {string} [params.method='naive'] - For area make labels only, a method for
 *   place labels. One of 'naive', 'reduced-search', or 'floodfill'.
 * @param {Array<string>} [params.as] - The output fields written by the transform.
 *   The default is ['x', 'y', 'opacity', 'align', 'baseline'].
 */
function Label(params) {
  Transform.call(this, null, params);
}
Label.Definition = {
  type: 'Label',
  metadata: {
    modifies: true
  },
  params: [{
    name: 'size',
    type: 'number',
    array: true,
    length: 2,
    required: true
  }, {
    name: 'sort',
    type: 'compare'
  }, {
    name: 'anchor',
    type: 'string',
    array: true,
    default: Anchors
  }, {
    name: 'offset',
    type: 'number',
    array: true,
    default: [1]
  }, {
    name: 'padding',
    type: 'number',
    default: 0,
    null: true
  }, {
    name: 'lineAnchor',
    type: 'string',
    values: ['start', 'end'],
    default: 'end'
  }, {
    name: 'markIndex',
    type: 'number',
    default: 0
  }, {
    name: 'avoidBaseMark',
    type: 'boolean',
    default: true
  }, {
    name: 'avoidMarks',
    type: 'data',
    array: true
  }, {
    name: 'method',
    type: 'string',
    default: 'naive'
  }, {
    name: 'as',
    type: 'string',
    array: true,
    length: vega_label_module_Output.length,
    default: vega_label_module_Output
  }]
};
inherits(Label, Transform, {
  transform(_, pulse) {
    function modp(param) {
      const p = _[param];
      return vega_util_module_isFunction(p) && pulse.modified(p.fields);
    }
    const mod = _.modified();
    if (!(mod || pulse.changed(pulse.ADD_REM) || modp('sort'))) return;
    if (!_.size || _.size.length !== 2) {
      vega_util_module_error('Size parameter should be specified as a [width, height] array.');
    }
    const as = _.as || vega_label_module_Output;

    // run label layout
    labelLayout(pulse.materialize(pulse.SOURCE).source || [], _.size, _.sort, vega_util_module_array(_.offset == null ? 1 : _.offset), vega_util_module_array(_.anchor || Anchors), _.avoidMarks || [], _.avoidBaseMark !== false, _.lineAnchor || 'end', _.markIndex || 0, _.padding === undefined ? 0 : _.padding, _.method || 'naive').forEach(l => {
      // write layout results to data stream
      const t = l.datum;
      t[as[0]] = l.x;
      t[as[1]] = l.y;
      t[as[2]] = l.opacity;
      t[as[3]] = l.align;
      t[as[4]] = l.baseline;
    });
    return pulse.reflow(mod).modifies(as);
  }
});



;// ../../node_modules/vega-regression/build/vega-regression.module.js




function vega_regression_module_partition (data, groupby) {
  var groups = [],
    get = function (f) {
      return f(t);
    },
    map,
    i,
    n,
    t,
    k,
    g;

  // partition data points into stack groups
  if (groupby == null) {
    groups.push(data);
  } else {
    for (map = {}, i = 0, n = data.length; i < n; ++i) {
      t = data[i];
      k = groupby.map(get);
      g = map[k];
      if (!g) {
        map[k] = g = [];
        g.dims = k;
        groups.push(g);
      }
      g.push(t);
    }
  }
  return groups;
}

/**
 * Compute locally-weighted regression fits for one or more data groups.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.x - An accessor for the predictor data field.
 * @param {function(object): *} params.y - An accessor for the predicted data field.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors to groupby.
 * @param {number} [params.bandwidth=0.3] - The loess bandwidth.
 */
function Loess(params) {
  Transform.call(this, null, params);
}
Loess.Definition = {
  'type': 'Loess',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'x',
    'type': 'field',
    'required': true
  }, {
    'name': 'y',
    'type': 'field',
    'required': true
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'bandwidth',
    'type': 'number',
    'default': 0.3
  }, {
    'name': 'as',
    'type': 'string',
    'array': true
  }]
};
inherits(Loess, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
    if (!this.value || pulse.changed() || _.modified()) {
      const source = pulse.materialize(pulse.SOURCE).source,
        groups = vega_regression_module_partition(source, _.groupby),
        names = (_.groupby || []).map(accessorName),
        m = names.length,
        as = _.as || [accessorName(_.x), accessorName(_.y)],
        values = [];
      groups.forEach(g => {
        loess(g, _.x, _.y, _.bandwidth || 0.3).forEach(p => {
          const t = {};
          for (let i = 0; i < m; ++i) {
            t[names[i]] = g.dims[i];
          }
          t[as[0]] = p[0];
          t[as[1]] = p[1];
          values.push(ingest$1(t));
        });
      });
      if (this.value) out.rem = this.value;
      this.value = out.add = out.source = values;
    }
    return out;
  }
});

const vega_regression_module_Methods = {
  constant: vega_statistics_module_constant,
  linear: vega_statistics_module_linear,
  log: vega_statistics_module_log,
  exp: vega_statistics_module_exp,
  pow: vega_statistics_module_pow,
  quad: quad,
  poly: poly
};
const degreesOfFreedom = (method, order) => method === 'poly' ? order : method === 'quad' ? 2 : 1;

/**
 * Compute regression fits for one or more data groups.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): *} params.x - An accessor for the predictor data field.
 * @param {function(object): *} params.y - An accessor for the predicted data field.
 * @param {string} [params.method='linear'] - The regression method to apply.
 * @param {Array<function(object): *>} [params.groupby] - An array of accessors to groupby.
 * @param {Array<number>} [params.extent] - The domain extent over which to plot the regression line.
 * @param {number} [params.order=3] - The polynomial order. Only applies to the 'poly' method.
 */
function Regression(params) {
  Transform.call(this, null, params);
}
Regression.Definition = {
  'type': 'Regression',
  'metadata': {
    'generates': true
  },
  'params': [{
    'name': 'x',
    'type': 'field',
    'required': true
  }, {
    'name': 'y',
    'type': 'field',
    'required': true
  }, {
    'name': 'groupby',
    'type': 'field',
    'array': true
  }, {
    'name': 'method',
    'type': 'string',
    'default': 'linear',
    'values': Object.keys(vega_regression_module_Methods)
  }, {
    'name': 'order',
    'type': 'number',
    'default': 3
  }, {
    'name': 'extent',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'params',
    'type': 'boolean',
    'default': false
  }, {
    'name': 'as',
    'type': 'string',
    'array': true
  }]
};
inherits(Regression, Transform, {
  transform(_, pulse) {
    const out = pulse.fork(pulse.NO_SOURCE | pulse.NO_FIELDS);
    if (!this.value || pulse.changed() || _.modified()) {
      const source = pulse.materialize(pulse.SOURCE).source,
        groups = vega_regression_module_partition(source, _.groupby),
        names = (_.groupby || []).map(accessorName),
        method = _.method || 'linear',
        order = _.order == null ? 3 : _.order,
        dof = degreesOfFreedom(method, order),
        as = _.as || [accessorName(_.x), accessorName(_.y)],
        fit = vega_regression_module_Methods[method],
        values = [];
      let domain = _.extent;
      if (!vega_util_module_has(vega_regression_module_Methods, method)) {
        vega_util_module_error('Invalid regression method: ' + method);
      }
      if (domain != null) {
        if (method === 'log' && domain[0] <= 0) {
          pulse.dataflow.warn('Ignoring extent with values <= 0 for log regression.');
          domain = null;
        }
      }
      groups.forEach(g => {
        const n = g.length;
        if (n <= dof) {
          pulse.dataflow.warn('Skipping regression with more parameters than data points.');
          return;
        }
        const model = fit(g, _.x, _.y, order);
        if (_.params) {
          // if parameter vectors requested return those
          values.push(ingest$1({
            keys: g.dims,
            coef: model.coef,
            rSquared: model.rSquared
          }));
          return;
        }
        const dom = domain || extent(g, _.x),
          add = p => {
            const t = {};
            for (let i = 0; i < names.length; ++i) {
              t[names[i]] = g.dims[i];
            }
            t[as[0]] = p[0];
            t[as[1]] = p[1];
            values.push(ingest$1(t));
          };
        if (method === 'linear' || method === 'constant') {
          // for linear or constant regression we only need the end points
          dom.forEach(x => add([x, model.predict(x)]));
        } else {
          // otherwise return trend line sample points
          sampleCurve(model.predict, dom, 25, 200).forEach(add);
        }
      });
      if (this.value) out.rem = this.value;
      this.value = out.add = out.source = values;
    }
    return out;
  }
});



;// ../../node_modules/robust-predicates/esm/util.js
const util_epsilon = 1.1102230246251565e-16;
const util_splitter = 134217729;
const util_resulterrbound = (3 + 8 * util_epsilon) * util_epsilon;

// fast_expansion_sum_zeroelim routine from oritinal code
function util_sum(elen, e, flen, f, h) {
    let Q, Qnew, hh, bvirt;
    let enow = e[0];
    let fnow = f[0];
    let eindex = 0;
    let findex = 0;
    if ((fnow > enow) === (fnow > -enow)) {
        Q = enow;
        enow = e[++eindex];
    } else {
        Q = fnow;
        fnow = f[++findex];
    }
    let hindex = 0;
    if (eindex < elen && findex < flen) {
        if ((fnow > enow) === (fnow > -enow)) {
            Qnew = enow + Q;
            hh = Q - (Qnew - enow);
            enow = e[++eindex];
        } else {
            Qnew = fnow + Q;
            hh = Q - (Qnew - fnow);
            fnow = f[++findex];
        }
        Q = Qnew;
        if (hh !== 0) {
            h[hindex++] = hh;
        }
        while (eindex < elen && findex < flen) {
            if ((fnow > enow) === (fnow > -enow)) {
                Qnew = Q + enow;
                bvirt = Qnew - Q;
                hh = Q - (Qnew - bvirt) + (enow - bvirt);
                enow = e[++eindex];
            } else {
                Qnew = Q + fnow;
                bvirt = Qnew - Q;
                hh = Q - (Qnew - bvirt) + (fnow - bvirt);
                fnow = f[++findex];
            }
            Q = Qnew;
            if (hh !== 0) {
                h[hindex++] = hh;
            }
        }
    }
    while (eindex < elen) {
        Qnew = Q + enow;
        bvirt = Qnew - Q;
        hh = Q - (Qnew - bvirt) + (enow - bvirt);
        enow = e[++eindex];
        Q = Qnew;
        if (hh !== 0) {
            h[hindex++] = hh;
        }
    }
    while (findex < flen) {
        Qnew = Q + fnow;
        bvirt = Qnew - Q;
        hh = Q - (Qnew - bvirt) + (fnow - bvirt);
        fnow = f[++findex];
        Q = Qnew;
        if (hh !== 0) {
            h[hindex++] = hh;
        }
    }
    if (Q !== 0 || hindex === 0) {
        h[hindex++] = Q;
    }
    return hindex;
}

function util_sum_three(alen, a, blen, b, clen, c, tmp, out) {
    return util_sum(util_sum(alen, a, blen, b, tmp), tmp, clen, c, out);
}

// scale_expansion_zeroelim routine from oritinal code
function util_scale(elen, e, b, h) {
    let Q, sum, hh, product1, product0;
    let bvirt, c, ahi, alo, bhi, blo;

    c = util_splitter * b;
    bhi = c - (c - b);
    blo = b - bhi;
    let enow = e[0];
    Q = enow * b;
    c = util_splitter * enow;
    ahi = c - (c - enow);
    alo = enow - ahi;
    hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);
    let hindex = 0;
    if (hh !== 0) {
        h[hindex++] = hh;
    }
    for (let i = 1; i < elen; i++) {
        enow = e[i];
        product1 = enow * b;
        c = util_splitter * enow;
        ahi = c - (c - enow);
        alo = enow - ahi;
        product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);
        sum = Q + product0;
        bvirt = sum - Q;
        hh = Q - (sum - bvirt) + (product0 - bvirt);
        if (hh !== 0) {
            h[hindex++] = hh;
        }
        Q = product1 + sum;
        hh = sum - (Q - product1);
        if (hh !== 0) {
            h[hindex++] = hh;
        }
    }
    if (Q !== 0 || hindex === 0) {
        h[hindex++] = Q;
    }
    return hindex;
}

function util_negate(elen, e) {
    for (let i = 0; i < elen; i++) e[i] = -e[i];
    return elen;
}

function util_estimate(elen, e) {
    let Q = e[0];
    for (let i = 1; i < elen; i++) Q += e[i];
    return Q;
}

function vec(n) {
    return new Float64Array(n);
}

;// ../../node_modules/robust-predicates/esm/orient2d.js


const ccwerrboundA = (3 + 16 * util_epsilon) * util_epsilon;
const ccwerrboundB = (2 + 12 * util_epsilon) * util_epsilon;
const ccwerrboundC = (9 + 64 * util_epsilon) * util_epsilon * util_epsilon;

const orient2d_B = vec(4);
const C1 = vec(8);
const C2 = vec(12);
const orient2d_D = vec(16);
const u = vec(4);

function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
    let acxtail, acytail, bcxtail, bcytail;
    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;

    const acx = ax - cx;
    const bcx = bx - cx;
    const acy = ay - cy;
    const bcy = by - cy;

    s1 = acx * bcy;
    c = util_splitter * acx;
    ahi = c - (c - acx);
    alo = acx - ahi;
    c = util_splitter * bcy;
    bhi = c - (c - bcy);
    blo = bcy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = acy * bcx;
    c = util_splitter * acy;
    ahi = c - (c - acy);
    alo = acy - ahi;
    c = util_splitter * bcx;
    bhi = c - (c - bcx);
    blo = bcx - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    orient2d_B[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    orient2d_B[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    orient2d_B[2] = _j - (u3 - bvirt) + (_i - bvirt);
    orient2d_B[3] = u3;

    let det = util_estimate(4, orient2d_B);
    let errbound = ccwerrboundB * detsum;
    if (det >= errbound || -det >= errbound) {
        return det;
    }

    bvirt = ax - acx;
    acxtail = ax - (acx + bvirt) + (bvirt - cx);
    bvirt = bx - bcx;
    bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
    bvirt = ay - acy;
    acytail = ay - (acy + bvirt) + (bvirt - cy);
    bvirt = by - bcy;
    bcytail = by - (bcy + bvirt) + (bvirt - cy);

    if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
        return det;
    }

    errbound = ccwerrboundC * detsum + util_resulterrbound * Math.abs(det);
    det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
    if (det >= errbound || -det >= errbound) return det;

    s1 = acxtail * bcy;
    c = util_splitter * acxtail;
    ahi = c - (c - acxtail);
    alo = acxtail - ahi;
    c = util_splitter * bcy;
    bhi = c - (c - bcy);
    blo = bcy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = acytail * bcx;
    c = util_splitter * acytail;
    ahi = c - (c - acytail);
    alo = acytail - ahi;
    c = util_splitter * bcx;
    bhi = c - (c - bcx);
    blo = bcx - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    u[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    u[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    u[2] = _j - (u3 - bvirt) + (_i - bvirt);
    u[3] = u3;
    const C1len = util_sum(4, orient2d_B, 4, u, C1);

    s1 = acx * bcytail;
    c = util_splitter * acx;
    ahi = c - (c - acx);
    alo = acx - ahi;
    c = util_splitter * bcytail;
    bhi = c - (c - bcytail);
    blo = bcytail - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = acy * bcxtail;
    c = util_splitter * acy;
    ahi = c - (c - acy);
    alo = acy - ahi;
    c = util_splitter * bcxtail;
    bhi = c - (c - bcxtail);
    blo = bcxtail - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    u[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    u[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    u[2] = _j - (u3 - bvirt) + (_i - bvirt);
    u[3] = u3;
    const C2len = util_sum(C1len, C1, 4, u, C2);

    s1 = acxtail * bcytail;
    c = util_splitter * acxtail;
    ahi = c - (c - acxtail);
    alo = acxtail - ahi;
    c = util_splitter * bcytail;
    bhi = c - (c - bcytail);
    blo = bcytail - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = acytail * bcxtail;
    c = util_splitter * acytail;
    ahi = c - (c - acytail);
    alo = acytail - ahi;
    c = util_splitter * bcxtail;
    bhi = c - (c - bcxtail);
    blo = bcxtail - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    u[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    u[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    u[2] = _j - (u3 - bvirt) + (_i - bvirt);
    u[3] = u3;
    const Dlen = util_sum(C2len, C2, 4, u, orient2d_D);

    return orient2d_D[Dlen - 1];
}

function orient2d(ax, ay, bx, by, cx, cy) {
    const detleft = (ay - cy) * (bx - cx);
    const detright = (ax - cx) * (by - cy);
    const det = detleft - detright;

    const detsum = Math.abs(detleft + detright);
    if (Math.abs(det) >= ccwerrboundA * detsum) return det;

    return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
}

function orient2dfast(ax, ay, bx, by, cx, cy) {
    return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);
}

;// ../../node_modules/robust-predicates/esm/orient3d.js


const o3derrboundA = (7 + 56 * util_epsilon) * util_epsilon;
const o3derrboundB = (3 + 28 * util_epsilon) * util_epsilon;
const o3derrboundC = (26 + 288 * util_epsilon) * util_epsilon * util_epsilon;

const bc = vec(4);
const ca = vec(4);
const ab = vec(4);
const at_b = vec(4);
const at_c = vec(4);
const bt_c = vec(4);
const bt_a = vec(4);
const ct_a = vec(4);
const ct_b = vec(4);
const bct = vec(8);
const cat = vec(8);
const abt = vec(8);
const orient3d_u = vec(4);

const _8 = vec(8);
const _8b = vec(8);
const _16 = vec(8);
const _12 = vec(12);

let fin = vec(192);
let fin2 = vec(192);

function finadd(finlen, alen, a) {
    finlen = sum(finlen, fin, alen, a, fin2);
    const tmp = fin; fin = fin2; fin2 = tmp;
    return finlen;
}

function tailinit(xtail, ytail, ax, ay, bx, by, a, b) {
    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3, negate;
    if (xtail === 0) {
        if (ytail === 0) {
            a[0] = 0;
            b[0] = 0;
            return 1;
        } else {
            negate = -ytail;
            s1 = negate * ax;
            c = splitter * negate;
            ahi = c - (c - negate);
            alo = negate - ahi;
            c = splitter * ax;
            bhi = c - (c - ax);
            blo = ax - bhi;
            a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            a[1] = s1;
            s1 = ytail * bx;
            c = splitter * ytail;
            ahi = c - (c - ytail);
            alo = ytail - ahi;
            c = splitter * bx;
            bhi = c - (c - bx);
            blo = bx - bhi;
            b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            b[1] = s1;
            return 2;
        }
    } else {
        if (ytail === 0) {
            s1 = xtail * ay;
            c = splitter * xtail;
            ahi = c - (c - xtail);
            alo = xtail - ahi;
            c = splitter * ay;
            bhi = c - (c - ay);
            blo = ay - bhi;
            a[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            a[1] = s1;
            negate = -xtail;
            s1 = negate * by;
            c = splitter * negate;
            ahi = c - (c - negate);
            alo = negate - ahi;
            c = splitter * by;
            bhi = c - (c - by);
            blo = by - bhi;
            b[0] = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            b[1] = s1;
            return 2;
        } else {
            s1 = xtail * ay;
            c = splitter * xtail;
            ahi = c - (c - xtail);
            alo = xtail - ahi;
            c = splitter * ay;
            bhi = c - (c - ay);
            blo = ay - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = ytail * ax;
            c = splitter * ytail;
            ahi = c - (c - ytail);
            alo = ytail - ahi;
            c = splitter * ax;
            bhi = c - (c - ax);
            blo = ax - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 - t0;
            bvirt = s0 - _i;
            a[0] = s0 - (_i + bvirt) + (bvirt - t0);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 - t1;
            bvirt = _0 - _i;
            a[1] = _0 - (_i + bvirt) + (bvirt - t1);
            u3 = _j + _i;
            bvirt = u3 - _j;
            a[2] = _j - (u3 - bvirt) + (_i - bvirt);
            a[3] = u3;
            s1 = ytail * bx;
            c = splitter * ytail;
            ahi = c - (c - ytail);
            alo = ytail - ahi;
            c = splitter * bx;
            bhi = c - (c - bx);
            blo = bx - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = xtail * by;
            c = splitter * xtail;
            ahi = c - (c - xtail);
            alo = xtail - ahi;
            c = splitter * by;
            bhi = c - (c - by);
            blo = by - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 - t0;
            bvirt = s0 - _i;
            b[0] = s0 - (_i + bvirt) + (bvirt - t0);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 - t1;
            bvirt = _0 - _i;
            b[1] = _0 - (_i + bvirt) + (bvirt - t1);
            u3 = _j + _i;
            bvirt = u3 - _j;
            b[2] = _j - (u3 - bvirt) + (_i - bvirt);
            b[3] = u3;
            return 4;
        }
    }
}

function tailadd(finlen, a, b, k, z) {
    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, u3;
    s1 = a * b;
    c = splitter * a;
    ahi = c - (c - a);
    alo = a - ahi;
    c = splitter * b;
    bhi = c - (c - b);
    blo = b - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    c = splitter * k;
    bhi = c - (c - k);
    blo = k - bhi;
    _i = s0 * k;
    c = splitter * s0;
    ahi = c - (c - s0);
    alo = s0 - ahi;
    orient3d_u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);
    _j = s1 * k;
    c = splitter * s1;
    ahi = c - (c - s1);
    alo = s1 - ahi;
    _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);
    _k = _i + _0;
    bvirt = _k - _i;
    orient3d_u[1] = _i - (_k - bvirt) + (_0 - bvirt);
    u3 = _j + _k;
    orient3d_u[2] = _k - (u3 - _j);
    orient3d_u[3] = u3;
    finlen = finadd(finlen, 4, orient3d_u);
    if (z !== 0) {
        c = splitter * z;
        bhi = c - (c - z);
        blo = z - bhi;
        _i = s0 * z;
        c = splitter * s0;
        ahi = c - (c - s0);
        alo = s0 - ahi;
        orient3d_u[0] = alo * blo - (_i - ahi * bhi - alo * bhi - ahi * blo);
        _j = s1 * z;
        c = splitter * s1;
        ahi = c - (c - s1);
        alo = s1 - ahi;
        _0 = alo * blo - (_j - ahi * bhi - alo * bhi - ahi * blo);
        _k = _i + _0;
        bvirt = _k - _i;
        orient3d_u[1] = _i - (_k - bvirt) + (_0 - bvirt);
        u3 = _j + _k;
        orient3d_u[2] = _k - (u3 - _j);
        orient3d_u[3] = u3;
        finlen = finadd(finlen, 4, orient3d_u);
    }
    return finlen;
}

function orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent) {
    let finlen;
    let adxtail, bdxtail, cdxtail;
    let adytail, bdytail, cdytail;
    let adztail, bdztail, cdztail;
    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _k, _0, s1, s0, t1, t0, u3;

    const adx = ax - dx;
    const bdx = bx - dx;
    const cdx = cx - dx;
    const ady = ay - dy;
    const bdy = by - dy;
    const cdy = cy - dy;
    const adz = az - dz;
    const bdz = bz - dz;
    const cdz = cz - dz;

    s1 = bdx * cdy;
    c = splitter * bdx;
    ahi = c - (c - bdx);
    alo = bdx - ahi;
    c = splitter * cdy;
    bhi = c - (c - cdy);
    blo = cdy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cdx * bdy;
    c = splitter * cdx;
    ahi = c - (c - cdx);
    alo = cdx - ahi;
    c = splitter * bdy;
    bhi = c - (c - bdy);
    blo = bdy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    bc[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    bc[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    bc[2] = _j - (u3 - bvirt) + (_i - bvirt);
    bc[3] = u3;
    s1 = cdx * ady;
    c = splitter * cdx;
    ahi = c - (c - cdx);
    alo = cdx - ahi;
    c = splitter * ady;
    bhi = c - (c - ady);
    blo = ady - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = adx * cdy;
    c = splitter * adx;
    ahi = c - (c - adx);
    alo = adx - ahi;
    c = splitter * cdy;
    bhi = c - (c - cdy);
    blo = cdy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    ca[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    ca[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    ca[2] = _j - (u3 - bvirt) + (_i - bvirt);
    ca[3] = u3;
    s1 = adx * bdy;
    c = splitter * adx;
    ahi = c - (c - adx);
    alo = adx - ahi;
    c = splitter * bdy;
    bhi = c - (c - bdy);
    blo = bdy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = bdx * ady;
    c = splitter * bdx;
    ahi = c - (c - bdx);
    alo = bdx - ahi;
    c = splitter * ady;
    bhi = c - (c - ady);
    blo = ady - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    ab[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    ab[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    ab[2] = _j - (u3 - bvirt) + (_i - bvirt);
    ab[3] = u3;

    finlen = sum(
        sum(
            scale(4, bc, adz, _8), _8,
            scale(4, ca, bdz, _8b), _8b, _16), _16,
        scale(4, ab, cdz, _8), _8, fin);

    let det = estimate(finlen, fin);
    let errbound = o3derrboundB * permanent;
    if (det >= errbound || -det >= errbound) {
        return det;
    }

    bvirt = ax - adx;
    adxtail = ax - (adx + bvirt) + (bvirt - dx);
    bvirt = bx - bdx;
    bdxtail = bx - (bdx + bvirt) + (bvirt - dx);
    bvirt = cx - cdx;
    cdxtail = cx - (cdx + bvirt) + (bvirt - dx);
    bvirt = ay - ady;
    adytail = ay - (ady + bvirt) + (bvirt - dy);
    bvirt = by - bdy;
    bdytail = by - (bdy + bvirt) + (bvirt - dy);
    bvirt = cy - cdy;
    cdytail = cy - (cdy + bvirt) + (bvirt - dy);
    bvirt = az - adz;
    adztail = az - (adz + bvirt) + (bvirt - dz);
    bvirt = bz - bdz;
    bdztail = bz - (bdz + bvirt) + (bvirt - dz);
    bvirt = cz - cdz;
    cdztail = cz - (cdz + bvirt) + (bvirt - dz);

    if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 &&
        adytail === 0 && bdytail === 0 && cdytail === 0 &&
        adztail === 0 && bdztail === 0 && cdztail === 0) {
        return det;
    }

    errbound = o3derrboundC * permanent + resulterrbound * Math.abs(det);
    det +=
        adz * (bdx * cdytail + cdy * bdxtail - (bdy * cdxtail + cdx * bdytail)) + adztail * (bdx * cdy - bdy * cdx) +
        bdz * (cdx * adytail + ady * cdxtail - (cdy * adxtail + adx * cdytail)) + bdztail * (cdx * ady - cdy * adx) +
        cdz * (adx * bdytail + bdy * adxtail - (ady * bdxtail + bdx * adytail)) + cdztail * (adx * bdy - ady * bdx);
    if (det >= errbound || -det >= errbound) {
        return det;
    }

    const at_len = tailinit(adxtail, adytail, bdx, bdy, cdx, cdy, at_b, at_c);
    const bt_len = tailinit(bdxtail, bdytail, cdx, cdy, adx, ady, bt_c, bt_a);
    const ct_len = tailinit(cdxtail, cdytail, adx, ady, bdx, bdy, ct_a, ct_b);

    const bctlen = sum(bt_len, bt_c, ct_len, ct_b, bct);
    finlen = finadd(finlen, scale(bctlen, bct, adz, _16), _16);

    const catlen = sum(ct_len, ct_a, at_len, at_c, cat);
    finlen = finadd(finlen, scale(catlen, cat, bdz, _16), _16);

    const abtlen = sum(at_len, at_b, bt_len, bt_a, abt);
    finlen = finadd(finlen, scale(abtlen, abt, cdz, _16), _16);

    if (adztail !== 0) {
        finlen = finadd(finlen, scale(4, bc, adztail, _12), _12);
        finlen = finadd(finlen, scale(bctlen, bct, adztail, _16), _16);
    }
    if (bdztail !== 0) {
        finlen = finadd(finlen, scale(4, ca, bdztail, _12), _12);
        finlen = finadd(finlen, scale(catlen, cat, bdztail, _16), _16);
    }
    if (cdztail !== 0) {
        finlen = finadd(finlen, scale(4, ab, cdztail, _12), _12);
        finlen = finadd(finlen, scale(abtlen, abt, cdztail, _16), _16);
    }

    if (adxtail !== 0) {
        if (bdytail !== 0) {
            finlen = tailadd(finlen, adxtail, bdytail, cdz, cdztail);
        }
        if (cdytail !== 0) {
            finlen = tailadd(finlen, -adxtail, cdytail, bdz, bdztail);
        }
    }
    if (bdxtail !== 0) {
        if (cdytail !== 0) {
            finlen = tailadd(finlen, bdxtail, cdytail, adz, adztail);
        }
        if (adytail !== 0) {
            finlen = tailadd(finlen, -bdxtail, adytail, cdz, cdztail);
        }
    }
    if (cdxtail !== 0) {
        if (adytail !== 0) {
            finlen = tailadd(finlen, cdxtail, adytail, bdz, bdztail);
        }
        if (bdytail !== 0) {
            finlen = tailadd(finlen, -cdxtail, bdytail, adz, adztail);
        }
    }

    return fin[finlen - 1];
}

function orient3d(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {
    const adx = ax - dx;
    const bdx = bx - dx;
    const cdx = cx - dx;
    const ady = ay - dy;
    const bdy = by - dy;
    const cdy = cy - dy;
    const adz = az - dz;
    const bdz = bz - dz;
    const cdz = cz - dz;

    const bdxcdy = bdx * cdy;
    const cdxbdy = cdx * bdy;

    const cdxady = cdx * ady;
    const adxcdy = adx * cdy;

    const adxbdy = adx * bdy;
    const bdxady = bdx * ady;

    const det =
        adz * (bdxcdy - cdxbdy) +
        bdz * (cdxady - adxcdy) +
        cdz * (adxbdy - bdxady);

    const permanent =
        (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) +
        (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) +
        (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz);

    const errbound = o3derrboundA * permanent;
    if (det > errbound || -det > errbound) {
        return det;
    }

    return orient3dadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, permanent);
}

function orient3dfast(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz) {
    const adx = ax - dx;
    const bdx = bx - dx;
    const cdx = cx - dx;
    const ady = ay - dy;
    const bdy = by - dy;
    const cdy = cy - dy;
    const adz = az - dz;
    const bdz = bz - dz;
    const cdz = cz - dz;

    return adx * (bdy * cdz - bdz * cdy) +
        bdx * (cdy * adz - cdz * ady) +
        cdx * (ady * bdz - adz * bdy);
}

;// ../../node_modules/robust-predicates/esm/incircle.js


const iccerrboundA = (10 + 96 * util_epsilon) * util_epsilon;
const iccerrboundB = (4 + 48 * util_epsilon) * util_epsilon;
const iccerrboundC = (44 + 576 * util_epsilon) * util_epsilon * util_epsilon;

const incircle_bc = vec(4);
const incircle_ca = vec(4);
const incircle_ab = vec(4);
const aa = vec(4);
const bb = vec(4);
const cc = vec(4);
const incircle_u = vec(4);
const v = vec(4);
const axtbc = vec(8);
const aytbc = vec(8);
const bxtca = vec(8);
const bytca = vec(8);
const cxtab = vec(8);
const cytab = vec(8);
const incircle_abt = vec(8);
const incircle_bct = vec(8);
const incircle_cat = vec(8);
const abtt = vec(4);
const bctt = vec(4);
const catt = vec(4);

const incircle_8 = vec(8);
const incircle_16 = vec(16);
const _16b = vec(16);
const _16c = vec(16);
const _32 = vec(32);
const _32b = vec(32);
const _48 = vec(48);
const _64 = vec(64);

let incircle_fin = vec(1152);
let incircle_fin2 = vec(1152);

function incircle_finadd(finlen, a, alen) {
    finlen = sum(finlen, incircle_fin, a, alen, incircle_fin2);
    const tmp = incircle_fin; incircle_fin = incircle_fin2; incircle_fin2 = tmp;
    return finlen;
}

function incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent) {
    let finlen;
    let adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
    let axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
    let abtlen, bctlen, catlen;
    let abttlen, bcttlen, cattlen;
    let n1, n0;

    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;

    const adx = ax - dx;
    const bdx = bx - dx;
    const cdx = cx - dx;
    const ady = ay - dy;
    const bdy = by - dy;
    const cdy = cy - dy;

    s1 = bdx * cdy;
    c = splitter * bdx;
    ahi = c - (c - bdx);
    alo = bdx - ahi;
    c = splitter * cdy;
    bhi = c - (c - cdy);
    blo = cdy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cdx * bdy;
    c = splitter * cdx;
    ahi = c - (c - cdx);
    alo = cdx - ahi;
    c = splitter * bdy;
    bhi = c - (c - bdy);
    blo = bdy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    incircle_bc[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    incircle_bc[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    incircle_bc[2] = _j - (u3 - bvirt) + (_i - bvirt);
    incircle_bc[3] = u3;
    s1 = cdx * ady;
    c = splitter * cdx;
    ahi = c - (c - cdx);
    alo = cdx - ahi;
    c = splitter * ady;
    bhi = c - (c - ady);
    blo = ady - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = adx * cdy;
    c = splitter * adx;
    ahi = c - (c - adx);
    alo = adx - ahi;
    c = splitter * cdy;
    bhi = c - (c - cdy);
    blo = cdy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    incircle_ca[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    incircle_ca[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    incircle_ca[2] = _j - (u3 - bvirt) + (_i - bvirt);
    incircle_ca[3] = u3;
    s1 = adx * bdy;
    c = splitter * adx;
    ahi = c - (c - adx);
    alo = adx - ahi;
    c = splitter * bdy;
    bhi = c - (c - bdy);
    blo = bdy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = bdx * ady;
    c = splitter * bdx;
    ahi = c - (c - bdx);
    alo = bdx - ahi;
    c = splitter * ady;
    bhi = c - (c - ady);
    blo = ady - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    incircle_ab[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    incircle_ab[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    incircle_ab[2] = _j - (u3 - bvirt) + (_i - bvirt);
    incircle_ab[3] = u3;

    finlen = sum(
        sum(
            sum(
                scale(scale(4, incircle_bc, adx, incircle_8), incircle_8, adx, incircle_16), incircle_16,
                scale(scale(4, incircle_bc, ady, incircle_8), incircle_8, ady, _16b), _16b, _32), _32,
            sum(
                scale(scale(4, incircle_ca, bdx, incircle_8), incircle_8, bdx, incircle_16), incircle_16,
                scale(scale(4, incircle_ca, bdy, incircle_8), incircle_8, bdy, _16b), _16b, _32b), _32b, _64), _64,
        sum(
            scale(scale(4, incircle_ab, cdx, incircle_8), incircle_8, cdx, incircle_16), incircle_16,
            scale(scale(4, incircle_ab, cdy, incircle_8), incircle_8, cdy, _16b), _16b, _32), _32, incircle_fin);

    let det = estimate(finlen, incircle_fin);
    let errbound = iccerrboundB * permanent;
    if (det >= errbound || -det >= errbound) {
        return det;
    }

    bvirt = ax - adx;
    adxtail = ax - (adx + bvirt) + (bvirt - dx);
    bvirt = ay - ady;
    adytail = ay - (ady + bvirt) + (bvirt - dy);
    bvirt = bx - bdx;
    bdxtail = bx - (bdx + bvirt) + (bvirt - dx);
    bvirt = by - bdy;
    bdytail = by - (bdy + bvirt) + (bvirt - dy);
    bvirt = cx - cdx;
    cdxtail = cx - (cdx + bvirt) + (bvirt - dx);
    bvirt = cy - cdy;
    cdytail = cy - (cdy + bvirt) + (bvirt - dy);
    if (adxtail === 0 && bdxtail === 0 && cdxtail === 0 && adytail === 0 && bdytail === 0 && cdytail === 0) {
        return det;
    }

    errbound = iccerrboundC * permanent + resulterrbound * Math.abs(det);
    det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail)) +
        2 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +
        ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail)) +
        2 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +
        ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail)) +
        2 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));

    if (det >= errbound || -det >= errbound) {
        return det;
    }

    if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {
        s1 = adx * adx;
        c = splitter * adx;
        ahi = c - (c - adx);
        alo = adx - ahi;
        s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);
        t1 = ady * ady;
        c = splitter * ady;
        ahi = c - (c - ady);
        alo = ady - ahi;
        t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);
        _i = s0 + t0;
        bvirt = _i - s0;
        aa[0] = s0 - (_i - bvirt) + (t0 - bvirt);
        _j = s1 + _i;
        bvirt = _j - s1;
        _0 = s1 - (_j - bvirt) + (_i - bvirt);
        _i = _0 + t1;
        bvirt = _i - _0;
        aa[1] = _0 - (_i - bvirt) + (t1 - bvirt);
        u3 = _j + _i;
        bvirt = u3 - _j;
        aa[2] = _j - (u3 - bvirt) + (_i - bvirt);
        aa[3] = u3;
    }
    if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {
        s1 = bdx * bdx;
        c = splitter * bdx;
        ahi = c - (c - bdx);
        alo = bdx - ahi;
        s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);
        t1 = bdy * bdy;
        c = splitter * bdy;
        ahi = c - (c - bdy);
        alo = bdy - ahi;
        t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);
        _i = s0 + t0;
        bvirt = _i - s0;
        bb[0] = s0 - (_i - bvirt) + (t0 - bvirt);
        _j = s1 + _i;
        bvirt = _j - s1;
        _0 = s1 - (_j - bvirt) + (_i - bvirt);
        _i = _0 + t1;
        bvirt = _i - _0;
        bb[1] = _0 - (_i - bvirt) + (t1 - bvirt);
        u3 = _j + _i;
        bvirt = u3 - _j;
        bb[2] = _j - (u3 - bvirt) + (_i - bvirt);
        bb[3] = u3;
    }
    if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {
        s1 = cdx * cdx;
        c = splitter * cdx;
        ahi = c - (c - cdx);
        alo = cdx - ahi;
        s0 = alo * alo - (s1 - ahi * ahi - (ahi + ahi) * alo);
        t1 = cdy * cdy;
        c = splitter * cdy;
        ahi = c - (c - cdy);
        alo = cdy - ahi;
        t0 = alo * alo - (t1 - ahi * ahi - (ahi + ahi) * alo);
        _i = s0 + t0;
        bvirt = _i - s0;
        cc[0] = s0 - (_i - bvirt) + (t0 - bvirt);
        _j = s1 + _i;
        bvirt = _j - s1;
        _0 = s1 - (_j - bvirt) + (_i - bvirt);
        _i = _0 + t1;
        bvirt = _i - _0;
        cc[1] = _0 - (_i - bvirt) + (t1 - bvirt);
        u3 = _j + _i;
        bvirt = u3 - _j;
        cc[2] = _j - (u3 - bvirt) + (_i - bvirt);
        cc[3] = u3;
    }

    if (adxtail !== 0) {
        axtbclen = scale(4, incircle_bc, adxtail, axtbc);
        finlen = incircle_finadd(finlen, sum_three(
            scale(axtbclen, axtbc, 2 * adx, incircle_16), incircle_16,
            scale(scale(4, cc, adxtail, incircle_8), incircle_8, bdy, _16b), _16b,
            scale(scale(4, bb, adxtail, incircle_8), incircle_8, -cdy, _16c), _16c, _32, _48), _48);
    }
    if (adytail !== 0) {
        aytbclen = scale(4, incircle_bc, adytail, aytbc);
        finlen = incircle_finadd(finlen, sum_three(
            scale(aytbclen, aytbc, 2 * ady, incircle_16), incircle_16,
            scale(scale(4, bb, adytail, incircle_8), incircle_8, cdx, _16b), _16b,
            scale(scale(4, cc, adytail, incircle_8), incircle_8, -bdx, _16c), _16c, _32, _48), _48);
    }
    if (bdxtail !== 0) {
        bxtcalen = scale(4, incircle_ca, bdxtail, bxtca);
        finlen = incircle_finadd(finlen, sum_three(
            scale(bxtcalen, bxtca, 2 * bdx, incircle_16), incircle_16,
            scale(scale(4, aa, bdxtail, incircle_8), incircle_8, cdy, _16b), _16b,
            scale(scale(4, cc, bdxtail, incircle_8), incircle_8, -ady, _16c), _16c, _32, _48), _48);
    }
    if (bdytail !== 0) {
        bytcalen = scale(4, incircle_ca, bdytail, bytca);
        finlen = incircle_finadd(finlen, sum_three(
            scale(bytcalen, bytca, 2 * bdy, incircle_16), incircle_16,
            scale(scale(4, cc, bdytail, incircle_8), incircle_8, adx, _16b), _16b,
            scale(scale(4, aa, bdytail, incircle_8), incircle_8, -cdx, _16c), _16c, _32, _48), _48);
    }
    if (cdxtail !== 0) {
        cxtablen = scale(4, incircle_ab, cdxtail, cxtab);
        finlen = incircle_finadd(finlen, sum_three(
            scale(cxtablen, cxtab, 2 * cdx, incircle_16), incircle_16,
            scale(scale(4, bb, cdxtail, incircle_8), incircle_8, ady, _16b), _16b,
            scale(scale(4, aa, cdxtail, incircle_8), incircle_8, -bdy, _16c), _16c, _32, _48), _48);
    }
    if (cdytail !== 0) {
        cytablen = scale(4, incircle_ab, cdytail, cytab);
        finlen = incircle_finadd(finlen, sum_three(
            scale(cytablen, cytab, 2 * cdy, incircle_16), incircle_16,
            scale(scale(4, aa, cdytail, incircle_8), incircle_8, bdx, _16b), _16b,
            scale(scale(4, bb, cdytail, incircle_8), incircle_8, -adx, _16c), _16c, _32, _48), _48);
    }

    if (adxtail !== 0 || adytail !== 0) {
        if (bdxtail !== 0 || bdytail !== 0 || cdxtail !== 0 || cdytail !== 0) {
            s1 = bdxtail * cdy;
            c = splitter * bdxtail;
            ahi = c - (c - bdxtail);
            alo = bdxtail - ahi;
            c = splitter * cdy;
            bhi = c - (c - cdy);
            blo = cdy - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = bdx * cdytail;
            c = splitter * bdx;
            ahi = c - (c - bdx);
            alo = bdx - ahi;
            c = splitter * cdytail;
            bhi = c - (c - cdytail);
            blo = cdytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            incircle_u[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            incircle_u[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            incircle_u[2] = _j - (u3 - bvirt) + (_i - bvirt);
            incircle_u[3] = u3;
            s1 = cdxtail * -bdy;
            c = splitter * cdxtail;
            ahi = c - (c - cdxtail);
            alo = cdxtail - ahi;
            c = splitter * -bdy;
            bhi = c - (c - -bdy);
            blo = -bdy - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = cdx * -bdytail;
            c = splitter * cdx;
            ahi = c - (c - cdx);
            alo = cdx - ahi;
            c = splitter * -bdytail;
            bhi = c - (c - -bdytail);
            blo = -bdytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            v[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            v[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            v[2] = _j - (u3 - bvirt) + (_i - bvirt);
            v[3] = u3;
            bctlen = sum(4, incircle_u, 4, v, incircle_bct);
            s1 = bdxtail * cdytail;
            c = splitter * bdxtail;
            ahi = c - (c - bdxtail);
            alo = bdxtail - ahi;
            c = splitter * cdytail;
            bhi = c - (c - cdytail);
            blo = cdytail - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = cdxtail * bdytail;
            c = splitter * cdxtail;
            ahi = c - (c - cdxtail);
            alo = cdxtail - ahi;
            c = splitter * bdytail;
            bhi = c - (c - bdytail);
            blo = bdytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 - t0;
            bvirt = s0 - _i;
            bctt[0] = s0 - (_i + bvirt) + (bvirt - t0);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 - t1;
            bvirt = _0 - _i;
            bctt[1] = _0 - (_i + bvirt) + (bvirt - t1);
            u3 = _j + _i;
            bvirt = u3 - _j;
            bctt[2] = _j - (u3 - bvirt) + (_i - bvirt);
            bctt[3] = u3;
            bcttlen = 4;
        } else {
            incircle_bct[0] = 0;
            bctlen = 1;
            bctt[0] = 0;
            bcttlen = 1;
        }
        if (adxtail !== 0) {
            const len = scale(bctlen, incircle_bct, adxtail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(axtbclen, axtbc, adxtail, incircle_16), incircle_16,
                scale(len, _16c, 2 * adx, _32), _32, _48), _48);

            const len2 = scale(bcttlen, bctt, adxtail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * adx, incircle_16), incircle_16,
                scale(len2, incircle_8, adxtail, _16b), _16b,
                scale(len, _16c, adxtail, _32), _32, _32b, _64), _64);

            if (bdytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, cc, adxtail, incircle_8), incircle_8, bdytail, incircle_16), incircle_16);
            }
            if (cdytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, bb, -adxtail, incircle_8), incircle_8, cdytail, incircle_16), incircle_16);
            }
        }
        if (adytail !== 0) {
            const len = scale(bctlen, incircle_bct, adytail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(aytbclen, aytbc, adytail, incircle_16), incircle_16,
                scale(len, _16c, 2 * ady, _32), _32, _48), _48);

            const len2 = scale(bcttlen, bctt, adytail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * ady, incircle_16), incircle_16,
                scale(len2, incircle_8, adytail, _16b), _16b,
                scale(len, _16c, adytail, _32), _32, _32b, _64), _64);
        }
    }
    if (bdxtail !== 0 || bdytail !== 0) {
        if (cdxtail !== 0 || cdytail !== 0 || adxtail !== 0 || adytail !== 0) {
            s1 = cdxtail * ady;
            c = splitter * cdxtail;
            ahi = c - (c - cdxtail);
            alo = cdxtail - ahi;
            c = splitter * ady;
            bhi = c - (c - ady);
            blo = ady - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = cdx * adytail;
            c = splitter * cdx;
            ahi = c - (c - cdx);
            alo = cdx - ahi;
            c = splitter * adytail;
            bhi = c - (c - adytail);
            blo = adytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            incircle_u[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            incircle_u[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            incircle_u[2] = _j - (u3 - bvirt) + (_i - bvirt);
            incircle_u[3] = u3;
            n1 = -cdy;
            n0 = -cdytail;
            s1 = adxtail * n1;
            c = splitter * adxtail;
            ahi = c - (c - adxtail);
            alo = adxtail - ahi;
            c = splitter * n1;
            bhi = c - (c - n1);
            blo = n1 - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = adx * n0;
            c = splitter * adx;
            ahi = c - (c - adx);
            alo = adx - ahi;
            c = splitter * n0;
            bhi = c - (c - n0);
            blo = n0 - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            v[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            v[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            v[2] = _j - (u3 - bvirt) + (_i - bvirt);
            v[3] = u3;
            catlen = sum(4, incircle_u, 4, v, incircle_cat);
            s1 = cdxtail * adytail;
            c = splitter * cdxtail;
            ahi = c - (c - cdxtail);
            alo = cdxtail - ahi;
            c = splitter * adytail;
            bhi = c - (c - adytail);
            blo = adytail - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = adxtail * cdytail;
            c = splitter * adxtail;
            ahi = c - (c - adxtail);
            alo = adxtail - ahi;
            c = splitter * cdytail;
            bhi = c - (c - cdytail);
            blo = cdytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 - t0;
            bvirt = s0 - _i;
            catt[0] = s0 - (_i + bvirt) + (bvirt - t0);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 - t1;
            bvirt = _0 - _i;
            catt[1] = _0 - (_i + bvirt) + (bvirt - t1);
            u3 = _j + _i;
            bvirt = u3 - _j;
            catt[2] = _j - (u3 - bvirt) + (_i - bvirt);
            catt[3] = u3;
            cattlen = 4;
        } else {
            incircle_cat[0] = 0;
            catlen = 1;
            catt[0] = 0;
            cattlen = 1;
        }
        if (bdxtail !== 0) {
            const len = scale(catlen, incircle_cat, bdxtail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(bxtcalen, bxtca, bdxtail, incircle_16), incircle_16,
                scale(len, _16c, 2 * bdx, _32), _32, _48), _48);

            const len2 = scale(cattlen, catt, bdxtail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * bdx, incircle_16), incircle_16,
                scale(len2, incircle_8, bdxtail, _16b), _16b,
                scale(len, _16c, bdxtail, _32), _32, _32b, _64), _64);

            if (cdytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, aa, bdxtail, incircle_8), incircle_8, cdytail, incircle_16), incircle_16);
            }
            if (adytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, cc, -bdxtail, incircle_8), incircle_8, adytail, incircle_16), incircle_16);
            }
        }
        if (bdytail !== 0) {
            const len = scale(catlen, incircle_cat, bdytail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(bytcalen, bytca, bdytail, incircle_16), incircle_16,
                scale(len, _16c, 2 * bdy, _32), _32, _48), _48);

            const len2 = scale(cattlen, catt, bdytail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * bdy, incircle_16), incircle_16,
                scale(len2, incircle_8, bdytail, _16b), _16b,
                scale(len, _16c, bdytail, _32), _32,  _32b, _64), _64);
        }
    }
    if (cdxtail !== 0 || cdytail !== 0) {
        if (adxtail !== 0 || adytail !== 0 || bdxtail !== 0 || bdytail !== 0) {
            s1 = adxtail * bdy;
            c = splitter * adxtail;
            ahi = c - (c - adxtail);
            alo = adxtail - ahi;
            c = splitter * bdy;
            bhi = c - (c - bdy);
            blo = bdy - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = adx * bdytail;
            c = splitter * adx;
            ahi = c - (c - adx);
            alo = adx - ahi;
            c = splitter * bdytail;
            bhi = c - (c - bdytail);
            blo = bdytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            incircle_u[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            incircle_u[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            incircle_u[2] = _j - (u3 - bvirt) + (_i - bvirt);
            incircle_u[3] = u3;
            n1 = -ady;
            n0 = -adytail;
            s1 = bdxtail * n1;
            c = splitter * bdxtail;
            ahi = c - (c - bdxtail);
            alo = bdxtail - ahi;
            c = splitter * n1;
            bhi = c - (c - n1);
            blo = n1 - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = bdx * n0;
            c = splitter * bdx;
            ahi = c - (c - bdx);
            alo = bdx - ahi;
            c = splitter * n0;
            bhi = c - (c - n0);
            blo = n0 - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 + t0;
            bvirt = _i - s0;
            v[0] = s0 - (_i - bvirt) + (t0 - bvirt);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 + t1;
            bvirt = _i - _0;
            v[1] = _0 - (_i - bvirt) + (t1 - bvirt);
            u3 = _j + _i;
            bvirt = u3 - _j;
            v[2] = _j - (u3 - bvirt) + (_i - bvirt);
            v[3] = u3;
            abtlen = sum(4, incircle_u, 4, v, incircle_abt);
            s1 = adxtail * bdytail;
            c = splitter * adxtail;
            ahi = c - (c - adxtail);
            alo = adxtail - ahi;
            c = splitter * bdytail;
            bhi = c - (c - bdytail);
            blo = bdytail - bhi;
            s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
            t1 = bdxtail * adytail;
            c = splitter * bdxtail;
            ahi = c - (c - bdxtail);
            alo = bdxtail - ahi;
            c = splitter * adytail;
            bhi = c - (c - adytail);
            blo = adytail - bhi;
            t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
            _i = s0 - t0;
            bvirt = s0 - _i;
            abtt[0] = s0 - (_i + bvirt) + (bvirt - t0);
            _j = s1 + _i;
            bvirt = _j - s1;
            _0 = s1 - (_j - bvirt) + (_i - bvirt);
            _i = _0 - t1;
            bvirt = _0 - _i;
            abtt[1] = _0 - (_i + bvirt) + (bvirt - t1);
            u3 = _j + _i;
            bvirt = u3 - _j;
            abtt[2] = _j - (u3 - bvirt) + (_i - bvirt);
            abtt[3] = u3;
            abttlen = 4;
        } else {
            incircle_abt[0] = 0;
            abtlen = 1;
            abtt[0] = 0;
            abttlen = 1;
        }
        if (cdxtail !== 0) {
            const len = scale(abtlen, incircle_abt, cdxtail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(cxtablen, cxtab, cdxtail, incircle_16), incircle_16,
                scale(len, _16c, 2 * cdx, _32), _32, _48), _48);

            const len2 = scale(abttlen, abtt, cdxtail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * cdx, incircle_16), incircle_16,
                scale(len2, incircle_8, cdxtail, _16b), _16b,
                scale(len, _16c, cdxtail, _32), _32, _32b, _64), _64);

            if (adytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, bb, cdxtail, incircle_8), incircle_8, adytail, incircle_16), incircle_16);
            }
            if (bdytail !== 0) {
                finlen = incircle_finadd(finlen, scale(scale(4, aa, -cdxtail, incircle_8), incircle_8, bdytail, incircle_16), incircle_16);
            }
        }
        if (cdytail !== 0) {
            const len = scale(abtlen, incircle_abt, cdytail, _16c);
            finlen = incircle_finadd(finlen, sum(
                scale(cytablen, cytab, cdytail, incircle_16), incircle_16,
                scale(len, _16c, 2 * cdy, _32), _32, _48), _48);

            const len2 = scale(abttlen, abtt, cdytail, incircle_8);
            finlen = incircle_finadd(finlen, sum_three(
                scale(len2, incircle_8, 2 * cdy, incircle_16), incircle_16,
                scale(len2, incircle_8, cdytail, _16b), _16b,
                scale(len, _16c, cdytail, _32), _32, _32b, _64), _64);
        }
    }

    return incircle_fin[finlen - 1];
}

function incircle(ax, ay, bx, by, cx, cy, dx, dy) {
    const adx = ax - dx;
    const bdx = bx - dx;
    const cdx = cx - dx;
    const ady = ay - dy;
    const bdy = by - dy;
    const cdy = cy - dy;

    const bdxcdy = bdx * cdy;
    const cdxbdy = cdx * bdy;
    const alift = adx * adx + ady * ady;

    const cdxady = cdx * ady;
    const adxcdy = adx * cdy;
    const blift = bdx * bdx + bdy * bdy;

    const adxbdy = adx * bdy;
    const bdxady = bdx * ady;
    const clift = cdx * cdx + cdy * cdy;

    const det =
        alift * (bdxcdy - cdxbdy) +
        blift * (cdxady - adxcdy) +
        clift * (adxbdy - bdxady);

    const permanent =
        (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * alift +
        (Math.abs(cdxady) + Math.abs(adxcdy)) * blift +
        (Math.abs(adxbdy) + Math.abs(bdxady)) * clift;

    const errbound = iccerrboundA * permanent;

    if (det > errbound || -det > errbound) {
        return det;
    }
    return incircleadapt(ax, ay, bx, by, cx, cy, dx, dy, permanent);
}

function incirclefast(ax, ay, bx, by, cx, cy, dx, dy) {
    const adx = ax - dx;
    const ady = ay - dy;
    const bdx = bx - dx;
    const bdy = by - dy;
    const cdx = cx - dx;
    const cdy = cy - dy;

    const abdet = adx * bdy - bdx * ady;
    const bcdet = bdx * cdy - cdx * bdy;
    const cadet = cdx * ady - adx * cdy;
    const alift = adx * adx + ady * ady;
    const blift = bdx * bdx + bdy * bdy;
    const clift = cdx * cdx + cdy * cdy;

    return alift * bcdet + blift * cadet + clift * abdet;
}

;// ../../node_modules/robust-predicates/esm/insphere.js


const isperrboundA = (16 + 224 * util_epsilon) * util_epsilon;
const isperrboundB = (5 + 72 * util_epsilon) * util_epsilon;
const isperrboundC = (71 + 1408 * util_epsilon) * util_epsilon * util_epsilon;

const insphere_ab = vec(4);
const insphere_bc = vec(4);
const cd = vec(4);
const de = vec(4);
const insphere_ea = vec(4);
const ac = vec(4);
const bd = vec(4);
const ce = vec(4);
const da = vec(4);
const eb = vec(4);

const abc = vec(24);
const bcd = vec(24);
const cde = vec(24);
const dea = vec(24);
const eab = vec(24);
const abd = vec(24);
const bce = vec(24);
const cda = vec(24);
const deb = vec(24);
const eac = vec(24);

const adet = vec(1152);
const bdet = vec(1152);
const cdet = vec(1152);
const ddet = vec(1152);
const edet = vec(1152);
const abdet = vec(2304);
const cddet = vec(2304);
const cdedet = vec(3456);
const deter = vec(5760);

const insphere_8 = vec(8);
const insphere_8b = vec(8);
const _8c = vec(8);
const insphere_16 = vec(16);
const _24 = vec(24);
const insphere_48 = vec(48);
const _48b = vec(48);
const _96 = vec(96);
const _192 = vec(192);
const _384x = vec(384);
const _384y = vec(384);
const _384z = vec(384);
const _768 = vec(768);

function sum_three_scale(a, b, c, az, bz, cz, out) {
    return sum_three(
        scale(4, a, az, insphere_8), insphere_8,
        scale(4, b, bz, insphere_8b), insphere_8b,
        scale(4, c, cz, _8c), _8c, insphere_16, out);
}

function liftexact(alen, a, blen, b, clen, c, dlen, d, x, y, z, out) {
    const len = sum(
        sum(alen, a, blen, b, insphere_48), insphere_48,
        negate(sum(clen, c, dlen, d, _48b), _48b), _48b, _96);

    return sum_three(
        scale(scale(len, _96, x, _192), _192, x, _384x), _384x,
        scale(scale(len, _96, y, _192), _192, y, _384y), _384y,
        scale(scale(len, _96, z, _192), _192, z, _384z), _384z, _768, out);
}

function insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {
    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;

    s1 = ax * by;
    c = splitter * ax;
    ahi = c - (c - ax);
    alo = ax - ahi;
    c = splitter * by;
    bhi = c - (c - by);
    blo = by - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = bx * ay;
    c = splitter * bx;
    ahi = c - (c - bx);
    alo = bx - ahi;
    c = splitter * ay;
    bhi = c - (c - ay);
    blo = ay - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    insphere_ab[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    insphere_ab[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    insphere_ab[2] = _j - (u3 - bvirt) + (_i - bvirt);
    insphere_ab[3] = u3;
    s1 = bx * cy;
    c = splitter * bx;
    ahi = c - (c - bx);
    alo = bx - ahi;
    c = splitter * cy;
    bhi = c - (c - cy);
    blo = cy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cx * by;
    c = splitter * cx;
    ahi = c - (c - cx);
    alo = cx - ahi;
    c = splitter * by;
    bhi = c - (c - by);
    blo = by - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    insphere_bc[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    insphere_bc[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    insphere_bc[2] = _j - (u3 - bvirt) + (_i - bvirt);
    insphere_bc[3] = u3;
    s1 = cx * dy;
    c = splitter * cx;
    ahi = c - (c - cx);
    alo = cx - ahi;
    c = splitter * dy;
    bhi = c - (c - dy);
    blo = dy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = dx * cy;
    c = splitter * dx;
    ahi = c - (c - dx);
    alo = dx - ahi;
    c = splitter * cy;
    bhi = c - (c - cy);
    blo = cy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    cd[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    cd[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    cd[2] = _j - (u3 - bvirt) + (_i - bvirt);
    cd[3] = u3;
    s1 = dx * ey;
    c = splitter * dx;
    ahi = c - (c - dx);
    alo = dx - ahi;
    c = splitter * ey;
    bhi = c - (c - ey);
    blo = ey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = ex * dy;
    c = splitter * ex;
    ahi = c - (c - ex);
    alo = ex - ahi;
    c = splitter * dy;
    bhi = c - (c - dy);
    blo = dy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    de[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    de[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    de[2] = _j - (u3 - bvirt) + (_i - bvirt);
    de[3] = u3;
    s1 = ex * ay;
    c = splitter * ex;
    ahi = c - (c - ex);
    alo = ex - ahi;
    c = splitter * ay;
    bhi = c - (c - ay);
    blo = ay - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = ax * ey;
    c = splitter * ax;
    ahi = c - (c - ax);
    alo = ax - ahi;
    c = splitter * ey;
    bhi = c - (c - ey);
    blo = ey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    insphere_ea[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    insphere_ea[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    insphere_ea[2] = _j - (u3 - bvirt) + (_i - bvirt);
    insphere_ea[3] = u3;
    s1 = ax * cy;
    c = splitter * ax;
    ahi = c - (c - ax);
    alo = ax - ahi;
    c = splitter * cy;
    bhi = c - (c - cy);
    blo = cy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cx * ay;
    c = splitter * cx;
    ahi = c - (c - cx);
    alo = cx - ahi;
    c = splitter * ay;
    bhi = c - (c - ay);
    blo = ay - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    ac[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    ac[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    ac[2] = _j - (u3 - bvirt) + (_i - bvirt);
    ac[3] = u3;
    s1 = bx * dy;
    c = splitter * bx;
    ahi = c - (c - bx);
    alo = bx - ahi;
    c = splitter * dy;
    bhi = c - (c - dy);
    blo = dy - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = dx * by;
    c = splitter * dx;
    ahi = c - (c - dx);
    alo = dx - ahi;
    c = splitter * by;
    bhi = c - (c - by);
    blo = by - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    bd[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    bd[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    bd[2] = _j - (u3 - bvirt) + (_i - bvirt);
    bd[3] = u3;
    s1 = cx * ey;
    c = splitter * cx;
    ahi = c - (c - cx);
    alo = cx - ahi;
    c = splitter * ey;
    bhi = c - (c - ey);
    blo = ey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = ex * cy;
    c = splitter * ex;
    ahi = c - (c - ex);
    alo = ex - ahi;
    c = splitter * cy;
    bhi = c - (c - cy);
    blo = cy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    ce[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    ce[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    ce[2] = _j - (u3 - bvirt) + (_i - bvirt);
    ce[3] = u3;
    s1 = dx * ay;
    c = splitter * dx;
    ahi = c - (c - dx);
    alo = dx - ahi;
    c = splitter * ay;
    bhi = c - (c - ay);
    blo = ay - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = ax * dy;
    c = splitter * ax;
    ahi = c - (c - ax);
    alo = ax - ahi;
    c = splitter * dy;
    bhi = c - (c - dy);
    blo = dy - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    da[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    da[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    da[2] = _j - (u3 - bvirt) + (_i - bvirt);
    da[3] = u3;
    s1 = ex * by;
    c = splitter * ex;
    ahi = c - (c - ex);
    alo = ex - ahi;
    c = splitter * by;
    bhi = c - (c - by);
    blo = by - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = bx * ey;
    c = splitter * bx;
    ahi = c - (c - bx);
    alo = bx - ahi;
    c = splitter * ey;
    bhi = c - (c - ey);
    blo = ey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    eb[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    eb[1] = _0 - (_i + bvirt) + (bvirt - t1);
    u3 = _j + _i;
    bvirt = u3 - _j;
    eb[2] = _j - (u3 - bvirt) + (_i - bvirt);
    eb[3] = u3;

    const abclen = sum_three_scale(insphere_ab, insphere_bc, ac, cz, az, -bz, abc);
    const bcdlen = sum_three_scale(insphere_bc, cd, bd, dz, bz, -cz, bcd);
    const cdelen = sum_three_scale(cd, de, ce, ez, cz, -dz, cde);
    const dealen = sum_three_scale(de, insphere_ea, da, az, dz, -ez, dea);
    const eablen = sum_three_scale(insphere_ea, insphere_ab, eb, bz, ez, -az, eab);
    const abdlen = sum_three_scale(insphere_ab, bd, da, dz, az, bz, abd);
    const bcelen = sum_three_scale(insphere_bc, ce, eb, ez, bz, cz, bce);
    const cdalen = sum_three_scale(cd, da, ac, az, cz, dz, cda);
    const deblen = sum_three_scale(de, eb, bd, bz, dz, ez, deb);
    const eaclen = sum_three_scale(insphere_ea, ac, ce, cz, ez, az, eac);

    const deterlen = sum_three(
        liftexact(cdelen, cde, bcelen, bce, deblen, deb, bcdlen, bcd, ax, ay, az, adet), adet,
        liftexact(dealen, dea, cdalen, cda, eaclen, eac, cdelen, cde, bx, by, bz, bdet), bdet,
        sum_three(
            liftexact(eablen, eab, deblen, deb, abdlen, abd, dealen, dea, cx, cy, cz, cdet), cdet,
            liftexact(abclen, abc, eaclen, eac, bcelen, bce, eablen, eab, dx, dy, dz, ddet), ddet,
            liftexact(bcdlen, bcd, abdlen, abd, cdalen, cda, abclen, abc, ex, ey, ez, edet), edet, cddet, cdedet), cdedet, abdet, deter);

    return deter[deterlen - 1];
}

const xdet = vec(96);
const ydet = vec(96);
const zdet = vec(96);
const insphere_fin = vec(1152);

function liftadapt(a, b, c, az, bz, cz, x, y, z, out) {
    const len = sum_three_scale(a, b, c, az, bz, cz, _24);
    return sum_three(
        scale(scale(len, _24, x, insphere_48), insphere_48, x, xdet), xdet,
        scale(scale(len, _24, y, insphere_48), insphere_48, y, ydet), ydet,
        scale(scale(len, _24, z, insphere_48), insphere_48, z, zdet), zdet, _192, out);
}

function insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent) {
    let ab3, bc3, cd3, da3, ac3, bd3;

    let aextail, bextail, cextail, dextail;
    let aeytail, beytail, ceytail, deytail;
    let aeztail, beztail, ceztail, deztail;

    let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0;

    const aex = ax - ex;
    const bex = bx - ex;
    const cex = cx - ex;
    const dex = dx - ex;
    const aey = ay - ey;
    const bey = by - ey;
    const cey = cy - ey;
    const dey = dy - ey;
    const aez = az - ez;
    const bez = bz - ez;
    const cez = cz - ez;
    const dez = dz - ez;

    s1 = aex * bey;
    c = splitter * aex;
    ahi = c - (c - aex);
    alo = aex - ahi;
    c = splitter * bey;
    bhi = c - (c - bey);
    blo = bey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = bex * aey;
    c = splitter * bex;
    ahi = c - (c - bex);
    alo = bex - ahi;
    c = splitter * aey;
    bhi = c - (c - aey);
    blo = aey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    insphere_ab[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    insphere_ab[1] = _0 - (_i + bvirt) + (bvirt - t1);
    ab3 = _j + _i;
    bvirt = ab3 - _j;
    insphere_ab[2] = _j - (ab3 - bvirt) + (_i - bvirt);
    insphere_ab[3] = ab3;
    s1 = bex * cey;
    c = splitter * bex;
    ahi = c - (c - bex);
    alo = bex - ahi;
    c = splitter * cey;
    bhi = c - (c - cey);
    blo = cey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cex * bey;
    c = splitter * cex;
    ahi = c - (c - cex);
    alo = cex - ahi;
    c = splitter * bey;
    bhi = c - (c - bey);
    blo = bey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    insphere_bc[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    insphere_bc[1] = _0 - (_i + bvirt) + (bvirt - t1);
    bc3 = _j + _i;
    bvirt = bc3 - _j;
    insphere_bc[2] = _j - (bc3 - bvirt) + (_i - bvirt);
    insphere_bc[3] = bc3;
    s1 = cex * dey;
    c = splitter * cex;
    ahi = c - (c - cex);
    alo = cex - ahi;
    c = splitter * dey;
    bhi = c - (c - dey);
    blo = dey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = dex * cey;
    c = splitter * dex;
    ahi = c - (c - dex);
    alo = dex - ahi;
    c = splitter * cey;
    bhi = c - (c - cey);
    blo = cey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    cd[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    cd[1] = _0 - (_i + bvirt) + (bvirt - t1);
    cd3 = _j + _i;
    bvirt = cd3 - _j;
    cd[2] = _j - (cd3 - bvirt) + (_i - bvirt);
    cd[3] = cd3;
    s1 = dex * aey;
    c = splitter * dex;
    ahi = c - (c - dex);
    alo = dex - ahi;
    c = splitter * aey;
    bhi = c - (c - aey);
    blo = aey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = aex * dey;
    c = splitter * aex;
    ahi = c - (c - aex);
    alo = aex - ahi;
    c = splitter * dey;
    bhi = c - (c - dey);
    blo = dey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    da[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    da[1] = _0 - (_i + bvirt) + (bvirt - t1);
    da3 = _j + _i;
    bvirt = da3 - _j;
    da[2] = _j - (da3 - bvirt) + (_i - bvirt);
    da[3] = da3;
    s1 = aex * cey;
    c = splitter * aex;
    ahi = c - (c - aex);
    alo = aex - ahi;
    c = splitter * cey;
    bhi = c - (c - cey);
    blo = cey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = cex * aey;
    c = splitter * cex;
    ahi = c - (c - cex);
    alo = cex - ahi;
    c = splitter * aey;
    bhi = c - (c - aey);
    blo = aey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    ac[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    ac[1] = _0 - (_i + bvirt) + (bvirt - t1);
    ac3 = _j + _i;
    bvirt = ac3 - _j;
    ac[2] = _j - (ac3 - bvirt) + (_i - bvirt);
    ac[3] = ac3;
    s1 = bex * dey;
    c = splitter * bex;
    ahi = c - (c - bex);
    alo = bex - ahi;
    c = splitter * dey;
    bhi = c - (c - dey);
    blo = dey - bhi;
    s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
    t1 = dex * bey;
    c = splitter * dex;
    ahi = c - (c - dex);
    alo = dex - ahi;
    c = splitter * bey;
    bhi = c - (c - bey);
    blo = bey - bhi;
    t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
    _i = s0 - t0;
    bvirt = s0 - _i;
    bd[0] = s0 - (_i + bvirt) + (bvirt - t0);
    _j = s1 + _i;
    bvirt = _j - s1;
    _0 = s1 - (_j - bvirt) + (_i - bvirt);
    _i = _0 - t1;
    bvirt = _0 - _i;
    bd[1] = _0 - (_i + bvirt) + (bvirt - t1);
    bd3 = _j + _i;
    bvirt = bd3 - _j;
    bd[2] = _j - (bd3 - bvirt) + (_i - bvirt);
    bd[3] = bd3;

    const finlen = sum(
        sum(
            negate(liftadapt(insphere_bc, cd, bd, dez, bez, -cez, aex, aey, aez, adet), adet), adet,
            liftadapt(cd, da, ac, aez, cez, dez, bex, bey, bez, bdet), bdet, abdet), abdet,
        sum(
            negate(liftadapt(da, insphere_ab, bd, bez, dez, aez, cex, cey, cez, cdet), cdet), cdet,
            liftadapt(insphere_ab, insphere_bc, ac, cez, aez, -bez, dex, dey, dez, ddet), ddet, cddet), cddet, insphere_fin);

    let det = estimate(finlen, insphere_fin);
    let errbound = isperrboundB * permanent;
    if (det >= errbound || -det >= errbound) {
        return det;
    }

    bvirt = ax - aex;
    aextail = ax - (aex + bvirt) + (bvirt - ex);
    bvirt = ay - aey;
    aeytail = ay - (aey + bvirt) + (bvirt - ey);
    bvirt = az - aez;
    aeztail = az - (aez + bvirt) + (bvirt - ez);
    bvirt = bx - bex;
    bextail = bx - (bex + bvirt) + (bvirt - ex);
    bvirt = by - bey;
    beytail = by - (bey + bvirt) + (bvirt - ey);
    bvirt = bz - bez;
    beztail = bz - (bez + bvirt) + (bvirt - ez);
    bvirt = cx - cex;
    cextail = cx - (cex + bvirt) + (bvirt - ex);
    bvirt = cy - cey;
    ceytail = cy - (cey + bvirt) + (bvirt - ey);
    bvirt = cz - cez;
    ceztail = cz - (cez + bvirt) + (bvirt - ez);
    bvirt = dx - dex;
    dextail = dx - (dex + bvirt) + (bvirt - ex);
    bvirt = dy - dey;
    deytail = dy - (dey + bvirt) + (bvirt - ey);
    bvirt = dz - dez;
    deztail = dz - (dez + bvirt) + (bvirt - ez);
    if (aextail === 0 && aeytail === 0 && aeztail === 0 &&
        bextail === 0 && beytail === 0 && beztail === 0 &&
        cextail === 0 && ceytail === 0 && ceztail === 0 &&
        dextail === 0 && deytail === 0 && deztail === 0) {
        return det;
    }

    errbound = isperrboundC * permanent + resulterrbound * Math.abs(det);

    const abeps = (aex * beytail + bey * aextail) - (aey * bextail + bex * aeytail);
    const bceps = (bex * ceytail + cey * bextail) - (bey * cextail + cex * beytail);
    const cdeps = (cex * deytail + dey * cextail) - (cey * dextail + dex * ceytail);
    const daeps = (dex * aeytail + aey * dextail) - (dey * aextail + aex * deytail);
    const aceps = (aex * ceytail + cey * aextail) - (aey * cextail + cex * aeytail);
    const bdeps = (bex * deytail + dey * bextail) - (bey * dextail + dex * beytail);
    det +=
        (((bex * bex + bey * bey + bez * bez) * ((cez * daeps + dez * aceps + aez * cdeps) +
        (ceztail * da3 + deztail * ac3 + aeztail * cd3)) + (dex * dex + dey * dey + dez * dez) *
        ((aez * bceps - bez * aceps + cez * abeps) + (aeztail * bc3 - beztail * ac3 + ceztail * ab3))) -
        ((aex * aex + aey * aey + aez * aez) * ((bez * cdeps - cez * bdeps + dez * bceps) +
        (beztail * cd3 - ceztail * bd3 + deztail * bc3)) + (cex * cex + cey * cey + cez * cez) *
        ((dez * abeps + aez * bdeps + bez * daeps) + (deztail * ab3 + aeztail * bd3 + beztail * da3)))) +
        2 * (((bex * bextail + bey * beytail + bez * beztail) * (cez * da3 + dez * ac3 + aez * cd3) +
        (dex * dextail + dey * deytail + dez * deztail) * (aez * bc3 - bez * ac3 + cez * ab3)) -
        ((aex * aextail + aey * aeytail + aez * aeztail) * (bez * cd3 - cez * bd3 + dez * bc3) +
        (cex * cextail + cey * ceytail + cez * ceztail) * (dez * ab3 + aez * bd3 + bez * da3)));

    if (det >= errbound || -det >= errbound) {
        return det;
    }

    return insphereexact(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez);
}

function insphere(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez) {
    const aex = ax - ex;
    const bex = bx - ex;
    const cex = cx - ex;
    const dex = dx - ex;
    const aey = ay - ey;
    const bey = by - ey;
    const cey = cy - ey;
    const dey = dy - ey;
    const aez = az - ez;
    const bez = bz - ez;
    const cez = cz - ez;
    const dez = dz - ez;

    const aexbey = aex * bey;
    const bexaey = bex * aey;
    const ab = aexbey - bexaey;
    const bexcey = bex * cey;
    const cexbey = cex * bey;
    const bc = bexcey - cexbey;
    const cexdey = cex * dey;
    const dexcey = dex * cey;
    const cd = cexdey - dexcey;
    const dexaey = dex * aey;
    const aexdey = aex * dey;
    const da = dexaey - aexdey;
    const aexcey = aex * cey;
    const cexaey = cex * aey;
    const ac = aexcey - cexaey;
    const bexdey = bex * dey;
    const dexbey = dex * bey;
    const bd = bexdey - dexbey;

    const alift = aex * aex + aey * aey + aez * aez;
    const blift = bex * bex + bey * bey + bez * bez;
    const clift = cex * cex + cey * cey + cez * cez;
    const dlift = dex * dex + dey * dey + dez * dez;

    const det =
        (clift * (dez * ab + aez * bd + bez * da) - dlift * (aez * bc - bez * ac + cez * ab)) +
        (alift * (bez * cd - cez * bd + dez * bc) - blift * (cez * da + dez * ac + aez * cd));

    const aezplus = Math.abs(aez);
    const bezplus = Math.abs(bez);
    const cezplus = Math.abs(cez);
    const dezplus = Math.abs(dez);
    const aexbeyplus = Math.abs(aexbey) + Math.abs(bexaey);
    const bexceyplus = Math.abs(bexcey) + Math.abs(cexbey);
    const cexdeyplus = Math.abs(cexdey) + Math.abs(dexcey);
    const dexaeyplus = Math.abs(dexaey) + Math.abs(aexdey);
    const aexceyplus = Math.abs(aexcey) + Math.abs(cexaey);
    const bexdeyplus = Math.abs(bexdey) + Math.abs(dexbey);
    const permanent =
        (cexdeyplus * bezplus + bexdeyplus * cezplus + bexceyplus * dezplus) * alift +
        (dexaeyplus * cezplus + aexceyplus * dezplus + cexdeyplus * aezplus) * blift +
        (aexbeyplus * dezplus + bexdeyplus * aezplus + dexaeyplus * bezplus) * clift +
        (bexceyplus * aezplus + aexceyplus * bezplus + aexbeyplus * cezplus) * dlift;

    const errbound = isperrboundA * permanent;
    if (det > errbound || -det > errbound) {
        return det;
    }
    return -insphereadapt(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ex, ey, ez, permanent);
}

function inspherefast(pax, pay, paz, pbx, pby, pbz, pcx, pcy, pcz, pdx, pdy, pdz, pex, pey, pez) {
    const aex = pax - pex;
    const bex = pbx - pex;
    const cex = pcx - pex;
    const dex = pdx - pex;
    const aey = pay - pey;
    const bey = pby - pey;
    const cey = pcy - pey;
    const dey = pdy - pey;
    const aez = paz - pez;
    const bez = pbz - pez;
    const cez = pcz - pez;
    const dez = pdz - pez;

    const ab = aex * bey - bex * aey;
    const bc = bex * cey - cex * bey;
    const cd = cex * dey - dex * cey;
    const da = dex * aey - aex * dey;
    const ac = aex * cey - cex * aey;
    const bd = bex * dey - dex * bey;

    const abc = aez * bc - bez * ac + cez * ab;
    const bcd = bez * cd - cez * bd + dez * bc;
    const cda = cez * da + dez * ac + aez * cd;
    const dab = dez * ab + aez * bd + bez * da;

    const alift = aex * aex + aey * aey + aez * aez;
    const blift = bex * bex + bey * bey + bez * bez;
    const clift = cex * cex + cey * cey + cez * cez;
    const dlift = dex * dex + dey * dey + dez * dez;

    return (clift * dab - dlift * abc) + (alift * bcd - blift * cda);
}

;// ../../node_modules/robust-predicates/index.js






;// ../../node_modules/delaunator/index.js

const delaunator_EPSILON = Math.pow(2, -52);
const EDGE_STACK = new Uint32Array(512);



class Delaunator {

    static from(points, getX = defaultGetX, getY = defaultGetY) {
        const n = points.length;
        const coords = new Float64Array(n * 2);

        for (let i = 0; i < n; i++) {
            const p = points[i];
            coords[2 * i] = getX(p);
            coords[2 * i + 1] = getY(p);
        }

        return new Delaunator(coords);
    }

    constructor(coords) {
        const n = coords.length >> 1;
        if (n > 0 && typeof coords[0] !== 'number') throw new Error('Expected coords to contain numbers.');

        this.coords = coords;

        // arrays that will store the triangulation graph
        const maxTriangles = Math.max(2 * n - 5, 0);
        this._triangles = new Uint32Array(maxTriangles * 3);
        this._halfedges = new Int32Array(maxTriangles * 3);

        // temporary arrays for tracking the edges of the advancing convex hull
        this._hashSize = Math.ceil(Math.sqrt(n));
        this._hullPrev = new Uint32Array(n); // edge to prev edge
        this._hullNext = new Uint32Array(n); // edge to next edge
        this._hullTri = new Uint32Array(n); // edge to adjacent triangle
        this._hullHash = new Int32Array(this._hashSize); // angular edge hash

        // temporary arrays for sorting points
        this._ids = new Uint32Array(n);
        this._dists = new Float64Array(n);

        this.update();
    }

    update() {
        const {coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash} =  this;
        const n = coords.length >> 1;

        // populate an array of point indices; calculate input data bbox
        let minX = Infinity;
        let minY = Infinity;
        let maxX = -Infinity;
        let maxY = -Infinity;

        for (let i = 0; i < n; i++) {
            const x = coords[2 * i];
            const y = coords[2 * i + 1];
            if (x < minX) minX = x;
            if (y < minY) minY = y;
            if (x > maxX) maxX = x;
            if (y > maxY) maxY = y;
            this._ids[i] = i;
        }
        const cx = (minX + maxX) / 2;
        const cy = (minY + maxY) / 2;

        let i0, i1, i2;

        // pick a seed point close to the center
        for (let i = 0, minDist = Infinity; i < n; i++) {
            const d = delaunator_dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
            if (d < minDist) {
                i0 = i;
                minDist = d;
            }
        }
        const i0x = coords[2 * i0];
        const i0y = coords[2 * i0 + 1];

        // find the point closest to the seed
        for (let i = 0, minDist = Infinity; i < n; i++) {
            if (i === i0) continue;
            const d = delaunator_dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);
            if (d < minDist && d > 0) {
                i1 = i;
                minDist = d;
            }
        }
        let i1x = coords[2 * i1];
        let i1y = coords[2 * i1 + 1];

        let minRadius = Infinity;

        // find the third point which forms the smallest circumcircle with the first two
        for (let i = 0; i < n; i++) {
            if (i === i0 || i === i1) continue;
            const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);
            if (r < minRadius) {
                i2 = i;
                minRadius = r;
            }
        }
        let i2x = coords[2 * i2];
        let i2y = coords[2 * i2 + 1];

        if (minRadius === Infinity) {
            // order collinear points by dx (or dy if all x are identical)
            // and return the list as a hull
            for (let i = 0; i < n; i++) {
                this._dists[i] = (coords[2 * i] - coords[0]) || (coords[2 * i + 1] - coords[1]);
            }
            quicksort(this._ids, this._dists, 0, n - 1);
            const hull = new Uint32Array(n);
            let j = 0;
            for (let i = 0, d0 = -Infinity; i < n; i++) {
                const id = this._ids[i];
                const d = this._dists[id];
                if (d > d0) {
                    hull[j++] = id;
                    d0 = d;
                }
            }
            this.hull = hull.subarray(0, j);
            this.triangles = new Uint32Array(0);
            this.halfedges = new Uint32Array(0);
            return;
        }

        // swap the order of the seed points for counter-clockwise orientation
        if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {
            const i = i1;
            const x = i1x;
            const y = i1y;
            i1 = i2;
            i1x = i2x;
            i1y = i2y;
            i2 = i;
            i2x = x;
            i2y = y;
        }

        const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
        this._cx = center.x;
        this._cy = center.y;

        for (let i = 0; i < n; i++) {
            this._dists[i] = delaunator_dist(coords[2 * i], coords[2 * i + 1], center.x, center.y);
        }

        // sort the points by distance from the seed triangle circumcenter
        quicksort(this._ids, this._dists, 0, n - 1);

        // set up the seed triangle as the starting hull
        this._hullStart = i0;
        let hullSize = 3;

        hullNext[i0] = hullPrev[i2] = i1;
        hullNext[i1] = hullPrev[i0] = i2;
        hullNext[i2] = hullPrev[i1] = i0;

        hullTri[i0] = 0;
        hullTri[i1] = 1;
        hullTri[i2] = 2;

        hullHash.fill(-1);
        hullHash[this._hashKey(i0x, i0y)] = i0;
        hullHash[this._hashKey(i1x, i1y)] = i1;
        hullHash[this._hashKey(i2x, i2y)] = i2;

        this.trianglesLen = 0;
        this._addTriangle(i0, i1, i2, -1, -1, -1);

        for (let k = 0, xp, yp; k < this._ids.length; k++) {
            const i = this._ids[k];
            const x = coords[2 * i];
            const y = coords[2 * i + 1];

            // skip near-duplicate points
            if (k > 0 && Math.abs(x - xp) <= delaunator_EPSILON && Math.abs(y - yp) <= delaunator_EPSILON) continue;
            xp = x;
            yp = y;

            // skip seed triangle points
            if (i === i0 || i === i1 || i === i2) continue;

            // find a visible edge on the convex hull using edge hash
            let start = 0;
            for (let j = 0, key = this._hashKey(x, y); j < this._hashSize; j++) {
                start = hullHash[(key + j) % this._hashSize];
                if (start !== -1 && start !== hullNext[start]) break;
            }

            start = hullPrev[start];
            let e = start, q;
            while (q = hullNext[e], orient2d(x, y, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {
                e = q;
                if (e === start) {
                    e = -1;
                    break;
                }
            }
            if (e === -1) continue; // likely a near-duplicate point; skip it

            // add the first triangle from the point
            let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);

            // recursively flip triangles from the point until they satisfy the Delaunay condition
            hullTri[i] = this._legalize(t + 2);
            hullTri[e] = t; // keep track of boundary triangles on the hull
            hullSize++;

            // walk forward through the hull, adding more triangles and flipping recursively
            let n = hullNext[e];
            while (q = hullNext[n], orient2d(x, y, coords[2 * n], coords[2 * n + 1], coords[2 * q], coords[2 * q + 1]) < 0) {
                t = this._addTriangle(n, i, q, hullTri[i], -1, hullTri[n]);
                hullTri[i] = this._legalize(t + 2);
                hullNext[n] = n; // mark as removed
                hullSize--;
                n = q;
            }

            // walk backward from the other side, adding more triangles and flipping
            if (e === start) {
                while (q = hullPrev[e], orient2d(x, y, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {
                    t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);
                    this._legalize(t + 2);
                    hullTri[q] = t;
                    hullNext[e] = e; // mark as removed
                    hullSize--;
                    e = q;
                }
            }

            // update the hull indices
            this._hullStart = hullPrev[i] = e;
            hullNext[e] = hullPrev[n] = i;
            hullNext[i] = n;

            // save the two new edges in the hash table
            hullHash[this._hashKey(x, y)] = i;
            hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
        }

        this.hull = new Uint32Array(hullSize);
        for (let i = 0, e = this._hullStart; i < hullSize; i++) {
            this.hull[i] = e;
            e = hullNext[e];
        }

        // trim typed triangle mesh arrays
        this.triangles = this._triangles.subarray(0, this.trianglesLen);
        this.halfedges = this._halfedges.subarray(0, this.trianglesLen);
    }

    _hashKey(x, y) {
        return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
    }

    _legalize(a) {
        const {_triangles: triangles, _halfedges: halfedges, coords} = this;

        let i = 0;
        let ar = 0;

        // recursion eliminated with a fixed-size stack
        while (true) {
            const b = halfedges[a];

            /* if the pair of triangles doesn't satisfy the Delaunay condition
             * (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
             * then do the same check/flip recursively for the new pair of triangles
             *
             *           pl                    pl
             *          /||\                  /  \
             *       al/ || \bl            al/    \a
             *        /  ||  \              /      \
             *       /  a||b  \    flip    /___ar___\
             *     p0\   ||   /p1   =>   p0\---bl---/p1
             *        \  ||  /              \      /
             *       ar\ || /br             b\    /br
             *          \||/                  \  /
             *           pr                    pr
             */
            const a0 = a - a % 3;
            ar = a0 + (a + 2) % 3;

            if (b === -1) { // convex hull edge
                if (i === 0) break;
                a = EDGE_STACK[--i];
                continue;
            }

            const b0 = b - b % 3;
            const al = a0 + (a + 1) % 3;
            const bl = b0 + (b + 2) % 3;

            const p0 = triangles[ar];
            const pr = triangles[a];
            const pl = triangles[al];
            const p1 = triangles[bl];

            const illegal = inCircle(
                coords[2 * p0], coords[2 * p0 + 1],
                coords[2 * pr], coords[2 * pr + 1],
                coords[2 * pl], coords[2 * pl + 1],
                coords[2 * p1], coords[2 * p1 + 1]);

            if (illegal) {
                triangles[a] = p1;
                triangles[b] = p0;

                const hbl = halfedges[bl];

                // edge swapped on the other side of the hull (rare); fix the halfedge reference
                if (hbl === -1) {
                    let e = this._hullStart;
                    do {
                        if (this._hullTri[e] === bl) {
                            this._hullTri[e] = a;
                            break;
                        }
                        e = this._hullPrev[e];
                    } while (e !== this._hullStart);
                }
                this._link(a, hbl);
                this._link(b, halfedges[ar]);
                this._link(ar, bl);

                const br = b0 + (b + 1) % 3;

                // don't worry about hitting the cap: it can only happen on extremely degenerate input
                if (i < EDGE_STACK.length) {
                    EDGE_STACK[i++] = br;
                }
            } else {
                if (i === 0) break;
                a = EDGE_STACK[--i];
            }
        }

        return ar;
    }

    _link(a, b) {
        this._halfedges[a] = b;
        if (b !== -1) this._halfedges[b] = a;
    }

    // add a new triangle given vertex indices and adjacent half-edge ids
    _addTriangle(i0, i1, i2, a, b, c) {
        const t = this.trianglesLen;

        this._triangles[t] = i0;
        this._triangles[t + 1] = i1;
        this._triangles[t + 2] = i2;

        this._link(t, a);
        this._link(t + 1, b);
        this._link(t + 2, c);

        this.trianglesLen += 3;

        return t;
    }
}

// monotonically increases with real angle, but doesn't need expensive trigonometry
function pseudoAngle(dx, dy) {
    const p = dx / (Math.abs(dx) + Math.abs(dy));
    return (dy > 0 ? 3 - p : 1 + p) / 4; // [0..1]
}

function delaunator_dist(ax, ay, bx, by) {
    const dx = ax - bx;
    const dy = ay - by;
    return dx * dx + dy * dy;
}

function inCircle(ax, ay, bx, by, cx, cy, px, py) {
    const dx = ax - px;
    const dy = ay - py;
    const ex = bx - px;
    const ey = by - py;
    const fx = cx - px;
    const fy = cy - py;

    const ap = dx * dx + dy * dy;
    const bp = ex * ex + ey * ey;
    const cp = fx * fx + fy * fy;

    return dx * (ey * cp - bp * fy) -
           dy * (ex * cp - bp * fx) +
           ap * (ex * fy - ey * fx) < 0;
}

function circumradius(ax, ay, bx, by, cx, cy) {
    const dx = bx - ax;
    const dy = by - ay;
    const ex = cx - ax;
    const ey = cy - ay;

    const bl = dx * dx + dy * dy;
    const cl = ex * ex + ey * ey;
    const d = 0.5 / (dx * ey - dy * ex);

    const x = (ey * bl - dy * cl) * d;
    const y = (dx * cl - ex * bl) * d;

    return x * x + y * y;
}

function circumcenter(ax, ay, bx, by, cx, cy) {
    const dx = bx - ax;
    const dy = by - ay;
    const ex = cx - ax;
    const ey = cy - ay;

    const bl = dx * dx + dy * dy;
    const cl = ex * ex + ey * ey;
    const d = 0.5 / (dx * ey - dy * ex);

    const x = ax + (ey * bl - dy * cl) * d;
    const y = ay + (dx * cl - ex * bl) * d;

    return {x, y};
}

function quicksort(ids, dists, left, right) {
    if (right - left <= 20) {
        for (let i = left + 1; i <= right; i++) {
            const temp = ids[i];
            const tempDist = dists[temp];
            let j = i - 1;
            while (j >= left && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];
            ids[j + 1] = temp;
        }
    } else {
        const median = (left + right) >> 1;
        let i = left + 1;
        let j = right;
        delaunator_swap(ids, median, i);
        if (dists[ids[left]] > dists[ids[right]]) delaunator_swap(ids, left, right);
        if (dists[ids[i]] > dists[ids[right]]) delaunator_swap(ids, i, right);
        if (dists[ids[left]] > dists[ids[i]]) delaunator_swap(ids, left, i);

        const temp = ids[i];
        const tempDist = dists[temp];
        while (true) {
            do i++; while (dists[ids[i]] < tempDist);
            do j--; while (dists[ids[j]] > tempDist);
            if (j < i) break;
            delaunator_swap(ids, i, j);
        }
        ids[left + 1] = ids[j];
        ids[j] = temp;

        if (right - i + 1 >= j - left) {
            quicksort(ids, dists, i, right);
            quicksort(ids, dists, left, j - 1);
        } else {
            quicksort(ids, dists, left, j - 1);
            quicksort(ids, dists, i, right);
        }
    }
}

function delaunator_swap(arr, i, j) {
    const tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

function defaultGetX(p) {
    return p[0];
}
function defaultGetY(p) {
    return p[1];
}

;// ../../node_modules/d3-delaunay/src/path.js
const src_path_epsilon = 1e-6;

class path_Path {
  constructor() {
    this._x0 = this._y0 = // start of current subpath
    this._x1 = this._y1 = null; // end of current subpath
    this._ = "";
  }
  moveTo(x, y) {
    this._ += `M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}`;
  }
  closePath() {
    if (this._x1 !== null) {
      this._x1 = this._x0, this._y1 = this._y0;
      this._ += "Z";
    }
  }
  lineTo(x, y) {
    this._ += `L${this._x1 = +x},${this._y1 = +y}`;
  }
  arc(x, y, r) {
    x = +x, y = +y, r = +r;
    const x0 = x + r;
    const y0 = y;
    if (r < 0) throw new Error("negative radius");
    if (this._x1 === null) this._ += `M${x0},${y0}`;
    else if (Math.abs(this._x1 - x0) > src_path_epsilon || Math.abs(this._y1 - y0) > src_path_epsilon) this._ += "L" + x0 + "," + y0;
    if (!r) return;
    this._ += `A${r},${r},0,1,1,${x - r},${y}A${r},${r},0,1,1,${this._x1 = x0},${this._y1 = y0}`;
  }
  rect(x, y, w, h) {
    this._ += `M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}h${+w}v${+h}h${-w}Z`;
  }
  value() {
    return this._ || null;
  }
}

;// ../../node_modules/d3-delaunay/src/polygon.js
class Polygon {
  constructor() {
    this._ = [];
  }
  moveTo(x, y) {
    this._.push([x, y]);
  }
  closePath() {
    this._.push(this._[0].slice());
  }
  lineTo(x, y) {
    this._.push([x, y]);
  }
  value() {
    return this._.length ? this._ : null;
  }
}

;// ../../node_modules/d3-delaunay/src/voronoi.js



class Voronoi {
  constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) {
    if (!((xmax = +xmax) >= (xmin = +xmin)) || !((ymax = +ymax) >= (ymin = +ymin))) throw new Error("invalid bounds");
    this.delaunay = delaunay;
    this._circumcenters = new Float64Array(delaunay.points.length * 2);
    this.vectors = new Float64Array(delaunay.points.length * 2);
    this.xmax = xmax, this.xmin = xmin;
    this.ymax = ymax, this.ymin = ymin;
    this._init();
  }
  update() {
    this.delaunay.update();
    this._init();
    return this;
  }
  _init() {
    const {delaunay: {points, hull, triangles}, vectors} = this;
    let bx, by; // lazily computed barycenter of the hull

    // Compute circumcenters.
    const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2);
    for (let i = 0, j = 0, n = triangles.length, x, y; i < n; i += 3, j += 2) {
      const t1 = triangles[i] * 2;
      const t2 = triangles[i + 1] * 2;
      const t3 = triangles[i + 2] * 2;
      const x1 = points[t1];
      const y1 = points[t1 + 1];
      const x2 = points[t2];
      const y2 = points[t2 + 1];
      const x3 = points[t3];
      const y3 = points[t3 + 1];

      const dx = x2 - x1;
      const dy = y2 - y1;
      const ex = x3 - x1;
      const ey = y3 - y1;
      const ab = (dx * ey - dy * ex) * 2;

      if (Math.abs(ab) < 1e-9) {
        // For a degenerate triangle, the circumcenter is at the infinity, in a
        // direction orthogonal to the halfedge and away from the “center” of
        // the diagram <bx, by>, defined as the hull’s barycenter.
        if (bx === undefined) {
          bx = by = 0;
          for (const i of hull) bx += points[i * 2], by += points[i * 2 + 1];
          bx /= hull.length, by /= hull.length;
        }
        const a = 1e9 * Math.sign((bx - x1) * ey - (by - y1) * ex);
        x = (x1 + x3) / 2 - a * ey;
        y = (y1 + y3) / 2 + a * ex;
      } else {
        const d = 1 / ab;
        const bl = dx * dx + dy * dy;
        const cl = ex * ex + ey * ey;
        x = x1 + (ey * bl - dy * cl) * d;
        y = y1 + (dx * cl - ex * bl) * d;
      }
      circumcenters[j] = x;
      circumcenters[j + 1] = y;
    }

    // Compute exterior cell rays.
    let h = hull[hull.length - 1];
    let p0, p1 = h * 4;
    let x0, x1 = points[2 * h];
    let y0, y1 = points[2 * h + 1];
    vectors.fill(0);
    for (let i = 0; i < hull.length; ++i) {
      h = hull[i];
      p0 = p1, x0 = x1, y0 = y1;
      p1 = h * 4, x1 = points[2 * h], y1 = points[2 * h + 1];
      vectors[p0 + 2] = vectors[p1] = y0 - y1;
      vectors[p0 + 3] = vectors[p1 + 1] = x1 - x0;
    }
  }
  render(context) {
    const buffer = context == null ? context = new path_Path : undefined;
    const {delaunay: {halfedges, inedges, hull}, circumcenters, vectors} = this;
    if (hull.length <= 1) return null;
    for (let i = 0, n = halfedges.length; i < n; ++i) {
      const j = halfedges[i];
      if (j < i) continue;
      const ti = Math.floor(i / 3) * 2;
      const tj = Math.floor(j / 3) * 2;
      const xi = circumcenters[ti];
      const yi = circumcenters[ti + 1];
      const xj = circumcenters[tj];
      const yj = circumcenters[tj + 1];
      this._renderSegment(xi, yi, xj, yj, context);
    }
    let h0, h1 = hull[hull.length - 1];
    for (let i = 0; i < hull.length; ++i) {
      h0 = h1, h1 = hull[i];
      const t = Math.floor(inedges[h1] / 3) * 2;
      const x = circumcenters[t];
      const y = circumcenters[t + 1];
      const v = h0 * 4;
      const p = this._project(x, y, vectors[v + 2], vectors[v + 3]);
      if (p) this._renderSegment(x, y, p[0], p[1], context);
    }
    return buffer && buffer.value();
  }
  renderBounds(context) {
    const buffer = context == null ? context = new path_Path : undefined;
    context.rect(this.xmin, this.ymin, this.xmax - this.xmin, this.ymax - this.ymin);
    return buffer && buffer.value();
  }
  renderCell(i, context) {
    const buffer = context == null ? context = new path_Path : undefined;
    const points = this._clip(i);
    if (points === null || !points.length) return;
    context.moveTo(points[0], points[1]);
    let n = points.length;
    while (points[0] === points[n-2] && points[1] === points[n-1] && n > 1) n -= 2;
    for (let i = 2; i < n; i += 2) {
      if (points[i] !== points[i-2] || points[i+1] !== points[i-1])
        context.lineTo(points[i], points[i + 1]);
    }
    context.closePath();
    return buffer && buffer.value();
  }
  *cellPolygons() {
    const {delaunay: {points}} = this;
    for (let i = 0, n = points.length / 2; i < n; ++i) {
      const cell = this.cellPolygon(i);
      if (cell) cell.index = i, yield cell;
    }
  }
  cellPolygon(i) {
    const polygon = new Polygon;
    this.renderCell(i, polygon);
    return polygon.value();
  }
  _renderSegment(x0, y0, x1, y1, context) {
    let S;
    const c0 = this._regioncode(x0, y0);
    const c1 = this._regioncode(x1, y1);
    if (c0 === 0 && c1 === 0) {
      context.moveTo(x0, y0);
      context.lineTo(x1, y1);
    } else if (S = this._clipSegment(x0, y0, x1, y1, c0, c1)) {
      context.moveTo(S[0], S[1]);
      context.lineTo(S[2], S[3]);
    }
  }
  contains(i, x, y) {
    if ((x = +x, x !== x) || (y = +y, y !== y)) return false;
    return this.delaunay._step(i, x, y) === i;
  }
  *neighbors(i) {
    const ci = this._clip(i);
    if (ci) for (const j of this.delaunay.neighbors(i)) {
      const cj = this._clip(j);
      // find the common edge
      if (cj) loop: for (let ai = 0, li = ci.length; ai < li; ai += 2) {
        for (let aj = 0, lj = cj.length; aj < lj; aj += 2) {
          if (ci[ai] === cj[aj]
              && ci[ai + 1] === cj[aj + 1]
              && ci[(ai + 2) % li] === cj[(aj + lj - 2) % lj]
              && ci[(ai + 3) % li] === cj[(aj + lj - 1) % lj]) {
            yield j;
            break loop;
          }
        }
      }
    }
  }
  _cell(i) {
    const {circumcenters, delaunay: {inedges, halfedges, triangles}} = this;
    const e0 = inedges[i];
    if (e0 === -1) return null; // coincident point
    const points = [];
    let e = e0;
    do {
      const t = Math.floor(e / 3);
      points.push(circumcenters[t * 2], circumcenters[t * 2 + 1]);
      e = e % 3 === 2 ? e - 2 : e + 1;
      if (triangles[e] !== i) break; // bad triangulation
      e = halfedges[e];
    } while (e !== e0 && e !== -1);
    return points;
  }
  _clip(i) {
    // degenerate case (1 valid point: return the box)
    if (i === 0 && this.delaunay.hull.length === 1) {
      return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];
    }
    const points = this._cell(i);
    if (points === null) return null;
    const {vectors: V} = this;
    const v = i * 4;
    return this._simplify(V[v] || V[v + 1]
        ? this._clipInfinite(i, points, V[v], V[v + 1], V[v + 2], V[v + 3])
        : this._clipFinite(i, points));
  }
  _clipFinite(i, points) {
    const n = points.length;
    let P = null;
    let x0, y0, x1 = points[n - 2], y1 = points[n - 1];
    let c0, c1 = this._regioncode(x1, y1);
    let e0, e1 = 0;
    for (let j = 0; j < n; j += 2) {
      x0 = x1, y0 = y1, x1 = points[j], y1 = points[j + 1];
      c0 = c1, c1 = this._regioncode(x1, y1);
      if (c0 === 0 && c1 === 0) {
        e0 = e1, e1 = 0;
        if (P) P.push(x1, y1);
        else P = [x1, y1];
      } else {
        let S, sx0, sy0, sx1, sy1;
        if (c0 === 0) {
          if ((S = this._clipSegment(x0, y0, x1, y1, c0, c1)) === null) continue;
          [sx0, sy0, sx1, sy1] = S;
        } else {
          if ((S = this._clipSegment(x1, y1, x0, y0, c1, c0)) === null) continue;
          [sx1, sy1, sx0, sy0] = S;
          e0 = e1, e1 = this._edgecode(sx0, sy0);
          if (e0 && e1) this._edge(i, e0, e1, P, P.length);
          if (P) P.push(sx0, sy0);
          else P = [sx0, sy0];
        }
        e0 = e1, e1 = this._edgecode(sx1, sy1);
        if (e0 && e1) this._edge(i, e0, e1, P, P.length);
        if (P) P.push(sx1, sy1);
        else P = [sx1, sy1];
      }
    }
    if (P) {
      e0 = e1, e1 = this._edgecode(P[0], P[1]);
      if (e0 && e1) this._edge(i, e0, e1, P, P.length);
    } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {
      return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];
    }
    return P;
  }
  _clipSegment(x0, y0, x1, y1, c0, c1) {
    // for more robustness, always consider the segment in the same order
    const flip = c0 < c1;
    if (flip) [x0, y0, x1, y1, c0, c1] = [x1, y1, x0, y0, c1, c0];
    while (true) {
      if (c0 === 0 && c1 === 0) return flip ? [x1, y1, x0, y0] : [x0, y0, x1, y1];
      if (c0 & c1) return null;
      let x, y, c = c0 || c1;
      if (c & 0b1000) x = x0 + (x1 - x0) * (this.ymax - y0) / (y1 - y0), y = this.ymax;
      else if (c & 0b0100) x = x0 + (x1 - x0) * (this.ymin - y0) / (y1 - y0), y = this.ymin;
      else if (c & 0b0010) y = y0 + (y1 - y0) * (this.xmax - x0) / (x1 - x0), x = this.xmax;
      else y = y0 + (y1 - y0) * (this.xmin - x0) / (x1 - x0), x = this.xmin;
      if (c0) x0 = x, y0 = y, c0 = this._regioncode(x0, y0);
      else x1 = x, y1 = y, c1 = this._regioncode(x1, y1);
    }
  }
  _clipInfinite(i, points, vx0, vy0, vxn, vyn) {
    let P = Array.from(points), p;
    if (p = this._project(P[0], P[1], vx0, vy0)) P.unshift(p[0], p[1]);
    if (p = this._project(P[P.length - 2], P[P.length - 1], vxn, vyn)) P.push(p[0], p[1]);
    if (P = this._clipFinite(i, P)) {
      for (let j = 0, n = P.length, c0, c1 = this._edgecode(P[n - 2], P[n - 1]); j < n; j += 2) {
        c0 = c1, c1 = this._edgecode(P[j], P[j + 1]);
        if (c0 && c1) j = this._edge(i, c0, c1, P, j), n = P.length;
      }
    } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {
      P = [this.xmin, this.ymin, this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax];
    }
    return P;
  }
  _edge(i, e0, e1, P, j) {
    while (e0 !== e1) {
      let x, y;
      switch (e0) {
        case 0b0101: e0 = 0b0100; continue; // top-left
        case 0b0100: e0 = 0b0110, x = this.xmax, y = this.ymin; break; // top
        case 0b0110: e0 = 0b0010; continue; // top-right
        case 0b0010: e0 = 0b1010, x = this.xmax, y = this.ymax; break; // right
        case 0b1010: e0 = 0b1000; continue; // bottom-right
        case 0b1000: e0 = 0b1001, x = this.xmin, y = this.ymax; break; // bottom
        case 0b1001: e0 = 0b0001; continue; // bottom-left
        case 0b0001: e0 = 0b0101, x = this.xmin, y = this.ymin; break; // left
      }
      // Note: this implicitly checks for out of bounds: if P[j] or P[j+1] are
      // undefined, the conditional statement will be executed.
      if ((P[j] !== x || P[j + 1] !== y) && this.contains(i, x, y)) {
        P.splice(j, 0, x, y), j += 2;
      }
    }
    return j;
  }
  _project(x0, y0, vx, vy) {
    let t = Infinity, c, x, y;
    if (vy < 0) { // top
      if (y0 <= this.ymin) return null;
      if ((c = (this.ymin - y0) / vy) < t) y = this.ymin, x = x0 + (t = c) * vx;
    } else if (vy > 0) { // bottom
      if (y0 >= this.ymax) return null;
      if ((c = (this.ymax - y0) / vy) < t) y = this.ymax, x = x0 + (t = c) * vx;
    }
    if (vx > 0) { // right
      if (x0 >= this.xmax) return null;
      if ((c = (this.xmax - x0) / vx) < t) x = this.xmax, y = y0 + (t = c) * vy;
    } else if (vx < 0) { // left
      if (x0 <= this.xmin) return null;
      if ((c = (this.xmin - x0) / vx) < t) x = this.xmin, y = y0 + (t = c) * vy;
    }
    return [x, y];
  }
  _edgecode(x, y) {
    return (x === this.xmin ? 0b0001
        : x === this.xmax ? 0b0010 : 0b0000)
        | (y === this.ymin ? 0b0100
        : y === this.ymax ? 0b1000 : 0b0000);
  }
  _regioncode(x, y) {
    return (x < this.xmin ? 0b0001
        : x > this.xmax ? 0b0010 : 0b0000)
        | (y < this.ymin ? 0b0100
        : y > this.ymax ? 0b1000 : 0b0000);
  }
  _simplify(P) {
    if (P && P.length > 4) {
      for (let i = 0; i < P.length; i+= 2) {
        const j = (i + 2) % P.length, k = (i + 4) % P.length;
        if (P[i] === P[j] && P[j] === P[k] || P[i + 1] === P[j + 1] && P[j + 1] === P[k + 1]) {
          P.splice(j, 2), i -= 2;
        }
      }
      if (!P.length) P = null;
    }
    return P;
  }
}

;// ../../node_modules/d3-delaunay/src/delaunay.js





const delaunay_tau = 2 * Math.PI, delaunay_pow = Math.pow;

function pointX(p) {
  return p[0];
}

function pointY(p) {
  return p[1];
}

// A triangulation is collinear if all its triangles have a non-null area
function delaunay_collinear(d) {
  const {triangles, coords} = d;
  for (let i = 0; i < triangles.length; i += 3) {
    const a = 2 * triangles[i],
          b = 2 * triangles[i + 1],
          c = 2 * triangles[i + 2],
          cross = (coords[c] - coords[a]) * (coords[b + 1] - coords[a + 1])
                - (coords[b] - coords[a]) * (coords[c + 1] - coords[a + 1]);
    if (cross > 1e-10) return false;
  }
  return true;
}

function jitter(x, y, r) {
  return [x + Math.sin(x + y) * r, y + Math.cos(x - y) * r];
}

class Delaunay {
  static from(points, fx = pointX, fy = pointY, that) {
    return new Delaunay("length" in points
        ? flatArray(points, fx, fy, that)
        : Float64Array.from(flatIterable(points, fx, fy, that)));
  }
  constructor(points) {
    this._delaunator = new Delaunator(points);
    this.inedges = new Int32Array(points.length / 2);
    this._hullIndex = new Int32Array(points.length / 2);
    this.points = this._delaunator.coords;
    this._init();
  }
  update() {
    this._delaunator.update();
    this._init();
    return this;
  }
  _init() {
    const d = this._delaunator, points = this.points;

    // check for collinear
    if (d.hull && d.hull.length > 2 && delaunay_collinear(d)) {
      this.collinear = Int32Array.from({length: points.length/2}, (_,i) => i)
        .sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); // for exact neighbors
      const e = this.collinear[0], f = this.collinear[this.collinear.length - 1],
        bounds = [ points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1] ],
        r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);
      for (let i = 0, n = points.length / 2; i < n; ++i) {
        const p = jitter(points[2 * i], points[2 * i + 1], r);
        points[2 * i] = p[0];
        points[2 * i + 1] = p[1];
      }
      this._delaunator = new Delaunator(points);
    } else {
      delete this.collinear;
    }

    const halfedges = this.halfedges = this._delaunator.halfedges;
    const hull = this.hull = this._delaunator.hull;
    const triangles = this.triangles = this._delaunator.triangles;
    const inedges = this.inedges.fill(-1);
    const hullIndex = this._hullIndex.fill(-1);

    // Compute an index from each point to an (arbitrary) incoming halfedge
    // Used to give the first neighbor of each point; for this reason,
    // on the hull we give priority to exterior halfedges
    for (let e = 0, n = halfedges.length; e < n; ++e) {
      const p = triangles[e % 3 === 2 ? e - 2 : e + 1];
      if (halfedges[e] === -1 || inedges[p] === -1) inedges[p] = e;
    }
    for (let i = 0, n = hull.length; i < n; ++i) {
      hullIndex[hull[i]] = i;
    }

    // degenerate case: 1 or 2 (distinct) points
    if (hull.length <= 2 && hull.length > 0) {
      this.triangles = new Int32Array(3).fill(-1);
      this.halfedges = new Int32Array(3).fill(-1);
      this.triangles[0] = hull[0];
      inedges[hull[0]] = 1;
      if (hull.length === 2) {
        inedges[hull[1]] = 0;
        this.triangles[1] = hull[1];
        this.triangles[2] = hull[1];
      }
    }
  }
  voronoi(bounds) {
    return new Voronoi(this, bounds);
  }
  *neighbors(i) {
    const {inedges, hull, _hullIndex, halfedges, triangles, collinear} = this;

    // degenerate case with several collinear points
    if (collinear) {
      const l = collinear.indexOf(i);
      if (l > 0) yield collinear[l - 1];
      if (l < collinear.length - 1) yield collinear[l + 1];
      return;
    }

    const e0 = inedges[i];
    if (e0 === -1) return; // coincident point
    let e = e0, p0 = -1;
    do {
      yield p0 = triangles[e];
      e = e % 3 === 2 ? e - 2 : e + 1;
      if (triangles[e] !== i) return; // bad triangulation
      e = halfedges[e];
      if (e === -1) {
        const p = hull[(_hullIndex[i] + 1) % hull.length];
        if (p !== p0) yield p;
        return;
      }
    } while (e !== e0);
  }
  find(x, y, i = 0) {
    if ((x = +x, x !== x) || (y = +y, y !== y)) return -1;
    const i0 = i;
    let c;
    while ((c = this._step(i, x, y)) >= 0 && c !== i && c !== i0) i = c;
    return c;
  }
  _step(i, x, y) {
    const {inedges, hull, _hullIndex, halfedges, triangles, points} = this;
    if (inedges[i] === -1 || !points.length) return (i + 1) % (points.length >> 1);
    let c = i;
    let dc = delaunay_pow(x - points[i * 2], 2) + delaunay_pow(y - points[i * 2 + 1], 2);
    const e0 = inedges[i];
    let e = e0;
    do {
      let t = triangles[e];
      const dt = delaunay_pow(x - points[t * 2], 2) + delaunay_pow(y - points[t * 2 + 1], 2);
      if (dt < dc) dc = dt, c = t;
      e = e % 3 === 2 ? e - 2 : e + 1;
      if (triangles[e] !== i) break; // bad triangulation
      e = halfedges[e];
      if (e === -1) {
        e = hull[(_hullIndex[i] + 1) % hull.length];
        if (e !== t) {
          if (delaunay_pow(x - points[e * 2], 2) + delaunay_pow(y - points[e * 2 + 1], 2) < dc) return e;
        }
        break;
      }
    } while (e !== e0);
    return c;
  }
  render(context) {
    const buffer = context == null ? context = new path_Path : undefined;
    const {points, halfedges, triangles} = this;
    for (let i = 0, n = halfedges.length; i < n; ++i) {
      const j = halfedges[i];
      if (j < i) continue;
      const ti = triangles[i] * 2;
      const tj = triangles[j] * 2;
      context.moveTo(points[ti], points[ti + 1]);
      context.lineTo(points[tj], points[tj + 1]);
    }
    this.renderHull(context);
    return buffer && buffer.value();
  }
  renderPoints(context, r) {
    if (r === undefined && (!context || typeof context.moveTo !== "function")) r = context, context = null;
    r = r == undefined ? 2 : +r;
    const buffer = context == null ? context = new path_Path : undefined;
    const {points} = this;
    for (let i = 0, n = points.length; i < n; i += 2) {
      const x = points[i], y = points[i + 1];
      context.moveTo(x + r, y);
      context.arc(x, y, r, 0, delaunay_tau);
    }
    return buffer && buffer.value();
  }
  renderHull(context) {
    const buffer = context == null ? context = new path_Path : undefined;
    const {hull, points} = this;
    const h = hull[0] * 2, n = hull.length;
    context.moveTo(points[h], points[h + 1]);
    for (let i = 1; i < n; ++i) {
      const h = 2 * hull[i];
      context.lineTo(points[h], points[h + 1]);
    }
    context.closePath();
    return buffer && buffer.value();
  }
  hullPolygon() {
    const polygon = new Polygon;
    this.renderHull(polygon);
    return polygon.value();
  }
  renderTriangle(i, context) {
    const buffer = context == null ? context = new path_Path : undefined;
    const {points, triangles} = this;
    const t0 = triangles[i *= 3] * 2;
    const t1 = triangles[i + 1] * 2;
    const t2 = triangles[i + 2] * 2;
    context.moveTo(points[t0], points[t0 + 1]);
    context.lineTo(points[t1], points[t1 + 1]);
    context.lineTo(points[t2], points[t2 + 1]);
    context.closePath();
    return buffer && buffer.value();
  }
  *trianglePolygons() {
    const {triangles} = this;
    for (let i = 0, n = triangles.length / 3; i < n; ++i) {
      yield this.trianglePolygon(i);
    }
  }
  trianglePolygon(i) {
    const polygon = new Polygon;
    this.renderTriangle(i, polygon);
    return polygon.value();
  }
}

function flatArray(points, fx, fy, that) {
  const n = points.length;
  const array = new Float64Array(n * 2);
  for (let i = 0; i < n; ++i) {
    const p = points[i];
    array[i * 2] = fx.call(that, p, i, points);
    array[i * 2 + 1] = fy.call(that, p, i, points);
  }
  return array;
}

function* flatIterable(points, fx, fy, that) {
  let i = 0;
  for (const p of points) {
    yield fx.call(that, p, i, points);
    yield fy.call(that, p, i, points);
    ++i;
  }
}

;// ../../node_modules/vega-voronoi/build/vega-voronoi.module.js




function vega_voronoi_module_Voronoi(params) {
  Transform.call(this, null, params);
}
vega_voronoi_module_Voronoi.Definition = {
  'type': 'Voronoi',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'x',
    'type': 'field',
    'required': true
  }, {
    'name': 'y',
    'type': 'field',
    'required': true
  }, {
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'extent',
    'type': 'array',
    'array': true,
    'length': 2,
    'default': [[-1e5, -1e5], [1e5, 1e5]],
    'content': {
      'type': 'number',
      'array': true,
      'length': 2
    }
  }, {
    'name': 'as',
    'type': 'string',
    'default': 'path'
  }]
};
const defaultExtent = [-1e5, -1e5, 1e5, 1e5];
inherits(vega_voronoi_module_Voronoi, Transform, {
  transform(_, pulse) {
    const as = _.as || 'path',
      data = pulse.source;

    // nothing to do if no data
    if (!data || !data.length) return pulse;

    // configure and construct voronoi diagram
    let s = _.size;
    s = s ? [0, 0, s[0], s[1]] : (s = _.extent) ? [s[0][0], s[0][1], s[1][0], s[1][1]] : defaultExtent;
    const voronoi = this.value = Delaunay.from(data, _.x, _.y).voronoi(s);

    // map polygons to paths
    for (let i = 0, n = data.length; i < n; ++i) {
      const polygon = voronoi.cellPolygon(i);
      data[i][as] = polygon && !isPoint(polygon) ? toPathString(polygon) : null;
    }
    return pulse.reflow(_.modified()).modifies(as);
  }
});

// suppress duplicated end point vertices
function toPathString(p) {
  const x = p[0][0],
    y = p[0][1];
  let n = p.length - 1;
  for (; p[n][0] === x && p[n][1] === y; --n);
  return 'M' + p.slice(0, n + 1).join('L') + 'Z';
}
function isPoint(p) {
  return p.length === 2 && p[0][0] === p[1][0] && p[0][1] === p[1][1];
}



;// ../../node_modules/vega-wordcloud/build/vega-wordcloud.module.js






/*
Copyright (c) 2013, Jason Davies.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  * The name Jason Davies may not be used to endorse or promote products
    derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL JASON DAVIES BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// Word cloud layout by Jason Davies, https://www.jasondavies.com/wordcloud/
// Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf

var cloudRadians = Math.PI / 180,
  cw = 1 << 11 >> 5,
  ch = 1 << 11;
function cloud () {
  var size = [256, 256],
    text,
    font,
    fontSize,
    fontStyle,
    fontWeight,
    rotate,
    padding,
    spiral = archimedeanSpiral,
    words = [],
    random = Math.random,
    cloud = {};
  cloud.layout = function () {
    var contextAndRatio = getContext(domCanvas()),
      board = zeroArray((size[0] >> 5) * size[1]),
      bounds = null,
      n = words.length,
      i = -1,
      tags = [],
      data = words.map(d => ({
        text: text(d),
        font: font(d),
        style: fontStyle(d),
        weight: fontWeight(d),
        rotate: rotate(d),
        size: ~~(fontSize(d) + 1e-14),
        padding: padding(d),
        xoff: 0,
        yoff: 0,
        x1: 0,
        y1: 0,
        x0: 0,
        y0: 0,
        hasText: false,
        sprite: null,
        datum: d
      })).sort((a, b) => b.size - a.size);
    while (++i < n) {
      var d = data[i];
      d.x = size[0] * (random() + .5) >> 1;
      d.y = size[1] * (random() + .5) >> 1;
      cloudSprite(contextAndRatio, d, data, i);
      if (d.hasText && place(board, d, bounds)) {
        tags.push(d);
        if (bounds) cloudBounds(bounds, d);else bounds = [{
          x: d.x + d.x0,
          y: d.y + d.y0
        }, {
          x: d.x + d.x1,
          y: d.y + d.y1
        }];
        // Temporary hack
        d.x -= size[0] >> 1;
        d.y -= size[1] >> 1;
      }
    }
    return tags;
  };
  function getContext(canvas) {
    canvas.width = canvas.height = 1;
    var ratio = Math.sqrt(canvas.getContext('2d').getImageData(0, 0, 1, 1).data.length >> 2);
    canvas.width = (cw << 5) / ratio;
    canvas.height = ch / ratio;
    var context = canvas.getContext('2d');
    context.fillStyle = context.strokeStyle = 'red';
    context.textAlign = 'center';
    return {
      context: context,
      ratio: ratio
    };
  }
  function place(board, tag, bounds) {
    var startX = tag.x,
      startY = tag.y,
      maxDelta = Math.hypot(size[0], size[1]),
      s = spiral(size),
      dt = random() < .5 ? 1 : -1,
      t = -dt,
      dxdy,
      dx,
      dy;
    while (dxdy = s(t += dt)) {
      dx = ~~dxdy[0];
      dy = ~~dxdy[1];
      if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break;
      tag.x = startX + dx;
      tag.y = startY + dy;
      if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
      // TODO only check for collisions within current bounds.
      if (!bounds || !cloudCollide(tag, board, size[0])) {
        if (!bounds || collideRects(tag, bounds)) {
          var sprite = tag.sprite,
            w = tag.width >> 5,
            sw = size[0] >> 5,
            lx = tag.x - (w << 4),
            sx = lx & 0x7f,
            msx = 32 - sx,
            h = tag.y1 - tag.y0,
            x = (tag.y + tag.y0) * sw + (lx >> 5),
            last;
          for (var j = 0; j < h; j++) {
            last = 0;
            for (var i = 0; i <= w; i++) {
              board[x + i] |= last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0);
            }
            x += sw;
          }
          tag.sprite = null;
          return true;
        }
      }
    }
    return false;
  }
  cloud.words = function (_) {
    if (arguments.length) {
      words = _;
      return cloud;
    } else {
      return words;
    }
  };
  cloud.size = function (_) {
    if (arguments.length) {
      size = [+_[0], +_[1]];
      return cloud;
    } else {
      return size;
    }
  };
  cloud.font = function (_) {
    if (arguments.length) {
      font = functor(_);
      return cloud;
    } else {
      return font;
    }
  };
  cloud.fontStyle = function (_) {
    if (arguments.length) {
      fontStyle = functor(_);
      return cloud;
    } else {
      return fontStyle;
    }
  };
  cloud.fontWeight = function (_) {
    if (arguments.length) {
      fontWeight = functor(_);
      return cloud;
    } else {
      return fontWeight;
    }
  };
  cloud.rotate = function (_) {
    if (arguments.length) {
      rotate = functor(_);
      return cloud;
    } else {
      return rotate;
    }
  };
  cloud.text = function (_) {
    if (arguments.length) {
      text = functor(_);
      return cloud;
    } else {
      return text;
    }
  };
  cloud.spiral = function (_) {
    if (arguments.length) {
      spiral = spirals[_] || _;
      return cloud;
    } else {
      return spiral;
    }
  };
  cloud.fontSize = function (_) {
    if (arguments.length) {
      fontSize = functor(_);
      return cloud;
    } else {
      return fontSize;
    }
  };
  cloud.padding = function (_) {
    if (arguments.length) {
      padding = functor(_);
      return cloud;
    } else {
      return padding;
    }
  };
  cloud.random = function (_) {
    if (arguments.length) {
      random = _;
      return cloud;
    } else {
      return random;
    }
  };
  return cloud;
}

// Fetches a monochrome sprite bitmap for the specified text.
// Load in batches for speed.
function cloudSprite(contextAndRatio, d, data, di) {
  if (d.sprite) return;
  var c = contextAndRatio.context,
    ratio = contextAndRatio.ratio;
  c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio);
  var x = 0,
    y = 0,
    maxh = 0,
    n = data.length,
    w,
    w32,
    h,
    i,
    j;
  --di;
  while (++di < n) {
    d = data[di];
    c.save();
    c.font = d.style + ' ' + d.weight + ' ' + ~~((d.size + 1) / ratio) + 'px ' + d.font;
    w = c.measureText(d.text + 'm').width * ratio;
    h = d.size << 1;
    if (d.rotate) {
      var sr = Math.sin(d.rotate * cloudRadians),
        cr = Math.cos(d.rotate * cloudRadians),
        wcr = w * cr,
        wsr = w * sr,
        hcr = h * cr,
        hsr = h * sr;
      w = Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f >> 5 << 5;
      h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr));
    } else {
      w = w + 0x1f >> 5 << 5;
    }
    if (h > maxh) maxh = h;
    if (x + w >= cw << 5) {
      x = 0;
      y += maxh;
      maxh = 0;
    }
    if (y + h >= ch) break;
    c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio);
    if (d.rotate) c.rotate(d.rotate * cloudRadians);
    c.fillText(d.text, 0, 0);
    if (d.padding) {
      c.lineWidth = 2 * d.padding;
      c.strokeText(d.text, 0, 0);
    }
    c.restore();
    d.width = w;
    d.height = h;
    d.xoff = x;
    d.yoff = y;
    d.x1 = w >> 1;
    d.y1 = h >> 1;
    d.x0 = -d.x1;
    d.y0 = -d.y1;
    d.hasText = true;
    x += w;
  }
  var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data,
    sprite = [];
  while (--di >= 0) {
    d = data[di];
    if (!d.hasText) continue;
    w = d.width;
    w32 = w >> 5;
    h = d.y1 - d.y0;
    // Zero the buffer
    for (i = 0; i < h * w32; i++) sprite[i] = 0;
    x = d.xoff;
    if (x == null) return;
    y = d.yoff;
    var seen = 0,
      seenRow = -1;
    for (j = 0; j < h; j++) {
      for (i = 0; i < w; i++) {
        var k = w32 * j + (i >> 5),
          m = pixels[(y + j) * (cw << 5) + (x + i) << 2] ? 1 << 31 - i % 32 : 0;
        sprite[k] |= m;
        seen |= m;
      }
      if (seen) seenRow = j;else {
        d.y0++;
        h--;
        j--;
        y++;
      }
    }
    d.y1 = d.y0 + seenRow;
    d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32);
  }
}

// Use mask-based collision detection.
function cloudCollide(tag, board, sw) {
  sw >>= 5;
  var sprite = tag.sprite,
    w = tag.width >> 5,
    lx = tag.x - (w << 4),
    sx = lx & 0x7f,
    msx = 32 - sx,
    h = tag.y1 - tag.y0,
    x = (tag.y + tag.y0) * sw + (lx >> 5),
    last;
  for (var j = 0; j < h; j++) {
    last = 0;
    for (var i = 0; i <= w; i++) {
      if ((last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0)) & board[x + i]) return true;
    }
    x += sw;
  }
  return false;
}
function cloudBounds(bounds, d) {
  var b0 = bounds[0],
    b1 = bounds[1];
  if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0;
  if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0;
  if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1;
  if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1;
}
function collideRects(a, b) {
  return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y;
}
function archimedeanSpiral(size) {
  var e = size[0] / size[1];
  return function (t) {
    return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)];
  };
}
function rectangularSpiral(size) {
  var dy = 4,
    dx = dy * size[0] / size[1],
    x = 0,
    y = 0;
  return function (t) {
    var sign = t < 0 ? -1 : 1;
    // See triangular numbers: T_n = n * (n + 1) / 2.
    switch (Math.sqrt(1 + 4 * sign * t) - sign & 3) {
      case 0:
        x += dx;
        break;
      case 1:
        y += dy;
        break;
      case 2:
        x -= dx;
        break;
      default:
        y -= dy;
        break;
    }
    return [x, y];
  };
}

// TODO reuse arrays?
function zeroArray(n) {
  var a = [],
    i = -1;
  while (++i < n) a[i] = 0;
  return a;
}
function functor(d) {
  return typeof d === 'function' ? d : function () {
    return d;
  };
}
var spirals = {
  archimedean: archimedeanSpiral,
  rectangular: rectangularSpiral
};

const vega_wordcloud_module_Output = ['x', 'y', 'font', 'fontSize', 'fontStyle', 'fontWeight', 'angle'];
const vega_wordcloud_module_Params = ['text', 'font', 'rotate', 'fontSize', 'fontStyle', 'fontWeight'];
function Wordcloud(params) {
  Transform.call(this, cloud(), params);
}
Wordcloud.Definition = {
  'type': 'Wordcloud',
  'metadata': {
    'modifies': true
  },
  'params': [{
    'name': 'size',
    'type': 'number',
    'array': true,
    'length': 2
  }, {
    'name': 'font',
    'type': 'string',
    'expr': true,
    'default': 'sans-serif'
  }, {
    'name': 'fontStyle',
    'type': 'string',
    'expr': true,
    'default': 'normal'
  }, {
    'name': 'fontWeight',
    'type': 'string',
    'expr': true,
    'default': 'normal'
  }, {
    'name': 'fontSize',
    'type': 'number',
    'expr': true,
    'default': 14
  }, {
    'name': 'fontSizeRange',
    'type': 'number',
    'array': 'nullable',
    'default': [10, 50]
  }, {
    'name': 'rotate',
    'type': 'number',
    'expr': true,
    'default': 0
  }, {
    'name': 'text',
    'type': 'field'
  }, {
    'name': 'spiral',
    'type': 'string',
    'values': ['archimedean', 'rectangular']
  }, {
    'name': 'padding',
    'type': 'number',
    'expr': true
  }, {
    'name': 'as',
    'type': 'string',
    'array': true,
    'length': 7,
    'default': vega_wordcloud_module_Output
  }]
};
inherits(Wordcloud, Transform, {
  transform(_, pulse) {
    if (_.size && !(_.size[0] && _.size[1])) {
      vega_util_module_error('Wordcloud size dimensions must be non-zero.');
    }
    function modp(param) {
      const p = _[param];
      return vega_util_module_isFunction(p) && pulse.modified(p.fields);
    }
    const mod = _.modified();
    if (!(mod || pulse.changed(pulse.ADD_REM) || vega_wordcloud_module_Params.some(modp))) return;
    const data = pulse.materialize(pulse.SOURCE).source,
      layout = this.value,
      as = _.as || vega_wordcloud_module_Output;
    let fontSize = _.fontSize || 14,
      range;
    vega_util_module_isFunction(fontSize) ? range = _.fontSizeRange : fontSize = vega_util_module_constant(fontSize);

    // create font size scaling function as needed
    if (range) {
      const fsize = fontSize,
        sizeScale = vega_scale_module_scale('sqrt')().domain(extent(data, fsize)).range(range);
      fontSize = x => sizeScale(fsize(x));
    }
    data.forEach(t => {
      t[as[0]] = NaN;
      t[as[1]] = NaN;
      t[as[3]] = 0;
    });

    // configure layout
    const words = layout.words(data).text(_.text).size(_.size || [500, 500]).padding(_.padding || 1).spiral(_.spiral || 'archimedean').rotate(_.rotate || 0).font(_.font || 'sans-serif').fontStyle(_.fontStyle || 'normal').fontWeight(_.fontWeight || 'normal').fontSize(fontSize).random(vega_statistics_module_random).layout();
    const size = layout.size(),
      dx = size[0] >> 1,
      dy = size[1] >> 1,
      n = words.length;
    for (let i = 0, w, t; i < n; ++i) {
      w = words[i];
      t = w.datum;
      t[as[0]] = w.x + dx;
      t[as[1]] = w.y + dy;
      t[as[2]] = w.font;
      t[as[3]] = w.size;
      t[as[4]] = w.style;
      t[as[5]] = w.weight;
      t[as[6]] = w.rotate;
    }
    return pulse.reflow(mod).modifies(as);
  }
});



;// ../../node_modules/d3-array/src/permute.js
function permute_permute(source, keys) {
  return Array.from(keys, key => source[key]);
}

;// ../../node_modules/vega-crossfilter/build/vega-crossfilter.module.js




const array8 = n => new Uint8Array(n);
const array16 = n => new Uint16Array(n);
const array32 = n => new Uint32Array(n);

/**
 * Maintains CrossFilter state.
 */
function Bitmaps() {
  let width = 8,
    data = [],
    seen = array32(0),
    curr = vega_crossfilter_module_array(0, width),
    prev = vega_crossfilter_module_array(0, width);
  return {
    data: () => data,
    seen: () => seen = lengthen(seen, data.length),
    add(array) {
      for (let i = 0, j = data.length, n = array.length, t; i < n; ++i) {
        t = array[i];
        t._index = j++;
        data.push(t);
      }
    },
    remove(num, map) {
      // map: index -> boolean (true => remove)
      const n = data.length,
        copy = Array(n - num),
        reindex = data; // reuse old data array for index map
      let t, i, j;

      // seek forward to first removal
      for (i = 0; !map[i] && i < n; ++i) {
        copy[i] = data[i];
        reindex[i] = i;
      }

      // condense arrays
      for (j = i; i < n; ++i) {
        t = data[i];
        if (!map[i]) {
          reindex[i] = j;
          curr[j] = curr[i];
          prev[j] = prev[i];
          copy[j] = t;
          t._index = j++;
        } else {
          reindex[i] = -1;
        }
        curr[i] = 0; // clear unused bits
      }
      data = copy;
      return reindex;
    },
    size: () => data.length,
    curr: () => curr,
    prev: () => prev,
    reset: k => prev[k] = curr[k],
    all: () => width < 0x101 ? 0xff : width < 0x10001 ? 0xffff : 0xffffffff,
    set(k, one) {
      curr[k] |= one;
    },
    clear(k, one) {
      curr[k] &= ~one;
    },
    resize(n, m) {
      const k = curr.length;
      if (n > k || m > width) {
        width = Math.max(m, width);
        curr = vega_crossfilter_module_array(n, width, curr);
        prev = vega_crossfilter_module_array(n, width);
      }
    }
  };
}
function lengthen(array, length, copy) {
  if (array.length >= length) return array;
  copy = copy || new array.constructor(length);
  copy.set(array);
  return copy;
}
function vega_crossfilter_module_array(n, m, array) {
  const copy = (m < 0x101 ? array8 : m < 0x10001 ? array16 : array32)(n);
  if (array) copy.set(array);
  return copy;
}

function Dimension (index, i, query) {
  const bit = 1 << i;
  return {
    one: bit,
    zero: ~bit,
    range: query.slice(),
    bisect: index.bisect,
    index: index.index,
    size: index.size,
    onAdd(added, curr) {
      const dim = this,
        range = dim.bisect(dim.range, added.value),
        idx = added.index,
        lo = range[0],
        hi = range[1],
        n1 = idx.length;
      let i;
      for (i = 0; i < lo; ++i) curr[idx[i]] |= bit;
      for (i = hi; i < n1; ++i) curr[idx[i]] |= bit;
      return dim;
    }
  };
}

/**
 * Maintains a list of values, sorted by key.
 */
function SortedIndex() {
  let index = array32(0),
    value = [],
    size = 0;
  function insert(key, data, base) {
    if (!data.length) return [];
    const n0 = size,
      n1 = data.length,
      addi = array32(n1);
    let addv = Array(n1),
      oldv,
      oldi,
      i;
    for (i = 0; i < n1; ++i) {
      addv[i] = key(data[i]);
      addi[i] = i;
    }
    addv = vega_crossfilter_module_sort(addv, addi);
    if (n0) {
      oldv = value;
      oldi = index;
      value = Array(n0 + n1);
      index = array32(n0 + n1);
      vega_crossfilter_module_merge(base, oldv, oldi, n0, addv, addi, n1, value, index);
    } else {
      if (base > 0) for (i = 0; i < n1; ++i) {
        addi[i] += base;
      }
      value = addv;
      index = addi;
    }
    size = n0 + n1;
    return {
      index: addi,
      value: addv
    };
  }
  function remove(num, map) {
    // map: index -> remove
    const n = size;
    let idx, i, j;

    // seek forward to first removal
    for (i = 0; !map[index[i]] && i < n; ++i);

    // condense index and value arrays
    for (j = i; i < n; ++i) {
      if (!map[idx = index[i]]) {
        index[j] = idx;
        value[j] = value[i];
        ++j;
      }
    }
    size = n - num;
  }
  function reindex(map) {
    for (let i = 0, n = size; i < n; ++i) {
      index[i] = map[index[i]];
    }
  }
  function bisect(range, array) {
    let n;
    if (array) {
      n = array.length;
    } else {
      array = value;
      n = size;
    }
    return [bisectLeft(array, range[0], 0, n), bisectRight(array, range[1], 0, n)];
  }
  return {
    insert: insert,
    remove: remove,
    bisect: bisect,
    reindex: reindex,
    index: () => index,
    size: () => size
  };
}
function vega_crossfilter_module_sort(values, index) {
  values.sort.call(index, (a, b) => {
    const x = values[a],
      y = values[b];
    return x < y ? -1 : x > y ? 1 : 0;
  });
  return permute_permute(values, index);
}
function vega_crossfilter_module_merge(base, value0, index0, n0, value1, index1, n1, value, index) {
  let i0 = 0,
    i1 = 0,
    i;
  for (i = 0; i0 < n0 && i1 < n1; ++i) {
    if (value0[i0] < value1[i1]) {
      value[i] = value0[i0];
      index[i] = index0[i0++];
    } else {
      value[i] = value1[i1];
      index[i] = index1[i1++] + base;
    }
  }
  for (; i0 < n0; ++i0, ++i) {
    value[i] = value0[i0];
    index[i] = index0[i0];
  }
  for (; i1 < n1; ++i1, ++i) {
    value[i] = value1[i1];
    index[i] = index1[i1] + base;
  }
}

/**
 * An indexed multi-dimensional filter.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {Array<function(object): *>} params.fields - An array of dimension accessors to filter.
 * @param {Array} params.query - An array of per-dimension range queries.
 */
function CrossFilter(params) {
  Transform.call(this, Bitmaps(), params);
  this._indices = null;
  this._dims = null;
}
CrossFilter.Definition = {
  'type': 'CrossFilter',
  'metadata': {},
  'params': [{
    'name': 'fields',
    'type': 'field',
    'array': true,
    'required': true
  }, {
    'name': 'query',
    'type': 'array',
    'array': true,
    'required': true,
    'content': {
      'type': 'number',
      'array': true,
      'length': 2
    }
  }]
};
inherits(CrossFilter, Transform, {
  transform(_, pulse) {
    if (!this._dims) {
      return this.init(_, pulse);
    } else {
      var init = _.modified('fields') || _.fields.some(f => pulse.modified(f.fields));
      return init ? this.reinit(_, pulse) : this.eval(_, pulse);
    }
  },
  init(_, pulse) {
    const fields = _.fields,
      query = _.query,
      indices = this._indices = {},
      dims = this._dims = [],
      m = query.length;
    let i = 0,
      key,
      index;

    // instantiate indices and dimensions
    for (; i < m; ++i) {
      key = fields[i].fname;
      index = indices[key] || (indices[key] = SortedIndex());
      dims.push(Dimension(index, i, query[i]));
    }
    return this.eval(_, pulse);
  },
  reinit(_, pulse) {
    const output = pulse.materialize().fork(),
      fields = _.fields,
      query = _.query,
      indices = this._indices,
      dims = this._dims,
      bits = this.value,
      curr = bits.curr(),
      prev = bits.prev(),
      all = bits.all(),
      out = output.rem = output.add,
      mod = output.mod,
      m = query.length,
      adds = {};
    let add, index, key, mods, remMap, modMap, i, n, f;

    // set prev to current state
    prev.set(curr);

    // if pulse has remove tuples, process them first
    if (pulse.rem.length) {
      remMap = this.remove(_, pulse, output);
    }

    // if pulse has added tuples, add them to state
    if (pulse.add.length) {
      bits.add(pulse.add);
    }

    // if pulse has modified tuples, create an index map
    if (pulse.mod.length) {
      modMap = {};
      for (mods = pulse.mod, i = 0, n = mods.length; i < n; ++i) {
        modMap[mods[i]._index] = 1;
      }
    }

    // re-initialize indices as needed, update curr bitmap
    for (i = 0; i < m; ++i) {
      f = fields[i];
      if (!dims[i] || _.modified('fields', i) || pulse.modified(f.fields)) {
        key = f.fname;
        if (!(add = adds[key])) {
          indices[key] = index = SortedIndex();
          adds[key] = add = index.insert(f, pulse.source, 0);
        }
        dims[i] = Dimension(index, i, query[i]).onAdd(add, curr);
      }
    }

    // visit each tuple
    // if filter state changed, push index to add/rem
    // else if in mod and passes a filter, push index to mod
    for (i = 0, n = bits.data().length; i < n; ++i) {
      if (remMap[i]) {
        // skip if removed tuple
        continue;
      } else if (prev[i] !== curr[i]) {
        // add if state changed
        out.push(i);
      } else if (modMap[i] && curr[i] !== all) {
        // otherwise, pass mods through
        mod.push(i);
      }
    }
    bits.mask = (1 << m) - 1;
    return output;
  },
  eval(_, pulse) {
    const output = pulse.materialize().fork(),
      m = this._dims.length;
    let mask = 0;
    if (pulse.rem.length) {
      this.remove(_, pulse, output);
      mask |= (1 << m) - 1;
    }
    if (_.modified('query') && !_.modified('fields')) {
      mask |= this.update(_, pulse, output);
    }
    if (pulse.add.length) {
      this.insert(_, pulse, output);
      mask |= (1 << m) - 1;
    }
    if (pulse.mod.length) {
      this.modify(pulse, output);
      mask |= (1 << m) - 1;
    }
    this.value.mask = mask;
    return output;
  },
  insert(_, pulse, output) {
    const tuples = pulse.add,
      bits = this.value,
      dims = this._dims,
      indices = this._indices,
      fields = _.fields,
      adds = {},
      out = output.add,
      n = bits.size() + tuples.length,
      m = dims.length;
    let k = bits.size(),
      j,
      key,
      add;

    // resize bitmaps and add tuples as needed
    bits.resize(n, m);
    bits.add(tuples);
    const curr = bits.curr(),
      prev = bits.prev(),
      all = bits.all();

    // add to dimensional indices
    for (j = 0; j < m; ++j) {
      key = fields[j].fname;
      add = adds[key] || (adds[key] = indices[key].insert(fields[j], tuples, k));
      dims[j].onAdd(add, curr);
    }

    // set previous filters, output if passes at least one filter
    for (; k < n; ++k) {
      prev[k] = all;
      if (curr[k] !== all) out.push(k);
    }
  },
  modify(pulse, output) {
    const out = output.mod,
      bits = this.value,
      curr = bits.curr(),
      all = bits.all(),
      tuples = pulse.mod;
    let i, n, k;
    for (i = 0, n = tuples.length; i < n; ++i) {
      k = tuples[i]._index;
      if (curr[k] !== all) out.push(k);
    }
  },
  remove(_, pulse, output) {
    const indices = this._indices,
      bits = this.value,
      curr = bits.curr(),
      prev = bits.prev(),
      all = bits.all(),
      map = {},
      out = output.rem,
      tuples = pulse.rem;
    let i, n, k, f;

    // process tuples, output if passes at least one filter
    for (i = 0, n = tuples.length; i < n; ++i) {
      k = tuples[i]._index;
      map[k] = 1; // build index map
      prev[k] = f = curr[k];
      curr[k] = all;
      if (f !== all) out.push(k);
    }

    // remove from dimensional indices
    for (k in indices) {
      indices[k].remove(n, map);
    }
    this.reindex(pulse, n, map);
    return map;
  },
  // reindex filters and indices after propagation completes
  reindex(pulse, num, map) {
    const indices = this._indices,
      bits = this.value;
    pulse.runAfter(() => {
      const indexMap = bits.remove(num, map);
      for (const key in indices) indices[key].reindex(indexMap);
    });
  },
  update(_, pulse, output) {
    const dims = this._dims,
      query = _.query,
      stamp = pulse.stamp,
      m = dims.length;
    let mask = 0,
      i,
      q;

    // survey how many queries have changed
    output.filters = 0;
    for (q = 0; q < m; ++q) {
      if (_.modified('query', q)) {
        i = q;
        ++mask;
      }
    }
    if (mask === 1) {
      // only one query changed, use more efficient update
      mask = dims[i].one;
      this.incrementOne(dims[i], query[i], output.add, output.rem);
    } else {
      // multiple queries changed, perform full record keeping
      for (q = 0, mask = 0; q < m; ++q) {
        if (!_.modified('query', q)) continue;
        mask |= dims[q].one;
        this.incrementAll(dims[q], query[q], stamp, output.add);
        output.rem = output.add; // duplicate add/rem for downstream resolve
      }
    }
    return mask;
  },
  incrementAll(dim, query, stamp, out) {
    const bits = this.value,
      seen = bits.seen(),
      curr = bits.curr(),
      prev = bits.prev(),
      index = dim.index(),
      old = dim.bisect(dim.range),
      range = dim.bisect(query),
      lo1 = range[0],
      hi1 = range[1],
      lo0 = old[0],
      hi0 = old[1],
      one = dim.one;
    let i, j, k;

    // Fast incremental update based on previous lo index.
    if (lo1 < lo0) {
      for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) {
        k = index[i];
        if (seen[k] !== stamp) {
          prev[k] = curr[k];
          seen[k] = stamp;
          out.push(k);
        }
        curr[k] ^= one;
      }
    } else if (lo1 > lo0) {
      for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) {
        k = index[i];
        if (seen[k] !== stamp) {
          prev[k] = curr[k];
          seen[k] = stamp;
          out.push(k);
        }
        curr[k] ^= one;
      }
    }

    // Fast incremental update based on previous hi index.
    if (hi1 > hi0) {
      for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) {
        k = index[i];
        if (seen[k] !== stamp) {
          prev[k] = curr[k];
          seen[k] = stamp;
          out.push(k);
        }
        curr[k] ^= one;
      }
    } else if (hi1 < hi0) {
      for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) {
        k = index[i];
        if (seen[k] !== stamp) {
          prev[k] = curr[k];
          seen[k] = stamp;
          out.push(k);
        }
        curr[k] ^= one;
      }
    }
    dim.range = query.slice();
  },
  incrementOne(dim, query, add, rem) {
    const bits = this.value,
      curr = bits.curr(),
      index = dim.index(),
      old = dim.bisect(dim.range),
      range = dim.bisect(query),
      lo1 = range[0],
      hi1 = range[1],
      lo0 = old[0],
      hi0 = old[1],
      one = dim.one;
    let i, j, k;

    // Fast incremental update based on previous lo index.
    if (lo1 < lo0) {
      for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) {
        k = index[i];
        curr[k] ^= one;
        add.push(k);
      }
    } else if (lo1 > lo0) {
      for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) {
        k = index[i];
        curr[k] ^= one;
        rem.push(k);
      }
    }

    // Fast incremental update based on previous hi index.
    if (hi1 > hi0) {
      for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) {
        k = index[i];
        curr[k] ^= one;
        add.push(k);
      }
    } else if (hi1 < hi0) {
      for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) {
        k = index[i];
        curr[k] ^= one;
        rem.push(k);
      }
    }
    dim.range = query.slice();
  }
});

/**
 * Selectively filters tuples by resolving against a filter bitmap.
 * Useful for processing the output of a cross-filter transform.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {object} params.ignore - A bit mask indicating which filters to ignore.
 * @param {object} params.filter - The per-tuple filter bitmaps. Typically this
 *   parameter value is a reference to a {@link CrossFilter} transform.
 */
function ResolveFilter(params) {
  Transform.call(this, null, params);
}
ResolveFilter.Definition = {
  'type': 'ResolveFilter',
  'metadata': {},
  'params': [{
    'name': 'ignore',
    'type': 'number',
    'required': true,
    'description': 'A bit mask indicating which filters to ignore.'
  }, {
    'name': 'filter',
    'type': 'object',
    'required': true,
    'description': 'Per-tuple filter bitmaps from a CrossFilter transform.'
  }]
};
inherits(ResolveFilter, Transform, {
  transform(_, pulse) {
    const ignore = ~(_.ignore || 0),
      // bit mask where zeros -> dims to ignore
      bitmap = _.filter,
      mask = bitmap.mask;

    // exit early if no relevant filter changes
    if ((mask & ignore) === 0) return pulse.StopPropagation;
    const output = pulse.fork(pulse.ALL),
      data = bitmap.data(),
      curr = bitmap.curr(),
      prev = bitmap.prev(),
      pass = k => !(curr[k] & ignore) ? data[k] : null;

    // propagate all mod tuples that pass the filter
    output.filter(output.MOD, pass);

    // determine add & rem tuples via filter functions
    // for efficiency, we do *not* populate new arrays,
    // instead we add filter functions applied downstream

    if (!(mask & mask - 1)) {
      // only one filter changed
      output.filter(output.ADD, pass);
      output.filter(output.REM, k => (curr[k] & ignore) === mask ? data[k] : null);
    } else {
      // multiple filters changed
      output.filter(output.ADD, k => {
        const c = curr[k] & ignore,
          f = !c && c ^ prev[k] & ignore;
        return f ? data[k] : null;
      });
      output.filter(output.REM, k => {
        const c = curr[k] & ignore,
          f = c && !(c ^ (c ^ prev[k] & ignore));
        return f ? data[k] : null;
      });
    }

    // add filter to source data in case of reflow...
    return output.filter(output.SOURCE, t => pass(t._index));
  }
});



;// ../../node_modules/vega-expression/build/vega-expression.module.js


const RawCode = 'RawCode';
const vega_expression_module_Literal = 'Literal';
const vega_expression_module_Property = 'Property';
const vega_expression_module_Identifier = 'Identifier';
const ArrayExpression = 'ArrayExpression';
const BinaryExpression = 'BinaryExpression';
const CallExpression = 'CallExpression';
const ConditionalExpression = 'ConditionalExpression';
const LogicalExpression = 'LogicalExpression';
const vega_expression_module_MemberExpression = 'MemberExpression';
const vega_expression_module_ObjectExpression = 'ObjectExpression';
const UnaryExpression = 'UnaryExpression';
function ASTNode(type) {
  this.type = type;
}
ASTNode.prototype.visit = function (visitor) {
  let c, i, n;
  if (visitor(this)) return 1;
  for (c = vega_expression_module_children(this), i = 0, n = c.length; i < n; ++i) {
    if (c[i].visit(visitor)) return 1;
  }
};
function vega_expression_module_children(node) {
  switch (node.type) {
    case ArrayExpression:
      return node.elements;
    case BinaryExpression:
    case LogicalExpression:
      return [node.left, node.right];
    case CallExpression:
      return [node.callee].concat(node.arguments);
    case ConditionalExpression:
      return [node.test, node.consequent, node.alternate];
    case vega_expression_module_MemberExpression:
      return [node.object, node.property];
    case vega_expression_module_ObjectExpression:
      return node.properties;
    case vega_expression_module_Property:
      return [node.key, node.value];
    case UnaryExpression:
      return [node.argument];
    case vega_expression_module_Identifier:
    case vega_expression_module_Literal:
    case RawCode:
    default:
      return [];
  }
}

/*
  The following expression parser is based on Esprima (http://esprima.org/).
  Original header comment and license for Esprima is included here:

  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
  Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be>
  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var TokenName, vega_expression_module_source, vega_expression_module_index, vega_expression_module_length, lookahead;
var TokenBooleanLiteral = 1,
  TokenEOF = 2,
  TokenIdentifier = 3,
  TokenKeyword = 4,
  TokenNullLiteral = 5,
  TokenNumericLiteral = 6,
  TokenPunctuator = 7,
  TokenStringLiteral = 8,
  TokenRegularExpression = 9;
TokenName = {};
TokenName[TokenBooleanLiteral] = 'Boolean';
TokenName[TokenEOF] = '<end>';
TokenName[TokenIdentifier] = 'Identifier';
TokenName[TokenKeyword] = 'Keyword';
TokenName[TokenNullLiteral] = 'Null';
TokenName[TokenNumericLiteral] = 'Numeric';
TokenName[TokenPunctuator] = 'Punctuator';
TokenName[TokenStringLiteral] = 'String';
TokenName[TokenRegularExpression] = 'RegularExpression';
var SyntaxArrayExpression = 'ArrayExpression',
  SyntaxBinaryExpression = 'BinaryExpression',
  SyntaxCallExpression = 'CallExpression',
  SyntaxConditionalExpression = 'ConditionalExpression',
  SyntaxIdentifier = 'Identifier',
  SyntaxLiteral = 'Literal',
  SyntaxLogicalExpression = 'LogicalExpression',
  SyntaxMemberExpression = 'MemberExpression',
  SyntaxObjectExpression = 'ObjectExpression',
  SyntaxProperty = 'Property',
  SyntaxUnaryExpression = 'UnaryExpression';

// Error messages should be identical to V8.
var MessageUnexpectedToken = 'Unexpected token %0',
  MessageUnexpectedNumber = 'Unexpected number',
  MessageUnexpectedString = 'Unexpected string',
  MessageUnexpectedIdentifier = 'Unexpected identifier',
  MessageUnexpectedReserved = 'Unexpected reserved word',
  MessageUnexpectedEOS = 'Unexpected end of input',
  MessageInvalidRegExp = 'Invalid regular expression',
  MessageUnterminatedRegExp = 'Invalid regular expression: missing /',
  MessageStrictOctalLiteral = 'Octal literals are not allowed in strict mode.',
  MessageStrictDuplicateProperty = 'Duplicate data property in object literal not allowed in strict mode';
var ILLEGAL = 'ILLEGAL',
  DISABLED = 'Disabled.';

// See also tools/generate-unicode-regex.py.
var RegexNonAsciiIdentifierStart = new RegExp('[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]'),
  // eslint-disable-next-line no-misleading-character-class
  RegexNonAsciiIdentifierPart = new RegExp('[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]');

// Ensure the condition is true, otherwise throw an error.
// This is only to have a better contract semantic, i.e. another safety net
// to catch a logic error. The condition shall be fulfilled in normal case.
// Do NOT use this to enforce a certain condition on any user input.

function assert(condition, message) {
  /* istanbul ignore next */
  if (!condition) {
    throw new Error('ASSERT: ' + message);
  }
}
function vega_expression_module_isDecimalDigit(ch) {
  return ch >= 0x30 && ch <= 0x39; // 0..9
}
function vega_expression_module_isHexDigit(ch) {
  return '0123456789abcdefABCDEF'.includes(ch);
}
function vega_expression_module_isOctalDigit(ch) {
  return '01234567'.includes(ch);
}

// 7.2 White Space

function isWhiteSpace(ch) {
  return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 || ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].includes(ch);
}

// 7.3 Line Terminators

function isLineTerminator(ch) {
  return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029;
}

// 7.6 Identifier Names and Identifiers

function vega_expression_module_isIdentifierStart(ch) {
  return ch === 0x24 || ch === 0x5F ||
  // $ (dollar) and _ (underscore)
  ch >= 0x41 && ch <= 0x5A ||
  // A..Z
  ch >= 0x61 && ch <= 0x7A ||
  // a..z
  ch === 0x5C ||
  // \ (backslash)
  ch >= 0x80 && RegexNonAsciiIdentifierStart.test(String.fromCharCode(ch));
}
function isIdentifierPart(ch) {
  return ch === 0x24 || ch === 0x5F ||
  // $ (dollar) and _ (underscore)
  ch >= 0x41 && ch <= 0x5A ||
  // A..Z
  ch >= 0x61 && ch <= 0x7A ||
  // a..z
  ch >= 0x30 && ch <= 0x39 ||
  // 0..9
  ch === 0x5C ||
  // \ (backslash)
  ch >= 0x80 && RegexNonAsciiIdentifierPart.test(String.fromCharCode(ch));
}

// 7.6.1.1 Keywords

const vega_expression_module_keywords = {
  'if': 1,
  'in': 1,
  'do': 1,
  'var': 1,
  'for': 1,
  'new': 1,
  'try': 1,
  'let': 1,
  'this': 1,
  'else': 1,
  'case': 1,
  'void': 1,
  'with': 1,
  'enum': 1,
  'while': 1,
  'break': 1,
  'catch': 1,
  'throw': 1,
  'const': 1,
  'yield': 1,
  'class': 1,
  'super': 1,
  'return': 1,
  'typeof': 1,
  'delete': 1,
  'switch': 1,
  'export': 1,
  'import': 1,
  'public': 1,
  'static': 1,
  'default': 1,
  'finally': 1,
  'extends': 1,
  'package': 1,
  'private': 1,
  'function': 1,
  'continue': 1,
  'debugger': 1,
  'interface': 1,
  'protected': 1,
  'instanceof': 1,
  'implements': 1
};
function skipComment() {
  while (vega_expression_module_index < vega_expression_module_length) {
    const ch = vega_expression_module_source.charCodeAt(vega_expression_module_index);
    if (isWhiteSpace(ch) || isLineTerminator(ch)) {
      ++vega_expression_module_index;
    } else {
      break;
    }
  }
}
function scanHexEscape(prefix) {
  var i,
    len,
    ch,
    code = 0;
  len = prefix === 'u' ? 4 : 2;
  for (i = 0; i < len; ++i) {
    if (vega_expression_module_index < vega_expression_module_length && vega_expression_module_isHexDigit(vega_expression_module_source[vega_expression_module_index])) {
      ch = vega_expression_module_source[vega_expression_module_index++];
      code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
    } else {
      throwError({}, MessageUnexpectedToken, ILLEGAL);
    }
  }
  return String.fromCharCode(code);
}
function scanUnicodeCodePointEscape() {
  var ch, code, cu1, cu2;
  ch = vega_expression_module_source[vega_expression_module_index];
  code = 0;

  // At least, one hex digit is required.
  if (ch === '}') {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source[vega_expression_module_index++];
    if (!vega_expression_module_isHexDigit(ch)) {
      break;
    }
    code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
  }
  if (code > 0x10FFFF || ch !== '}') {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }

  // UTF-16 Encoding
  if (code <= 0xFFFF) {
    return String.fromCharCode(code);
  }
  cu1 = (code - 0x10000 >> 10) + 0xD800;
  cu2 = (code - 0x10000 & 1023) + 0xDC00;
  return String.fromCharCode(cu1, cu2);
}
function getEscapedIdentifier() {
  var ch, id;
  ch = vega_expression_module_source.charCodeAt(vega_expression_module_index++);
  id = String.fromCharCode(ch);

  // '\u' (U+005C, U+0075) denotes an escaped character.
  if (ch === 0x5C) {
    if (vega_expression_module_source.charCodeAt(vega_expression_module_index) !== 0x75) {
      throwError({}, MessageUnexpectedToken, ILLEGAL);
    }
    ++vega_expression_module_index;
    ch = scanHexEscape('u');
    if (!ch || ch === '\\' || !vega_expression_module_isIdentifierStart(ch.charCodeAt(0))) {
      throwError({}, MessageUnexpectedToken, ILLEGAL);
    }
    id = ch;
  }
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source.charCodeAt(vega_expression_module_index);
    if (!isIdentifierPart(ch)) {
      break;
    }
    ++vega_expression_module_index;
    id += String.fromCharCode(ch);

    // '\u' (U+005C, U+0075) denotes an escaped character.
    if (ch === 0x5C) {
      id = id.substr(0, id.length - 1);
      if (vega_expression_module_source.charCodeAt(vega_expression_module_index) !== 0x75) {
        throwError({}, MessageUnexpectedToken, ILLEGAL);
      }
      ++vega_expression_module_index;
      ch = scanHexEscape('u');
      if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
        throwError({}, MessageUnexpectedToken, ILLEGAL);
      }
      id += ch;
    }
  }
  return id;
}
function getIdentifier() {
  var start, ch;
  start = vega_expression_module_index++;
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source.charCodeAt(vega_expression_module_index);
    if (ch === 0x5C) {
      // Blackslash (U+005C) marks Unicode escape sequence.
      vega_expression_module_index = start;
      return getEscapedIdentifier();
    }
    if (isIdentifierPart(ch)) {
      ++vega_expression_module_index;
    } else {
      break;
    }
  }
  return vega_expression_module_source.slice(start, vega_expression_module_index);
}
function scanIdentifier() {
  var start, id, type;
  start = vega_expression_module_index;

  // Backslash (U+005C) starts an escaped character.
  id = vega_expression_module_source.charCodeAt(vega_expression_module_index) === 0x5C ? getEscapedIdentifier() : getIdentifier();

  // There is no keyword or literal with only one character.
  // Thus, it must be an identifier.
  if (id.length === 1) {
    type = TokenIdentifier;
  } else if (vega_expression_module_keywords.hasOwnProperty(id)) {
    // eslint-disable-line no-prototype-builtins
    type = TokenKeyword;
  } else if (id === 'null') {
    type = TokenNullLiteral;
  } else if (id === 'true' || id === 'false') {
    type = TokenBooleanLiteral;
  } else {
    type = TokenIdentifier;
  }
  return {
    type: type,
    value: id,
    start: start,
    end: vega_expression_module_index
  };
}

// 7.7 Punctuators

function scanPunctuator() {
  var start = vega_expression_module_index,
    code = vega_expression_module_source.charCodeAt(vega_expression_module_index),
    code2,
    ch1 = vega_expression_module_source[vega_expression_module_index],
    ch2,
    ch3,
    ch4;
  switch (code) {
    // Check for most common single-character punctuators.
    case 0x2E: // . dot
    case 0x28: // ( open bracket
    case 0x29: // ) close bracket
    case 0x3B: // ; semicolon
    case 0x2C: // , comma
    case 0x7B: // { open curly brace
    case 0x7D: // } close curly brace
    case 0x5B: // [
    case 0x5D: // ]
    case 0x3A: // :
    case 0x3F: // ?
    case 0x7E:
      // ~
      ++vega_expression_module_index;
      return {
        type: TokenPunctuator,
        value: String.fromCharCode(code),
        start: start,
        end: vega_expression_module_index
      };
    default:
      code2 = vega_expression_module_source.charCodeAt(vega_expression_module_index + 1);

      // '=' (U+003D) marks an assignment or comparison operator.
      if (code2 === 0x3D) {
        switch (code) {
          case 0x2B: // +
          case 0x2D: // -
          case 0x2F: // /
          case 0x3C: // <
          case 0x3E: // >
          case 0x5E: // ^
          case 0x7C: // |
          case 0x25: // %
          case 0x26: // &
          case 0x2A:
            // *
            vega_expression_module_index += 2;
            return {
              type: TokenPunctuator,
              value: String.fromCharCode(code) + String.fromCharCode(code2),
              start: start,
              end: vega_expression_module_index
            };
          case 0x21: // !
          case 0x3D:
            // =
            vega_expression_module_index += 2;

            // !== and ===
            if (vega_expression_module_source.charCodeAt(vega_expression_module_index) === 0x3D) {
              ++vega_expression_module_index;
            }
            return {
              type: TokenPunctuator,
              value: vega_expression_module_source.slice(start, vega_expression_module_index),
              start: start,
              end: vega_expression_module_index
            };
        }
      }
  }

  // 4-character punctuator: >>>=

  ch4 = vega_expression_module_source.substr(vega_expression_module_index, 4);
  if (ch4 === '>>>=') {
    vega_expression_module_index += 4;
    return {
      type: TokenPunctuator,
      value: ch4,
      start: start,
      end: vega_expression_module_index
    };
  }

  // 3-character punctuators: === !== >>> <<= >>=

  ch3 = ch4.substr(0, 3);
  if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
    vega_expression_module_index += 3;
    return {
      type: TokenPunctuator,
      value: ch3,
      start: start,
      end: vega_expression_module_index
    };
  }

  // Other 2-character punctuators: ++ -- << >> && ||
  ch2 = ch3.substr(0, 2);
  if (ch1 === ch2[1] && '+-<>&|'.includes(ch1) || ch2 === '=>') {
    vega_expression_module_index += 2;
    return {
      type: TokenPunctuator,
      value: ch2,
      start: start,
      end: vega_expression_module_index
    };
  }
  if (ch2 === '//') {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }

  // 1-character punctuators: < > = ! + - * % & | ^ /

  if ('<>=!+-*%&|^/'.includes(ch1)) {
    ++vega_expression_module_index;
    return {
      type: TokenPunctuator,
      value: ch1,
      start: start,
      end: vega_expression_module_index
    };
  }
  throwError({}, MessageUnexpectedToken, ILLEGAL);
}

// 7.8.3 Numeric Literals

function scanHexLiteral(start) {
  let number = '';
  while (vega_expression_module_index < vega_expression_module_length) {
    if (!vega_expression_module_isHexDigit(vega_expression_module_source[vega_expression_module_index])) {
      break;
    }
    number += vega_expression_module_source[vega_expression_module_index++];
  }
  if (number.length === 0) {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  if (vega_expression_module_isIdentifierStart(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  return {
    type: TokenNumericLiteral,
    value: parseInt('0x' + number, 16),
    start: start,
    end: vega_expression_module_index
  };
}
function scanOctalLiteral(start) {
  let number = '0' + vega_expression_module_source[vega_expression_module_index++];
  while (vega_expression_module_index < vega_expression_module_length) {
    if (!vega_expression_module_isOctalDigit(vega_expression_module_source[vega_expression_module_index])) {
      break;
    }
    number += vega_expression_module_source[vega_expression_module_index++];
  }
  if (vega_expression_module_isIdentifierStart(vega_expression_module_source.charCodeAt(vega_expression_module_index)) || vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  return {
    type: TokenNumericLiteral,
    value: parseInt(number, 8),
    octal: true,
    start: start,
    end: vega_expression_module_index
  };
}
function scanNumericLiteral() {
  var number, start, ch;
  ch = vega_expression_module_source[vega_expression_module_index];
  assert(vega_expression_module_isDecimalDigit(ch.charCodeAt(0)) || ch === '.', 'Numeric literal must start with a decimal digit or a decimal point');
  start = vega_expression_module_index;
  number = '';
  if (ch !== '.') {
    number = vega_expression_module_source[vega_expression_module_index++];
    ch = vega_expression_module_source[vega_expression_module_index];

    // Hex number starts with '0x'.
    // Octal number starts with '0'.
    if (number === '0') {
      if (ch === 'x' || ch === 'X') {
        ++vega_expression_module_index;
        return scanHexLiteral(start);
      }
      if (vega_expression_module_isOctalDigit(ch)) {
        return scanOctalLiteral(start);
      }

      // decimal number starts with '0' such as '09' is illegal.
      if (ch && vega_expression_module_isDecimalDigit(ch.charCodeAt(0))) {
        throwError({}, MessageUnexpectedToken, ILLEGAL);
      }
    }
    while (vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
      number += vega_expression_module_source[vega_expression_module_index++];
    }
    ch = vega_expression_module_source[vega_expression_module_index];
  }
  if (ch === '.') {
    number += vega_expression_module_source[vega_expression_module_index++];
    while (vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
      number += vega_expression_module_source[vega_expression_module_index++];
    }
    ch = vega_expression_module_source[vega_expression_module_index];
  }
  if (ch === 'e' || ch === 'E') {
    number += vega_expression_module_source[vega_expression_module_index++];
    ch = vega_expression_module_source[vega_expression_module_index];
    if (ch === '+' || ch === '-') {
      number += vega_expression_module_source[vega_expression_module_index++];
    }
    if (vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
      while (vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
        number += vega_expression_module_source[vega_expression_module_index++];
      }
    } else {
      throwError({}, MessageUnexpectedToken, ILLEGAL);
    }
  }
  if (vega_expression_module_isIdentifierStart(vega_expression_module_source.charCodeAt(vega_expression_module_index))) {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  return {
    type: TokenNumericLiteral,
    value: parseFloat(number),
    start: start,
    end: vega_expression_module_index
  };
}

// 7.8.4 String Literals

function scanStringLiteral() {
  var str = '',
    quote,
    start,
    ch,
    code,
    octal = false;
  quote = vega_expression_module_source[vega_expression_module_index];
  assert(quote === '\'' || quote === '"', 'String literal must starts with a quote');
  start = vega_expression_module_index;
  ++vega_expression_module_index;
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source[vega_expression_module_index++];
    if (ch === quote) {
      quote = '';
      break;
    } else if (ch === '\\') {
      ch = vega_expression_module_source[vega_expression_module_index++];
      if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
        switch (ch) {
          case 'u':
          case 'x':
            if (vega_expression_module_source[vega_expression_module_index] === '{') {
              ++vega_expression_module_index;
              str += scanUnicodeCodePointEscape();
            } else {
              str += scanHexEscape(ch);
            }
            break;
          case 'n':
            str += '\n';
            break;
          case 'r':
            str += '\r';
            break;
          case 't':
            str += '\t';
            break;
          case 'b':
            str += '\b';
            break;
          case 'f':
            str += '\f';
            break;
          case 'v':
            str += '\x0B';
            break;
          default:
            if (vega_expression_module_isOctalDigit(ch)) {
              code = '01234567'.indexOf(ch);

              // \0 is not octal escape sequence
              if (code !== 0) {
                octal = true;
              }
              if (vega_expression_module_index < vega_expression_module_length && vega_expression_module_isOctalDigit(vega_expression_module_source[vega_expression_module_index])) {
                octal = true;
                code = code * 8 + '01234567'.indexOf(vega_expression_module_source[vega_expression_module_index++]);

                // 3 digits are only allowed when string starts
                // with 0, 1, 2, 3
                if ('0123'.includes(ch) && vega_expression_module_index < vega_expression_module_length && vega_expression_module_isOctalDigit(vega_expression_module_source[vega_expression_module_index])) {
                  code = code * 8 + '01234567'.indexOf(vega_expression_module_source[vega_expression_module_index++]);
                }
              }
              str += String.fromCharCode(code);
            } else {
              str += ch;
            }
            break;
        }
      } else {
        if (ch === '\r' && vega_expression_module_source[vega_expression_module_index] === '\n') {
          ++vega_expression_module_index;
        }
      }
    } else if (isLineTerminator(ch.charCodeAt(0))) {
      break;
    } else {
      str += ch;
    }
  }
  if (quote !== '') {
    throwError({}, MessageUnexpectedToken, ILLEGAL);
  }
  return {
    type: TokenStringLiteral,
    value: str,
    octal: octal,
    start: start,
    end: vega_expression_module_index
  };
}
function testRegExp(pattern, flags) {
  let tmp = pattern;
  if (flags.includes('u')) {
    // Replace each astral symbol and every Unicode code point
    // escape sequence with a single ASCII symbol to avoid throwing on
    // regular expressions that are only valid in combination with the
    // `/u` flag.
    // Note: replacing with the ASCII symbol `x` might cause false
    // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
    // perfectly valid pattern that is equivalent to `[a-b]`, but it
    // would be replaced by `[x-b]` which throws an error.
    tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, ($0, $1) => {
      if (parseInt($1, 16) <= 0x10FFFF) {
        return 'x';
      }
      throwError({}, MessageInvalidRegExp);
    }).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
  }

  // First, detect invalid regular expressions.
  try {
    new RegExp(tmp);
  } catch (e) {
    throwError({}, MessageInvalidRegExp);
  }

  // Return a regular expression object for this pattern-flag pair, or
  // `null` in case the current environment doesn't support the flags it
  // uses.
  try {
    return new RegExp(pattern, flags);
  } catch (exception) {
    return null;
  }
}
function scanRegExpBody() {
  var ch, str, classMarker, terminated, body;
  ch = vega_expression_module_source[vega_expression_module_index];
  assert(ch === '/', 'Regular expression literal must start with a slash');
  str = vega_expression_module_source[vega_expression_module_index++];
  classMarker = false;
  terminated = false;
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source[vega_expression_module_index++];
    str += ch;
    if (ch === '\\') {
      ch = vega_expression_module_source[vega_expression_module_index++];
      // ECMA-262 7.8.5
      if (isLineTerminator(ch.charCodeAt(0))) {
        throwError({}, MessageUnterminatedRegExp);
      }
      str += ch;
    } else if (isLineTerminator(ch.charCodeAt(0))) {
      throwError({}, MessageUnterminatedRegExp);
    } else if (classMarker) {
      if (ch === ']') {
        classMarker = false;
      }
    } else {
      if (ch === '/') {
        terminated = true;
        break;
      } else if (ch === '[') {
        classMarker = true;
      }
    }
  }
  if (!terminated) {
    throwError({}, MessageUnterminatedRegExp);
  }

  // Exclude leading and trailing slash.
  body = str.substr(1, str.length - 2);
  return {
    value: body,
    literal: str
  };
}
function scanRegExpFlags() {
  var ch, str, flags;
  str = '';
  flags = '';
  while (vega_expression_module_index < vega_expression_module_length) {
    ch = vega_expression_module_source[vega_expression_module_index];
    if (!isIdentifierPart(ch.charCodeAt(0))) {
      break;
    }
    ++vega_expression_module_index;
    if (ch === '\\' && vega_expression_module_index < vega_expression_module_length) {
      throwError({}, MessageUnexpectedToken, ILLEGAL);
    } else {
      flags += ch;
      str += ch;
    }
  }
  if (flags.search(/[^gimuy]/g) >= 0) {
    throwError({}, MessageInvalidRegExp, flags);
  }
  return {
    value: flags,
    literal: str
  };
}
function scanRegExp() {
  var start, body, flags, value;
  lookahead = null;
  skipComment();
  start = vega_expression_module_index;
  body = scanRegExpBody();
  flags = scanRegExpFlags();
  value = testRegExp(body.value, flags.value);
  return {
    literal: body.literal + flags.literal,
    value: value,
    regex: {
      pattern: body.value,
      flags: flags.value
    },
    start: start,
    end: vega_expression_module_index
  };
}
function isIdentifierName(token) {
  return token.type === TokenIdentifier || token.type === TokenKeyword || token.type === TokenBooleanLiteral || token.type === TokenNullLiteral;
}
function advance() {
  skipComment();
  if (vega_expression_module_index >= vega_expression_module_length) {
    return {
      type: TokenEOF,
      start: vega_expression_module_index,
      end: vega_expression_module_index
    };
  }
  const ch = vega_expression_module_source.charCodeAt(vega_expression_module_index);
  if (vega_expression_module_isIdentifierStart(ch)) {
    return scanIdentifier();
  }

  // Very common: ( and ) and ;
  if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
    return scanPunctuator();
  }

  // String literal starts with single quote (U+0027) or double quote (U+0022).
  if (ch === 0x27 || ch === 0x22) {
    return scanStringLiteral();
  }

  // Dot (.) U+002E can also start a floating-point number, hence the need
  // to check the next character.
  if (ch === 0x2E) {
    if (vega_expression_module_isDecimalDigit(vega_expression_module_source.charCodeAt(vega_expression_module_index + 1))) {
      return scanNumericLiteral();
    }
    return scanPunctuator();
  }
  if (vega_expression_module_isDecimalDigit(ch)) {
    return scanNumericLiteral();
  }
  return scanPunctuator();
}
function lex() {
  const token = lookahead;
  vega_expression_module_index = token.end;
  lookahead = advance();
  vega_expression_module_index = token.end;
  return token;
}
function vega_expression_module_peek() {
  const pos = vega_expression_module_index;
  lookahead = advance();
  vega_expression_module_index = pos;
}
function finishArrayExpression(elements) {
  const node = new ASTNode(SyntaxArrayExpression);
  node.elements = elements;
  return node;
}
function finishBinaryExpression(operator, left, right) {
  const node = new ASTNode(operator === '||' || operator === '&&' ? SyntaxLogicalExpression : SyntaxBinaryExpression);
  node.operator = operator;
  node.left = left;
  node.right = right;
  return node;
}
function finishCallExpression(callee, args) {
  const node = new ASTNode(SyntaxCallExpression);
  node.callee = callee;
  node.arguments = args;
  return node;
}
function finishConditionalExpression(test, consequent, alternate) {
  const node = new ASTNode(SyntaxConditionalExpression);
  node.test = test;
  node.consequent = consequent;
  node.alternate = alternate;
  return node;
}
function finishIdentifier(name) {
  const node = new ASTNode(SyntaxIdentifier);
  node.name = name;
  return node;
}
function finishLiteral(token) {
  const node = new ASTNode(SyntaxLiteral);
  node.value = token.value;
  node.raw = vega_expression_module_source.slice(token.start, token.end);
  if (token.regex) {
    if (node.raw === '//') {
      node.raw = '/(?:)/';
    }
    node.regex = token.regex;
  }
  return node;
}
function finishMemberExpression(accessor, object, property) {
  const node = new ASTNode(SyntaxMemberExpression);
  node.computed = accessor === '[';
  node.object = object;
  node.property = property;
  if (!node.computed) property.member = true;
  return node;
}
function finishObjectExpression(properties) {
  const node = new ASTNode(SyntaxObjectExpression);
  node.properties = properties;
  return node;
}
function finishProperty(kind, key, value) {
  const node = new ASTNode(SyntaxProperty);
  node.key = key;
  node.value = value;
  node.kind = kind;
  return node;
}
function finishUnaryExpression(operator, argument) {
  const node = new ASTNode(SyntaxUnaryExpression);
  node.operator = operator;
  node.argument = argument;
  node.prefix = true;
  return node;
}

// Throw an exception

function throwError(token, messageFormat) {
  var error,
    args = Array.prototype.slice.call(arguments, 2),
    msg = messageFormat.replace(/%(\d)/g, (whole, index) => {
      assert(index < args.length, 'Message reference must be in range');
      return args[index];
    });
  error = new Error(msg);
  error.index = vega_expression_module_index;
  error.description = msg;
  throw error;
}

// Throw an exception because of the token.

function throwUnexpected(token) {
  if (token.type === TokenEOF) {
    throwError(token, MessageUnexpectedEOS);
  }
  if (token.type === TokenNumericLiteral) {
    throwError(token, MessageUnexpectedNumber);
  }
  if (token.type === TokenStringLiteral) {
    throwError(token, MessageUnexpectedString);
  }
  if (token.type === TokenIdentifier) {
    throwError(token, MessageUnexpectedIdentifier);
  }
  if (token.type === TokenKeyword) {
    throwError(token, MessageUnexpectedReserved);
  }

  // BooleanLiteral, NullLiteral, or Punctuator.
  throwError(token, MessageUnexpectedToken, token.value);
}

// Expect the next token to match the specified punctuator.
// If not, an exception will be thrown.

function expect(value) {
  const token = lex();
  if (token.type !== TokenPunctuator || token.value !== value) {
    throwUnexpected(token);
  }
}

// Return true if the next token matches the specified punctuator.

function vega_expression_module_match(value) {
  return lookahead.type === TokenPunctuator && lookahead.value === value;
}

// Return true if the next token matches the specified keyword

function matchKeyword(keyword) {
  return lookahead.type === TokenKeyword && lookahead.value === keyword;
}

// 11.1.4 Array Initialiser

function parseArrayInitialiser() {
  const elements = [];
  vega_expression_module_index = lookahead.start;
  expect('[');
  while (!vega_expression_module_match(']')) {
    if (vega_expression_module_match(',')) {
      lex();
      elements.push(null);
    } else {
      elements.push(parseConditionalExpression());
      if (!vega_expression_module_match(']')) {
        expect(',');
      }
    }
  }
  lex();
  return finishArrayExpression(elements);
}

// 11.1.5 Object Initialiser

function parseObjectPropertyKey() {
  vega_expression_module_index = lookahead.start;
  const token = lex();

  // Note: This function is called only from parseObjectProperty(), where
  // EOF and Punctuator tokens are already filtered out.

  if (token.type === TokenStringLiteral || token.type === TokenNumericLiteral) {
    if (token.octal) {
      throwError(token, MessageStrictOctalLiteral);
    }
    return finishLiteral(token);
  }
  return finishIdentifier(token.value);
}
function parseObjectProperty() {
  var token, key, id, value;
  vega_expression_module_index = lookahead.start;
  token = lookahead;
  if (token.type === TokenIdentifier) {
    id = parseObjectPropertyKey();
    expect(':');
    value = parseConditionalExpression();
    return finishProperty('init', id, value);
  }
  if (token.type === TokenEOF || token.type === TokenPunctuator) {
    throwUnexpected(token);
  } else {
    key = parseObjectPropertyKey();
    expect(':');
    value = parseConditionalExpression();
    return finishProperty('init', key, value);
  }
}
function parseObjectInitialiser() {
  var properties = [],
    property,
    name,
    key,
    map = {},
    toString = String;
  vega_expression_module_index = lookahead.start;
  expect('{');
  while (!vega_expression_module_match('}')) {
    property = parseObjectProperty();
    if (property.key.type === SyntaxIdentifier) {
      name = property.key.name;
    } else {
      name = toString(property.key.value);
    }
    key = '$' + name;
    if (Object.prototype.hasOwnProperty.call(map, key)) {
      throwError({}, MessageStrictDuplicateProperty);
    } else {
      map[key] = true;
    }
    properties.push(property);
    if (!vega_expression_module_match('}')) {
      expect(',');
    }
  }
  expect('}');
  return finishObjectExpression(properties);
}

// 11.1.6 The Grouping Operator

function parseGroupExpression() {
  expect('(');
  const expr = vega_expression_module_parseExpression();
  expect(')');
  return expr;
}

// 11.1 Primary Expressions

const legalKeywords = {
  'if': 1
};
function parsePrimaryExpression() {
  var type, token, expr;
  if (vega_expression_module_match('(')) {
    return parseGroupExpression();
  }
  if (vega_expression_module_match('[')) {
    return parseArrayInitialiser();
  }
  if (vega_expression_module_match('{')) {
    return parseObjectInitialiser();
  }
  type = lookahead.type;
  vega_expression_module_index = lookahead.start;
  if (type === TokenIdentifier || legalKeywords[lookahead.value]) {
    expr = finishIdentifier(lex().value);
  } else if (type === TokenStringLiteral || type === TokenNumericLiteral) {
    if (lookahead.octal) {
      throwError(lookahead, MessageStrictOctalLiteral);
    }
    expr = finishLiteral(lex());
  } else if (type === TokenKeyword) {
    throw new Error(DISABLED);
  } else if (type === TokenBooleanLiteral) {
    token = lex();
    token.value = token.value === 'true';
    expr = finishLiteral(token);
  } else if (type === TokenNullLiteral) {
    token = lex();
    token.value = null;
    expr = finishLiteral(token);
  } else if (vega_expression_module_match('/') || vega_expression_module_match('/=')) {
    expr = finishLiteral(scanRegExp());
    vega_expression_module_peek();
  } else {
    throwUnexpected(lex());
  }
  return expr;
}

// 11.2 Left-Hand-Side Expressions

function parseArguments() {
  const args = [];
  expect('(');
  if (!vega_expression_module_match(')')) {
    while (vega_expression_module_index < vega_expression_module_length) {
      args.push(parseConditionalExpression());
      if (vega_expression_module_match(')')) {
        break;
      }
      expect(',');
    }
  }
  expect(')');
  return args;
}
function parseNonComputedProperty() {
  vega_expression_module_index = lookahead.start;
  const token = lex();
  if (!isIdentifierName(token)) {
    throwUnexpected(token);
  }
  return finishIdentifier(token.value);
}
function parseNonComputedMember() {
  expect('.');
  return parseNonComputedProperty();
}
function parseComputedMember() {
  expect('[');
  const expr = vega_expression_module_parseExpression();
  expect(']');
  return expr;
}
function parseLeftHandSideExpressionAllowCall() {
  var expr, args, property;
  expr = parsePrimaryExpression();
  for (;;) {
    if (vega_expression_module_match('.')) {
      property = parseNonComputedMember();
      expr = finishMemberExpression('.', expr, property);
    } else if (vega_expression_module_match('(')) {
      args = parseArguments();
      expr = finishCallExpression(expr, args);
    } else if (vega_expression_module_match('[')) {
      property = parseComputedMember();
      expr = finishMemberExpression('[', expr, property);
    } else {
      break;
    }
  }
  return expr;
}

// 11.3 Postfix Expressions

function parsePostfixExpression() {
  const expr = parseLeftHandSideExpressionAllowCall();
  if (lookahead.type === TokenPunctuator) {
    if (vega_expression_module_match('++') || vega_expression_module_match('--')) {
      throw new Error(DISABLED);
    }
  }
  return expr;
}

// 11.4 Unary Operators

function parseUnaryExpression() {
  var token, expr;
  if (lookahead.type !== TokenPunctuator && lookahead.type !== TokenKeyword) {
    expr = parsePostfixExpression();
  } else if (vega_expression_module_match('++') || vega_expression_module_match('--')) {
    throw new Error(DISABLED);
  } else if (vega_expression_module_match('+') || vega_expression_module_match('-') || vega_expression_module_match('~') || vega_expression_module_match('!')) {
    token = lex();
    expr = parseUnaryExpression();
    expr = finishUnaryExpression(token.value, expr);
  } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
    throw new Error(DISABLED);
  } else {
    expr = parsePostfixExpression();
  }
  return expr;
}
function binaryPrecedence(token) {
  let prec = 0;
  if (token.type !== TokenPunctuator && token.type !== TokenKeyword) {
    return 0;
  }
  switch (token.value) {
    case '||':
      prec = 1;
      break;
    case '&&':
      prec = 2;
      break;
    case '|':
      prec = 3;
      break;
    case '^':
      prec = 4;
      break;
    case '&':
      prec = 5;
      break;
    case '==':
    case '!=':
    case '===':
    case '!==':
      prec = 6;
      break;
    case '<':
    case '>':
    case '<=':
    case '>=':
    case 'instanceof':
    case 'in':
      prec = 7;
      break;
    case '<<':
    case '>>':
    case '>>>':
      prec = 8;
      break;
    case '+':
    case '-':
      prec = 9;
      break;
    case '*':
    case '/':
    case '%':
      prec = 11;
      break;
  }
  return prec;
}

// 11.5 Multiplicative Operators
// 11.6 Additive Operators
// 11.7 Bitwise Shift Operators
// 11.8 Relational Operators
// 11.9 Equality Operators
// 11.10 Binary Bitwise Operators
// 11.11 Binary Logical Operators

function parseBinaryExpression() {
  var marker, markers, expr, token, prec, stack, right, operator, left, i;
  marker = lookahead;
  left = parseUnaryExpression();
  token = lookahead;
  prec = binaryPrecedence(token);
  if (prec === 0) {
    return left;
  }
  token.prec = prec;
  lex();
  markers = [marker, lookahead];
  right = parseUnaryExpression();
  stack = [left, token, right];
  while ((prec = binaryPrecedence(lookahead)) > 0) {
    // Reduce: make a binary expression from the three topmost entries.
    while (stack.length > 2 && prec <= stack[stack.length - 2].prec) {
      right = stack.pop();
      operator = stack.pop().value;
      left = stack.pop();
      markers.pop();
      expr = finishBinaryExpression(operator, left, right);
      stack.push(expr);
    }

    // Shift.
    token = lex();
    token.prec = prec;
    stack.push(token);
    markers.push(lookahead);
    expr = parseUnaryExpression();
    stack.push(expr);
  }

  // Final reduce to clean-up the stack.
  i = stack.length - 1;
  expr = stack[i];
  markers.pop();
  while (i > 1) {
    markers.pop();
    expr = finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
    i -= 2;
  }
  return expr;
}

// 11.12 Conditional Operator

function parseConditionalExpression() {
  var expr, consequent, alternate;
  expr = parseBinaryExpression();
  if (vega_expression_module_match('?')) {
    lex();
    consequent = parseConditionalExpression();
    expect(':');
    alternate = parseConditionalExpression();
    expr = finishConditionalExpression(expr, consequent, alternate);
  }
  return expr;
}

// 11.14 Comma Operator

function vega_expression_module_parseExpression() {
  const expr = parseConditionalExpression();
  if (vega_expression_module_match(',')) {
    throw new Error(DISABLED); // no sequence expressions
  }
  return expr;
}
function parser (code) {
  vega_expression_module_source = code;
  vega_expression_module_index = 0;
  vega_expression_module_length = vega_expression_module_source.length;
  lookahead = null;
  vega_expression_module_peek();
  const expr = vega_expression_module_parseExpression();
  if (lookahead.type !== TokenEOF) {
    throw new Error('Unexpect token after expression.');
  }
  return expr;
}

var Constants = {
  NaN: 'NaN',
  E: 'Math.E',
  LN2: 'Math.LN2',
  LN10: 'Math.LN10',
  LOG2E: 'Math.LOG2E',
  LOG10E: 'Math.LOG10E',
  PI: 'Math.PI',
  SQRT1_2: 'Math.SQRT1_2',
  SQRT2: 'Math.SQRT2',
  MIN_VALUE: 'Number.MIN_VALUE',
  MAX_VALUE: 'Number.MAX_VALUE'
};

function Functions (codegen) {
  function fncall(name, args, cast, type) {
    let obj = codegen(args[0]);
    if (cast) {
      obj = cast + '(' + obj + ')';
      if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
    }
    return obj + '.' + name + (type < 0 ? '' : type === 0 ? '()' : '(' + args.slice(1).map(codegen).join(',') + ')');
  }
  function fn(name, cast, type) {
    return args => fncall(name, args, cast, type);
  }
  const DATE = 'new Date',
    STRING = 'String',
    REGEXP = 'RegExp';
  return {
    // MATH functions
    isNaN: 'Number.isNaN',
    isFinite: 'Number.isFinite',
    abs: 'Math.abs',
    acos: 'Math.acos',
    asin: 'Math.asin',
    atan: 'Math.atan',
    atan2: 'Math.atan2',
    ceil: 'Math.ceil',
    cos: 'Math.cos',
    exp: 'Math.exp',
    floor: 'Math.floor',
    hypot: 'Math.hypot',
    log: 'Math.log',
    max: 'Math.max',
    min: 'Math.min',
    pow: 'Math.pow',
    random: 'Math.random',
    round: 'Math.round',
    sin: 'Math.sin',
    sqrt: 'Math.sqrt',
    tan: 'Math.tan',
    clamp: function (args) {
      if (args.length < 3) vega_util_module_error('Missing arguments to clamp function.');
      if (args.length > 3) vega_util_module_error('Too many arguments to clamp function.');
      const a = args.map(codegen);
      return 'Math.max(' + a[1] + ', Math.min(' + a[2] + ',' + a[0] + '))';
    },
    // DATE functions
    now: 'Date.now',
    utc: 'Date.UTC',
    datetime: DATE,
    date: fn('getDate', DATE, 0),
    day: fn('getDay', DATE, 0),
    year: fn('getFullYear', DATE, 0),
    month: fn('getMonth', DATE, 0),
    hours: fn('getHours', DATE, 0),
    minutes: fn('getMinutes', DATE, 0),
    seconds: fn('getSeconds', DATE, 0),
    milliseconds: fn('getMilliseconds', DATE, 0),
    time: fn('getTime', DATE, 0),
    timezoneoffset: fn('getTimezoneOffset', DATE, 0),
    utcdate: fn('getUTCDate', DATE, 0),
    utcday: fn('getUTCDay', DATE, 0),
    utcyear: fn('getUTCFullYear', DATE, 0),
    utcmonth: fn('getUTCMonth', DATE, 0),
    utchours: fn('getUTCHours', DATE, 0),
    utcminutes: fn('getUTCMinutes', DATE, 0),
    utcseconds: fn('getUTCSeconds', DATE, 0),
    utcmilliseconds: fn('getUTCMilliseconds', DATE, 0),
    // sequence functions
    length: fn('length', null, -1),
    // STRING functions
    parseFloat: 'parseFloat',
    parseInt: 'parseInt',
    upper: fn('toUpperCase', STRING, 0),
    lower: fn('toLowerCase', STRING, 0),
    substring: fn('substring', STRING),
    split: fn('split', STRING),
    trim: fn('trim', STRING, 0),
    // base64 encode/decode
    btoa: 'btoa',
    atob: 'atob',
    // REGEXP functions
    regexp: REGEXP,
    test: fn('test', REGEXP),
    // Control Flow functions
    if: function (args) {
      if (args.length < 3) vega_util_module_error('Missing arguments to if function.');
      if (args.length > 3) vega_util_module_error('Too many arguments to if function.');
      const a = args.map(codegen);
      return '(' + a[0] + '?' + a[1] + ':' + a[2] + ')';
    }
  };
}

function stripQuotes(s) {
  const n = s && s.length - 1;
  return n && (s[0] === '"' && s[n] === '"' || s[0] === '\'' && s[n] === '\'') ? s.slice(1, -1) : s;
}
function vega_expression_module_codegen (opt) {
  opt = opt || {};
  const allowed = opt.allowed ? vega_util_module_toSet(opt.allowed) : {},
    forbidden = opt.forbidden ? vega_util_module_toSet(opt.forbidden) : {},
    constants = opt.constants || Constants,
    functions = (opt.functions || Functions)(visit),
    globalvar = opt.globalvar,
    fieldvar = opt.fieldvar,
    outputGlobal = vega_util_module_isFunction(globalvar) ? globalvar : id => `${globalvar}["${id}"]`;
  let globals = {},
    fields = {},
    memberDepth = 0;
  function visit(ast) {
    if (vega_util_module_isString(ast)) return ast;
    const generator = Generators[ast.type];
    if (generator == null) vega_util_module_error('Unsupported type: ' + ast.type);
    return generator(ast);
  }
  const Generators = {
    Literal: n => n.raw,
    Identifier: n => {
      const id = n.name;
      if (memberDepth > 0) {
        return id;
      } else if (vega_util_module_has(forbidden, id)) {
        return vega_util_module_error('Illegal identifier: ' + id);
      } else if (vega_util_module_has(constants, id)) {
        return constants[id];
      } else if (vega_util_module_has(allowed, id)) {
        return id;
      } else {
        globals[id] = 1;
        return outputGlobal(id);
      }
    },
    MemberExpression: n => {
      const d = !n.computed,
        o = visit(n.object);
      if (d) memberDepth += 1;
      const p = visit(n.property);
      if (o === fieldvar) {
        // strip quotes to sanitize field name (#1653)
        fields[stripQuotes(p)] = 1;
      }
      if (d) memberDepth -= 1;
      return o + (d ? '.' + p : '[' + p + ']');
    },
    CallExpression: n => {
      if (n.callee.type !== 'Identifier') {
        vega_util_module_error('Illegal callee type: ' + n.callee.type);
      }
      const callee = n.callee.name,
        args = n.arguments,
        fn = vega_util_module_has(functions, callee) && functions[callee];
      if (!fn) vega_util_module_error('Unrecognized function: ' + callee);
      return vega_util_module_isFunction(fn) ? fn(args) : fn + '(' + args.map(visit).join(',') + ')';
    },
    ArrayExpression: n => '[' + n.elements.map(visit).join(',') + ']',
    BinaryExpression: n => '(' + visit(n.left) + ' ' + n.operator + ' ' + visit(n.right) + ')',
    UnaryExpression: n => '(' + n.operator + visit(n.argument) + ')',
    ConditionalExpression: n => '(' + visit(n.test) + '?' + visit(n.consequent) + ':' + visit(n.alternate) + ')',
    LogicalExpression: n => '(' + visit(n.left) + n.operator + visit(n.right) + ')',
    ObjectExpression: n => '{' + n.properties.map(visit).join(',') + '}',
    Property: n => {
      memberDepth += 1;
      const k = visit(n.key);
      memberDepth -= 1;
      return k + ':' + visit(n.value);
    }
  };
  function codegen(ast) {
    const result = {
      code: visit(ast),
      globals: Object.keys(globals),
      fields: Object.keys(fields)
    };
    globals = {};
    fields = {};
    return result;
  }
  codegen.functions = functions;
  codegen.constants = constants;
  return codegen;
}



;// ../../node_modules/d3-geo/src/area.js





var area_areaRingSum = new Adder();

// hello?

var area_areaSum = new Adder(),
    lambda00,
    phi00,
    lambda0,
    cosPhi0,
    sinPhi0;

var area_areaStream = {
  point: noop_noop,
  lineStart: noop_noop,
  lineEnd: noop_noop,
  polygonStart: function() {
    area_areaRingSum = new Adder();
    area_areaStream.lineStart = area_areaRingStart;
    area_areaStream.lineEnd = area_areaRingEnd;
  },
  polygonEnd: function() {
    var areaRing = +area_areaRingSum;
    area_areaSum.add(areaRing < 0 ? math_tau + areaRing : areaRing);
    this.lineStart = this.lineEnd = this.point = noop_noop;
  },
  sphere: function() {
    area_areaSum.add(math_tau);
  }
};

function area_areaRingStart() {
  area_areaStream.point = area_areaPointFirst;
}

function area_areaRingEnd() {
  area_areaPoint(lambda00, phi00);
}

function area_areaPointFirst(lambda, phi) {
  area_areaStream.point = area_areaPoint;
  lambda00 = lambda, phi00 = phi;
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  lambda0 = lambda, cosPhi0 = src_math_cos(phi = phi / 2 + quarterPi), sinPhi0 = src_math_sin(phi);
}

function area_areaPoint(lambda, phi) {
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  phi = phi / 2 + quarterPi; // half the angular distance from south pole

  // Spherical excess E for a spherical triangle with vertices: south pole,
  // previous point, current point.  Uses a formula derived from Cagnoli’s
  // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
  var dLambda = lambda - lambda0,
      sdLambda = dLambda >= 0 ? 1 : -1,
      adLambda = sdLambda * dLambda,
      cosPhi = src_math_cos(phi),
      sinPhi = src_math_sin(phi),
      k = sinPhi0 * sinPhi,
      u = cosPhi0 * cosPhi + k * src_math_cos(adLambda),
      v = k * sdLambda * src_math_sin(adLambda);
  area_areaRingSum.add(src_math_atan2(v, u));

  // Advance the previous points.
  lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
}

/* harmony default export */ function d3_geo_src_area(object) {
  area_areaSum = new Adder();
  src_stream(object, area_areaStream);
  return area_areaSum * 2;
}

;// ../../node_modules/d3-geo/src/bounds.js






var bounds_lambda0, phi0, lambda1, phi1, // bounds
    lambda2, // previous lambda-coordinate
    bounds_lambda00, bounds_phi00, // first point
    p0, // previous 3D point
    deltaSum,
    ranges,
    bounds_range;

var bounds_boundsStream = {
  point: bounds_boundsPoint,
  lineStart: boundsLineStart,
  lineEnd: boundsLineEnd,
  polygonStart: function() {
    bounds_boundsStream.point = boundsRingPoint;
    bounds_boundsStream.lineStart = boundsRingStart;
    bounds_boundsStream.lineEnd = boundsRingEnd;
    deltaSum = new Adder();
    area_areaStream.polygonStart();
  },
  polygonEnd: function() {
    area_areaStream.polygonEnd();
    bounds_boundsStream.point = bounds_boundsPoint;
    bounds_boundsStream.lineStart = boundsLineStart;
    bounds_boundsStream.lineEnd = boundsLineEnd;
    if (area_areaRingSum < 0) bounds_lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90);
    else if (deltaSum > src_math_epsilon) phi1 = 90;
    else if (deltaSum < -src_math_epsilon) phi0 = -90;
    bounds_range[0] = bounds_lambda0, bounds_range[1] = lambda1;
  },
  sphere: function() {
    bounds_lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90);
  }
};

function bounds_boundsPoint(lambda, phi) {
  ranges.push(bounds_range = [bounds_lambda0 = lambda, lambda1 = lambda]);
  if (phi < phi0) phi0 = phi;
  if (phi > phi1) phi1 = phi;
}

function linePoint(lambda, phi) {
  var p = cartesian_cartesian([lambda * d3_geo_src_math_radians, phi * d3_geo_src_math_radians]);
  if (p0) {
    var normal = cartesianCross(p0, p),
        equatorial = [normal[1], -normal[0], 0],
        inflection = cartesianCross(equatorial, normal);
    cartesianNormalizeInPlace(inflection);
    inflection = spherical(inflection);
    var delta = lambda - lambda2,
        sign = delta > 0 ? 1 : -1,
        lambdai = inflection[0] * d3_geo_src_math_degrees * sign,
        phii,
        antimeridian = src_math_abs(delta) > 180;
    if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
      phii = inflection[1] * d3_geo_src_math_degrees;
      if (phii > phi1) phi1 = phii;
    } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
      phii = -inflection[1] * d3_geo_src_math_degrees;
      if (phii < phi0) phi0 = phii;
    } else {
      if (phi < phi0) phi0 = phi;
      if (phi > phi1) phi1 = phi;
    }
    if (antimeridian) {
      if (lambda < lambda2) {
        if (angle(bounds_lambda0, lambda) > angle(bounds_lambda0, lambda1)) lambda1 = lambda;
      } else {
        if (angle(lambda, lambda1) > angle(bounds_lambda0, lambda1)) bounds_lambda0 = lambda;
      }
    } else {
      if (lambda1 >= bounds_lambda0) {
        if (lambda < bounds_lambda0) bounds_lambda0 = lambda;
        if (lambda > lambda1) lambda1 = lambda;
      } else {
        if (lambda > lambda2) {
          if (angle(bounds_lambda0, lambda) > angle(bounds_lambda0, lambda1)) lambda1 = lambda;
        } else {
          if (angle(lambda, lambda1) > angle(bounds_lambda0, lambda1)) bounds_lambda0 = lambda;
        }
      }
    }
  } else {
    ranges.push(bounds_range = [bounds_lambda0 = lambda, lambda1 = lambda]);
  }
  if (phi < phi0) phi0 = phi;
  if (phi > phi1) phi1 = phi;
  p0 = p, lambda2 = lambda;
}

function boundsLineStart() {
  bounds_boundsStream.point = linePoint;
}

function boundsLineEnd() {
  bounds_range[0] = bounds_lambda0, bounds_range[1] = lambda1;
  bounds_boundsStream.point = bounds_boundsPoint;
  p0 = null;
}

function boundsRingPoint(lambda, phi) {
  if (p0) {
    var delta = lambda - lambda2;
    deltaSum.add(src_math_abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
  } else {
    bounds_lambda00 = lambda, bounds_phi00 = phi;
  }
  area_areaStream.point(lambda, phi);
  linePoint(lambda, phi);
}

function boundsRingStart() {
  area_areaStream.lineStart();
}

function boundsRingEnd() {
  boundsRingPoint(bounds_lambda00, bounds_phi00);
  area_areaStream.lineEnd();
  if (src_math_abs(deltaSum) > src_math_epsilon) bounds_lambda0 = -(lambda1 = 180);
  bounds_range[0] = bounds_lambda0, bounds_range[1] = lambda1;
  p0 = null;
}

// Finds the left-right distance between two longitudes.
// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
// the distance between ±180° to be 360°.
function angle(lambda0, lambda1) {
  return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
}

function rangeCompare(a, b) {
  return a[0] - b[0];
}

function rangeContains(range, x) {
  return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
}

/* harmony default export */ function src_bounds(feature) {
  var i, n, a, b, merged, deltaMax, delta;

  phi1 = lambda1 = -(bounds_lambda0 = phi0 = Infinity);
  ranges = [];
  src_stream(feature, bounds_boundsStream);

  // First, sort ranges by their minimum longitudes.
  if (n = ranges.length) {
    ranges.sort(rangeCompare);

    // Then, merge any ranges that overlap.
    for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
      b = ranges[i];
      if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
        if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
        if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
      } else {
        merged.push(a = b);
      }
    }

    // Finally, find the largest gap between the merged ranges.
    // The final bounding box will be the inverse of this gap.
    for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
      b = merged[i];
      if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, bounds_lambda0 = b[0], lambda1 = a[1];
    }
  }

  ranges = bounds_range = null;

  return bounds_lambda0 === Infinity || phi0 === Infinity
      ? [[NaN, NaN], [NaN, NaN]]
      : [[bounds_lambda0, phi0], [lambda1, phi1]];
}

;// ../../node_modules/d3-geo/src/centroid.js





var W0, W1,
    centroid_X0, centroid_Y0, centroid_Z0,
    centroid_X1, centroid_Y1, centroid_Z1,
    centroid_X2, centroid_Y2, centroid_Z2,
    centroid_lambda00, centroid_phi00, // first point
    src_centroid_x0, src_centroid_y0, z0; // previous point

var centroid_centroidStream = {
  sphere: noop_noop,
  point: centroid_centroidPoint,
  lineStart: centroid_centroidLineStart,
  lineEnd: centroid_centroidLineEnd,
  polygonStart: function() {
    centroid_centroidStream.lineStart = centroid_centroidRingStart;
    centroid_centroidStream.lineEnd = centroid_centroidRingEnd;
  },
  polygonEnd: function() {
    centroid_centroidStream.lineStart = centroid_centroidLineStart;
    centroid_centroidStream.lineEnd = centroid_centroidLineEnd;
  }
};

// Arithmetic mean of Cartesian vectors.
function centroid_centroidPoint(lambda, phi) {
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  var cosPhi = src_math_cos(phi);
  centroidPointCartesian(cosPhi * src_math_cos(lambda), cosPhi * src_math_sin(lambda), src_math_sin(phi));
}

function centroidPointCartesian(x, y, z) {
  ++W0;
  centroid_X0 += (x - centroid_X0) / W0;
  centroid_Y0 += (y - centroid_Y0) / W0;
  centroid_Z0 += (z - centroid_Z0) / W0;
}

function centroid_centroidLineStart() {
  centroid_centroidStream.point = centroidLinePointFirst;
}

function centroidLinePointFirst(lambda, phi) {
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  var cosPhi = src_math_cos(phi);
  src_centroid_x0 = cosPhi * src_math_cos(lambda);
  src_centroid_y0 = cosPhi * src_math_sin(lambda);
  z0 = src_math_sin(phi);
  centroid_centroidStream.point = centroidLinePoint;
  centroidPointCartesian(src_centroid_x0, src_centroid_y0, z0);
}

function centroidLinePoint(lambda, phi) {
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  var cosPhi = src_math_cos(phi),
      x = cosPhi * src_math_cos(lambda),
      y = cosPhi * src_math_sin(lambda),
      z = src_math_sin(phi),
      w = src_math_atan2(src_math_sqrt((w = src_centroid_y0 * z - z0 * y) * w + (w = z0 * x - src_centroid_x0 * z) * w + (w = src_centroid_x0 * y - src_centroid_y0 * x) * w), src_centroid_x0 * x + src_centroid_y0 * y + z0 * z);
  W1 += w;
  centroid_X1 += w * (src_centroid_x0 + (src_centroid_x0 = x));
  centroid_Y1 += w * (src_centroid_y0 + (src_centroid_y0 = y));
  centroid_Z1 += w * (z0 + (z0 = z));
  centroidPointCartesian(src_centroid_x0, src_centroid_y0, z0);
}

function centroid_centroidLineEnd() {
  centroid_centroidStream.point = centroid_centroidPoint;
}

// See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
// J. Applied Mechanics 42, 239 (1975).
function centroid_centroidRingStart() {
  centroid_centroidStream.point = centroidRingPointFirst;
}

function centroid_centroidRingEnd() {
  centroidRingPoint(centroid_lambda00, centroid_phi00);
  centroid_centroidStream.point = centroid_centroidPoint;
}

function centroidRingPointFirst(lambda, phi) {
  centroid_lambda00 = lambda, centroid_phi00 = phi;
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  centroid_centroidStream.point = centroidRingPoint;
  var cosPhi = src_math_cos(phi);
  src_centroid_x0 = cosPhi * src_math_cos(lambda);
  src_centroid_y0 = cosPhi * src_math_sin(lambda);
  z0 = src_math_sin(phi);
  centroidPointCartesian(src_centroid_x0, src_centroid_y0, z0);
}

function centroidRingPoint(lambda, phi) {
  lambda *= d3_geo_src_math_radians, phi *= d3_geo_src_math_radians;
  var cosPhi = src_math_cos(phi),
      x = cosPhi * src_math_cos(lambda),
      y = cosPhi * src_math_sin(lambda),
      z = src_math_sin(phi),
      cx = src_centroid_y0 * z - z0 * y,
      cy = z0 * x - src_centroid_x0 * z,
      cz = src_centroid_x0 * y - src_centroid_y0 * x,
      m = hypot(cx, cy, cz),
      w = src_math_asin(m), // line weight = angle
      v = m && -w / m; // area weight multiplier
  centroid_X2.add(v * cx);
  centroid_Y2.add(v * cy);
  centroid_Z2.add(v * cz);
  W1 += w;
  centroid_X1 += w * (src_centroid_x0 + (src_centroid_x0 = x));
  centroid_Y1 += w * (src_centroid_y0 + (src_centroid_y0 = y));
  centroid_Z1 += w * (z0 + (z0 = z));
  centroidPointCartesian(src_centroid_x0, src_centroid_y0, z0);
}

/* harmony default export */ function src_centroid(object) {
  W0 = W1 =
  centroid_X0 = centroid_Y0 = centroid_Z0 =
  centroid_X1 = centroid_Y1 = centroid_Z1 = 0;
  centroid_X2 = new Adder();
  centroid_Y2 = new Adder();
  centroid_Z2 = new Adder();
  src_stream(object, centroid_centroidStream);

  var x = +centroid_X2,
      y = +centroid_Y2,
      z = +centroid_Z2,
      m = hypot(x, y, z);

  // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
  if (m < math_epsilon2) {
    x = centroid_X1, y = centroid_Y1, z = centroid_Z1;
    // If the feature has zero length, fall back to arithmetic mean of point vectors.
    if (W1 < src_math_epsilon) x = centroid_X0, y = centroid_Y0, z = centroid_Z0;
    m = hypot(x, y, z);
    // If the feature still has an undefined ccentroid, then return.
    if (m < math_epsilon2) return [NaN, NaN];
  }

  return [src_math_atan2(y, x) * d3_geo_src_math_degrees, src_math_asin(z / m) * d3_geo_src_math_degrees];
}

;// ../../node_modules/d3-array/src/union.js


function union_union(...others) {
  const set = new InternSet();
  for (const other of others) {
    for (const o of other) {
      set.add(o);
    }
  }
  return set;
}

;// ../../node_modules/d3-array/src/intersection.js


function intersection(values, ...others) {
  values = new InternSet(values);
  others = others.map(intersection_set);
  out: for (const value of values) {
    for (const other of others) {
      if (!other.has(value)) {
        values.delete(value);
        continue out;
      }
    }
  }
  return values;
}

function intersection_set(values) {
  return values instanceof InternSet ? values : new InternSet(values);
}

;// ../../node_modules/vega-selections/build/vega-selection.module.js




// Registers vega-util field accessors to protect against XSS attacks
const SELECTION_GETTER = Symbol('vega_selection_getter');
function vega_selection_module_getter(f) {
  if (!f.getter || !f.getter[SELECTION_GETTER]) {
    f.getter = vega_util_module_field(f.field);
    f.getter[SELECTION_GETTER] = true;
  }
  return f.getter;
}
const Intersect = 'intersect';
const Union = 'union';
const VlMulti = 'vlMulti';
const VlPoint = 'vlPoint';
const Or = 'or';
const And = 'and';
const SelectionId = '_vgsid_';
const $selectionId = vega_util_module_field(SelectionId);

const TYPE_ENUM = 'E',
  TYPE_RANGE_INC = 'R',
  TYPE_RANGE_EXC = 'R-E',
  TYPE_RANGE_LE = 'R-LE',
  TYPE_RANGE_RE = 'R-RE',
  TYPE_PRED_LT = 'E-LT',
  TYPE_PRED_LTE = 'E-LTE',
  TYPE_PRED_GT = 'E-GT',
  TYPE_PRED_GTE = 'E-GTE',
  TYPE_PRED_VALID = 'E-VALID',
  TYPE_PRED_ONE_OF = 'E-ONE',
  UNIT_INDEX = 'index:unit';

// TODO: revisit date coercion?
function testPoint(datum, entry) {
  var fields = entry.fields,
    values = entry.values,
    n = fields.length,
    i = 0,
    dval,
    f;
  for (; i < n; ++i) {
    f = fields[i];
    dval = vega_selection_module_getter(f)(datum);
    if (vega_util_module_isDate(dval)) dval = vega_util_module_toNumber(dval);
    if (vega_util_module_isDate(values[i])) values[i] = vega_util_module_toNumber(values[i]);
    if (vega_util_module_isArray(values[i]) && vega_util_module_isDate(values[i][0])) values[i] = values[i].map(vega_util_module_toNumber);
    if (f.type === TYPE_ENUM) {
      // Enumerated fields can either specify individual values (single/multi selections)
      // or an array of values (interval selections).
      if (vega_util_module_isArray(values[i]) ? !values[i].includes(dval) : dval !== values[i]) {
        return false;
      }
    } else {
      if (f.type === TYPE_RANGE_INC) {
        if (!inrange(dval, values[i])) return false;
      } else if (f.type === TYPE_RANGE_RE) {
        // Discrete selection of bins test within the range [bin_start, bin_end).
        if (!inrange(dval, values[i], true, false)) return false;
      } else if (f.type === TYPE_RANGE_EXC) {
        // 'R-E'/'R-LE' included for completeness.
        if (!inrange(dval, values[i], false, false)) return false;
      } else if (f.type === TYPE_RANGE_LE) {
        if (!inrange(dval, values[i], false, true)) return false;
      } else if (f.type === TYPE_PRED_LT) {
        if (dval >= values[i]) return false;
      } else if (f.type === TYPE_PRED_LTE) {
        if (dval > values[i]) return false;
      } else if (f.type === TYPE_PRED_GT) {
        if (dval <= values[i]) return false;
      } else if (f.type === TYPE_PRED_GTE) {
        if (dval < values[i]) return false;
      } else if (f.type === TYPE_PRED_VALID) {
        if (dval === null || isNaN(dval)) return false;
      } else if (f.type === TYPE_PRED_ONE_OF) {
        if (values[i].indexOf(dval) === -1) return false;
      }
    }
  }
  return true;
}

/**
 * Tests if a tuple is contained within an interactive selection.
 * @param {string} name - The name of the data set representing the selection.
 *  Tuples in the dataset are of the form
 *  {unit: string, fields: array<fielddef>, values: array<*>}.
 *  Fielddef is of the form
 *  {field: string, channel: string, type: 'E' | 'R'} where
 *  'type' identifies whether tuples in the dataset enumerate
 *  values for the field, or specify a continuous range.
 * @param {object} datum - The tuple to test for inclusion.
 * @param {string} op - The set operation for combining selections.
 *   One of 'intersect' or 'union' (default).
 * @return {boolean} - True if the datum is in the selection, false otherwise.
 */
function selectionTest(name, datum, op) {
  var data = this.context.data[name],
    entries = data ? data.values.value : [],
    unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined,
    intersect = op === Intersect,
    n = entries.length,
    i = 0,
    entry,
    miss,
    count,
    unit,
    b;
  for (; i < n; ++i) {
    entry = entries[i];
    if (unitIdx && intersect) {
      // multi selections union within the same unit and intersect across units.
      miss = miss || {};
      count = miss[unit = entry.unit] || 0;

      // if we've already matched this unit, skip.
      if (count === -1) continue;
      b = testPoint(datum, entry);
      miss[unit] = b ? -1 : ++count;

      // if we match and there are no other units return true
      // if we've missed against all tuples in this unit return false
      if (b && unitIdx.size === 1) return true;
      if (!b && count === unitIdx.get(unit).count) return false;
    } else {
      b = testPoint(datum, entry);

      // if we find a miss and we do require intersection return false
      // if we find a match and we don't require intersection return true
      if (intersect ^ b) return b;
    }
  }

  // if intersecting and we made it here, then we saw no misses
  // if not intersecting, then we saw no matches
  // if no active selections, return false
  return n && intersect;
}
const vega_selection_module_bisect = bisector_bisector($selectionId),
  vega_selection_module_bisectLeft = vega_selection_module_bisect.left,
  vega_selection_module_bisectRight = vega_selection_module_bisect.right;
function selectionIdTest(name, datum, op) {
  const data = this.context.data[name],
    entries = data ? data.values.value : [],
    unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined,
    intersect = op === Intersect,
    value = $selectionId(datum),
    index = vega_selection_module_bisectLeft(entries, value);
  if (index === entries.length) return false;
  if ($selectionId(entries[index]) !== value) return false;
  if (unitIdx && intersect) {
    if (unitIdx.size === 1) return true;
    if (vega_selection_module_bisectRight(entries, value) - index < unitIdx.size) return false;
  }
  return true;
}

/**
 * Maps an array of scene graph items to an array of selection tuples.
 * @param {string} name  - The name of the dataset representing the selection.
 * @param {string} base  - The base object that generated tuples extend.
 *
 * @returns {array} An array of selection entries for the given unit.
 */
function selectionTuples(array, base) {
  return array.map(x => extend(base.fields ? {
    values: base.fields.map(f => vega_selection_module_getter(f)(x.datum))
  } : {
    [SelectionId]: $selectionId(x.datum)
  }, base));
}

/**
 * Resolves selection for use as a scale domain or reads via the API.
 * @param {string} name - The name of the dataset representing the selection
 * @param {string} [op='union'] - The set operation for combining selections.
 *                 One of 'intersect' or 'union' (default).
 * @param {boolean} isMulti - Identifies a "multi" selection to perform more
 *                 expensive resolution computation.
 * @param {boolean} vl5 - With Vega-Lite v5, "multi" selections are now called "point"
 *                 selections, and thus the resolved tuple should reflect this name.
 *                 This parameter allows us to reflect this change without triggering
 *                 a major version bump for Vega.
 * @returns {object} An object of selected fields and values.
 */
function selectionResolve(name, op, isMulti, vl5) {
  var data = this.context.data[name],
    entries = data ? data.values.value : [],
    resolved = {},
    multiRes = {},
    types = {},
    entry,
    fields,
    values,
    unit,
    field,
    value,
    res,
    resUnit,
    type,
    union,
    n = entries.length,
    i = 0,
    j,
    m;

  // First union all entries within the same unit.
  for (; i < n; ++i) {
    entry = entries[i];
    unit = entry.unit;
    fields = entry.fields;
    values = entry.values;
    if (fields && values) {
      // Intentional selection stores
      for (j = 0, m = fields.length; j < m; ++j) {
        field = fields[j];
        res = resolved[field.field] || (resolved[field.field] = {});
        resUnit = res[unit] || (res[unit] = []);
        types[field.field] = type = field.type.charAt(0);
        union = ops[`${type}_union`];
        res[unit] = union(resUnit, vega_util_module_array(values[j]));
      }

      // If the same multi-selection is repeated over views and projected over
      // an encoding, it may operate over different fields making it especially
      // tricky to reliably resolve it. At best, we can de-dupe identical entries
      // but doing so may be more computationally expensive than it is worth.
      // Instead, for now, we simply transform our store representation into
      // a more human-friendly one.
      if (isMulti) {
        resUnit = multiRes[unit] || (multiRes[unit] = []);
        resUnit.push(vega_util_module_array(values).reduce((obj, curr, j) => (obj[fields[j].field] = curr, obj), {}));
      }
    } else {
      // Short circuit extensional selectionId stores which hold sorted IDs unique to each unit.
      field = SelectionId;
      value = $selectionId(entry);
      res = resolved[field] || (resolved[field] = {});
      resUnit = res[unit] || (res[unit] = []);
      resUnit.push(value);
      if (isMulti) {
        resUnit = multiRes[unit] || (multiRes[unit] = []);
        resUnit.push({
          [SelectionId]: value
        });
      }
    }
  }

  // Then resolve fields across units as per the op.
  op = op || Union;
  if (resolved[SelectionId]) {
    resolved[SelectionId] = ops[`${SelectionId}_${op}`](...Object.values(resolved[SelectionId]));
  } else {
    Object.keys(resolved).forEach(field => {
      resolved[field] = Object.keys(resolved[field]).map(unit => resolved[field][unit]).reduce((acc, curr) => acc === undefined ? curr : ops[`${types[field]}_${op}`](acc, curr));
    });
  }
  entries = Object.keys(multiRes);
  if (isMulti && entries.length) {
    const key = vl5 ? VlPoint : VlMulti;
    resolved[key] = op === Union ? {
      [Or]: entries.reduce((acc, k) => (acc.push(...multiRes[k]), acc), [])
    } : {
      [And]: entries.map(k => ({
        [Or]: multiRes[k]
      }))
    };
  }
  return resolved;
}
var ops = {
  [`${SelectionId}_union`]: union_union,
  [`${SelectionId}_intersect`]: intersection,
  E_union: function (base, value) {
    if (!base.length) return value;
    var i = 0,
      n = value.length;
    for (; i < n; ++i) if (!base.includes(value[i])) base.push(value[i]);
    return base;
  },
  E_intersect: function (base, value) {
    return !base.length ? value : base.filter(v => value.includes(v));
  },
  R_union: function (base, value) {
    var lo = vega_util_module_toNumber(value[0]),
      hi = vega_util_module_toNumber(value[1]);
    if (lo > hi) {
      lo = value[1];
      hi = value[0];
    }
    if (!base.length) return [lo, hi];
    if (base[0] > lo) base[0] = lo;
    if (base[1] < hi) base[1] = hi;
    return base;
  },
  R_intersect: function (base, value) {
    var lo = vega_util_module_toNumber(value[0]),
      hi = vega_util_module_toNumber(value[1]);
    if (lo > hi) {
      lo = value[1];
      hi = value[0];
    }
    if (!base.length) return [lo, hi];
    if (hi < base[0] || base[1] < lo) {
      return [];
    } else {
      if (base[0] < lo) base[0] = lo;
      if (base[1] > hi) base[1] = hi;
    }
    return base;
  }
};

const DataPrefix = ':',
  IndexPrefix = '@';
function selectionVisitor(name, args, scope, params) {
  if (args[0].type !== vega_expression_module_Literal) vega_util_module_error('First argument to selection functions must be a string literal.');
  const data = args[0].value,
    op = args.length >= 2 && peek(args).value,
    field = 'unit',
    indexName = IndexPrefix + field,
    dataName = DataPrefix + data;

  // eslint-disable-next-line no-prototype-builtins
  if (op === Intersect && !vega_util_module_has(params, indexName)) {
    params[indexName] = scope.getData(data).indataRef(scope, field);
  }

  // eslint-disable-next-line no-prototype-builtins
  if (!vega_util_module_has(params, dataName)) {
    params[dataName] = scope.getData(data).tuplesRef();
  }
}



;// ../../node_modules/vega-functions/build/vega-functions.module.js












function vega_functions_module_data(name) {
  const data = this.context.data[name];
  return data ? data.values.value : [];
}
function indata(name, field, value) {
  const index = this.context.data[name]['index:' + field],
    entry = index ? index.value.get(value) : undefined;
  return entry ? entry.count : entry;
}
function setdata(name, tuples) {
  const df = this.context.dataflow,
    data = this.context.data[name],
    input = data.input;
  df.pulse(input, df.changeset().remove(truthy).insert(tuples));
  return 1;
}

function encode (item, name, retval) {
  if (item) {
    const df = this.context.dataflow,
      target = item.mark.source;
    df.pulse(target, df.changeset().encode(item, name));
  }
  return retval !== undefined ? retval : item;
}

const vega_functions_module_wrap = method => function (value, spec) {
  const locale = this.context.dataflow.locale();
  return value === null ? 'null' : locale[method](spec)(value);
};
const vega_functions_module_format = vega_functions_module_wrap('format');
const vega_functions_module_timeFormat = vega_functions_module_wrap('timeFormat');
const vega_functions_module_utcFormat = vega_functions_module_wrap('utcFormat');
const vega_functions_module_timeParse = vega_functions_module_wrap('timeParse');
const vega_functions_module_utcParse = vega_functions_module_wrap('utcParse');
const dateObj = new Date(2000, 0, 1);
function vega_functions_module_time(month, day, specifier) {
  if (!Number.isInteger(month) || !Number.isInteger(day)) return '';
  dateObj.setYear(2000);
  dateObj.setMonth(month);
  dateObj.setDate(day);
  return vega_functions_module_timeFormat.call(this, dateObj, specifier);
}
function monthFormat(month) {
  return vega_functions_module_time.call(this, month, 1, '%B');
}
function monthAbbrevFormat(month) {
  return vega_functions_module_time.call(this, month, 1, '%b');
}
function dayFormat(day) {
  return vega_functions_module_time.call(this, 0, 2 + day, '%A');
}
function dayAbbrevFormat(day) {
  return vega_functions_module_time.call(this, 0, 2 + day, '%a');
}

const vega_functions_module_DataPrefix = ':';
const vega_functions_module_IndexPrefix = '@';
const ScalePrefix = '%';
const SignalPrefix = '$';

function dataVisitor(name, args, scope, params) {
  if (args[0].type !== vega_expression_module_Literal) {
    vega_util_module_error('First argument to data functions must be a string literal.');
  }
  const data = args[0].value,
    dataName = vega_functions_module_DataPrefix + data;
  if (!vega_util_module_has(dataName, params)) {
    try {
      params[dataName] = scope.getData(data).tuplesRef();
    } catch (err) {
      // if data set does not exist, there's nothing to track
    }
  }
}
function indataVisitor(name, args, scope, params) {
  if (args[0].type !== vega_expression_module_Literal) vega_util_module_error('First argument to indata must be a string literal.');
  if (args[1].type !== vega_expression_module_Literal) vega_util_module_error('Second argument to indata must be a string literal.');
  const data = args[0].value,
    field = args[1].value,
    indexName = vega_functions_module_IndexPrefix + field;
  if (!vega_util_module_has(indexName, params)) {
    params[indexName] = scope.getData(data).indataRef(scope, field);
  }
}
function scaleVisitor(name, args, scope, params) {
  if (args[0].type === vega_expression_module_Literal) {
    // add scale dependency
    addScaleDependency(scope, params, args[0].value);
  } else {
    // indirect scale lookup; add all scales as parameters
    for (name in scope.scales) {
      addScaleDependency(scope, params, name);
    }
  }
}
function addScaleDependency(scope, params, name) {
  const scaleName = ScalePrefix + name;
  if (!vega_util_module_has(params, scaleName)) {
    try {
      params[scaleName] = scope.scaleRef(name);
    } catch (err) {
      // TODO: error handling? warning?
    }
  }
}

/**
 * nameOrFunction must be a string or function that was registered.
 * Return undefined if scale is not recognized.
 */
function getScale(nameOrFunction, ctx) {
  if (vega_util_module_isString(nameOrFunction)) {
    const maybeScale = ctx.scales[nameOrFunction];
    return maybeScale && isRegisteredScale(maybeScale.value) ? maybeScale.value : undefined;
  } else if (vega_util_module_isFunction(nameOrFunction)) {
    return isRegisteredScale(nameOrFunction) ? nameOrFunction : undefined;
  }
  return undefined;
}
function internalScaleFunctions(codegen, fnctx, visitors) {
  // add helper method to the 'this' expression function context
  fnctx.__bandwidth = s => s && s.bandwidth ? s.bandwidth() : 0;

  // register AST visitors for internal scale functions
  visitors._bandwidth = scaleVisitor;
  visitors._range = scaleVisitor;
  visitors._scale = scaleVisitor;

  // resolve scale reference directly to the signal hash argument
  const ref = arg => '_[' + (arg.type === vega_expression_module_Literal ? $(ScalePrefix + arg.value) : $(ScalePrefix) + '+' + codegen(arg)) + ']';

  // define and return internal scale function code generators
  // these internal functions are called by mark encoders
  return {
    _bandwidth: args => `this.__bandwidth(${ref(args[0])})`,
    _range: args => `${ref(args[0])}.range()`,
    _scale: args => `${ref(args[0])}(${codegen(args[1])})`
  };
}

function geoMethod(methodName, globalMethod) {
  return function (projection, geojson, group) {
    if (projection) {
      // projection defined, use it
      const p = getScale(projection, (group || this).context);
      return p && p.path[methodName](geojson);
    } else {
      // projection undefined, use global method
      return globalMethod(geojson);
    }
  };
}
const geoArea = geoMethod('area', d3_geo_src_area);
const geoBounds = geoMethod('bounds', src_bounds);
const geoCentroid = geoMethod('centroid', src_centroid);
function geoScale(projection, group) {
  const p = getScale(projection, (group || this).context);
  return p && p.scale();
}

function inScope (item) {
  const group = this.context.group;
  let value = false;
  if (group) while (item) {
    if (item === group) {
      value = true;
      break;
    }
    item = item.mark.group;
  }
  return value;
}

function vega_functions_module_log(df, method, args) {
  try {
    df[method].apply(df, ['EXPRESSION'].concat([].slice.call(args)));
  } catch (err) {
    df.warn(err);
  }
  return args[args.length - 1];
}
function warn() {
  return vega_functions_module_log(this.context.dataflow, 'warn', arguments);
}
function info() {
  return vega_functions_module_log(this.context.dataflow, 'info', arguments);
}
function vega_functions_module_debug() {
  return vega_functions_module_log(this.context.dataflow, 'debug', arguments);
}

// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
function channel_luminance_value(channelValue) {
  const val = channelValue / 255;
  if (val <= 0.03928) {
    return val / 12.92;
  }
  return Math.pow((val + 0.055) / 1.055, 2.4);
}
function luminance(color) {
  const c = color_rgb(color),
    r = channel_luminance_value(c.r),
    g = channel_luminance_value(c.g),
    b = channel_luminance_value(c.b);
  return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}

// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
function contrast(color1, color2) {
  const lum1 = luminance(color1),
    lum2 = luminance(color2),
    lumL = Math.max(lum1, lum2),
    lumD = Math.min(lum1, lum2);
  return (lumL + 0.05) / (lumD + 0.05);
}

function vega_functions_module_merge () {
  const args = [].slice.call(arguments);
  args.unshift({});
  return extend(...args);
}

function vega_functions_module_equal(a, b) {
  return a === b || a !== a && b !== b ? true : vega_util_module_isArray(a) ? vega_util_module_isArray(b) && a.length === b.length ? equalArray(a, b) : false : vega_util_module_isObject(a) && vega_util_module_isObject(b) ? equalObject(a, b) : false;
}
function equalArray(a, b) {
  for (let i = 0, n = a.length; i < n; ++i) {
    if (!vega_functions_module_equal(a[i], b[i])) return false;
  }
  return true;
}
function equalObject(a, b) {
  for (const key in a) {
    if (!vega_functions_module_equal(a[key], b[key])) return false;
  }
  return true;
}
function removePredicate(props) {
  return _ => equalObject(props, _);
}
function modify (name, insert, remove, toggle, modify, values) {
  const df = this.context.dataflow,
    data = this.context.data[name],
    input = data.input,
    stamp = df.stamp();
  let changes = data.changes,
    predicate,
    key;
  if (df._trigger === false || !(input.value.length || insert || toggle)) {
    // nothing to do!
    return 0;
  }
  if (!changes || changes.stamp < stamp) {
    data.changes = changes = df.changeset();
    changes.stamp = stamp;
    df.runAfter(() => {
      data.modified = true;
      df.pulse(input, changes).run();
    }, true, 1);
  }
  if (remove) {
    predicate = remove === true ? truthy : vega_util_module_isArray(remove) || isTuple(remove) ? remove : removePredicate(remove);
    changes.remove(predicate);
  }
  if (insert) {
    changes.insert(insert);
  }
  if (toggle) {
    predicate = removePredicate(toggle);
    if (input.value.some(predicate)) {
      changes.remove(predicate);
    } else {
      changes.insert(toggle);
    }
  }
  if (modify) {
    for (key in values) {
      changes.modify(modify, key, values[key]);
    }
  }
  return 1;
}

function pinchDistance(event) {
  const t = event.touches,
    dx = t[0].clientX - t[1].clientX,
    dy = t[0].clientY - t[1].clientY;
  return Math.hypot(dx, dy);
}
function pinchAngle(event) {
  const t = event.touches;
  return Math.atan2(t[0].clientY - t[1].clientY, t[0].clientX - t[1].clientX);
}

// memoize accessor functions
const accessors = {};
function vega_functions_module_pluck (data, name) {
  const accessor = accessors[name] || (accessors[name] = vega_util_module_field(name));
  return vega_util_module_isArray(data) ? data.map(accessor) : accessor(data);
}

function vega_functions_module_array(seq) {
  return vega_util_module_isArray(seq) || ArrayBuffer.isView(seq) ? seq : null;
}
function vega_functions_module_sequence(seq) {
  return vega_functions_module_array(seq) || (vega_util_module_isString(seq) ? seq : null);
}
function vega_functions_module_join(seq) {
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    args[_key - 1] = arguments[_key];
  }
  return vega_functions_module_array(seq).join(...args);
}
function vega_functions_module_indexof(seq) {
  for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
    args[_key2 - 1] = arguments[_key2];
  }
  return vega_functions_module_sequence(seq).indexOf(...args);
}
function vega_functions_module_lastindexof(seq) {
  for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
    args[_key3 - 1] = arguments[_key3];
  }
  return vega_functions_module_sequence(seq).lastIndexOf(...args);
}
function vega_functions_module_slice(seq) {
  for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
    args[_key4 - 1] = arguments[_key4];
  }
  return vega_functions_module_sequence(seq).slice(...args);
}
function vega_functions_module_replace(str, pattern, repl) {
  if (vega_util_module_isFunction(repl)) vega_util_module_error('Function argument passed to replace.');
  if (!vega_util_module_isString(pattern) && !vega_util_module_isRegExp(pattern)) vega_util_module_error('Please pass a string or RegExp argument to replace.');
  return String(str).replace(pattern, repl);
}
function vega_functions_module_reverse(seq) {
  return vega_functions_module_array(seq).slice().reverse();
}
function vega_functions_module_sort(seq) {
  return vega_functions_module_array(seq).slice().sort(vega_util_module_ascending);
}

function bandspace(count, paddingInner, paddingOuter) {
  return bandSpace(count || 0, paddingInner || 0, paddingOuter || 0);
}
function bandwidth(name, group) {
  const s = getScale(name, (group || this).context);
  return s && s.bandwidth ? s.bandwidth() : 0;
}
function vega_functions_module_copy(name, group) {
  const s = getScale(name, (group || this).context);
  return s ? s.copy() : undefined;
}
function domain(name, group) {
  const s = getScale(name, (group || this).context);
  return s ? s.domain() : [];
}
function invert(name, range, group) {
  const s = getScale(name, (group || this).context);
  return !s ? undefined : vega_util_module_isArray(range) ? (s.invertRange || s.invert)(range) : (s.invert || s.invertExtent)(range);
}
function vega_functions_module_range(name, group) {
  const s = getScale(name, (group || this).context);
  return s && s.range ? s.range() : [];
}
function vega_functions_module_scale(name, value, group) {
  const s = getScale(name, (group || this).context);
  return s ? s(value) : undefined;
}

function scaleGradient (scale, p0, p1, count, group) {
  scale = getScale(scale, (group || this).context);
  const gradient = Gradient(p0, p1);
  let stops = scale.domain(),
    min = stops[0],
    max = peek(stops),
    fraction = vega_util_module_identity;
  if (!(max - min)) {
    // expand scale if domain has zero span, fix #1479
    scale = (scale.interpolator ? vega_scale_module_scale('sequential')().interpolator(scale.interpolator()) : vega_scale_module_scale('linear')().interpolate(scale.interpolate()).range(scale.range())).domain([min = 0, max = 1]);
  } else {
    fraction = scaleFraction(scale, min, max);
  }
  if (scale.ticks) {
    stops = scale.ticks(+count || 15);
    if (min !== stops[0]) stops.unshift(min);
    if (max !== peek(stops)) stops.push(max);
  }
  stops.forEach(_ => gradient.stop(fraction(_), scale(_)));
  return gradient;
}

function geoShape(projection, geojson, group) {
  const p = getScale(projection, (group || this).context);
  return function (context) {
    return p ? p.path.context(context)(geojson) : '';
  };
}
function pathShape(path) {
  let p = null;
  return function (context) {
    return context ? pathRender(context, p = p || vega_scenegraph_module_parse(path)) : path;
  };
}

const datum = d => d.data;
function treeNodes(name, context) {
  const tree = vega_functions_module_data.call(context, name);
  return tree.root && tree.root.lookup || {};
}
function treePath(name, source, target) {
  const nodes = treeNodes(name, this),
    s = nodes[source],
    t = nodes[target];
  return s && t ? s.path(t).map(datum) : undefined;
}
function treeAncestors(name, node) {
  const n = treeNodes(name, this)[node];
  return n ? n.ancestors().map(datum) : undefined;
}

const _window = () => typeof window !== 'undefined' && window || null;
function extension_screen() {
  const w = _window();
  return w ? w.screen : {};
}
function windowSize() {
  const w = _window();
  return w ? [w.innerWidth, w.innerHeight] : [undefined, undefined];
}
function containerSize() {
  const view = this.context.dataflow,
    el = view.container && view.container();
  return el ? [el.clientWidth, el.clientHeight] : [undefined, undefined];
}

function vega_functions_module_intersect (b, opt, group) {
  if (!b) return [];
  const [u, v] = b,
    box = new Bounds().set(u[0], u[1], v[0], v[1]),
    scene = group || this.context.dataflow.scenegraph().root;
  return vega_scenegraph_module_intersect(scene, box, vega_functions_module_filter(opt));
}
function vega_functions_module_filter(opt) {
  let p = null;
  if (opt) {
    const types = vega_util_module_array(opt.marktype),
      names = vega_util_module_array(opt.markname);
    p = _ => (!types.length || types.some(t => _.marktype === t)) && (!names.length || names.some(s => _.name === s));
  }
  return p;
}

/**
 * Appends a new point to the lasso
 *
 * @param {*} lasso the lasso in pixel space
 * @param {*} x the x coordinate in pixel space
 * @param {*} y the y coordinate in pixel space
 * @param {*} minDist the minimum distance, in pixels, that thenew point needs to be apart from the last point
 * @returns a new array containing the lasso with the new point
 */
function lassoAppend(lasso, x, y) {
  let minDist = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5;
  lasso = vega_util_module_array(lasso);
  const last = lasso[lasso.length - 1];

  // Add point to lasso if its the first point or distance to last point exceed minDist
  return last === undefined || Math.hypot(last[0] - x, last[1] - y) > minDist ? [...lasso, [x, y]] : lasso;
}

/**
 * Generates a svg path command which draws a lasso
 *
 * @param {*} lasso the lasso in pixel space in the form [[x,y], [x,y], ...]
 * @returns the svg path command that draws the lasso
 */
function lassoPath(lasso) {
  return vega_util_module_array(lasso).reduce((svg, _ref, i) => {
    let [x, y] = _ref;
    return svg += i == 0 ? `M ${x},${y} ` : i === lasso.length - 1 ? ' Z' : `L ${x},${y} `;
  }, '');
}

/**
 * Inverts the lasso from pixel space to an array of vega scenegraph tuples
 *
 * @param {*} data the dataset
 * @param {*} pixelLasso the lasso in pixel space, [[x,y], [x,y], ...]
 * @param {*} unit the unit where the lasso is defined
 *
 * @returns an array of vega scenegraph tuples
 */
function intersectLasso(markname, pixelLasso, unit) {
  const {
    x,
    y,
    mark
  } = unit;
  const bb = new Bounds().set(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);

  // Get bounding box around lasso
  for (const [px, py] of pixelLasso) {
    if (px < bb.x1) bb.x1 = px;
    if (px > bb.x2) bb.x2 = px;
    if (py < bb.y1) bb.y1 = py;
    if (py > bb.y2) bb.y2 = py;
  }

  // Translate bb against unit coordinates
  bb.translate(x, y);
  const intersection = vega_functions_module_intersect([[bb.x1, bb.y1], [bb.x2, bb.y2]], markname, mark);

  // Check every point against the lasso
  return intersection.filter(tuple => pointInPolygon(tuple.x, tuple.y, pixelLasso));
}

/**
 * Performs a test if a point is inside a polygon based on the idea from
 * https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
 *
 * This method will not need the same start/end point since it wraps around the edges of the array
 *
 * @param {*} test a point to test against
 * @param {*} polygon a polygon in the form [[x,y], [x,y], ...]
 * @returns true if the point lies inside the polygon, false otherwise
 */
function pointInPolygon(testx, testy, polygon) {
  let intersections = 0;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const [prevX, prevY] = polygon[j];
    const [x, y] = polygon[i];

    // count intersections
    if (y > testy != prevY > testy && testx < (prevX - x) * (testy - y) / (prevY - y) + x) {
      intersections++;
    }
  }

  // point is in polygon if intersection count is odd
  return intersections & 1;
}

// Expression function context object
const functionContext = {
  random() {
    return vega_statistics_module_random();
  },
  // override default
  cumulativeNormal: cumulativeNormal,
  cumulativeLogNormal: cumulativeLogNormal,
  cumulativeUniform: cumulativeUniform,
  densityNormal: densityNormal,
  densityLogNormal: densityLogNormal,
  densityUniform: densityUniform,
  quantileNormal: quantileNormal,
  quantileLogNormal: quantileLogNormal,
  quantileUniform: quantileUniform,
  sampleNormal: sampleNormal,
  sampleLogNormal: sampleLogNormal,
  sampleUniform: sampleUniform,
  isArray: vega_util_module_isArray,
  isBoolean: isBoolean,
  isDate: vega_util_module_isDate,
  isDefined(_) {
    return _ !== undefined;
  },
  isNumber: vega_util_module_isNumber,
  isObject: vega_util_module_isObject,
  isRegExp: vega_util_module_isRegExp,
  isString: vega_util_module_isString,
  isTuple: isTuple,
  isValid(_) {
    return _ != null && _ === _;
  },
  toBoolean: toBoolean,
  toDate(_) {
    return toDate(_);
  },
  // suppress extra arguments
  toNumber: vega_util_module_toNumber,
  toString: vega_util_module_toString,
  indexof: vega_functions_module_indexof,
  join: vega_functions_module_join,
  lastindexof: vega_functions_module_lastindexof,
  replace: vega_functions_module_replace,
  reverse: vega_functions_module_reverse,
  sort: vega_functions_module_sort,
  slice: vega_functions_module_slice,
  flush: vega_util_module_flush,
  lerp: lerp,
  merge: vega_functions_module_merge,
  pad: vega_util_module_pad,
  peek: peek,
  pluck: vega_functions_module_pluck,
  span: span,
  inrange: inrange,
  truncate: truncate,
  rgb: color_rgb,
  lab: lab,
  hcl: hcl,
  hsl: hsl,
  luminance,
  contrast,
  sequence: range_range,
  format: vega_functions_module_format,
  utcFormat: vega_functions_module_utcFormat,
  utcParse: vega_functions_module_utcParse,
  utcOffset: utcOffset,
  utcSequence: utcSequence,
  timeFormat: vega_functions_module_timeFormat,
  timeParse: vega_functions_module_timeParse,
  timeOffset: timeOffset,
  timeSequence: timeSequence,
  timeUnitSpecifier: timeUnitSpecifier,
  monthFormat,
  monthAbbrevFormat,
  dayFormat,
  dayAbbrevFormat,
  quarter: vega_util_module_quarter,
  utcquarter: vega_util_module_utcquarter,
  week: vega_time_module_week,
  utcweek: vega_time_module_utcweek,
  dayofyear: vega_time_module_dayofyear,
  utcdayofyear: vega_time_module_utcdayofyear,
  warn,
  info,
  debug: vega_functions_module_debug,
  extent(_) {
    return extent(_);
  },
  // suppress extra arguments
  inScope,
  intersect: vega_functions_module_intersect,
  clampRange: clampRange,
  pinchDistance,
  pinchAngle,
  screen: extension_screen,
  containerSize,
  windowSize,
  bandspace,
  setdata,
  pathShape,
  panLinear: panLinear,
  panLog: panLog,
  panPow: panPow,
  panSymlog: panSymlog,
  zoomLinear: zoomLinear,
  zoomLog: zoomLog,
  zoomPow: zoomPow,
  zoomSymlog: zoomSymlog,
  encode,
  modify,
  lassoAppend,
  lassoPath,
  intersectLasso
};
const eventFunctions = ['view', 'item', 'group', 'xy', 'x', 'y'],
  // event functions
  eventPrefix = 'event.vega.',
  // event function prefix
  thisPrefix = 'this.',
  // function context prefix
  astVisitors = {}; // AST visitors for dependency analysis

// export code generator parameters
const codegenParams = {
  forbidden: ['_'],
  allowed: ['datum', 'event', 'item'],
  fieldvar: 'datum',
  globalvar: id => `_[${$(SignalPrefix + id)}]`,
  functions: buildFunctions,
  constants: Constants,
  visitors: astVisitors
};

// export code generator
const codeGenerator = vega_expression_module_codegen(codegenParams);

// Build expression function registry
function buildFunctions(codegen) {
  const fn = Functions(codegen);
  eventFunctions.forEach(name => fn[name] = eventPrefix + name);
  for (const name in functionContext) {
    fn[name] = thisPrefix + name;
  }
  extend(fn, internalScaleFunctions(codegen, functionContext, astVisitors));
  return fn;
}

// Register an expression function
function expressionFunction(name, fn, visitor) {
  if (arguments.length === 1) {
    return functionContext[name];
  }

  // register with the functionContext
  functionContext[name] = fn;

  // if there is an astVisitor register that, too
  if (visitor) astVisitors[name] = visitor;

  // if the code generator has already been initialized,
  // we need to also register the function with it
  if (codeGenerator) codeGenerator.functions[name] = thisPrefix + name;
  return this;
}

// register expression functions with ast visitors
expressionFunction('bandwidth', bandwidth, scaleVisitor);
expressionFunction('copy', vega_functions_module_copy, scaleVisitor);
expressionFunction('domain', domain, scaleVisitor);
expressionFunction('range', vega_functions_module_range, scaleVisitor);
expressionFunction('invert', invert, scaleVisitor);
expressionFunction('scale', vega_functions_module_scale, scaleVisitor);
expressionFunction('gradient', scaleGradient, scaleVisitor);
expressionFunction('geoArea', geoArea, scaleVisitor);
expressionFunction('geoBounds', geoBounds, scaleVisitor);
expressionFunction('geoCentroid', geoCentroid, scaleVisitor);
expressionFunction('geoShape', geoShape, scaleVisitor);
expressionFunction('geoScale', geoScale, scaleVisitor);
expressionFunction('indata', indata, indataVisitor);
expressionFunction('data', vega_functions_module_data, dataVisitor);
expressionFunction('treePath', treePath, dataVisitor);
expressionFunction('treeAncestors', treeAncestors, dataVisitor);

// register Vega-Lite selection functions
expressionFunction('vlSelectionTest', selectionTest, selectionVisitor);
expressionFunction('vlSelectionIdTest', selectionIdTest, selectionVisitor);
expressionFunction('vlSelectionResolve', selectionResolve, selectionVisitor);
expressionFunction('vlSelectionTuples', selectionTuples);

function vega_functions_module_parser (expr, scope) {
  const params = {};

  // parse the expression to an abstract syntax tree (ast)
  let ast;
  try {
    expr = vega_util_module_isString(expr) ? expr : $(expr) + '';
    ast = parser(expr);
  } catch (err) {
    vega_util_module_error('Expression parse error: ' + expr);
  }

  // analyze ast function calls for dependencies
  ast.visit(node => {
    if (node.type !== CallExpression) return;
    const name = node.callee.name,
      visit = codegenParams.visitors[name];
    if (visit) visit(name, node.arguments, scope, params);
  });

  // perform code generation
  const gen = codeGenerator(ast);

  // collect signal dependencies
  gen.globals.forEach(name => {
    const signalName = SignalPrefix + name;
    if (!vega_util_module_has(params, signalName) && scope.getSignal(name)) {
      params[signalName] = scope.signalRef(name);
    }
  });

  // return generated expression code and dependencies
  return {
    $expr: extend({
      code: gen.code
    }, scope.options.ast ? {
      ast
    } : null),
    $fields: gen.fields,
    $params: params
  };
}



;// ../../node_modules/vega-runtime/build/vega-runtime.module.js



/**
 * Parse a serialized dataflow specification.
 */
function vega_runtime_module_parse (spec) {
  const ctx = this,
    operators = spec.operators || [];

  // parse background
  if (spec.background) {
    ctx.background = spec.background;
  }

  // parse event configuration
  if (spec.eventConfig) {
    ctx.eventConfig = spec.eventConfig;
  }

  // parse locale configuration
  if (spec.locale) {
    ctx.locale = spec.locale;
  }

  // parse operators
  operators.forEach(entry => ctx.parseOperator(entry));

  // parse operator parameters
  operators.forEach(entry => ctx.parseOperatorParameters(entry));

  // parse streams
  (spec.streams || []).forEach(entry => ctx.parseStream(entry));

  // parse updates
  (spec.updates || []).forEach(entry => ctx.parseUpdate(entry));
  return ctx.resolve();
}

const Skip = vega_util_module_toSet(['rule']),
  Swap = vega_util_module_toSet(['group', 'image', 'rect']);
function adjustSpatial(encode, marktype) {
  let code = '';
  if (Skip[marktype]) return code;
  if (encode.x2) {
    if (encode.x) {
      if (Swap[marktype]) {
        code += 'if(o.x>o.x2)$=o.x,o.x=o.x2,o.x2=$;';
      }
      code += 'o.width=o.x2-o.x;';
    } else {
      code += 'o.x=o.x2-(o.width||0);';
    }
  }
  if (encode.xc) {
    code += 'o.x=o.xc-(o.width||0)/2;';
  }
  if (encode.y2) {
    if (encode.y) {
      if (Swap[marktype]) {
        code += 'if(o.y>o.y2)$=o.y,o.y=o.y2,o.y2=$;';
      }
      code += 'o.height=o.y2-o.y;';
    } else {
      code += 'o.y=o.y2-(o.height||0);';
    }
  }
  if (encode.yc) {
    code += 'o.y=o.yc-(o.height||0)/2;';
  }
  return code;
}
function canonicalType(type) {
  return (type + '').toLowerCase();
}
function isOperator(type) {
  return canonicalType(type) === 'operator';
}
function isCollect(type) {
  return canonicalType(type) === 'collect';
}

function expression(ctx, args, code) {
  // wrap code in return statement if expression does not terminate
  if (!code.endsWith(';')) {
    code = 'return(' + code + ');';
  }
  const fn = Function(...args.concat(code));
  return ctx && ctx.functions ? fn.bind(ctx.functions) : fn;
}

// generate code for comparing a single field
function vega_runtime_module_compare(u, v, lt, gt) {
  return `((u = ${u}) < (v = ${v}) || u == null) && v != null ? ${lt}
  : (u > v || v == null) && u != null ? ${gt}
  : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${lt}
  : v !== v && u === u ? ${gt} : `;
}
var expressionCodegen = {
  /**
   * Parse an expression used to update an operator value.
   */
  operator: (ctx, expr) => expression(ctx, ['_'], expr.code),
  /**
   * Parse an expression provided as an operator parameter value.
   */
  parameter: (ctx, expr) => expression(ctx, ['datum', '_'], expr.code),
  /**
   * Parse an expression applied to an event stream.
   */
  event: (ctx, expr) => expression(ctx, ['event'], expr.code),
  /**
   * Parse an expression used to handle an event-driven operator update.
   */
  handler: (ctx, expr) => {
    const code = `var datum=event.item&&event.item.datum;return ${expr.code};`;
    return expression(ctx, ['_', 'event'], code);
  },
  /**
   * Parse an expression that performs visual encoding.
   */
  encode: (ctx, encode) => {
    const {
      marktype,
      channels
    } = encode;
    let code = 'var o=item,datum=o.datum,m=0,$;';
    for (const name in channels) {
      const o = 'o[' + $(name) + ']';
      code += `$=${channels[name].code};if(${o}!==$)${o}=$,m=1;`;
    }
    code += adjustSpatial(channels, marktype);
    code += 'return m;';
    return expression(ctx, ['item', '_'], code);
  },
  /**
   * Optimized code generators for access and comparison.
   */
  codegen: {
    get(path) {
      const ref = `[${path.map($).join('][')}]`;
      const get = Function('_', `return _${ref};`);
      get.path = ref;
      return get;
    },
    comparator(fields, orders) {
      let t;
      const map = (f, i) => {
        const o = orders[i];
        let u, v;
        if (f.path) {
          u = `a${f.path}`;
          v = `b${f.path}`;
        } else {
          (t = t || {})['f' + i] = f;
          u = `this.f${i}(a)`;
          v = `this.f${i}(b)`;
        }
        return vega_runtime_module_compare(u, v, -o, o);
      };
      const fn = Function('a', 'b', 'var u, v; return ' + fields.map(map).join('') + '0;');
      return t ? fn.bind(t) : fn;
    }
  }
};

/**
 * Parse a dataflow operator.
 */
function vega_runtime_module_parseOperator(spec) {
  const ctx = this;
  if (isOperator(spec.type) || !spec.type) {
    ctx.operator(spec, spec.update ? ctx.operatorExpression(spec.update) : null);
  } else {
    ctx.transform(spec, spec.type);
  }
}

/**
 * Parse and assign operator parameters.
 */
function parseOperatorParameters(spec) {
  const ctx = this;
  if (spec.params) {
    const op = ctx.get(spec.id);
    if (!op) vega_util_module_error('Invalid operator id: ' + spec.id);
    ctx.dataflow.connect(op, op.parameters(ctx.parseParameters(spec.params), spec.react, spec.initonly));
  }
}

/**
 * Parse a set of operator parameters.
 */
function parseParameters(spec, params) {
  params = params || {};
  const ctx = this;
  for (const key in spec) {
    const value = spec[key];
    params[key] = vega_util_module_isArray(value) ? value.map(v => parseParameter(v, ctx, params)) : parseParameter(value, ctx, params);
  }
  return params;
}

/**
 * Parse a single parameter.
 */
function parseParameter(spec, ctx, params) {
  if (!spec || !vega_util_module_isObject(spec)) return spec;
  for (let i = 0, n = PARSERS.length, p; i < n; ++i) {
    p = PARSERS[i];
    if (vega_util_module_has(spec, p.key)) {
      return p.parse(spec, ctx, params);
    }
  }
  return spec;
}

/** Reference parsers. */
var PARSERS = [{
  key: '$ref',
  parse: getOperator
}, {
  key: '$key',
  parse: getKey
}, {
  key: '$expr',
  parse: getExpression
}, {
  key: '$field',
  parse: vega_runtime_module_getField
}, {
  key: '$encode',
  parse: getEncode
}, {
  key: '$compare',
  parse: getCompare
}, {
  key: '$context',
  parse: vega_runtime_module_getContext
}, {
  key: '$subflow',
  parse: getSubflow
}, {
  key: '$tupleid',
  parse: getTupleId
}];

/**
 * Resolve an operator reference.
 */
function getOperator(_, ctx) {
  return ctx.get(_.$ref) || vega_util_module_error('Operator not defined: ' + _.$ref);
}

/**
 * Resolve an expression reference.
 */
function getExpression(_, ctx, params) {
  if (_.$params) {
    // parse expression parameters
    ctx.parseParameters(_.$params, params);
  }
  const k = 'e:' + _.$expr.code;
  return ctx.fn[k] || (ctx.fn[k] = accessor(ctx.parameterExpression(_.$expr), _.$fields));
}

/**
 * Resolve a key accessor reference.
 */
function getKey(_, ctx) {
  const k = 'k:' + _.$key + '_' + !!_.$flat;
  return ctx.fn[k] || (ctx.fn[k] = vega_util_module_key(_.$key, _.$flat, ctx.expr.codegen));
}

/**
 * Resolve a field accessor reference.
 */
function vega_runtime_module_getField(_, ctx) {
  if (!_.$field) return null;
  const k = 'f:' + _.$field + '_' + _.$name;
  return ctx.fn[k] || (ctx.fn[k] = vega_util_module_field(_.$field, _.$name, ctx.expr.codegen));
}

/**
 * Resolve a comparator function reference.
 */
function getCompare(_, ctx) {
  // As of Vega 5.5.3, $tupleid sort is no longer used.
  // Keep here for now for backwards compatibility.
  const k = 'c:' + _.$compare + '_' + _.$order,
    c = vega_util_module_array(_.$compare).map(_ => _ && _.$tupleid ? tupleid : _);
  return ctx.fn[k] || (ctx.fn[k] = vega_util_module_compare(c, _.$order, ctx.expr.codegen));
}

/**
 * Resolve an encode operator reference.
 */
function getEncode(_, ctx) {
  const spec = _.$encode,
    encode = {};
  for (const name in spec) {
    const enc = spec[name];
    encode[name] = accessor(ctx.encodeExpression(enc.$expr), enc.$fields);
    encode[name].output = enc.$output;
  }
  return encode;
}

/**
 * Resolve a context reference.
 */
function vega_runtime_module_getContext(_, ctx) {
  return ctx;
}

/**
 * Resolve a recursive subflow specification.
 */
function getSubflow(_, ctx) {
  const spec = _.$subflow;
  return function (dataflow, key, parent) {
    const subctx = ctx.fork().parse(spec),
      op = subctx.get(spec.operators[0].id),
      p = subctx.signals.parent;
    if (p) p.set(parent);
    op.detachSubflow = () => ctx.detach(subctx);
    return op;
  };
}

/**
 * Resolve a tuple id reference.
 */
function getTupleId() {
  return tupleid;
}

/**
 * Parse an event stream specification.
 */
function parseStream (spec) {
  var ctx = this,
    filter = spec.filter != null ? ctx.eventExpression(spec.filter) : undefined,
    stream = spec.stream != null ? ctx.get(spec.stream) : undefined,
    args;
  if (spec.source) {
    stream = ctx.events(spec.source, spec.type, filter);
  } else if (spec.merge) {
    args = spec.merge.map(_ => ctx.get(_));
    stream = args[0].merge.apply(args[0], args.slice(1));
  }
  if (spec.between) {
    args = spec.between.map(_ => ctx.get(_));
    stream = stream.between(args[0], args[1]);
  }
  if (spec.filter) {
    stream = stream.filter(filter);
  }
  if (spec.throttle != null) {
    stream = stream.throttle(+spec.throttle);
  }
  if (spec.debounce != null) {
    stream = stream.debounce(+spec.debounce);
  }
  if (stream == null) {
    vega_util_module_error('Invalid stream definition: ' + JSON.stringify(spec));
  }
  if (spec.consume) stream.consume(true);
  ctx.stream(spec, stream);
}

/**
 * Parse an event-driven operator update.
 */
function parseUpdate (spec) {
  var ctx = this,
    srcid = vega_util_module_isObject(srcid = spec.source) ? srcid.$ref : srcid,
    source = ctx.get(srcid),
    target = null,
    update = spec.update,
    params = undefined;
  if (!source) vega_util_module_error('Source not defined: ' + spec.source);
  target = spec.target && spec.target.$expr ? ctx.eventExpression(spec.target.$expr) : ctx.get(spec.target);
  if (update && update.$expr) {
    if (update.$params) {
      params = ctx.parseParameters(update.$params);
    }
    update = ctx.handlerExpression(update.$expr);
  }
  ctx.update(spec, source, target, update, params);
}

const vega_runtime_module_SKIP = {
  skip: true
};
function getState(options) {
  var ctx = this,
    state = {};
  if (options.signals) {
    var signals = state.signals = {};
    Object.keys(ctx.signals).forEach(key => {
      const op = ctx.signals[key];
      if (options.signals(key, op)) {
        signals[key] = op.value;
      }
    });
  }
  if (options.data) {
    var data = state.data = {};
    Object.keys(ctx.data).forEach(key => {
      const dataset = ctx.data[key];
      if (options.data(key, dataset)) {
        data[key] = dataset.input.value;
      }
    });
  }
  if (ctx.subcontext && options.recurse !== false) {
    state.subcontext = ctx.subcontext.map(ctx => ctx.getState(options));
  }
  return state;
}
function setState(state) {
  var ctx = this,
    df = ctx.dataflow,
    data = state.data,
    signals = state.signals;
  Object.keys(signals || {}).forEach(key => {
    df.update(ctx.signals[key], signals[key], vega_runtime_module_SKIP);
  });
  Object.keys(data || {}).forEach(key => {
    df.pulse(ctx.data[key].input, df.changeset().remove(truthy).insert(data[key]));
  });
  (state.subcontext || []).forEach((substate, i) => {
    const subctx = ctx.subcontext[i];
    if (subctx) subctx.setState(substate);
  });
}

/**
 * Context objects store the current parse state.
 * Enables lookup of parsed operators, event streams, accessors, etc.
 * Provides a 'fork' method for creating child contexts for subflows.
 */
function vega_runtime_module_context (df, transforms, functions, expr) {
  return new Context(df, transforms, functions, expr);
}
function Context(df, transforms, functions, expr) {
  this.dataflow = df;
  this.transforms = transforms;
  this.events = df.events.bind(df);
  this.expr = expr || expressionCodegen, this.signals = {};
  this.scales = {};
  this.nodes = {};
  this.data = {};
  this.fn = {};
  if (functions) {
    this.functions = Object.create(functions);
    this.functions.context = this;
  }
}
function Subcontext(ctx) {
  this.dataflow = ctx.dataflow;
  this.transforms = ctx.transforms;
  this.events = ctx.events;
  this.expr = ctx.expr;
  this.signals = Object.create(ctx.signals);
  this.scales = Object.create(ctx.scales);
  this.nodes = Object.create(ctx.nodes);
  this.data = Object.create(ctx.data);
  this.fn = Object.create(ctx.fn);
  if (ctx.functions) {
    this.functions = Object.create(ctx.functions);
    this.functions.context = this;
  }
}
Context.prototype = Subcontext.prototype = {
  fork() {
    const ctx = new Subcontext(this);
    (this.subcontext || (this.subcontext = [])).push(ctx);
    return ctx;
  },
  detach(ctx) {
    this.subcontext = this.subcontext.filter(c => c !== ctx);

    // disconnect all nodes in the subcontext
    // wipe out targets first for better efficiency
    const keys = Object.keys(ctx.nodes);
    for (const key of keys) ctx.nodes[key]._targets = null;
    for (const key of keys) ctx.nodes[key].detach();
    ctx.nodes = null;
  },
  get(id) {
    return this.nodes[id];
  },
  set(id, node) {
    return this.nodes[id] = node;
  },
  add(spec, op) {
    const ctx = this,
      df = ctx.dataflow,
      data = spec.value;
    ctx.set(spec.id, op);
    if (isCollect(spec.type) && data) {
      if (data.$ingest) {
        df.ingest(op, data.$ingest, data.$format);
      } else if (data.$request) {
        df.preload(op, data.$request, data.$format);
      } else {
        df.pulse(op, df.changeset().insert(data));
      }
    }
    if (spec.root) {
      ctx.root = op;
    }
    if (spec.parent) {
      let p = ctx.get(spec.parent.$ref);
      if (p) {
        df.connect(p, [op]);
        op.targets().add(p);
      } else {
        (ctx.unresolved = ctx.unresolved || []).push(() => {
          p = ctx.get(spec.parent.$ref);
          df.connect(p, [op]);
          op.targets().add(p);
        });
      }
    }
    if (spec.signal) {
      ctx.signals[spec.signal] = op;
    }
    if (spec.scale) {
      ctx.scales[spec.scale] = op;
    }
    if (spec.data) {
      for (const name in spec.data) {
        const data = ctx.data[name] || (ctx.data[name] = {});
        spec.data[name].forEach(role => data[role] = op);
      }
    }
  },
  resolve() {
    (this.unresolved || []).forEach(fn => fn());
    delete this.unresolved;
    return this;
  },
  operator(spec, update) {
    this.add(spec, this.dataflow.add(spec.value, update));
  },
  transform(spec, type) {
    this.add(spec, this.dataflow.add(this.transforms[canonicalType(type)]));
  },
  stream(spec, stream) {
    this.set(spec.id, stream);
  },
  update(spec, stream, target, update, params) {
    this.dataflow.on(stream, target, update, params, spec.options);
  },
  // expression parsing
  operatorExpression(expr) {
    return this.expr.operator(this, expr);
  },
  parameterExpression(expr) {
    return this.expr.parameter(this, expr);
  },
  eventExpression(expr) {
    return this.expr.event(this, expr);
  },
  handlerExpression(expr) {
    return this.expr.handler(this, expr);
  },
  encodeExpression(encode) {
    return this.expr.encode(this, encode);
  },
  // parse methods
  parse: vega_runtime_module_parse,
  parseOperator: vega_runtime_module_parseOperator,
  parseOperatorParameters,
  parseParameters,
  parseStream,
  parseUpdate,
  // state methods
  getState,
  setState
};



;// ../../node_modules/d3-timer/src/interval.js


/* harmony default export */ function src_interval(callback, delay, time) {
  var t = new Timer, total = delay;
  if (delay == null) return t.restart(callback, delay, time), t;
  t._restart = t.restart;
  t.restart = function(callback, delay, time) {
    delay = +delay, time = time == null ? timer_now() : +time;
    t._restart(function tick(elapsed) {
      elapsed += total;
      t._restart(tick, total += delay, time);
      callback(elapsed);
    }, delay, time);
  }
  t.restart(callback, delay, time);
  return t;
}

;// ../../node_modules/vega-view/build/vega-view.module.js









// initialize aria role and label attributes
function initializeAria(view) {
  const el = view.container();
  if (el) {
    el.setAttribute('role', 'graphics-document');
    el.setAttribute('aria-roleDescription', 'visualization');
    ariaLabel(el, view.description());
  }
}

// update aria-label if we have a DOM container element
function ariaLabel(el, desc) {
  if (el) desc == null ? el.removeAttribute('aria-label') : el.setAttribute('aria-label', desc);
}

function vega_view_module_background (view) {
  // respond to background signal
  view.add(null, _ => {
    view._background = _.bg;
    view._resize = 1;
    return _.bg;
  }, {
    bg: view._signals.background
  });
}

const Default = 'default';
function cursor (view) {
  // get cursor signal, add to dataflow if needed
  const cursor = view._signals.cursor || (view._signals.cursor = view.add({
    user: Default,
    item: null
  }));

  // evaluate cursor on each pointermove event
  view.on(view.events('view', 'pointermove'), cursor, (_, event) => {
    const value = cursor.value,
      user = value ? vega_util_module_isString(value) ? value : value.user : Default,
      item = event.item && event.item.cursor || null;
    return value && user === value.user && item == value.item ? value : {
      user: user,
      item: item
    };
  });

  // when cursor signal updates, set visible cursor
  view.add(null, function (_) {
    let user = _.cursor,
      item = this.value;
    if (!vega_util_module_isString(user)) {
      item = user.item;
      user = user.user;
    }
    setCursor(view, user && user !== Default ? user : item || user);
    return item;
  }, {
    cursor: cursor
  });
}
function setCursor(view, cursor) {
  const el = view.globalCursor() ? typeof document !== 'undefined' && document.body : view.container();
  if (el) {
    return cursor == null ? el.style.removeProperty('cursor') : el.style.cursor = cursor;
  }
}

function dataref(view, name) {
  var data = view._runtime.data;
  if (!vega_util_module_has(data, name)) {
    vega_util_module_error('Unrecognized data set: ' + name);
  }
  return data[name];
}
function vega_view_module_data(name, values) {
  return arguments.length < 2 ? dataref(this, name).values.value : change.call(this, name, changeset().remove(truthy).insert(values));
}
function change(name, changes) {
  if (!isChangeSet(changes)) {
    vega_util_module_error('Second argument to changes must be a changeset.');
  }
  const dataset = dataref(this, name);
  dataset.modified = true;
  return this.pulse(dataset.input, changes);
}
function vega_view_module_insert(name, _) {
  return change.call(this, name, changeset().insert(_));
}
function vega_view_module_remove(name, _) {
  return change.call(this, name, changeset().remove(_));
}

function width(view) {
  var padding = view.padding();
  return Math.max(0, view._viewWidth + padding.left + padding.right);
}
function height(view) {
  var padding = view.padding();
  return Math.max(0, view._viewHeight + padding.top + padding.bottom);
}
function vega_view_module_offset(view) {
  var padding = view.padding(),
    origin = view._origin;
  return [padding.left + origin[0], padding.top + origin[1]];
}
function resizeRenderer(view) {
  var origin = vega_view_module_offset(view),
    w = width(view),
    h = height(view);
  view._renderer.background(view.background());
  view._renderer.resize(w, h, origin);
  view._handler.origin(origin);
  view._resizeListeners.forEach(handler => {
    try {
      handler(w, h);
    } catch (error) {
      view.error(error);
    }
  });
}

/**
 * Extend an event with additional view-specific methods.
 * Adds a new property ('vega') to an event that provides a number
 * of methods for querying information about the current interaction.
 * The vega object provides the following methods:
 *   view - Returns the backing View instance.
 *   item - Returns the currently active scenegraph item (if any).
 *   group - Returns the currently active scenegraph group (if any).
 *     This method accepts a single string-typed argument indicating the name
 *     of the desired parent group. The scenegraph will be traversed from
 *     the item up towards the root to search for a matching group. If no
 *     argument is provided the enclosing group for the active item is
 *     returned, unless the item it itself a group, in which case it is
 *     returned directly.
 *   xy - Returns a two-element array containing the x and y coordinates for
 *     mouse or touch events. For touch events, this is based on the first
 *     elements in the changedTouches array. This method accepts a single
 *     argument: either an item instance or mark name that should serve as
 *     the reference coordinate system. If no argument is provided the
 *     top-level view coordinate system is assumed.
 *   x - Returns the current x-coordinate, accepts the same arguments as xy.
 *   y - Returns the current y-coordinate, accepts the same arguments as xy.
 * @param {Event} event - The input event to extend.
 * @param {Item} item - The currently active scenegraph item (if any).
 * @return {Event} - The extended input event.
 */
function eventExtend (view, event, item) {
  var r = view._renderer,
    el = r && r.canvas(),
    p,
    e,
    translate;
  if (el) {
    translate = vega_view_module_offset(view);
    e = event.changedTouches ? event.changedTouches[0] : event;
    p = vega_scenegraph_module_point(e, el);
    p[0] -= translate[0];
    p[1] -= translate[1];
  }
  event.dataflow = view;
  event.item = item;
  event.vega = extension(view, item, p);
  return event;
}
function extension(view, item, point) {
  const itemGroup = item ? item.mark.marktype === 'group' ? item : item.mark.group : null;
  function group(name) {
    var g = itemGroup,
      i;
    if (name) for (i = item; i; i = i.mark.group) {
      if (i.mark.name === name) {
        g = i;
        break;
      }
    }
    return g && g.mark && g.mark.interactive ? g : {};
  }
  function xy(item) {
    if (!item) return point;
    if (vega_util_module_isString(item)) item = group(item);
    const p = point.slice();
    while (item) {
      p[0] -= item.x || 0;
      p[1] -= item.y || 0;
      item = item.mark && item.mark.group;
    }
    return p;
  }
  return {
    view: vega_util_module_constant(view),
    item: vega_util_module_constant(item || {}),
    group: group,
    xy: xy,
    x: item => xy(item)[0],
    y: item => xy(item)[1]
  };
}

const VIEW = 'view',
  TIMER = 'timer',
  WINDOW = 'window',
  NO_TRAP = {
    trap: false
  };

/**
 * Initialize event handling configuration.
 * @param {object} config - The configuration settings.
 * @return {object}
 */
function initializeEventConfig(config) {
  const events = extend({
    defaults: {}
  }, config);
  const unpack = (obj, keys) => {
    keys.forEach(k => {
      if (vega_util_module_isArray(obj[k])) obj[k] = vega_util_module_toSet(obj[k]);
    });
  };
  unpack(events.defaults, ['prevent', 'allow']);
  unpack(events, ['view', 'window', 'selector']);
  return events;
}
function trackEventListener(view, sources, type, handler) {
  view._eventListeners.push({
    type: type,
    sources: vega_util_module_array(sources),
    handler: handler
  });
}
function prevent(view, type) {
  var def = view._eventConfig.defaults,
    prevent = def.prevent,
    allow = def.allow;
  return prevent === false || allow === true ? false : prevent === true || allow === false ? true : prevent ? prevent[type] : allow ? !allow[type] : view.preventDefault();
}
function permit(view, key, type) {
  const rule = view._eventConfig && view._eventConfig[key];
  if (rule === false || vega_util_module_isObject(rule) && !rule[type]) {
    view.warn(`Blocked ${key} ${type} event listener.`);
    return false;
  }
  return true;
}

/**
 * Create a new event stream from an event source.
 * @param {object} source - The event source to monitor.
 * @param {string} type - The event type.
 * @param {function(object): boolean} [filter] - Event filter function.
 * @return {EventStream}
 */
function vega_view_module_events(source, type, filter) {
  var view = this,
    s = new EventStream(filter),
    send = function (e, item) {
      view.runAsync(null, () => {
        if (source === VIEW && prevent(view, type)) {
          e.preventDefault();
        }
        s.receive(eventExtend(view, e, item));
      });
    },
    sources;
  if (source === TIMER) {
    if (permit(view, 'timer', type)) {
      view.timer(send, type);
    }
  } else if (source === VIEW) {
    if (permit(view, 'view', type)) {
      // send traps errors, so use {trap: false} option
      view.addEventListener(type, send, NO_TRAP);
    }
  } else {
    if (source === WINDOW) {
      if (permit(view, 'window', type) && typeof window !== 'undefined') {
        sources = [window];
      }
    } else if (typeof document !== 'undefined') {
      if (permit(view, 'selector', type)) {
        sources = Array.from(document.querySelectorAll(source));
      }
    }
    if (!sources) {
      view.warn('Can not resolve event source: ' + source);
    } else {
      for (var i = 0, n = sources.length; i < n; ++i) {
        sources[i].addEventListener(type, send);
      }
      trackEventListener(view, sources, type, send);
    }
  }
  return s;
}

function itemFilter(event) {
  return event.item;
}
function markTarget(event) {
  // grab upstream collector feeding the mark operator
  return event.item.mark.source;
}
function invoke(name) {
  return function (_, event) {
    return event.vega.view().changeset().encode(event.item, name);
  };
}
function vega_view_module_hover (hoverSet, leaveSet) {
  hoverSet = [hoverSet || 'hover'];
  leaveSet = [leaveSet || 'update', hoverSet[0]];

  // invoke hover set upon pointerover
  this.on(this.events('view', 'pointerover', itemFilter), markTarget, invoke(hoverSet));

  // invoke leave set upon pointerout
  this.on(this.events('view', 'pointerout', itemFilter), markTarget, invoke(leaveSet));
  return this;
}

/**
 * Finalize a View instance that is being removed.
 * Cancel any running timers.
 * Remove all external event listeners.
 * Remove any currently displayed tooltip.
 */
function finalize () {
  var tooltip = this._tooltip,
    timers = this._timers,
    handlers = this._handler.handlers(),
    listeners = this._eventListeners,
    n,
    m,
    e,
    h,
    t;
  n = timers.length;
  while (--n >= 0) {
    timers[n].stop();
  }
  n = listeners.length;
  while (--n >= 0) {
    e = listeners[n];
    m = e.sources.length;
    while (--m >= 0) {
      e.sources[m].removeEventListener(e.type, e.handler);
    }
  }
  if (tooltip) {
    tooltip.call(this, this._handler, null, null, null);
  }

  // turn off all registered handlers
  n = handlers.length;
  while (--n >= 0) {
    t = handlers[n].type;
    h = handlers[n].handler;
    this._handler.off(t, h);
  }
  return this;
}

function vega_view_module_element (tag, attr, text) {
  const el = document.createElement(tag);
  for (const key in attr) el.setAttribute(key, attr[key]);
  if (text != null) el.textContent = text;
  return el;
}

const BindClass = 'vega-bind',
  NameClass = 'vega-bind-name',
  RadioClass = 'vega-bind-radio';

/**
 * Bind a signal to an external HTML input element. The resulting two-way
 * binding will propagate input changes to signals, and propagate signal
 * changes to the input element state. If this view instance has no parent
 * element, we assume the view is headless and no bindings are created.
 * @param {Element|string} el - The parent DOM element to which the input
 *   element should be appended as a child. If string-valued, this argument
 *   will be treated as a CSS selector. If null or undefined, the parent
 *   element of this view will be used as the element.
 * @param {object} param - The binding parameters which specify the signal
 *   to bind to, the input element type, and type-specific configuration.
 * @return {View} - This view instance.
 */
function vega_view_module_bind (view, el, binding) {
  if (!el) return;
  const param = binding.param;
  let bind = binding.state;
  if (!bind) {
    bind = binding.state = {
      elements: null,
      active: false,
      set: null,
      update: value => {
        if (value != view.signal(param.signal)) {
          view.runAsync(null, () => {
            bind.source = true;
            view.signal(param.signal, value);
          });
        }
      }
    };
    if (param.debounce) {
      bind.update = debounce(param.debounce, bind.update);
    }
  }
  const create = param.input == null && param.element ? target : generate;
  create(bind, el, param, view);
  if (!bind.active) {
    view.on(view._signals[param.signal], null, () => {
      bind.source ? bind.source = false : bind.set(view.signal(param.signal));
    });
    bind.active = true;
  }
  return bind;
}

/**
 * Bind the signal to an external EventTarget.
 */
function target(bind, node, param, view) {
  const type = param.event || 'input';
  const handler = () => bind.update(node.value);

  // initialize signal value to external input value
  view.signal(param.signal, node.value);

  // listen for changes on the element
  node.addEventListener(type, handler);

  // register with view, so we can remove it upon finalization
  trackEventListener(view, node, type, handler);

  // propagate change to element
  bind.set = value => {
    node.value = value;
    node.dispatchEvent(vega_view_module_event(type));
  };
}
function vega_view_module_event(type) {
  return typeof Event !== 'undefined' ? new Event(type) : {
    type
  };
}

/**
 * Generate an HTML input form element and bind it to a signal.
 */
function generate(bind, el, param, view) {
  const value = view.signal(param.signal);
  const div = vega_view_module_element('div', {
    'class': BindClass
  });
  const wrapper = param.input === 'radio' ? div : div.appendChild(vega_view_module_element('label'));
  wrapper.appendChild(vega_view_module_element('span', {
    'class': NameClass
  }, param.name || param.signal));
  el.appendChild(div);
  let input = vega_view_module_form;
  switch (param.input) {
    case 'checkbox':
      input = vega_view_module_checkbox;
      break;
    case 'select':
      input = vega_view_module_select;
      break;
    case 'radio':
      input = vega_view_module_radio;
      break;
    case 'range':
      input = vega_view_module_range;
      break;
  }
  input(bind, wrapper, param, value);
}

/**
 * Generates an arbitrary input form element.
 * The input type is controlled via user-provided parameters.
 */
function vega_view_module_form(bind, el, param, value) {
  const node = vega_view_module_element('input');
  for (const key in param) {
    if (key !== 'signal' && key !== 'element') {
      node.setAttribute(key === 'input' ? 'type' : key, param[key]);
    }
  }
  node.setAttribute('name', param.signal);
  node.value = value;
  el.appendChild(node);
  node.addEventListener('input', () => bind.update(node.value));
  bind.elements = [node];
  bind.set = value => node.value = value;
}

/**
 * Generates a checkbox input element.
 */
function vega_view_module_checkbox(bind, el, param, value) {
  const attr = {
    type: 'checkbox',
    name: param.signal
  };
  if (value) attr.checked = true;
  const node = vega_view_module_element('input', attr);
  el.appendChild(node);
  node.addEventListener('change', () => bind.update(node.checked));
  bind.elements = [node];
  bind.set = value => node.checked = !!value || null;
}

/**
 * Generates a selection list input element.
 */
function vega_view_module_select(bind, el, param, value) {
  const node = vega_view_module_element('select', {
      name: param.signal
    }),
    labels = param.labels || [];
  param.options.forEach((option, i) => {
    const attr = {
      value: option
    };
    if (valuesEqual(option, value)) attr.selected = true;
    node.appendChild(vega_view_module_element('option', attr, (labels[i] || option) + ''));
  });
  el.appendChild(node);
  node.addEventListener('change', () => {
    bind.update(param.options[node.selectedIndex]);
  });
  bind.elements = [node];
  bind.set = value => {
    for (let i = 0, n = param.options.length; i < n; ++i) {
      if (valuesEqual(param.options[i], value)) {
        node.selectedIndex = i;
        return;
      }
    }
  };
}

/**
 * Generates a radio button group.
 */
function vega_view_module_radio(bind, el, param, value) {
  const group = vega_view_module_element('span', {
      'class': RadioClass
    }),
    labels = param.labels || [];
  el.appendChild(group);
  bind.elements = param.options.map((option, i) => {
    const attr = {
      type: 'radio',
      name: param.signal,
      value: option
    };
    if (valuesEqual(option, value)) attr.checked = true;
    const input = vega_view_module_element('input', attr);
    input.addEventListener('change', () => bind.update(option));
    const label = vega_view_module_element('label', {}, (labels[i] || option) + '');
    label.prepend(input);
    group.appendChild(label);
    return input;
  });
  bind.set = value => {
    const nodes = bind.elements,
      n = nodes.length;
    for (let i = 0; i < n; ++i) {
      if (valuesEqual(nodes[i].value, value)) nodes[i].checked = true;
    }
  };
}

/**
 * Generates a slider input element.
 */
function vega_view_module_range(bind, el, param, value) {
  value = value !== undefined ? value : (+param.max + +param.min) / 2;
  const max = param.max != null ? param.max : Math.max(100, +value) || 100,
    min = param.min || Math.min(0, max, +value) || 0,
    step = param.step || tickStep(min, max, 100);
  const node = vega_view_module_element('input', {
    type: 'range',
    name: param.signal,
    min: min,
    max: max,
    step: step
  });
  node.value = value;
  const span = vega_view_module_element('span', {}, +value);
  el.appendChild(node);
  el.appendChild(span);
  const update = () => {
    span.textContent = node.value;
    bind.update(+node.value);
  };

  // subscribe to both input and change
  node.addEventListener('input', update);
  node.addEventListener('change', update);
  bind.elements = [node];
  bind.set = value => {
    node.value = value;
    span.textContent = value;
  };
}
function valuesEqual(a, b) {
  return a === b || a + '' === b + '';
}

function initializeRenderer (view, r, el, constructor, scaleFactor, opt) {
  r = r || new constructor(view.loader());
  return r.initialize(el, width(view), height(view), vega_view_module_offset(view), scaleFactor, opt).background(view.background());
}

function trap (view, fn) {
  return !fn ? null : function () {
    try {
      fn.apply(this, arguments);
    } catch (error) {
      view.error(error);
    }
  };
}

function initializeHandler (view, prevHandler, el, constructor) {
  // instantiate scenegraph handler
  const handler = new constructor(view.loader(), trap(view, view.tooltip())).scene(view.scenegraph().root).initialize(el, vega_view_module_offset(view), view);

  // transfer event handlers
  if (prevHandler) {
    prevHandler.handlers().forEach(h => {
      handler.on(h.type, h.handler);
    });
  }
  return handler;
}

function vega_view_module_initialize (el, elBind) {
  const view = this,
    type = view._renderType,
    config = view._eventConfig.bind,
    module = renderModule(type);

  // containing dom element
  el = view._el = el ? vega_view_module_lookup(view, el, true) : null;

  // initialize aria attributes
  initializeAria(view);

  // select appropriate renderer & handler
  if (!module) view.error('Unrecognized renderer type: ' + type);
  const Handler = module.handler || CanvasHandler,
    Renderer = el ? module.renderer : module.headless;

  // initialize renderer and input handler
  view._renderer = !Renderer ? null : initializeRenderer(view, view._renderer, el, Renderer);
  view._handler = initializeHandler(view, view._handler, el, Handler);
  view._redraw = true;

  // initialize signal bindings
  if (el && config !== 'none') {
    elBind = elBind ? view._elBind = vega_view_module_lookup(view, elBind, true) : el.appendChild(vega_view_module_element('form', {
      'class': 'vega-bindings'
    }));
    view._bind.forEach(_ => {
      if (_.param.element && config !== 'container') {
        _.element = vega_view_module_lookup(view, _.param.element, !!_.param.input);
      }
    });
    view._bind.forEach(_ => {
      vega_view_module_bind(view, _.element || elBind, _);
    });
  }
  return view;
}
function vega_view_module_lookup(view, el, clear) {
  if (typeof el === 'string') {
    if (typeof document !== 'undefined') {
      el = document.querySelector(el);
      if (!el) {
        view.error('Signal bind element not found: ' + el);
        return null;
      }
    } else {
      view.error('DOM document instance not found.');
      return null;
    }
  }
  if (el && clear) {
    try {
      el.textContent = '';
    } catch (e) {
      el = null;
      view.error(e);
    }
  }
  return el;
}

const vega_view_module_number = _ => +_ || 0;
const paddingObject = _ => ({
  top: _,
  bottom: _,
  left: _,
  right: _
});
function padding (_) {
  return vega_util_module_isObject(_) ? {
    top: vega_view_module_number(_.top),
    bottom: vega_view_module_number(_.bottom),
    left: vega_view_module_number(_.left),
    right: vega_view_module_number(_.right)
  } : paddingObject(vega_view_module_number(_));
}

/**
 * Render the current scene in a headless fashion.
 * This method is asynchronous, returning a Promise instance.
 * @return {Promise} - A Promise that resolves to a renderer.
 */
async function renderHeadless (view, type, scaleFactor, opt) {
  const module = renderModule(type),
    ctr = module && module.headless;
  if (!ctr) vega_util_module_error('Unrecognized renderer type: ' + type);
  await view.runAsync();
  return initializeRenderer(view, null, null, ctr, scaleFactor, opt).renderAsync(view._scenegraph.root);
}

/**
 * Produce an image URL for the visualization. Depending on the type
 * parameter, the generated URL contains data for either a PNG or SVG image.
 * The URL can be used (for example) to download images of the visualization.
 * This method is asynchronous, returning a Promise instance.
 * @param {string} type - The image type. One of 'svg', 'png' or 'canvas'.
 *   The 'canvas' and 'png' types are synonyms for a PNG image.
 * @return {Promise} - A promise that resolves to an image URL.
 */
async function renderToImageURL (type, scaleFactor) {
  if (type !== RenderType.Canvas && type !== RenderType.SVG && type !== RenderType.PNG) {
    vega_util_module_error('Unrecognized image type: ' + type);
  }
  const r = await renderHeadless(this, type, scaleFactor);
  return type === RenderType.SVG ? toBlobURL(r.svg(), 'image/svg+xml') : r.canvas().toDataURL('image/png');
}
function toBlobURL(data, mime) {
  const blob = new Blob([data], {
    type: mime
  });
  return window.URL.createObjectURL(blob);
}

/**
 * Produce a Canvas instance containing a rendered visualization.
 * This method is asynchronous, returning a Promise instance.
 * @return {Promise} - A promise that resolves to a Canvas instance.
 */
async function renderToCanvas (scaleFactor, opt) {
  const r = await renderHeadless(this, RenderType.Canvas, scaleFactor, opt);
  return r.canvas();
}

/**
 * Produce a rendered SVG string of the visualization.
 * This method is asynchronous, returning a Promise instance.
 * @return {Promise} - A promise that resolves to an SVG string.
 */
async function renderToSVG (scaleFactor) {
  const r = await renderHeadless(this, RenderType.SVG, scaleFactor);
  return r.svg();
}

function runtime (view, spec, expr) {
  return vega_runtime_module_context(view, vega_dataflow_module_transforms, functionContext, expr).parse(spec);
}

function vega_view_module_scale(name) {
  var scales = this._runtime.scales;
  if (!vega_util_module_has(scales, name)) {
    vega_util_module_error('Unrecognized scale or projection: ' + name);
  }
  return scales[name].value;
}

var Width = 'width',
  Height = 'height',
  vega_view_module_Padding = 'padding',
  vega_view_module_Skip = {
    skip: true
  };
function viewWidth(view, width) {
  var a = view.autosize(),
    p = view.padding();
  return width - (a && a.contains === vega_view_module_Padding ? p.left + p.right : 0);
}
function viewHeight(view, height) {
  var a = view.autosize(),
    p = view.padding();
  return height - (a && a.contains === vega_view_module_Padding ? p.top + p.bottom : 0);
}
function initializeResize(view) {
  var s = view._signals,
    w = s[Width],
    h = s[Height],
    p = s[vega_view_module_Padding];
  function resetSize() {
    view._autosize = view._resize = 1;
  }

  // respond to width signal
  view._resizeWidth = view.add(null, _ => {
    view._width = _.size;
    view._viewWidth = viewWidth(view, _.size);
    resetSize();
  }, {
    size: w
  });

  // respond to height signal
  view._resizeHeight = view.add(null, _ => {
    view._height = _.size;
    view._viewHeight = viewHeight(view, _.size);
    resetSize();
  }, {
    size: h
  });

  // respond to padding signal
  const resizePadding = view.add(null, resetSize, {
    pad: p
  });

  // set rank to run immediately after source signal
  view._resizeWidth.rank = w.rank + 1;
  view._resizeHeight.rank = h.rank + 1;
  resizePadding.rank = p.rank + 1;
}
function resizeView(viewWidth, viewHeight, width, height, origin, auto) {
  this.runAfter(view => {
    let rerun = 0;

    // reset autosize flag
    view._autosize = 0;

    // width value changed: update signal, skip resize op
    if (view.width() !== width) {
      rerun = 1;
      view.signal(Width, width, vega_view_module_Skip); // set width, skip update calc
      view._resizeWidth.skip(true); // skip width resize handler
    }

    // height value changed: update signal, skip resize op
    if (view.height() !== height) {
      rerun = 1;
      view.signal(Height, height, vega_view_module_Skip); // set height, skip update calc
      view._resizeHeight.skip(true); // skip height resize handler
    }

    // view width changed: update view property, set resize flag
    if (view._viewWidth !== viewWidth) {
      view._resize = 1;
      view._viewWidth = viewWidth;
    }

    // view height changed: update view property, set resize flag
    if (view._viewHeight !== viewHeight) {
      view._resize = 1;
      view._viewHeight = viewHeight;
    }

    // origin changed: update view property, set resize flag
    if (view._origin[0] !== origin[0] || view._origin[1] !== origin[1]) {
      view._resize = 1;
      view._origin = origin;
    }

    // run dataflow on width/height signal change
    if (rerun) view.run('enter');
    if (auto) view.runAfter(v => v.resize());
  }, false, 1);
}

/**
 * Get the current view state, consisting of signal values and/or data sets.
 * @param {object} [options] - Options flags indicating which state to export.
 *   If unspecified, all signals and data sets will be exported.
 * @param {function(string, Operator):boolean} [options.signals] - Optional
 *   predicate function for testing if a signal should be included in the
 *   exported state. If unspecified, all signals will be included, except for
 *   those named 'parent' or those which refer to a Transform value.
 * @param {function(string, object):boolean} [options.data] - Optional
 *   predicate function for testing if a data set's input should be included
 *   in the exported state. If unspecified, all data sets that have been
 *   explicitly modified will be included.
 * @param {boolean} [options.recurse=true] - Flag indicating if the exported
 *   state should recursively include state from group mark sub-contexts.
 * @return {object} - An object containing the exported state values.
 */
function vega_view_module_getState(options) {
  return this._runtime.getState(options || {
    data: dataTest,
    signals: signalTest,
    recurse: true
  });
}
function dataTest(name, data) {
  return data.modified && vega_util_module_isArray(data.input.value) && !name.startsWith('_:vega:_');
}
function signalTest(name, op) {
  return !(name === 'parent' || op instanceof vega_dataflow_module_transforms.proxy);
}

/**
 * Sets the current view state and updates the view by invoking run.
 * @param {object} state - A state object containing signal and/or
 *   data set values, following the format used by the getState method.
 * @return {View} - This view instance.
 */
function vega_view_module_setState(state) {
  this.runAsync(null, v => {
    v._trigger = false;
    v._runtime.setState(state);
  }, v => {
    v._trigger = true;
  });
  return this;
}

function vega_view_module_timer (callback, delay) {
  function tick(elapsed) {
    callback({
      timestamp: Date.now(),
      elapsed: elapsed
    });
  }
  this._timers.push(src_interval(tick, delay));
}

function vega_view_module_defaultTooltip (handler, event, item, value) {
  const el = handler.element();
  if (el) el.setAttribute('title', formatTooltip(value));
}
function formatTooltip(value) {
  return value == null ? '' : vega_util_module_isArray(value) ? formatArray(value) : vega_util_module_isObject(value) && !vega_util_module_isDate(value) ? formatObject(value) : value + '';
}
function formatObject(obj) {
  return Object.keys(obj).map(key => {
    const v = obj[key];
    return key + ': ' + (vega_util_module_isArray(v) ? formatArray(v) : vega_view_module_formatValue(v));
  }).join('\n');
}
function formatArray(value) {
  return '[' + value.map(vega_view_module_formatValue).join(', ') + ']';
}
function vega_view_module_formatValue(value) {
  return vega_util_module_isArray(value) ? '[\u2026]' : vega_util_module_isObject(value) && !vega_util_module_isDate(value) ? '{\u2026}' : value;
}

function watchPixelRatio () {
  // based on https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes
  if (this.renderer() === 'canvas' && this._renderer._canvas) {
    let remove = null;
    const updatePixelRatio = () => {
      if (remove != null) {
        remove();
      }
      const media = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
      media.addEventListener('change', updatePixelRatio);
      remove = () => {
        media.removeEventListener('change', updatePixelRatio);
      };
      this._renderer._canvas.getContext('2d').pixelRatio = window.devicePixelRatio || 1;
      this._redraw = true;
      this._resize = 1;
      this.resize().runAsync();
    };
    updatePixelRatio();
  }
}

/**
 * Create a new View instance from a Vega dataflow runtime specification.
 * The generated View will not immediately be ready for display. Callers
 * should also invoke the initialize method (e.g., to set the parent
 * DOM element in browser-based deployment) and then invoke the run
 * method to evaluate the dataflow graph. Rendering will automatically
 * be performed upon dataflow runs.
 * @constructor
 * @param {object} spec - The Vega dataflow runtime specification.
 */
function View(spec, options) {
  const view = this;
  options = options || {};
  Dataflow.call(view);
  if (options.loader) view.loader(options.loader);
  if (options.logger) view.logger(options.logger);
  if (options.logLevel != null) view.logLevel(options.logLevel);
  if (options.locale || spec.locale) {
    const loc = extend({}, spec.locale, options.locale);
    view.locale(vega_format_module_locale(loc.number, loc.time));
  }
  view._el = null;
  view._elBind = null;
  view._renderType = options.renderer || RenderType.Canvas;
  view._scenegraph = new Scenegraph();
  const root = view._scenegraph.root;

  // initialize renderer, handler and event management
  view._renderer = null;
  view._tooltip = options.tooltip || vega_view_module_defaultTooltip, view._redraw = true;
  view._handler = new CanvasHandler().scene(root);
  view._globalCursor = false;
  view._preventDefault = false;
  view._timers = [];
  view._eventListeners = [];
  view._resizeListeners = [];

  // initialize event configuration
  view._eventConfig = initializeEventConfig(spec.eventConfig);
  view.globalCursor(view._eventConfig.globalCursor);

  // initialize dataflow graph
  const ctx = runtime(view, spec, options.expr);
  view._runtime = ctx;
  view._signals = ctx.signals;
  view._bind = (spec.bindings || []).map(_ => ({
    state: null,
    param: extend({}, _)
  }));

  // initialize scenegraph
  if (ctx.root) ctx.root.set(root);
  root.source = ctx.data.root.input;
  view.pulse(ctx.data.root.input, view.changeset().insert(root.items));

  // initialize view size
  view._width = view.width();
  view._height = view.height();
  view._viewWidth = viewWidth(view, view._width);
  view._viewHeight = viewHeight(view, view._height);
  view._origin = [0, 0];
  view._resize = 0;
  view._autosize = 1;
  initializeResize(view);

  // initialize background color
  vega_view_module_background(view);

  // initialize cursor
  cursor(view);

  // initialize view description
  view.description(spec.description);

  // initialize hover proessing, if requested
  if (options.hover) view.hover();

  // initialize DOM container(s) and renderer
  if (options.container) view.initialize(options.container, options.bind);
  if (options.watchPixelRatio) view._watchPixelRatio();
}
function lookupSignal(view, name) {
  return vega_util_module_has(view._signals, name) ? view._signals[name] : vega_util_module_error('Unrecognized signal name: ' + $(name));
}
function findOperatorHandler(op, handler) {
  const h = (op._targets || []).filter(op => op._update && op._update.handler === handler);
  return h.length ? h[0] : null;
}
function addOperatorListener(view, name, op, handler) {
  let h = findOperatorHandler(op, handler);
  if (!h) {
    h = trap(view, () => handler(name, op.value));
    h.handler = handler;
    view.on(op, null, h);
  }
  return view;
}
function removeOperatorListener(view, op, handler) {
  const h = findOperatorHandler(op, handler);
  if (h) op._targets.remove(h);
  return view;
}
inherits(View, Dataflow, {
  // -- DATAFLOW / RENDERING ----

  async evaluate(encode, prerun, postrun) {
    // evaluate dataflow and prerun
    await Dataflow.prototype.evaluate.call(this, encode, prerun);

    // render as needed
    if (this._redraw || this._resize) {
      try {
        if (this._renderer) {
          if (this._resize) {
            this._resize = 0;
            resizeRenderer(this);
          }
          await this._renderer.renderAsync(this._scenegraph.root);
        }
        this._redraw = false;
      } catch (e) {
        this.error(e);
      }
    }

    // evaluate postrun
    if (postrun) asyncCallback(this, postrun);
    return this;
  },
  dirty(item) {
    this._redraw = true;
    this._renderer && this._renderer.dirty(item);
  },
  // -- GET / SET ----

  description(text) {
    if (arguments.length) {
      const desc = text != null ? text + '' : null;
      if (desc !== this._desc) ariaLabel(this._el, this._desc = desc);
      return this;
    }
    return this._desc;
  },
  container() {
    return this._el;
  },
  scenegraph() {
    return this._scenegraph;
  },
  origin() {
    return this._origin.slice();
  },
  signal(name, value, options) {
    const op = lookupSignal(this, name);
    return arguments.length === 1 ? op.value : this.update(op, value, options);
  },
  width(_) {
    return arguments.length ? this.signal('width', _) : this.signal('width');
  },
  height(_) {
    return arguments.length ? this.signal('height', _) : this.signal('height');
  },
  padding(_) {
    return arguments.length ? this.signal('padding', padding(_)) : padding(this.signal('padding'));
  },
  autosize(_) {
    return arguments.length ? this.signal('autosize', _) : this.signal('autosize');
  },
  background(_) {
    return arguments.length ? this.signal('background', _) : this.signal('background');
  },
  renderer(type) {
    if (!arguments.length) return this._renderType;
    if (!renderModule(type)) vega_util_module_error('Unrecognized renderer type: ' + type);
    if (type !== this._renderType) {
      this._renderType = type;
      this._resetRenderer();
    }
    return this;
  },
  tooltip(handler) {
    if (!arguments.length) return this._tooltip;
    if (handler !== this._tooltip) {
      this._tooltip = handler;
      this._resetRenderer();
    }
    return this;
  },
  loader(loader) {
    if (!arguments.length) return this._loader;
    if (loader !== this._loader) {
      Dataflow.prototype.loader.call(this, loader);
      this._resetRenderer();
    }
    return this;
  },
  resize() {
    // set flag to perform autosize
    this._autosize = 1;
    // touch autosize signal to ensure top-level ViewLayout runs
    return this.touch(lookupSignal(this, 'autosize'));
  },
  _resetRenderer() {
    if (this._renderer) {
      this._renderer = null;
      this.initialize(this._el, this._elBind);
    }
  },
  // -- SIZING ----
  _resizeView: resizeView,
  // -- EVENT HANDLING ----

  addEventListener(type, handler, options) {
    let callback = handler;
    if (!(options && options.trap === false)) {
      // wrap callback in error handler
      callback = trap(this, handler);
      callback.raw = handler;
    }
    this._handler.on(type, callback);
    return this;
  },
  removeEventListener(type, handler) {
    var handlers = this._handler.handlers(type),
      i = handlers.length,
      h,
      t;

    // search registered handlers, remove if match found
    while (--i >= 0) {
      t = handlers[i].type;
      h = handlers[i].handler;
      if (type === t && (handler === h || handler === h.raw)) {
        this._handler.off(t, h);
        break;
      }
    }
    return this;
  },
  addResizeListener(handler) {
    const l = this._resizeListeners;
    if (!l.includes(handler)) {
      // add handler if it isn't already registered
      // note: error trapping handled elsewhere, so
      // no need to wrap handlers here
      l.push(handler);
    }
    return this;
  },
  removeResizeListener(handler) {
    var l = this._resizeListeners,
      i = l.indexOf(handler);
    if (i >= 0) {
      l.splice(i, 1);
    }
    return this;
  },
  addSignalListener(name, handler) {
    return addOperatorListener(this, name, lookupSignal(this, name), handler);
  },
  removeSignalListener(name, handler) {
    return removeOperatorListener(this, lookupSignal(this, name), handler);
  },
  addDataListener(name, handler) {
    return addOperatorListener(this, name, dataref(this, name).values, handler);
  },
  removeDataListener(name, handler) {
    return removeOperatorListener(this, dataref(this, name).values, handler);
  },
  globalCursor(_) {
    if (arguments.length) {
      if (this._globalCursor !== !!_) {
        const prev = setCursor(this, null); // clear previous cursor
        this._globalCursor = !!_;
        if (prev) setCursor(this, prev); // swap cursor
      }
      return this;
    } else {
      return this._globalCursor;
    }
  },
  preventDefault(_) {
    if (arguments.length) {
      this._preventDefault = _;
      return this;
    } else {
      return this._preventDefault;
    }
  },
  timer: vega_view_module_timer,
  events: vega_view_module_events,
  finalize,
  hover: vega_view_module_hover,
  // -- DATA ----
  data: vega_view_module_data,
  change,
  insert: vega_view_module_insert,
  remove: vega_view_module_remove,
  // -- SCALES --
  scale: vega_view_module_scale,
  // -- INITIALIZATION ----
  initialize: vega_view_module_initialize,
  // -- HEADLESS RENDERING ----
  toImageURL: renderToImageURL,
  toCanvas: renderToCanvas,
  toSVG: renderToSVG,
  // -- SAVE / RESTORE STATE ----
  getState: vega_view_module_getState,
  setState: vega_view_module_setState,
  // RE-RENDER ON ZOOM
  _watchPixelRatio: watchPixelRatio
});



;// ../../node_modules/vega-event-selector/build/vega-event-selector.module.js
const vega_event_selector_module_VIEW = 'view',
  LBRACK = '[',
  RBRACK = ']',
  LBRACE = '{',
  RBRACE = '}',
  COLON = ':',
  COMMA = ',',
  NAME = '@',
  GT = '>',
  vega_event_selector_module_ILLEGAL = /[[\]{}]/,
  DEFAULT_MARKS = {
    '*': 1,
    arc: 1,
    area: 1,
    group: 1,
    image: 1,
    line: 1,
    path: 1,
    rect: 1,
    rule: 1,
    shape: 1,
    symbol: 1,
    text: 1,
    trail: 1
  };
let DEFAULT_SOURCE, MARKS;

/**
 * Parse an event selector string.
 * Returns an array of event stream definitions.
 */
function eventSelector (selector, source, marks) {
  DEFAULT_SOURCE = source || vega_event_selector_module_VIEW;
  MARKS = marks || DEFAULT_MARKS;
  return parseMerge(selector.trim()).map(parseSelector);
}
function isMarkType(type) {
  return MARKS[type];
}
function vega_event_selector_module_find(s, i, endChar, pushChar, popChar) {
  const n = s.length;
  let count = 0,
    c;
  for (; i < n; ++i) {
    c = s[i];
    if (!count && c === endChar) return i;else if (popChar && popChar.indexOf(c) >= 0) --count;else if (pushChar && pushChar.indexOf(c) >= 0) ++count;
  }
  return i;
}
function parseMerge(s) {
  const output = [],
    n = s.length;
  let start = 0,
    i = 0;
  while (i < n) {
    i = vega_event_selector_module_find(s, i, COMMA, LBRACK + LBRACE, RBRACK + RBRACE);
    output.push(s.substring(start, i).trim());
    start = ++i;
  }
  if (output.length === 0) {
    throw 'Empty event selector: ' + s;
  }
  return output;
}
function parseSelector(s) {
  return s[0] === '[' ? parseBetween(s) : vega_event_selector_module_parseStream(s);
}
function parseBetween(s) {
  const n = s.length;
  let i = 1,
    b;
  i = vega_event_selector_module_find(s, i, RBRACK, LBRACK, RBRACK);
  if (i === n) {
    throw 'Empty between selector: ' + s;
  }
  b = parseMerge(s.substring(1, i));
  if (b.length !== 2) {
    throw 'Between selector must have two elements: ' + s;
  }
  s = s.slice(i + 1).trim();
  if (s[0] !== GT) {
    throw 'Expected \'>\' after between selector: ' + s;
  }
  b = b.map(parseSelector);
  const stream = parseSelector(s.slice(1).trim());
  if (stream.between) {
    return {
      between: b,
      stream: stream
    };
  } else {
    stream.between = b;
  }
  return stream;
}
function vega_event_selector_module_parseStream(s) {
  const stream = {
      source: DEFAULT_SOURCE
    },
    source = [];
  let throttle = [0, 0],
    markname = 0,
    start = 0,
    n = s.length,
    i = 0,
    j,
    filter;

  // extract throttle from end
  if (s[n - 1] === RBRACE) {
    i = s.lastIndexOf(LBRACE);
    if (i >= 0) {
      try {
        throttle = parseThrottle(s.substring(i + 1, n - 1));
      } catch (e) {
        throw 'Invalid throttle specification: ' + s;
      }
      s = s.slice(0, i).trim();
      n = s.length;
    } else throw 'Unmatched right brace: ' + s;
    i = 0;
  }
  if (!n) throw s;

  // set name flag based on first char
  if (s[0] === NAME) markname = ++i;

  // extract first part of multi-part stream selector
  j = vega_event_selector_module_find(s, i, COLON);
  if (j < n) {
    source.push(s.substring(start, j).trim());
    start = i = ++j;
  }

  // extract remaining part of stream selector
  i = vega_event_selector_module_find(s, i, LBRACK);
  if (i === n) {
    source.push(s.substring(start, n).trim());
  } else {
    source.push(s.substring(start, i).trim());
    filter = [];
    start = ++i;
    if (start === n) throw 'Unmatched left bracket: ' + s;
  }

  // extract filters
  while (i < n) {
    i = vega_event_selector_module_find(s, i, RBRACK);
    if (i === n) throw 'Unmatched left bracket: ' + s;
    filter.push(s.substring(start, i).trim());
    if (i < n - 1 && s[++i] !== LBRACK) throw 'Expected left bracket: ' + s;
    start = ++i;
  }

  // marshall event stream specification
  if (!(n = source.length) || vega_event_selector_module_ILLEGAL.test(source[n - 1])) {
    throw 'Invalid event selector: ' + s;
  }
  if (n > 1) {
    stream.type = source[1];
    if (markname) {
      stream.markname = source[0].slice(1);
    } else if (isMarkType(source[0])) {
      stream.marktype = source[0];
    } else {
      stream.source = source[0];
    }
  } else {
    stream.type = source[0];
  }
  if (stream.type.slice(-1) === '!') {
    stream.consume = true;
    stream.type = stream.type.slice(0, -1);
  }
  if (filter != null) stream.filter = filter;
  if (throttle[0]) stream.throttle = throttle[0];
  if (throttle[1]) stream.debounce = throttle[1];
  return stream;
}
function parseThrottle(s) {
  const a = s.split(COMMA);
  if (!s.length || a.length > 2) throw s;
  return a.map(_ => {
    const x = +_;
    if (x !== x) throw s;
    return x;
  });
}



;// ../../node_modules/vega-parser/build/vega-parser.module.js






function parseAutosize (spec) {
  return vega_util_module_isObject(spec) ? spec : {
    type: spec || 'pad'
  };
}

const vega_parser_module_number = _ => +_ || 0;
const vega_parser_module_paddingObject = _ => ({
  top: _,
  bottom: _,
  left: _,
  right: _
});
function parsePadding (spec) {
  return !vega_util_module_isObject(spec) ? vega_parser_module_paddingObject(vega_parser_module_number(spec)) : spec.signal ? spec : {
    top: vega_parser_module_number(spec.top),
    bottom: vega_parser_module_number(spec.bottom),
    left: vega_parser_module_number(spec.left),
    right: vega_parser_module_number(spec.right)
  };
}

const encoder = _ => vega_util_module_isObject(_) && !vega_util_module_isArray(_) ? extend({}, _) : {
  value: _
};
function addEncode(object, name, value, set) {
  if (value != null) {
    const isEncoder = vega_util_module_isObject(value) && !vega_util_module_isArray(value) || vega_util_module_isArray(value) && value.length && vega_util_module_isObject(value[0]);

    // Always assign signal to update, even if the signal is from the enter block
    if (isEncoder) {
      object.update[name] = value;
    } else {
      object[set || 'enter'][name] = {
        value: value
      };
    }
    return 1;
  } else {
    return 0;
  }
}
function addEncoders(object, enter, update) {
  for (const name in enter) {
    addEncode(object, name, enter[name]);
  }
  for (const name in update) {
    addEncode(object, name, update[name], 'update');
  }
}
function extendEncode(encode, extra, skip) {
  for (const name in extra) {
    if (skip && vega_util_module_has(skip, name)) continue;
    encode[name] = extend(encode[name] || {}, extra[name]);
  }
  return encode;
}
function vega_parser_module_has(key, encode) {
  return encode && (encode.enter && encode.enter[key] || encode.update && encode.update[key]);
}

const MarkRole = 'mark';
const vega_parser_module_FrameRole = 'frame';
const vega_parser_module_ScopeRole = 'scope';
const vega_parser_module_AxisRole = 'axis';
const AxisDomainRole = 'axis-domain';
const AxisGridRole = 'axis-grid';
const AxisLabelRole = 'axis-label';
const AxisTickRole = 'axis-tick';
const AxisTitleRole = 'axis-title';
const vega_parser_module_LegendRole = 'legend';
const LegendBandRole = 'legend-band';
const LegendEntryRole = 'legend-entry';
const LegendGradientRole = 'legend-gradient';
const LegendLabelRole = 'legend-label';
const LegendSymbolRole = 'legend-symbol';
const LegendTitleRole = 'legend-title';
const vega_parser_module_TitleRole = 'title';
const TitleTextRole = 'title-text';
const TitleSubtitleRole = 'title-subtitle';

function applyDefaults (encode, type, role, style, config) {
  const defaults = {},
    enter = {};
  let update, key, skip, props;

  // if text mark, apply global lineBreak settings (#2370)
  key = 'lineBreak';
  if (type === 'text' && config[key] != null && !vega_parser_module_has(key, encode)) {
    applyDefault(defaults, key, config[key]);
  }

  // ignore legend and axis roles
  if (role == 'legend' || String(role).startsWith('axis')) {
    role = null;
  }

  // resolve mark config
  props = role === vega_parser_module_FrameRole ? config.group : role === MarkRole ? extend({}, config.mark, config[type]) : null;
  for (key in props) {
    // do not apply defaults if relevant fields are defined
    skip = vega_parser_module_has(key, encode) || (key === 'fill' || key === 'stroke') && (vega_parser_module_has('fill', encode) || vega_parser_module_has('stroke', encode));
    if (!skip) applyDefault(defaults, key, props[key]);
  }

  // resolve styles, apply with increasing precedence
  vega_util_module_array(style).forEach(name => {
    const props = config.style && config.style[name];
    for (const key in props) {
      if (!vega_parser_module_has(key, encode)) {
        applyDefault(defaults, key, props[key]);
      }
    }
  });
  encode = extend({}, encode); // defensive copy
  for (key in defaults) {
    props = defaults[key];
    if (props.signal) {
      (update = update || {})[key] = props;
    } else {
      enter[key] = props;
    }
  }
  encode.enter = extend(enter, encode.enter);
  if (update) encode.update = extend(update, encode.update);
  return encode;
}
function applyDefault(defaults, key, value) {
  defaults[key] = value && value.signal ? {
    signal: value.signal
  } : {
    value: value
  };
}

const scaleRef = scale => vega_util_module_isString(scale) ? $(scale) : scale.signal ? `(${scale.signal})` : vega_parser_module_field(scale);
function entry$1(enc) {
  if (enc.gradient != null) {
    return vega_parser_module_gradient(enc);
  }
  let value = enc.signal ? `(${enc.signal})` : enc.color ? vega_parser_module_color(enc.color) : enc.field != null ? vega_parser_module_field(enc.field) : enc.value !== undefined ? $(enc.value) : undefined;
  if (enc.scale != null) {
    value = vega_parser_module_scale(enc, value);
  }
  if (value === undefined) {
    value = null;
  }
  if (enc.exponent != null) {
    value = `pow(${value},${property(enc.exponent)})`;
  }
  if (enc.mult != null) {
    value += `*${property(enc.mult)}`;
  }
  if (enc.offset != null) {
    value += `+${property(enc.offset)}`;
  }
  if (enc.round) {
    value = `round(${value})`;
  }
  return value;
}
const _color = (type, x, y, z) => `(${type}(${[x, y, z].map(entry$1).join(',')})+'')`;
function vega_parser_module_color(enc) {
  return enc.c ? _color('hcl', enc.h, enc.c, enc.l) : enc.h || enc.s ? _color('hsl', enc.h, enc.s, enc.l) : enc.l || enc.a ? _color('lab', enc.l, enc.a, enc.b) : enc.r || enc.g || enc.b ? _color('rgb', enc.r, enc.g, enc.b) : null;
}
function vega_parser_module_gradient(enc) {
  // map undefined to null; expression lang does not allow undefined
  const args = [enc.start, enc.stop, enc.count].map(_ => _ == null ? null : $(_));

  // trim null inputs from the end
  while (args.length && peek(args) == null) args.pop();
  args.unshift(scaleRef(enc.gradient));
  return `gradient(${args.join(',')})`;
}
function property(property) {
  return vega_util_module_isObject(property) ? '(' + entry$1(property) + ')' : property;
}
function vega_parser_module_field(ref) {
  return resolveField(vega_util_module_isObject(ref) ? ref : {
    datum: ref
  });
}
function resolveField(ref) {
  let object, level, field;
  if (ref.signal) {
    object = 'datum';
    field = ref.signal;
  } else if (ref.group || ref.parent) {
    level = Math.max(1, ref.level || 1);
    object = 'item';
    while (level-- > 0) {
      object += '.mark.group';
    }
    if (ref.parent) {
      field = ref.parent;
      object += '.datum';
    } else {
      field = ref.group;
    }
  } else if (ref.datum) {
    object = 'datum';
    field = ref.datum;
  } else {
    vega_util_module_error('Invalid field reference: ' + $(ref));
  }
  if (!ref.signal) {
    field = vega_util_module_isString(field) ? splitAccessPath(field).map($).join('][') : resolveField(field);
  }
  return object + '[' + field + ']';
}
function vega_parser_module_scale(enc, value) {
  const scale = scaleRef(enc.scale);
  if (enc.range != null) {
    // pull value from scale range
    value = `lerp(_range(${scale}), ${+enc.range})`;
  } else {
    // run value through scale and/or pull scale bandwidth
    if (value !== undefined) value = `_scale(${scale}, ${value})`;
    if (enc.band) {
      value = (value ? value + '+' : '') + `_bandwidth(${scale})` + (+enc.band === 1 ? '' : '*' + property(enc.band));
      if (enc.extra) {
        // include logic to handle extraneous elements
        value = `(datum.extra ? _scale(${scale}, datum.extra.value) : ${value})`;
      }
    }
    if (value == null) value = '0';
  }
  return value;
}

function vega_parser_module_rule (enc) {
  let code = '';
  enc.forEach(rule => {
    const value = entry$1(rule);
    code += rule.test ? `(${rule.test})?${value}:` : value;
  });

  // if no else clause, terminate with null (#1366)
  if (peek(code) === ':') {
    code += 'null';
  }
  return code;
}

function parseEncode (encode, type, role, style, scope, params) {
  const enc = {};
  params = params || {};
  params.encoders = {
    $encode: enc
  };
  encode = applyDefaults(encode, type, role, style, scope.config);
  for (const key in encode) {
    enc[key] = parseBlock(encode[key], type, params, scope);
  }
  return params;
}
function parseBlock(block, marktype, params, scope) {
  const channels = {},
    fields = {};
  for (const name in block) {
    if (block[name] != null) {
      // skip any null entries
      channels[name] = parse$1(expr(block[name]), scope, params, fields);
    }
  }
  return {
    $expr: {
      marktype,
      channels
    },
    $fields: Object.keys(fields),
    $output: Object.keys(block)
  };
}
function expr(enc) {
  return vega_util_module_isArray(enc) ? vega_parser_module_rule(enc) : entry$1(enc);
}
function parse$1(code, scope, params, fields) {
  const expr = vega_functions_module_parser(code, scope);
  expr.$fields.forEach(name => fields[name] = 1);
  extend(params, expr.$params);
  return expr.$expr;
}

const OUTER = 'outer',
  OUTER_INVALID = ['value', 'update', 'init', 'react', 'bind'];
function outerError(prefix, name) {
  vega_util_module_error(prefix + ' for "outer" push: ' + $(name));
}
function parseSignal (signal, scope) {
  const name = signal.name;
  if (signal.push === OUTER) {
    // signal must already be defined, raise error if not
    if (!scope.signals[name]) outerError('No prior signal definition', name);
    // signal push must not use properties reserved for standard definition
    OUTER_INVALID.forEach(prop => {
      if (signal[prop] !== undefined) outerError('Invalid property ', prop);
    });
  } else {
    // define a new signal in the current scope
    const op = scope.addSignal(name, signal.value);
    if (signal.react === false) op.react = false;
    if (signal.bind) scope.addBinding(name, signal.bind);
  }
}

function Entry(type, value, params, parent) {
  this.id = -1;
  this.type = type;
  this.value = value;
  this.params = params;
  if (parent) this.parent = parent;
}
function entry(type, value, params, parent) {
  return new Entry(type, value, params, parent);
}
function operator(value, params) {
  return entry('operator', value, params);
}

// -----

function vega_parser_module_ref(op) {
  const ref = {
    $ref: op.id
  };
  // if operator not yet registered, cache ref to resolve later
  if (op.id < 0) (op.refs = op.refs || []).push(ref);
  return ref;
}
function fieldRef$1(field, name) {
  return name ? {
    $field: field,
    $name: name
  } : {
    $field: field
  };
}
const keyFieldRef = fieldRef$1('key');
function compareRef(fields, orders) {
  return {
    $compare: fields,
    $order: orders
  };
}
function keyRef(fields, flat) {
  const ref = {
    $key: fields
  };
  if (flat) ref.$flat = true;
  return ref;
}

// -----

const Ascending = 'ascending';
const Descending = 'descending';
function sortKey(sort) {
  return !vega_util_module_isObject(sort) ? '' : (sort.order === Descending ? '-' : '+') + aggrField(sort.op, sort.field);
}
function aggrField(op, field) {
  return (op && op.signal ? '$' + op.signal : op || '') + (op && field ? '_' : '') + (field && field.signal ? '$' + field.signal : field || '');
}

// -----

const Scope$1 = 'scope';
const vega_parser_module_View = 'view';
function isSignal(_) {
  return _ && _.signal;
}
function isExpr$1(_) {
  return _ && _.expr;
}
function hasSignal(_) {
  if (isSignal(_)) return true;
  if (vega_util_module_isObject(_)) for (const key in _) {
    if (hasSignal(_[key])) return true;
  }
  return false;
}
function vega_parser_module_value(specValue, defaultValue) {
  return specValue != null ? specValue : defaultValue;
}
function deref(v) {
  return v && v.signal || v;
}

const vega_parser_module_Timer = 'timer';
function vega_parser_module_parseStream(stream, scope) {
  const method = stream.merge ? mergeStream : stream.stream ? nestedStream : stream.type ? eventStream : vega_util_module_error('Invalid stream specification: ' + $(stream));
  return method(stream, scope);
}
function eventSource(source) {
  return source === Scope$1 ? vega_parser_module_View : source || vega_parser_module_View;
}
function mergeStream(stream, scope) {
  const list = stream.merge.map(s => vega_parser_module_parseStream(s, scope)),
    entry = streamParameters({
      merge: list
    }, stream, scope);
  return scope.addStream(entry).id;
}
function nestedStream(stream, scope) {
  const id = vega_parser_module_parseStream(stream.stream, scope),
    entry = streamParameters({
      stream: id
    }, stream, scope);
  return scope.addStream(entry).id;
}
function eventStream(stream, scope) {
  let id;
  if (stream.type === vega_parser_module_Timer) {
    id = scope.event(vega_parser_module_Timer, stream.throttle);
    stream = {
      between: stream.between,
      filter: stream.filter
    };
  } else {
    id = scope.event(eventSource(stream.source), stream.type);
  }
  const entry = streamParameters({
    stream: id
  }, stream, scope);
  return Object.keys(entry).length === 1 ? id : scope.addStream(entry).id;
}
function streamParameters(entry, stream, scope) {
  let param = stream.between;
  if (param) {
    if (param.length !== 2) {
      vega_util_module_error('Stream "between" parameter must have 2 entries: ' + $(stream));
    }
    entry.between = [vega_parser_module_parseStream(param[0], scope), vega_parser_module_parseStream(param[1], scope)];
  }
  param = stream.filter ? [].concat(stream.filter) : [];
  if (stream.marktype || stream.markname || stream.markrole) {
    // add filter for mark type, name and/or role
    param.push(filterMark(stream.marktype, stream.markname, stream.markrole));
  }
  if (stream.source === Scope$1) {
    // add filter to limit events from sub-scope only
    param.push('inScope(event.item)');
  }
  if (param.length) {
    entry.filter = vega_functions_module_parser('(' + param.join(')&&(') + ')', scope).$expr;
  }
  if ((param = stream.throttle) != null) {
    entry.throttle = +param;
  }
  if ((param = stream.debounce) != null) {
    entry.debounce = +param;
  }
  if (stream.consume) {
    entry.consume = true;
  }
  return entry;
}
function filterMark(type, name, role) {
  const item = 'event.item';
  return item + (type && type !== '*' ? '&&' + item + '.mark.marktype===\'' + type + '\'' : '') + (role ? '&&' + item + '.mark.role===\'' + role + '\'' : '') + (name ? '&&' + item + '.mark.name===\'' + name + '\'' : '');
}

// bypass expression parser for internal operator references
const OP_VALUE_EXPR = {
  code: '_.$value',
  ast: {
    type: 'Identifier',
    value: 'value'
  }
};
function vega_parser_module_parseUpdate (spec, scope, target) {
  const encode = spec.encode,
    entry = {
      target: target
    };
  let events = spec.events,
    update = spec.update,
    sources = [];
  if (!events) {
    vega_util_module_error('Signal update missing events specification.');
  }

  // interpret as an event selector string
  if (vega_util_module_isString(events)) {
    events = eventSelector(events, scope.isSubscope() ? Scope$1 : vega_parser_module_View);
  }

  // separate event streams from signal updates
  events = vega_util_module_array(events).filter(s => s.signal || s.scale ? (sources.push(s), 0) : 1);

  // merge internal operator listeners
  if (sources.length > 1) {
    sources = [mergeSources(sources)];
  }

  // merge event streams, include as source
  if (events.length) {
    sources.push(events.length > 1 ? {
      merge: events
    } : events[0]);
  }
  if (encode != null) {
    if (update) vega_util_module_error('Signal encode and update are mutually exclusive.');
    update = 'encode(item(),' + $(encode) + ')';
  }

  // resolve update value
  entry.update = vega_util_module_isString(update) ? vega_functions_module_parser(update, scope) : update.expr != null ? vega_functions_module_parser(update.expr, scope) : update.value != null ? update.value : update.signal != null ? {
    $expr: OP_VALUE_EXPR,
    $params: {
      $value: scope.signalRef(update.signal)
    }
  } : vega_util_module_error('Invalid signal update specification.');
  if (spec.force) {
    entry.options = {
      force: true
    };
  }
  sources.forEach(source => scope.addUpdate(extend(streamSource(source, scope), entry)));
}
function streamSource(stream, scope) {
  return {
    source: stream.signal ? scope.signalRef(stream.signal) : stream.scale ? scope.scaleRef(stream.scale) : vega_parser_module_parseStream(stream, scope)
  };
}
function mergeSources(sources) {
  return {
    signal: '[' + sources.map(s => s.scale ? 'scale("' + s.scale + '")' : s.signal) + ']'
  };
}

function parseSignalUpdates (signal, scope) {
  const op = scope.getSignal(signal.name);
  let expr = signal.update;
  if (signal.init) {
    if (expr) {
      vega_util_module_error('Signals can not include both init and update expressions.');
    } else {
      expr = signal.init;
      op.initonly = true;
    }
  }
  if (expr) {
    expr = vega_functions_module_parser(expr, scope);
    op.update = expr.$expr;
    op.params = expr.$params;
  }
  if (signal.on) {
    signal.on.forEach(_ => vega_parser_module_parseUpdate(_, scope, op.id));
  }
}

const vega_parser_module_transform = name => (params, value, parent) => entry(name, value, params || undefined, parent);
const vega_parser_module_Aggregate = vega_parser_module_transform('aggregate');
const vega_parser_module_AxisTicks = vega_parser_module_transform('axisticks');
const vega_parser_module_Bound = vega_parser_module_transform('bound');
const vega_parser_module_Collect = vega_parser_module_transform('collect');
const vega_parser_module_Compare = vega_parser_module_transform('compare');
const vega_parser_module_DataJoin = vega_parser_module_transform('datajoin');
const vega_parser_module_Encode = vega_parser_module_transform('encode');
const vega_parser_module_Expression = vega_parser_module_transform('expression');
const vega_parser_module_Facet = vega_parser_module_transform('facet');
const vega_parser_module_Field = vega_parser_module_transform('field');
const vega_parser_module_Key = vega_parser_module_transform('key');
const vega_parser_module_LegendEntries = vega_parser_module_transform('legendentries');
const vega_parser_module_Load = vega_parser_module_transform('load');
const vega_parser_module_Mark = vega_parser_module_transform('mark');
const vega_parser_module_MultiExtent = vega_parser_module_transform('multiextent');
const vega_parser_module_MultiValues = vega_parser_module_transform('multivalues');
const vega_parser_module_Overlap = vega_parser_module_transform('overlap');
const vega_parser_module_Params = vega_parser_module_transform('params');
const vega_parser_module_PreFacet = vega_parser_module_transform('prefacet');
const vega_parser_module_Projection = vega_parser_module_transform('projection');
const vega_parser_module_Proxy = vega_parser_module_transform('proxy');
const vega_parser_module_Relay = vega_parser_module_transform('relay');
const vega_parser_module_Render = vega_parser_module_transform('render');
const vega_parser_module_Scale = vega_parser_module_transform('scale');
const vega_parser_module_Sieve = vega_parser_module_transform('sieve');
const vega_parser_module_SortItems = vega_parser_module_transform('sortitems');
const vega_parser_module_ViewLayout = vega_parser_module_transform('viewlayout');
const vega_parser_module_Values = vega_parser_module_transform('values');

let FIELD_REF_ID = 0;
const MULTIDOMAIN_SORT_OPS = {
  min: 'min',
  max: 'max',
  count: 'sum'
};
function initScale(spec, scope) {
  const type = spec.type || 'linear';
  if (!isValidScaleType(type)) {
    vega_util_module_error('Unrecognized scale type: ' + $(type));
  }
  scope.addScale(spec.name, {
    type,
    domain: undefined
  });
}
function parseScale(spec, scope) {
  const params = scope.getScale(spec.name).params;
  let key;
  params.domain = parseScaleDomain(spec.domain, spec, scope);
  if (spec.range != null) {
    params.range = parseScaleRange(spec, scope, params);
  }
  if (spec.interpolate != null) {
    parseScaleInterpolate(spec.interpolate, params);
  }
  if (spec.nice != null) {
    params.nice = parseScaleNice(spec.nice, scope);
  }
  if (spec.bins != null) {
    params.bins = parseScaleBins(spec.bins, scope);
  }
  for (key in spec) {
    if (vega_util_module_has(params, key) || key === 'name') continue;
    params[key] = parseLiteral(spec[key], scope);
  }
}
function parseLiteral(v, scope) {
  return !vega_util_module_isObject(v) ? v : v.signal ? scope.signalRef(v.signal) : vega_util_module_error('Unsupported object: ' + $(v));
}
function parseArray(v, scope) {
  return v.signal ? scope.signalRef(v.signal) : v.map(v => parseLiteral(v, scope));
}
function dataLookupError(name) {
  vega_util_module_error('Can not find data set: ' + $(name));
}

// -- SCALE DOMAIN ----

function parseScaleDomain(domain, spec, scope) {
  if (!domain) {
    if (spec.domainMin != null || spec.domainMax != null) {
      vega_util_module_error('No scale domain defined for domainMin/domainMax to override.');
    }
    return; // default domain
  }
  return domain.signal ? scope.signalRef(domain.signal) : (vega_util_module_isArray(domain) ? explicitDomain : domain.fields ? multipleDomain : singularDomain)(domain, spec, scope);
}
function explicitDomain(domain, spec, scope) {
  return domain.map(v => parseLiteral(v, scope));
}
function singularDomain(domain, spec, scope) {
  const data = scope.getData(domain.data);
  if (!data) dataLookupError(domain.data);
  return isDiscrete(spec.type) ? data.valuesRef(scope, domain.field, parseSort(domain.sort, false)) : isQuantile(spec.type) ? data.domainRef(scope, domain.field) : data.extentRef(scope, domain.field);
}
function multipleDomain(domain, spec, scope) {
  const data = domain.data,
    fields = domain.fields.reduce((dom, d) => {
      d = vega_util_module_isString(d) ? {
        data: data,
        field: d
      } : vega_util_module_isArray(d) || d.signal ? vega_parser_module_fieldRef(d, scope) : d;
      dom.push(d);
      return dom;
    }, []);
  return (isDiscrete(spec.type) ? ordinalMultipleDomain : isQuantile(spec.type) ? quantileMultipleDomain : numericMultipleDomain)(domain, scope, fields);
}
function vega_parser_module_fieldRef(data, scope) {
  const name = '_:vega:_' + FIELD_REF_ID++,
    coll = vega_parser_module_Collect({});
  if (vega_util_module_isArray(data)) {
    coll.value = {
      $ingest: data
    };
  } else if (data.signal) {
    const code = 'setdata(' + $(name) + ',' + data.signal + ')';
    coll.params.input = scope.signalRef(code);
  }
  scope.addDataPipeline(name, [coll, vega_parser_module_Sieve({})]);
  return {
    data: name,
    field: 'data'
  };
}
function ordinalMultipleDomain(domain, scope, fields) {
  const sort = parseSort(domain.sort, true);
  let a, v;

  // get value counts for each domain field
  const counts = fields.map(f => {
    const data = scope.getData(f.data);
    if (!data) dataLookupError(f.data);
    return data.countsRef(scope, f.field, sort);
  });

  // aggregate the results from each domain field
  const p = {
    groupby: keyFieldRef,
    pulse: counts
  };
  if (sort) {
    a = sort.op || 'count';
    v = sort.field ? aggrField(a, sort.field) : 'count';
    p.ops = [MULTIDOMAIN_SORT_OPS[a]];
    p.fields = [scope.fieldRef(v)];
    p.as = [v];
  }
  a = scope.add(vega_parser_module_Aggregate(p));

  // collect aggregate output
  const c = scope.add(vega_parser_module_Collect({
    pulse: vega_parser_module_ref(a)
  }));

  // extract values for combined domain
  v = scope.add(vega_parser_module_Values({
    field: keyFieldRef,
    sort: scope.sortRef(sort),
    pulse: vega_parser_module_ref(c)
  }));
  return vega_parser_module_ref(v);
}
function parseSort(sort, multidomain) {
  if (sort) {
    if (!sort.field && !sort.op) {
      if (vega_util_module_isObject(sort)) sort.field = 'key';else sort = {
        field: 'key'
      };
    } else if (!sort.field && sort.op !== 'count') {
      vega_util_module_error('No field provided for sort aggregate op: ' + sort.op);
    } else if (multidomain && sort.field) {
      if (sort.op && !MULTIDOMAIN_SORT_OPS[sort.op]) {
        vega_util_module_error('Multiple domain scales can not be sorted using ' + sort.op);
      }
    }
  }
  return sort;
}
function quantileMultipleDomain(domain, scope, fields) {
  // get value arrays for each domain field
  const values = fields.map(f => {
    const data = scope.getData(f.data);
    if (!data) dataLookupError(f.data);
    return data.domainRef(scope, f.field);
  });

  // combine value arrays
  return vega_parser_module_ref(scope.add(vega_parser_module_MultiValues({
    values: values
  })));
}
function numericMultipleDomain(domain, scope, fields) {
  // get extents for each domain field
  const extents = fields.map(f => {
    const data = scope.getData(f.data);
    if (!data) dataLookupError(f.data);
    return data.extentRef(scope, f.field);
  });

  // combine extents
  return vega_parser_module_ref(scope.add(vega_parser_module_MultiExtent({
    extents: extents
  })));
}

// -- SCALE BINS -----

function parseScaleBins(v, scope) {
  return v.signal || vega_util_module_isArray(v) ? parseArray(v, scope) : scope.objectProperty(v);
}

// -- SCALE NICE -----

function parseScaleNice(nice, scope) {
  return nice.signal ? scope.signalRef(nice.signal) : vega_util_module_isObject(nice) ? {
    interval: parseLiteral(nice.interval),
    step: parseLiteral(nice.step)
  } : parseLiteral(nice);
}

// -- SCALE INTERPOLATION -----

function parseScaleInterpolate(interpolate, params) {
  params.interpolate = parseLiteral(interpolate.type || interpolate);
  if (interpolate.gamma != null) {
    params.interpolateGamma = parseLiteral(interpolate.gamma);
  }
}

// -- SCALE RANGE -----

function parseScaleRange(spec, scope, params) {
  const config = scope.config.range;
  let range = spec.range;
  if (range.signal) {
    return scope.signalRef(range.signal);
  } else if (vega_util_module_isString(range)) {
    if (config && vega_util_module_has(config, range)) {
      spec = extend({}, spec, {
        range: config[range]
      });
      return parseScaleRange(spec, scope, params);
    } else if (range === 'width') {
      range = [0, {
        signal: 'width'
      }];
    } else if (range === 'height') {
      range = isDiscrete(spec.type) ? [0, {
        signal: 'height'
      }] : [{
        signal: 'height'
      }, 0];
    } else {
      vega_util_module_error('Unrecognized scale range value: ' + $(range));
    }
  } else if (range.scheme) {
    params.scheme = vega_util_module_isArray(range.scheme) ? parseArray(range.scheme, scope) : parseLiteral(range.scheme, scope);
    if (range.extent) params.schemeExtent = parseArray(range.extent, scope);
    if (range.count) params.schemeCount = parseLiteral(range.count, scope);
    return;
  } else if (range.step) {
    params.rangeStep = parseLiteral(range.step, scope);
    return;
  } else if (isDiscrete(spec.type) && !vega_util_module_isArray(range)) {
    return parseScaleDomain(range, spec, scope);
  } else if (!vega_util_module_isArray(range)) {
    vega_util_module_error('Unsupported range type: ' + $(range));
  }
  return range.map(v => (vega_util_module_isArray(v) ? parseArray : parseLiteral)(v, scope));
}

function parseProjection (proj, scope) {
  const config = scope.config.projection || {},
    params = {};
  for (const name in proj) {
    if (name === 'name') continue;
    params[name] = parseParameter$1(proj[name], name, scope);
  }

  // apply projection defaults from config
  for (const name in config) {
    if (params[name] == null) {
      params[name] = parseParameter$1(config[name], name, scope);
    }
  }
  scope.addProjection(proj.name, params);
}
function parseParameter$1(_, name, scope) {
  return vega_util_module_isArray(_) ? _.map(_ => parseParameter$1(_, name, scope)) : !vega_util_module_isObject(_) ? _ : _.signal ? scope.signalRef(_.signal) : name === 'fit' ? _ : vega_util_module_error('Unsupported parameter object: ' + $(_));
}

const vega_parser_module_Top = 'top';
const vega_parser_module_Left = 'left';
const vega_parser_module_Right = 'right';
const vega_parser_module_Bottom = 'bottom';
const vega_parser_module_Center = 'center';
const Vertical = 'vertical';
const vega_parser_module_Start = 'start';
const vega_parser_module_Middle = 'middle';
const vega_parser_module_End = 'end';
const Index = 'index';
const vega_parser_module_Label = 'label';
const Offset = 'offset';
const Perc = 'perc';
const Perc2 = 'perc2';
const Value = 'value';
const GuideLabelStyle = 'guide-label';
const GuideTitleStyle = 'guide-title';
const GroupTitleStyle = 'group-title';
const GroupSubtitleStyle = 'group-subtitle';

/** All values of LegendType */
const vega_parser_module_Symbols = 'symbol';
const vega_parser_module_Gradient = 'gradient';
const vega_parser_module_Discrete = 'discrete';
const Size = 'size';
const Shape = 'shape';
const Fill = 'fill';
const Stroke = 'stroke';
const StrokeWidth = 'strokeWidth';
const StrokeDash = 'strokeDash';
const Opacity = 'opacity';

// Encoding channels supported by legends
// In priority order of 'canonical' scale
const LegendScales = [Size, Shape, Fill, Stroke, StrokeWidth, StrokeDash, Opacity];
const vega_parser_module_Skip = {
  name: 1,
  style: 1,
  interactive: 1
};
const vega_parser_module_zero = {
  value: 0
};
const vega_parser_module_one = {
  value: 1
};

const GroupMark = 'group';
const RectMark = 'rect';
const RuleMark = 'rule';
const SymbolMark = 'symbol';
const TextMark = 'text';

function guideGroup (mark) {
  mark.type = GroupMark;
  mark.interactive = mark.interactive || false;
  return mark;
}

function vega_parser_module_lookup(spec, config) {
  const _ = (name, dflt) => vega_parser_module_value(spec[name], vega_parser_module_value(config[name], dflt));
  _.isVertical = s => Vertical === vega_parser_module_value(spec.direction, config.direction || (s ? config.symbolDirection : config.gradientDirection));
  _.gradientLength = () => vega_parser_module_value(spec.gradientLength, config.gradientLength || config.gradientWidth);
  _.gradientThickness = () => vega_parser_module_value(spec.gradientThickness, config.gradientThickness || config.gradientHeight);
  _.entryColumns = () => vega_parser_module_value(spec.columns, vega_parser_module_value(config.columns, +_.isVertical(true)));
  return _;
}
function getEncoding(name, encode) {
  const v = encode && (encode.update && encode.update[name] || encode.enter && encode.enter[name]);
  return v && v.signal ? v : v ? v.value : null;
}
function getStyle(name, scope, style) {
  const s = scope.config.style[style];
  return s && s[name];
}
function anchorExpr(s, e, m) {
  return `item.anchor === '${vega_parser_module_Start}' ? ${s} : item.anchor === '${vega_parser_module_End}' ? ${e} : ${m}`;
}
const alignExpr$1 = anchorExpr($(vega_parser_module_Left), $(vega_parser_module_Right), $(vega_parser_module_Center));
function tickBand(_) {
  const v = _('tickBand');
  let offset = _('tickOffset'),
    band,
    extra;
  if (!v) {
    // if no tick band entry, fall back on other properties
    band = _('bandPosition');
    extra = _('tickExtra');
  } else if (v.signal) {
    // if signal, augment code to interpret values
    band = {
      signal: `(${v.signal}) === 'extent' ? 1 : 0.5`
    };
    extra = {
      signal: `(${v.signal}) === 'extent'`
    };
    if (!vega_util_module_isObject(offset)) {
      offset = {
        signal: `(${v.signal}) === 'extent' ? 0 : ${offset}`
      };
    }
  } else if (v === 'extent') {
    // if constant, simply set values
    band = 1;
    extra = true;
    offset = 0;
  } else {
    band = 0.5;
    extra = false;
  }
  return {
    extra,
    band,
    offset
  };
}
function extendOffset(value, offset) {
  return !offset ? value : !value ? offset : !vega_util_module_isObject(value) ? {
    value,
    offset
  } : Object.assign({}, value, {
    offset: extendOffset(value.offset, offset)
  });
}

function guideMark (mark, extras) {
  if (extras) {
    mark.name = extras.name;
    mark.style = extras.style || mark.style;
    mark.interactive = !!extras.interactive;
    mark.encode = extendEncode(mark.encode, extras, vega_parser_module_Skip);
  } else {
    mark.interactive = false;
  }
  return mark;
}

function legendGradient (spec, scale, config, userEncode) {
  const _ = vega_parser_module_lookup(spec, config),
    vertical = _.isVertical(),
    thickness = _.gradientThickness(),
    length = _.gradientLength();
  let enter, start, stop, width, height;
  if (vertical) {
    start = [0, 1];
    stop = [0, 0];
    width = thickness;
    height = length;
  } else {
    start = [0, 0];
    stop = [1, 0];
    width = length;
    height = thickness;
  }
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero,
      x: vega_parser_module_zero,
      y: vega_parser_module_zero,
      width: encoder(width),
      height: encoder(height)
    },
    update: extend({}, enter, {
      opacity: vega_parser_module_one,
      fill: {
        gradient: scale,
        start: start,
        stop: stop
      }
    }),
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    stroke: _('gradientStrokeColor'),
    strokeWidth: _('gradientStrokeWidth')
  }, {
    // update
    opacity: _('gradientOpacity')
  });
  return guideMark({
    type: RectMark,
    role: LegendGradientRole,
    encode
  }, userEncode);
}

function legendGradientDiscrete (spec, scale, config, userEncode, dataRef) {
  const _ = vega_parser_module_lookup(spec, config),
    vertical = _.isVertical(),
    thickness = _.gradientThickness(),
    length = _.gradientLength();
  let u,
    v,
    uu,
    vv,
    adjust = '';
  vertical ? (u = 'y', uu = 'y2', v = 'x', vv = 'width', adjust = '1-') : (u = 'x', uu = 'x2', v = 'y', vv = 'height');
  const enter = {
    opacity: vega_parser_module_zero,
    fill: {
      scale: scale,
      field: Value
    }
  };
  enter[u] = {
    signal: adjust + 'datum.' + Perc,
    mult: length
  };
  enter[v] = vega_parser_module_zero;
  enter[uu] = {
    signal: adjust + 'datum.' + Perc2,
    mult: length
  };
  enter[vv] = encoder(thickness);
  const encode = {
    enter: enter,
    update: extend({}, enter, {
      opacity: vega_parser_module_one
    }),
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    stroke: _('gradientStrokeColor'),
    strokeWidth: _('gradientStrokeWidth')
  }, {
    // update
    opacity: _('gradientOpacity')
  });
  return guideMark({
    type: RectMark,
    role: LegendBandRole,
    key: Value,
    from: dataRef,
    encode
  }, userEncode);
}

const alignExpr = `datum.${Perc}<=0?"${vega_parser_module_Left}":datum.${Perc}>=1?"${vega_parser_module_Right}":"${vega_parser_module_Center}"`,
  baselineExpr = `datum.${Perc}<=0?"${vega_parser_module_Bottom}":datum.${Perc}>=1?"${vega_parser_module_Top}":"${vega_parser_module_Middle}"`;
function legendGradientLabels (spec, config, userEncode, dataRef) {
  const _ = vega_parser_module_lookup(spec, config),
    vertical = _.isVertical(),
    thickness = encoder(_.gradientThickness()),
    length = _.gradientLength();
  let overlap = _('labelOverlap'),
    enter,
    update,
    u,
    v,
    adjust = '';
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero
    },
    update: update = {
      opacity: vega_parser_module_one,
      text: {
        field: vega_parser_module_Label
      }
    },
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    fill: _('labelColor'),
    fillOpacity: _('labelOpacity'),
    font: _('labelFont'),
    fontSize: _('labelFontSize'),
    fontStyle: _('labelFontStyle'),
    fontWeight: _('labelFontWeight'),
    limit: vega_parser_module_value(spec.labelLimit, config.gradientLabelLimit)
  });
  if (vertical) {
    enter.align = {
      value: 'left'
    };
    enter.baseline = update.baseline = {
      signal: baselineExpr
    };
    u = 'y';
    v = 'x';
    adjust = '1-';
  } else {
    enter.align = update.align = {
      signal: alignExpr
    };
    enter.baseline = {
      value: 'top'
    };
    u = 'x';
    v = 'y';
  }
  enter[u] = update[u] = {
    signal: adjust + 'datum.' + Perc,
    mult: length
  };
  enter[v] = update[v] = thickness;
  thickness.offset = vega_parser_module_value(spec.labelOffset, config.gradientLabelOffset) || 0;
  overlap = overlap ? {
    separation: _('labelSeparation'),
    method: overlap,
    order: 'datum.' + Index
  } : undefined;

  // type, role, style, key, dataRef, encode, extras
  return guideMark({
    type: TextMark,
    role: LegendLabelRole,
    style: GuideLabelStyle,
    key: Value,
    from: dataRef,
    encode,
    overlap
  }, userEncode);
}

// userEncode is top-level, includes entries, symbols, labels
function legendSymbolGroups (spec, config, userEncode, dataRef, columns) {
  const _ = vega_parser_module_lookup(spec, config),
    entries = userEncode.entries,
    interactive = !!(entries && entries.interactive),
    name = entries ? entries.name : undefined,
    height = _('clipHeight'),
    symbolOffset = _('symbolOffset'),
    valueRef = {
      data: 'value'
    },
    xSignal = `(${columns}) ? datum.${Offset} : datum.${Size}`,
    yEncode = height ? encoder(height) : {
      field: Size
    },
    index = `datum.${Index}`,
    ncols = `max(1, ${columns})`;
  let encode, enter, update, nrows, sort;
  yEncode.mult = 0.5;

  // -- LEGEND SYMBOLS --
  encode = {
    enter: enter = {
      opacity: vega_parser_module_zero,
      x: {
        signal: xSignal,
        mult: 0.5,
        offset: symbolOffset
      },
      y: yEncode
    },
    update: update = {
      opacity: vega_parser_module_one,
      x: enter.x,
      y: enter.y
    },
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  let baseFill = null,
    baseStroke = null;
  if (!spec.fill) {
    baseFill = config.symbolBaseFillColor;
    baseStroke = config.symbolBaseStrokeColor;
  }
  addEncoders(encode, {
    fill: _('symbolFillColor', baseFill),
    shape: _('symbolType'),
    size: _('symbolSize'),
    stroke: _('symbolStrokeColor', baseStroke),
    strokeDash: _('symbolDash'),
    strokeDashOffset: _('symbolDashOffset'),
    strokeWidth: _('symbolStrokeWidth')
  }, {
    // update
    opacity: _('symbolOpacity')
  });
  LegendScales.forEach(scale => {
    if (spec[scale]) {
      update[scale] = enter[scale] = {
        scale: spec[scale],
        field: Value
      };
    }
  });
  const symbols = guideMark({
    type: SymbolMark,
    role: LegendSymbolRole,
    key: Value,
    from: valueRef,
    clip: height ? true : undefined,
    encode
  }, userEncode.symbols);

  // -- LEGEND LABELS --
  const labelOffset = encoder(symbolOffset);
  labelOffset.offset = _('labelOffset');
  encode = {
    enter: enter = {
      opacity: vega_parser_module_zero,
      x: {
        signal: xSignal,
        offset: labelOffset
      },
      y: yEncode
    },
    update: update = {
      opacity: vega_parser_module_one,
      text: {
        field: vega_parser_module_Label
      },
      x: enter.x,
      y: enter.y
    },
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    align: _('labelAlign'),
    baseline: _('labelBaseline'),
    fill: _('labelColor'),
    fillOpacity: _('labelOpacity'),
    font: _('labelFont'),
    fontSize: _('labelFontSize'),
    fontStyle: _('labelFontStyle'),
    fontWeight: _('labelFontWeight'),
    limit: _('labelLimit')
  });
  const labels = guideMark({
    type: TextMark,
    role: LegendLabelRole,
    style: GuideLabelStyle,
    key: Value,
    from: valueRef,
    encode
  }, userEncode.labels);

  // -- LEGEND ENTRY GROUPS --
  encode = {
    enter: {
      noBound: {
        value: !height
      },
      // ignore width/height in bounds calc
      width: vega_parser_module_zero,
      height: height ? encoder(height) : vega_parser_module_zero,
      opacity: vega_parser_module_zero
    },
    exit: {
      opacity: vega_parser_module_zero
    },
    update: update = {
      opacity: vega_parser_module_one,
      row: {
        signal: null
      },
      column: {
        signal: null
      }
    }
  };

  // annotate and sort groups to ensure correct ordering
  if (_.isVertical(true)) {
    nrows = `ceil(item.mark.items.length / ${ncols})`;
    update.row.signal = `${index}%${nrows}`;
    update.column.signal = `floor(${index} / ${nrows})`;
    sort = {
      field: ['row', index]
    };
  } else {
    update.row.signal = `floor(${index} / ${ncols})`;
    update.column.signal = `${index} % ${ncols}`;
    sort = {
      field: index
    };
  }
  // handle zero column case (implies infinite columns)
  update.column.signal = `(${columns})?${update.column.signal}:${index}`;

  // facet legend entries into sub-groups
  dataRef = {
    facet: {
      data: dataRef,
      name: 'value',
      groupby: Index
    }
  };
  return guideGroup({
    role: vega_parser_module_ScopeRole,
    from: dataRef,
    encode: extendEncode(encode, entries, vega_parser_module_Skip),
    marks: [symbols, labels],
    name,
    interactive,
    sort
  });
}
function legendSymbolLayout(spec, config) {
  const _ = vega_parser_module_lookup(spec, config);

  // layout parameters for legend entries
  return {
    align: _('gridAlign'),
    columns: _.entryColumns(),
    center: {
      row: true,
      column: false
    },
    padding: {
      row: _('rowPadding'),
      column: _('columnPadding')
    }
  };
}

// expression logic for align, anchor, angle, and baseline calculation
const isL = 'item.orient === "left"',
  isR = 'item.orient === "right"',
  isLR = `(${isL} || ${isR})`,
  isVG = `datum.vgrad && ${isLR}`,
  baseline = anchorExpr('"top"', '"bottom"', '"middle"'),
  alignFlip = anchorExpr('"right"', '"left"', '"center"'),
  exprAlign = `datum.vgrad && ${isR} ? (${alignFlip}) : (${isLR} && !(datum.vgrad && ${isL})) ? "left" : ${alignExpr$1}`,
  exprAnchor = `item._anchor || (${isLR} ? "middle" : "start")`,
  exprAngle = `${isVG} ? (${isL} ? -90 : 90) : 0`,
  exprBaseline = `${isLR} ? (datum.vgrad ? (${isR} ? "bottom" : "top") : ${baseline}) : "top"`;
function legendTitle (spec, config, userEncode, dataRef) {
  const _ = vega_parser_module_lookup(spec, config);
  const encode = {
    enter: {
      opacity: vega_parser_module_zero
    },
    update: {
      opacity: vega_parser_module_one,
      x: {
        field: {
          group: 'padding'
        }
      },
      y: {
        field: {
          group: 'padding'
        }
      }
    },
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    orient: _('titleOrient'),
    _anchor: _('titleAnchor'),
    anchor: {
      signal: exprAnchor
    },
    angle: {
      signal: exprAngle
    },
    align: {
      signal: exprAlign
    },
    baseline: {
      signal: exprBaseline
    },
    text: spec.title,
    fill: _('titleColor'),
    fillOpacity: _('titleOpacity'),
    font: _('titleFont'),
    fontSize: _('titleFontSize'),
    fontStyle: _('titleFontStyle'),
    fontWeight: _('titleFontWeight'),
    limit: _('titleLimit'),
    lineHeight: _('titleLineHeight')
  }, {
    // require update
    align: _('titleAlign'),
    baseline: _('titleBaseline')
  });
  return guideMark({
    type: TextMark,
    role: LegendTitleRole,
    style: GuideTitleStyle,
    from: dataRef,
    encode
  }, userEncode);
}

function vega_parser_module_clip (clip, scope) {
  let expr;
  if (vega_util_module_isObject(clip)) {
    if (clip.signal) {
      expr = clip.signal;
    } else if (clip.path) {
      expr = 'pathShape(' + param(clip.path) + ')';
    } else if (clip.sphere) {
      expr = 'geoShape(' + param(clip.sphere) + ', {type: "Sphere"})';
    }
  }
  return expr ? scope.signalRef(expr) : !!clip;
}
function param(value) {
  return vega_util_module_isObject(value) && value.signal ? value.signal : $(value);
}

function getRole (spec) {
  const role = spec.role || '';
  return role.startsWith('axis') || role.startsWith('legend') || role.startsWith('title') ? role : spec.type === GroupMark ? vega_parser_module_ScopeRole : role || MarkRole;
}

function vega_parser_module_definition (spec) {
  return {
    marktype: spec.type,
    name: spec.name || undefined,
    role: spec.role || getRole(spec),
    zindex: +spec.zindex || undefined,
    aria: spec.aria,
    description: spec.description
  };
}

function interactive (spec, scope) {
  return spec && spec.signal ? scope.signalRef(spec.signal) : spec === false ? false : true;
}

/**
 * Parse a data transform specification.
 */
function parseTransform (spec, scope) {
  const def = definition(spec.type);
  if (!def) vega_util_module_error('Unrecognized transform type: ' + $(spec.type));
  const t = entry(def.type.toLowerCase(), null, vega_parser_module_parseParameters(def, spec, scope));
  if (spec.signal) scope.addSignal(spec.signal, scope.proxy(t));
  t.metadata = def.metadata || {};
  return t;
}

/**
 * Parse all parameters of a data transform.
 */
function vega_parser_module_parseParameters(def, spec, scope) {
  const params = {},
    n = def.params.length;
  for (let i = 0; i < n; ++i) {
    const pdef = def.params[i];
    params[pdef.name] = vega_parser_module_parseParameter(pdef, spec, scope);
  }
  return params;
}

/**
 * Parse a data transform parameter.
 */
function vega_parser_module_parseParameter(def, spec, scope) {
  const type = def.type,
    value = spec[def.name];
  if (type === 'index') {
    return parseIndexParameter(def, spec, scope);
  } else if (value === undefined) {
    if (def.required) {
      vega_util_module_error('Missing required ' + $(spec.type) + ' parameter: ' + $(def.name));
    }
    return;
  } else if (type === 'param') {
    return parseSubParameters(def, spec, scope);
  } else if (type === 'projection') {
    return scope.projectionRef(spec[def.name]);
  }
  return def.array && !isSignal(value) ? value.map(v => parameterValue(def, v, scope)) : parameterValue(def, value, scope);
}

/**
 * Parse a single parameter value.
 */
function parameterValue(def, value, scope) {
  const type = def.type;
  if (isSignal(value)) {
    return isExpr(type) ? vega_util_module_error('Expression references can not be signals.') : vega_parser_module_isField(type) ? scope.fieldRef(value) : isCompare(type) ? scope.compareRef(value) : scope.signalRef(value.signal);
  } else {
    const expr = def.expr || vega_parser_module_isField(type);
    return expr && outerExpr(value) ? scope.exprRef(value.expr, value.as) : expr && outerField(value) ? fieldRef$1(value.field, value.as) : isExpr(type) ? vega_functions_module_parser(value, scope) : isData(type) ? vega_parser_module_ref(scope.getData(value).values) : vega_parser_module_isField(type) ? fieldRef$1(value) : isCompare(type) ? scope.compareRef(value) : value;
  }
}

/**
 * Parse parameter for accessing an index of another data set.
 */
function parseIndexParameter(def, spec, scope) {
  if (!vega_util_module_isString(spec.from)) {
    vega_util_module_error('Lookup "from" parameter must be a string literal.');
  }
  return scope.getData(spec.from).lookupRef(scope, spec.key);
}

/**
 * Parse a parameter that contains one or more sub-parameter objects.
 */
function parseSubParameters(def, spec, scope) {
  const value = spec[def.name];
  if (def.array) {
    if (!vega_util_module_isArray(value)) {
      // signals not allowed!
      vega_util_module_error('Expected an array of sub-parameters. Instead: ' + $(value));
    }
    return value.map(v => parseSubParameter(def, v, scope));
  } else {
    return parseSubParameter(def, value, scope);
  }
}

/**
 * Parse a sub-parameter object.
 */
function parseSubParameter(def, value, scope) {
  const n = def.params.length;
  let pdef;

  // loop over defs to find matching key
  for (let i = 0; i < n; ++i) {
    pdef = def.params[i];
    for (const k in pdef.key) {
      if (pdef.key[k] !== value[k]) {
        pdef = null;
        break;
      }
    }
    if (pdef) break;
  }
  // raise error if matching key not found
  if (!pdef) vega_util_module_error('Unsupported parameter: ' + $(value));

  // parse params, create Params transform, return ref
  const params = extend(vega_parser_module_parseParameters(pdef, value, scope), pdef.key);
  return vega_parser_module_ref(scope.add(vega_parser_module_Params(params)));
}

// -- Utilities -----

const outerExpr = _ => _ && _.expr;
const outerField = _ => _ && _.field;
const isData = _ => _ === 'data';
const isExpr = _ => _ === 'expr';
const vega_parser_module_isField = _ => _ === 'field';
const isCompare = _ => _ === 'compare';

function parseData$1 (from, group, scope) {
  let facet, key, op, dataRef, parent;

  // if no source data, generate singleton datum
  if (!from) {
    dataRef = vega_parser_module_ref(scope.add(vega_parser_module_Collect(null, [{}])));
  }

  // if faceted, process facet specification
  else if (facet = from.facet) {
    if (!group) vega_util_module_error('Only group marks can be faceted.');

    // use pre-faceted source data, if available
    if (facet.field != null) {
      dataRef = parent = getDataRef(facet, scope);
    } else {
      // generate facet aggregates if no direct data specification
      if (!from.data) {
        op = parseTransform(extend({
          type: 'aggregate',
          groupby: vega_util_module_array(facet.groupby)
        }, facet.aggregate), scope);
        op.params.key = scope.keyRef(facet.groupby);
        op.params.pulse = getDataRef(facet, scope);
        dataRef = parent = vega_parser_module_ref(scope.add(op));
      } else {
        parent = vega_parser_module_ref(scope.getData(from.data).aggregate);
      }
      key = scope.keyRef(facet.groupby, true);
    }
  }

  // if not yet defined, get source data reference
  if (!dataRef) {
    dataRef = getDataRef(from, scope);
  }
  return {
    key: key,
    pulse: dataRef,
    parent: parent
  };
}
function getDataRef(from, scope) {
  return from.$ref ? from : from.data && from.data.$ref ? from.data : vega_parser_module_ref(scope.getData(from.data).output);
}

function DataScope(scope, input, output, values, aggr) {
  this.scope = scope; // parent scope object
  this.input = input; // first operator in pipeline (tuple input)
  this.output = output; // last operator in pipeline (tuple output)
  this.values = values; // operator for accessing tuples (but not tuple flow)

  // last aggregate in transform pipeline
  this.aggregate = aggr;

  // lookup table of field indices
  this.index = {};
}
DataScope.fromEntries = function (scope, entries) {
  const n = entries.length,
    values = entries[n - 1],
    output = entries[n - 2];
  let input = entries[0],
    aggr = null,
    i = 1;
  if (input && input.type === 'load') {
    input = entries[1];
  }

  // add operator entries to this scope, wire up pulse chain
  scope.add(entries[0]);
  for (; i < n; ++i) {
    entries[i].params.pulse = vega_parser_module_ref(entries[i - 1]);
    scope.add(entries[i]);
    if (entries[i].type === 'aggregate') aggr = entries[i];
  }
  return new DataScope(scope, input, output, values, aggr);
};
function fieldKey(field) {
  return vega_util_module_isString(field) ? field : null;
}
function addSortField(scope, p, sort) {
  const as = aggrField(sort.op, sort.field);
  let s;
  if (p.ops) {
    for (let i = 0, n = p.as.length; i < n; ++i) {
      if (p.as[i] === as) return;
    }
  } else {
    p.ops = ['count'];
    p.fields = [null];
    p.as = ['count'];
  }
  if (sort.op) {
    p.ops.push((s = sort.op.signal) ? scope.signalRef(s) : sort.op);
    p.fields.push(scope.fieldRef(sort.field));
    p.as.push(as);
  }
}
function cache(scope, ds, name, optype, field, counts, index) {
  const cache = ds[name] || (ds[name] = {}),
    sort = sortKey(counts);
  let k = fieldKey(field),
    v,
    op;
  if (k != null) {
    scope = ds.scope;
    k = k + (sort ? '|' + sort : '');
    v = cache[k];
  }
  if (!v) {
    const params = counts ? {
      field: keyFieldRef,
      pulse: ds.countsRef(scope, field, counts)
    } : {
      field: scope.fieldRef(field),
      pulse: vega_parser_module_ref(ds.output)
    };
    if (sort) params.sort = scope.sortRef(counts);
    op = scope.add(entry(optype, undefined, params));
    if (index) ds.index[field] = op;
    v = vega_parser_module_ref(op);
    if (k != null) cache[k] = v;
  }
  return v;
}
DataScope.prototype = {
  countsRef(scope, field, sort) {
    const ds = this,
      cache = ds.counts || (ds.counts = {}),
      k = fieldKey(field);
    let v, a, p;
    if (k != null) {
      scope = ds.scope;
      v = cache[k];
    }
    if (!v) {
      p = {
        groupby: scope.fieldRef(field, 'key'),
        pulse: vega_parser_module_ref(ds.output)
      };
      if (sort && sort.field) addSortField(scope, p, sort);
      a = scope.add(vega_parser_module_Aggregate(p));
      v = scope.add(vega_parser_module_Collect({
        pulse: vega_parser_module_ref(a)
      }));
      v = {
        agg: a,
        ref: vega_parser_module_ref(v)
      };
      if (k != null) cache[k] = v;
    } else if (sort && sort.field) {
      addSortField(scope, v.agg.params, sort);
    }
    return v.ref;
  },
  tuplesRef() {
    return vega_parser_module_ref(this.values);
  },
  extentRef(scope, field) {
    return cache(scope, this, 'extent', 'extent', field, false);
  },
  domainRef(scope, field) {
    return cache(scope, this, 'domain', 'values', field, false);
  },
  valuesRef(scope, field, sort) {
    return cache(scope, this, 'vals', 'values', field, sort || true);
  },
  lookupRef(scope, field) {
    return cache(scope, this, 'lookup', 'tupleindex', field, false);
  },
  indataRef(scope, field) {
    return cache(scope, this, 'indata', 'tupleindex', field, true, true);
  }
};

function parseFacet (spec, scope, group) {
  const facet = spec.from.facet,
    name = facet.name,
    data = getDataRef(facet, scope);
  let op;
  if (!facet.name) {
    vega_util_module_error('Facet must have a name: ' + $(facet));
  }
  if (!facet.data) {
    vega_util_module_error('Facet must reference a data set: ' + $(facet));
  }
  if (facet.field) {
    op = scope.add(vega_parser_module_PreFacet({
      field: scope.fieldRef(facet.field),
      pulse: data
    }));
  } else if (facet.groupby) {
    op = scope.add(vega_parser_module_Facet({
      key: scope.keyRef(facet.groupby),
      group: vega_parser_module_ref(scope.proxy(group.parent)),
      pulse: data
    }));
  } else {
    vega_util_module_error('Facet must specify groupby or field: ' + $(facet));
  }

  // initialize facet subscope
  const subscope = scope.fork(),
    source = subscope.add(vega_parser_module_Collect()),
    values = subscope.add(vega_parser_module_Sieve({
      pulse: vega_parser_module_ref(source)
    }));
  subscope.addData(name, new DataScope(subscope, source, source, values));
  subscope.addSignal('parent', null);

  // parse faceted subflow
  op.params.subflow = {
    $subflow: subscope.parse(spec).toRuntime()
  };
}

function parseSubflow (spec, scope, input) {
  const op = scope.add(vega_parser_module_PreFacet({
      pulse: input.pulse
    })),
    subscope = scope.fork();
  subscope.add(vega_parser_module_Sieve());
  subscope.addSignal('parent', null);

  // parse group mark subflow
  op.params.subflow = {
    $subflow: subscope.parse(spec).toRuntime()
  };
}

function parseTrigger (spec, scope, name) {
  const remove = spec.remove,
    insert = spec.insert,
    toggle = spec.toggle,
    modify = spec.modify,
    values = spec.values,
    op = scope.add(operator());
  const update = 'if(' + spec.trigger + ',modify("' + name + '",' + [insert, remove, toggle, modify, values].map(_ => _ == null ? 'null' : _).join(',') + '),0)';
  const expr = vega_functions_module_parser(update, scope);
  op.update = expr.$expr;
  op.params = expr.$params;
}

function parseMark (spec, scope) {
  const role = getRole(spec),
    group = spec.type === GroupMark,
    facet = spec.from && spec.from.facet,
    overlap = spec.overlap;
  let layout = spec.layout || role === vega_parser_module_ScopeRole || role === vega_parser_module_FrameRole,
    ops,
    op,
    store,
    enc,
    name,
    layoutRef,
    boundRef;
  const nested = role === MarkRole || layout || facet;

  // resolve input data
  const input = parseData$1(spec.from, group, scope);

  // data join to map tuples to visual items
  op = scope.add(vega_parser_module_DataJoin({
    key: input.key || (spec.key ? fieldRef$1(spec.key) : undefined),
    pulse: input.pulse,
    clean: !group
  }));
  const joinRef = vega_parser_module_ref(op);

  // collect visual items
  op = store = scope.add(vega_parser_module_Collect({
    pulse: joinRef
  }));

  // connect visual items to scenegraph
  op = scope.add(vega_parser_module_Mark({
    markdef: vega_parser_module_definition(spec),
    interactive: interactive(spec.interactive, scope),
    clip: vega_parser_module_clip(spec.clip, scope),
    context: {
      $context: true
    },
    groups: scope.lookup(),
    parent: scope.signals.parent ? scope.signalRef('parent') : null,
    index: scope.markpath(),
    pulse: vega_parser_module_ref(op)
  }));
  const markRef = vega_parser_module_ref(op);

  // add visual encoders
  op = enc = scope.add(vega_parser_module_Encode(parseEncode(spec.encode, spec.type, role, spec.style, scope, {
    mod: false,
    pulse: markRef
  })));

  // monitor parent marks to propagate changes
  op.params.parent = scope.encode();

  // add post-encoding transforms, if defined
  if (spec.transform) {
    spec.transform.forEach(_ => {
      const tx = parseTransform(_, scope),
        md = tx.metadata;
      if (md.generates || md.changes) {
        vega_util_module_error('Mark transforms should not generate new data.');
      }
      if (!md.nomod) enc.params.mod = true; // update encode mod handling
      tx.params.pulse = vega_parser_module_ref(op);
      scope.add(op = tx);
    });
  }

  // if item sort specified, perform post-encoding
  if (spec.sort) {
    op = scope.add(vega_parser_module_SortItems({
      sort: scope.compareRef(spec.sort),
      pulse: vega_parser_module_ref(op)
    }));
  }
  const encodeRef = vega_parser_module_ref(op);

  // add view layout operator if needed
  if (facet || layout) {
    layout = scope.add(vega_parser_module_ViewLayout({
      layout: scope.objectProperty(spec.layout),
      legends: scope.legends,
      mark: markRef,
      pulse: encodeRef
    }));
    layoutRef = vega_parser_module_ref(layout);
  }

  // compute bounding boxes
  const bound = scope.add(vega_parser_module_Bound({
    mark: markRef,
    pulse: layoutRef || encodeRef
  }));
  boundRef = vega_parser_module_ref(bound);

  // if group mark, recurse to parse nested content
  if (group) {
    // juggle layout & bounds to ensure they run *after* any faceting transforms
    if (nested) {
      ops = scope.operators;
      ops.pop();
      if (layout) ops.pop();
    }
    scope.pushState(encodeRef, layoutRef || boundRef, joinRef);
    facet ? parseFacet(spec, scope, input) // explicit facet
    : nested ? parseSubflow(spec, scope, input) // standard mark group
    : scope.parse(spec); // guide group, we can avoid nested scopes
    scope.popState();
    if (nested) {
      if (layout) ops.push(layout);
      ops.push(bound);
    }
  }

  // if requested, add overlap removal transform
  if (overlap) {
    boundRef = parseOverlap(overlap, boundRef, scope);
  }

  // render / sieve items
  const render = scope.add(vega_parser_module_Render({
      pulse: boundRef
    })),
    sieve = scope.add(vega_parser_module_Sieve({
      pulse: vega_parser_module_ref(render)
    }, undefined, scope.parent()));

  // if mark is named, make accessible as reactive geometry
  // add trigger updates if defined
  if (spec.name != null) {
    name = spec.name;
    scope.addData(name, new DataScope(scope, store, render, sieve));
    if (spec.on) spec.on.forEach(on => {
      if (on.insert || on.remove || on.toggle) {
        vega_util_module_error('Marks only support modify triggers.');
      }
      parseTrigger(on, scope, name);
    });
  }
}
function parseOverlap(overlap, source, scope) {
  const method = overlap.method,
    bound = overlap.bound,
    sep = overlap.separation;
  const params = {
    separation: isSignal(sep) ? scope.signalRef(sep.signal) : sep,
    method: isSignal(method) ? scope.signalRef(method.signal) : method,
    pulse: source
  };
  if (overlap.order) {
    params.sort = scope.compareRef({
      field: overlap.order
    });
  }
  if (bound) {
    const tol = bound.tolerance;
    params.boundTolerance = isSignal(tol) ? scope.signalRef(tol.signal) : +tol;
    params.boundScale = scope.scaleRef(bound.scale);
    params.boundOrient = bound.orient;
  }
  return vega_parser_module_ref(scope.add(vega_parser_module_Overlap(params)));
}

function parseLegend (spec, scope) {
  const config = scope.config.legend,
    encode = spec.encode || {},
    _ = vega_parser_module_lookup(spec, config),
    legendEncode = encode.legend || {},
    name = legendEncode.name || undefined,
    interactive = legendEncode.interactive,
    style = legendEncode.style,
    scales = {};
  let scale = 0,
    entryLayout,
    params,
    children;

  // resolve scales and 'canonical' scale name
  LegendScales.forEach(s => spec[s] ? (scales[s] = spec[s], scale = scale || spec[s]) : 0);
  if (!scale) vega_util_module_error('Missing valid scale for legend.');

  // resolve legend type (symbol, gradient, or discrete gradient)
  const type = legendType(spec, scope.scaleType(scale));

  // single-element data source for legend group
  const datum = {
    title: spec.title != null,
    scales: scales,
    type: type,
    vgrad: type !== 'symbol' && _.isVertical()
  };
  const dataRef = vega_parser_module_ref(scope.add(vega_parser_module_Collect(null, [datum])));

  // encoding properties for legend entry sub-group
  const entryEncode = {
    enter: {
      x: {
        value: 0
      },
      y: {
        value: 0
      }
    }
  };

  // data source for legend values
  const entryRef = vega_parser_module_ref(scope.add(vega_parser_module_LegendEntries(params = {
    type: type,
    scale: scope.scaleRef(scale),
    count: scope.objectProperty(_('tickCount')),
    limit: scope.property(_('symbolLimit')),
    values: scope.objectProperty(spec.values),
    minstep: scope.property(spec.tickMinStep),
    formatType: scope.property(spec.formatType),
    formatSpecifier: scope.property(spec.format)
  })));

  // continuous gradient legend
  if (type === vega_parser_module_Gradient) {
    children = [legendGradient(spec, scale, config, encode.gradient), legendGradientLabels(spec, config, encode.labels, entryRef)];
    // adjust default tick count based on the gradient length
    params.count = params.count || scope.signalRef(`max(2,2*floor((${deref(_.gradientLength())})/100))`);
  }

  // discrete gradient legend
  else if (type === vega_parser_module_Discrete) {
    children = [legendGradientDiscrete(spec, scale, config, encode.gradient, entryRef), legendGradientLabels(spec, config, encode.labels, entryRef)];
  }

  // symbol legend
  else {
    // determine legend symbol group layout
    entryLayout = legendSymbolLayout(spec, config);
    children = [legendSymbolGroups(spec, config, encode, entryRef, deref(entryLayout.columns))];
    // pass symbol size information to legend entry generator
    params.size = sizeExpression(spec, scope, children[0].marks);
  }

  // generate legend marks
  children = [guideGroup({
    role: LegendEntryRole,
    from: dataRef,
    encode: entryEncode,
    marks: children,
    layout: entryLayout,
    interactive
  })];

  // include legend title if defined
  if (datum.title) {
    children.push(legendTitle(spec, config, encode.title, dataRef));
  }

  // parse legend specification
  return parseMark(guideGroup({
    role: vega_parser_module_LegendRole,
    from: dataRef,
    encode: extendEncode(buildLegendEncode(_, spec, config), legendEncode, vega_parser_module_Skip),
    marks: children,
    aria: _('aria'),
    description: _('description'),
    zindex: _('zindex'),
    name,
    interactive,
    style
  }), scope);
}
function legendType(spec, scaleType) {
  let type = spec.type || vega_parser_module_Symbols;
  if (!spec.type && scaleCount(spec) === 1 && (spec.fill || spec.stroke)) {
    type = isContinuous(scaleType) ? vega_parser_module_Gradient : isDiscretizing(scaleType) ? vega_parser_module_Discrete : vega_parser_module_Symbols;
  }
  return type !== vega_parser_module_Gradient ? type : isDiscretizing(scaleType) ? vega_parser_module_Discrete : vega_parser_module_Gradient;
}
function scaleCount(spec) {
  return LegendScales.reduce((count, type) => count + (spec[type] ? 1 : 0), 0);
}
function buildLegendEncode(_, spec, config) {
  const encode = {
    enter: {},
    update: {}
  };
  addEncoders(encode, {
    orient: _('orient'),
    offset: _('offset'),
    padding: _('padding'),
    titlePadding: _('titlePadding'),
    cornerRadius: _('cornerRadius'),
    fill: _('fillColor'),
    stroke: _('strokeColor'),
    strokeWidth: config.strokeWidth,
    strokeDash: config.strokeDash,
    x: _('legendX'),
    y: _('legendY'),
    // accessibility support
    format: spec.format,
    formatType: spec.formatType
  });
  return encode;
}
function sizeExpression(spec, scope, marks) {
  const size = deref(getChannel('size', spec, marks)),
    strokeWidth = deref(getChannel('strokeWidth', spec, marks)),
    fontSize = deref(getFontSize(marks[1].encode, scope, GuideLabelStyle));
  return vega_functions_module_parser(`max(ceil(sqrt(${size})+${strokeWidth}),${fontSize})`, scope);
}
function getChannel(name, spec, marks) {
  return spec[name] ? `scale("${spec[name]}",datum)` : getEncoding(name, marks[0].encode);
}
function getFontSize(encode, scope, style) {
  return getEncoding('fontSize', encode) || getStyle('fontSize', scope, style);
}

const angleExpr = `item.orient==="${vega_parser_module_Left}"?-90:item.orient==="${vega_parser_module_Right}"?90:0`;
function parseTitle (spec, scope) {
  spec = vega_util_module_isString(spec) ? {
    text: spec
  } : spec;
  const _ = vega_parser_module_lookup(spec, scope.config.title),
    encode = spec.encode || {},
    userEncode = encode.group || {},
    name = userEncode.name || undefined,
    interactive = userEncode.interactive,
    style = userEncode.style,
    children = [];

  // single-element data source for group title
  const datum = {},
    dataRef = vega_parser_module_ref(scope.add(vega_parser_module_Collect(null, [datum])));

  // include title text
  children.push(buildTitle(spec, _, titleEncode(spec), dataRef));

  // include subtitle text
  if (spec.subtitle) {
    children.push(buildSubTitle(spec, _, encode.subtitle, dataRef));
  }

  // parse title specification
  return parseMark(guideGroup({
    role: vega_parser_module_TitleRole,
    from: dataRef,
    encode: groupEncode(_, userEncode),
    marks: children,
    aria: _('aria'),
    description: _('description'),
    zindex: _('zindex'),
    name,
    interactive,
    style
  }), scope);
}

// provide backwards-compatibility for title custom encode;
// the top-level encode block has been *deprecated*.
function titleEncode(spec) {
  const encode = spec.encode;
  return encode && encode.title || extend({
    name: spec.name,
    interactive: spec.interactive,
    style: spec.style
  }, encode);
}
function groupEncode(_, userEncode) {
  const encode = {
    enter: {},
    update: {}
  };
  addEncoders(encode, {
    orient: _('orient'),
    anchor: _('anchor'),
    align: {
      signal: alignExpr$1
    },
    angle: {
      signal: angleExpr
    },
    limit: _('limit'),
    frame: _('frame'),
    offset: _('offset') || 0,
    padding: _('subtitlePadding')
  });
  return extendEncode(encode, userEncode, vega_parser_module_Skip);
}
function buildTitle(spec, _, userEncode, dataRef) {
  const zero = {
      value: 0
    },
    text = spec.text,
    encode = {
      enter: {
        opacity: zero
      },
      update: {
        opacity: {
          value: 1
        }
      },
      exit: {
        opacity: zero
      }
    };
  addEncoders(encode, {
    text: text,
    align: {
      signal: 'item.mark.group.align'
    },
    angle: {
      signal: 'item.mark.group.angle'
    },
    limit: {
      signal: 'item.mark.group.limit'
    },
    baseline: 'top',
    dx: _('dx'),
    dy: _('dy'),
    fill: _('color'),
    font: _('font'),
    fontSize: _('fontSize'),
    fontStyle: _('fontStyle'),
    fontWeight: _('fontWeight'),
    lineHeight: _('lineHeight')
  }, {
    // update
    align: _('align'),
    angle: _('angle'),
    baseline: _('baseline')
  });
  return guideMark({
    type: TextMark,
    role: TitleTextRole,
    style: GroupTitleStyle,
    from: dataRef,
    encode
  }, userEncode);
}
function buildSubTitle(spec, _, userEncode, dataRef) {
  const zero = {
      value: 0
    },
    text = spec.subtitle,
    encode = {
      enter: {
        opacity: zero
      },
      update: {
        opacity: {
          value: 1
        }
      },
      exit: {
        opacity: zero
      }
    };
  addEncoders(encode, {
    text: text,
    align: {
      signal: 'item.mark.group.align'
    },
    angle: {
      signal: 'item.mark.group.angle'
    },
    limit: {
      signal: 'item.mark.group.limit'
    },
    baseline: 'top',
    dx: _('dx'),
    dy: _('dy'),
    fill: _('subtitleColor'),
    font: _('subtitleFont'),
    fontSize: _('subtitleFontSize'),
    fontStyle: _('subtitleFontStyle'),
    fontWeight: _('subtitleFontWeight'),
    lineHeight: _('subtitleLineHeight')
  }, {
    // update
    align: _('align'),
    angle: _('angle'),
    baseline: _('baseline')
  });
  return guideMark({
    type: TextMark,
    role: TitleSubtitleRole,
    style: GroupSubtitleStyle,
    from: dataRef,
    encode
  }, userEncode);
}

function parseData(data, scope) {
  const transforms = [];
  if (data.transform) {
    data.transform.forEach(tx => {
      transforms.push(parseTransform(tx, scope));
    });
  }
  if (data.on) {
    data.on.forEach(on => {
      parseTrigger(on, scope, data.name);
    });
  }
  scope.addDataPipeline(data.name, analyze(data, scope, transforms));
}

/**
 * Analyze a data pipeline, add needed operators.
 */
function analyze(data, scope, ops) {
  const output = [];
  let source = null,
    modify = false,
    generate = false,
    upstream,
    i,
    n,
    t,
    m;
  if (data.values) {
    // hard-wired input data set
    if (isSignal(data.values) || hasSignal(data.format)) {
      // if either values is signal or format has signal, use dynamic loader
      output.push(vega_parser_module_load(scope, data));
      output.push(source = collect());
    } else {
      // otherwise, ingest upon dataflow init
      output.push(source = collect({
        $ingest: data.values,
        $format: data.format
      }));
    }
  } else if (data.url) {
    // load data from external source
    if (hasSignal(data.url) || hasSignal(data.format)) {
      // if either url or format has signal, use dynamic loader
      output.push(vega_parser_module_load(scope, data));
      output.push(source = collect());
    } else {
      // otherwise, request load upon dataflow init
      output.push(source = collect({
        $request: data.url,
        $format: data.format
      }));
    }
  } else if (data.source) {
    // derives from one or more other data sets
    source = upstream = vega_util_module_array(data.source).map(d => vega_parser_module_ref(scope.getData(d).output));
    output.push(null); // populate later
  }

  // scan data transforms, add collectors as needed
  for (i = 0, n = ops.length; i < n; ++i) {
    t = ops[i];
    m = t.metadata;
    if (!source && !m.source) {
      output.push(source = collect());
    }
    output.push(t);
    if (m.generates) generate = true;
    if (m.modifies && !generate) modify = true;
    if (m.source) source = t;else if (m.changes) source = null;
  }
  if (upstream) {
    n = upstream.length - 1;
    output[0] = vega_parser_module_Relay({
      derive: modify,
      pulse: n ? upstream : upstream[0]
    });
    if (modify || n) {
      // collect derived and multi-pulse tuples
      output.splice(1, 0, collect());
    }
  }
  if (!source) output.push(collect());
  output.push(vega_parser_module_Sieve({}));
  return output;
}
function collect(values) {
  const s = vega_parser_module_Collect({}, values);
  s.metadata = {
    source: true
  };
  return s;
}
function vega_parser_module_load(scope, data) {
  return vega_parser_module_Load({
    url: data.url ? scope.property(data.url) : undefined,
    async: data.async ? scope.property(data.async) : undefined,
    values: data.values ? scope.property(data.values) : undefined,
    format: scope.objectProperty(data.format)
  });
}

const isX = orient => orient === vega_parser_module_Bottom || orient === vega_parser_module_Top;

// get sign coefficient based on axis orient
const getSign = (orient, a, b) => isSignal(orient) ? ifLeftTopExpr(orient.signal, a, b) : orient === vega_parser_module_Left || orient === vega_parser_module_Top ? a : b;

// condition on axis x-direction
const ifX = (orient, a, b) => isSignal(orient) ? ifXEnc(orient.signal, a, b) : isX(orient) ? a : b;

// condition on axis y-direction
const ifY = (orient, a, b) => isSignal(orient) ? ifYEnc(orient.signal, a, b) : isX(orient) ? b : a;
const ifTop = (orient, a, b) => isSignal(orient) ? ifTopExpr(orient.signal, a, b) : orient === vega_parser_module_Top ? {
  value: a
} : {
  value: b
};
const ifRight = (orient, a, b) => isSignal(orient) ? ifRightExpr(orient.signal, a, b) : orient === vega_parser_module_Right ? {
  value: a
} : {
  value: b
};
const ifXEnc = ($orient, a, b) => ifEnc(`${$orient} === '${vega_parser_module_Top}' || ${$orient} === '${vega_parser_module_Bottom}'`, a, b);
const ifYEnc = ($orient, a, b) => ifEnc(`${$orient} !== '${vega_parser_module_Top}' && ${$orient} !== '${vega_parser_module_Bottom}'`, a, b);
const ifLeftTopExpr = ($orient, a, b) => ifExpr(`${$orient} === '${vega_parser_module_Left}' || ${$orient} === '${vega_parser_module_Top}'`, a, b);
const ifTopExpr = ($orient, a, b) => ifExpr(`${$orient} === '${vega_parser_module_Top}'`, a, b);
const ifRightExpr = ($orient, a, b) => ifExpr(`${$orient} === '${vega_parser_module_Right}'`, a, b);
const ifEnc = (test, a, b) => {
  // ensure inputs are encoder objects (or null)
  a = a != null ? encoder(a) : a;
  b = b != null ? encoder(b) : b;
  if (isSimple(a) && isSimple(b)) {
    // if possible generate simple signal expression
    a = a ? a.signal || $(a.value) : null;
    b = b ? b.signal || $(b.value) : null;
    return {
      signal: `${test} ? (${a}) : (${b})`
    };
  } else {
    // otherwise generate rule set
    return [extend({
      test
    }, a)].concat(b || []);
  }
};
const isSimple = enc => enc == null || Object.keys(enc).length === 1;
const ifExpr = (test, a, b) => ({
  signal: `${test} ? (${toExpr(a)}) : (${toExpr(b)})`
});
const ifOrient = ($orient, t, b, l, r) => ({
  signal: (l != null ? `${$orient} === '${vega_parser_module_Left}' ? (${toExpr(l)}) : ` : '') + (b != null ? `${$orient} === '${vega_parser_module_Bottom}' ? (${toExpr(b)}) : ` : '') + (r != null ? `${$orient} === '${vega_parser_module_Right}' ? (${toExpr(r)}) : ` : '') + (t != null ? `${$orient} === '${vega_parser_module_Top}' ? (${toExpr(t)}) : ` : '') + '(null)'
});
const toExpr = v => isSignal(v) ? v.signal : v == null ? null : $(v);
const mult = (sign, value) => value === 0 ? 0 : isSignal(sign) ? {
  signal: `(${sign.signal}) * ${value}`
} : {
  value: sign * value
};
const patch = (value, base) => {
  const s = value.signal;
  return s && s.endsWith('(null)') ? {
    signal: s.slice(0, -6) + base.signal
  } : value;
};

function fallback(prop, config, axisConfig, style) {
  let styleProp;
  if (config && vega_util_module_has(config, prop)) {
    return config[prop];
  } else if (vega_util_module_has(axisConfig, prop)) {
    return axisConfig[prop];
  } else if (prop.startsWith('title')) {
    switch (prop) {
      case 'titleColor':
        styleProp = 'fill';
        break;
      case 'titleFont':
      case 'titleFontSize':
      case 'titleFontWeight':
        styleProp = prop[5].toLowerCase() + prop.slice(6);
    }
    return style[GuideTitleStyle][styleProp];
  } else if (prop.startsWith('label')) {
    switch (prop) {
      case 'labelColor':
        styleProp = 'fill';
        break;
      case 'labelFont':
      case 'labelFontSize':
        styleProp = prop[5].toLowerCase() + prop.slice(6);
    }
    return style[GuideLabelStyle][styleProp];
  }
  return null;
}
function vega_parser_module_keys(objects) {
  const map = {};
  for (const obj of objects) {
    if (!obj) continue;
    for (const key in obj) map[key] = 1;
  }
  return Object.keys(map);
}
function axisConfig (spec, scope) {
  var config = scope.config,
    style = config.style,
    axis = config.axis,
    band = scope.scaleType(spec.scale) === 'band' && config.axisBand,
    orient = spec.orient,
    xy,
    or,
    key;
  if (isSignal(orient)) {
    const xyKeys = vega_parser_module_keys([config.axisX, config.axisY]),
      orientKeys = vega_parser_module_keys([config.axisTop, config.axisBottom, config.axisLeft, config.axisRight]);
    xy = {};
    for (key of xyKeys) {
      xy[key] = ifX(orient, fallback(key, config.axisX, axis, style), fallback(key, config.axisY, axis, style));
    }
    or = {};
    for (key of orientKeys) {
      or[key] = ifOrient(orient.signal, fallback(key, config.axisTop, axis, style), fallback(key, config.axisBottom, axis, style), fallback(key, config.axisLeft, axis, style), fallback(key, config.axisRight, axis, style));
    }
  } else {
    xy = orient === vega_parser_module_Top || orient === vega_parser_module_Bottom ? config.axisX : config.axisY;
    or = config['axis' + orient[0].toUpperCase() + orient.slice(1)];
  }
  const result = xy || or || band ? extend({}, axis, xy, or, band) : axis;
  return result;
}

function axisDomain (spec, config, userEncode, dataRef) {
  const _ = vega_parser_module_lookup(spec, config),
    orient = spec.orient;
  let enter, update;
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero
    },
    update: update = {
      opacity: vega_parser_module_one
    },
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    stroke: _('domainColor'),
    strokeCap: _('domainCap'),
    strokeDash: _('domainDash'),
    strokeDashOffset: _('domainDashOffset'),
    strokeWidth: _('domainWidth'),
    strokeOpacity: _('domainOpacity')
  });
  const pos0 = position(spec, 0);
  const pos1 = position(spec, 1);
  enter.x = update.x = ifX(orient, pos0, vega_parser_module_zero);
  enter.x2 = update.x2 = ifX(orient, pos1);
  enter.y = update.y = ifY(orient, pos0, vega_parser_module_zero);
  enter.y2 = update.y2 = ifY(orient, pos1);
  return guideMark({
    type: RuleMark,
    role: AxisDomainRole,
    from: dataRef,
    encode
  }, userEncode);
}
function position(spec, pos) {
  return {
    scale: spec.scale,
    range: pos
  };
}

function axisGrid (spec, config, userEncode, dataRef, band) {
  const _ = vega_parser_module_lookup(spec, config),
    orient = spec.orient,
    vscale = spec.gridScale,
    sign = getSign(orient, 1, -1),
    offset = vega_parser_module_offsetValue(spec.offset, sign);
  let enter, exit, update;
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero
    },
    update: update = {
      opacity: vega_parser_module_one
    },
    exit: exit = {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    stroke: _('gridColor'),
    strokeCap: _('gridCap'),
    strokeDash: _('gridDash'),
    strokeDashOffset: _('gridDashOffset'),
    strokeOpacity: _('gridOpacity'),
    strokeWidth: _('gridWidth')
  });
  const tickPos = {
    scale: spec.scale,
    field: Value,
    band: band.band,
    extra: band.extra,
    offset: band.offset,
    round: _('tickRound')
  };
  const sz = ifX(orient, {
    signal: 'height'
  }, {
    signal: 'width'
  });
  const gridStart = vscale ? {
    scale: vscale,
    range: 0,
    mult: sign,
    offset: offset
  } : {
    value: 0,
    offset: offset
  };
  const gridEnd = vscale ? {
    scale: vscale,
    range: 1,
    mult: sign,
    offset: offset
  } : extend(sz, {
    mult: sign,
    offset: offset
  });
  enter.x = update.x = ifX(orient, tickPos, gridStart);
  enter.y = update.y = ifY(orient, tickPos, gridStart);
  enter.x2 = update.x2 = ifY(orient, gridEnd);
  enter.y2 = update.y2 = ifX(orient, gridEnd);
  exit.x = ifX(orient, tickPos);
  exit.y = ifY(orient, tickPos);
  return guideMark({
    type: RuleMark,
    role: AxisGridRole,
    key: Value,
    from: dataRef,
    encode
  }, userEncode);
}
function vega_parser_module_offsetValue(offset, sign) {
  if (sign === 1) ; else if (!vega_util_module_isObject(offset)) {
    offset = isSignal(sign) ? {
      signal: `(${sign.signal}) * (${offset || 0})`
    } : sign * (offset || 0);
  } else {
    let entry = offset = extend({}, offset);
    while (entry.mult != null) {
      if (!vega_util_module_isObject(entry.mult)) {
        entry.mult = isSignal(sign) // no offset if sign === 1
        ? {
          signal: `(${entry.mult}) * (${sign.signal})`
        } : entry.mult * sign;
        return offset;
      } else {
        entry = entry.mult = extend({}, entry.mult);
      }
    }
    entry.mult = sign;
  }
  return offset;
}

function axisTicks (spec, config, userEncode, dataRef, size, band) {
  const _ = vega_parser_module_lookup(spec, config),
    orient = spec.orient,
    sign = getSign(orient, -1, 1);
  let enter, exit, update;
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero
    },
    update: update = {
      opacity: vega_parser_module_one
    },
    exit: exit = {
      opacity: vega_parser_module_zero
    }
  };
  addEncoders(encode, {
    stroke: _('tickColor'),
    strokeCap: _('tickCap'),
    strokeDash: _('tickDash'),
    strokeDashOffset: _('tickDashOffset'),
    strokeOpacity: _('tickOpacity'),
    strokeWidth: _('tickWidth')
  });
  const tickSize = encoder(size);
  tickSize.mult = sign;
  const tickPos = {
    scale: spec.scale,
    field: Value,
    band: band.band,
    extra: band.extra,
    offset: band.offset,
    round: _('tickRound')
  };
  update.y = enter.y = ifX(orient, vega_parser_module_zero, tickPos);
  update.y2 = enter.y2 = ifX(orient, tickSize);
  exit.x = ifX(orient, tickPos);
  update.x = enter.x = ifY(orient, vega_parser_module_zero, tickPos);
  update.x2 = enter.x2 = ifY(orient, tickSize);
  exit.y = ifY(orient, tickPos);
  return guideMark({
    type: RuleMark,
    role: AxisTickRole,
    key: Value,
    from: dataRef,
    encode
  }, userEncode);
}

function flushExpr(scale, threshold, a, b, c) {
  return {
    signal: 'flush(range("' + scale + '"), ' + 'scale("' + scale + '", datum.value), ' + threshold + ',' + a + ',' + b + ',' + c + ')'
  };
}
function axisLabels (spec, config, userEncode, dataRef, size, band) {
  const _ = vega_parser_module_lookup(spec, config),
    orient = spec.orient,
    scale = spec.scale,
    sign = getSign(orient, -1, 1),
    flush = deref(_('labelFlush')),
    flushOffset = deref(_('labelFlushOffset')),
    labelAlign = _('labelAlign'),
    labelBaseline = _('labelBaseline');
  let flushOn = flush === 0 || !!flush,
    update;
  const tickSize = encoder(size);
  tickSize.mult = sign;
  tickSize.offset = encoder(_('labelPadding') || 0);
  tickSize.offset.mult = sign;
  const tickPos = {
    scale: scale,
    field: Value,
    band: 0.5,
    offset: extendOffset(band.offset, _('labelOffset'))
  };
  const align = ifX(orient, flushOn ? flushExpr(scale, flush, '"left"', '"right"', '"center"') : {
    value: 'center'
  }, ifRight(orient, 'left', 'right'));
  const baseline = ifX(orient, ifTop(orient, 'bottom', 'top'), flushOn ? flushExpr(scale, flush, '"top"', '"bottom"', '"middle"') : {
    value: 'middle'
  });
  const offsetExpr = flushExpr(scale, flush, `-(${flushOffset})`, flushOffset, 0);
  flushOn = flushOn && flushOffset;
  const enter = {
    opacity: vega_parser_module_zero,
    x: ifX(orient, tickPos, tickSize),
    y: ifY(orient, tickPos, tickSize)
  };
  const encode = {
    enter: enter,
    update: update = {
      opacity: vega_parser_module_one,
      text: {
        field: vega_parser_module_Label
      },
      x: enter.x,
      y: enter.y,
      align,
      baseline
    },
    exit: {
      opacity: vega_parser_module_zero,
      x: enter.x,
      y: enter.y
    }
  };
  addEncoders(encode, {
    dx: !labelAlign && flushOn ? ifX(orient, offsetExpr) : null,
    dy: !labelBaseline && flushOn ? ifY(orient, offsetExpr) : null
  });
  addEncoders(encode, {
    angle: _('labelAngle'),
    fill: _('labelColor'),
    fillOpacity: _('labelOpacity'),
    font: _('labelFont'),
    fontSize: _('labelFontSize'),
    fontWeight: _('labelFontWeight'),
    fontStyle: _('labelFontStyle'),
    limit: _('labelLimit'),
    lineHeight: _('labelLineHeight')
  }, {
    align: labelAlign,
    baseline: labelBaseline
  });
  const bound = _('labelBound');
  let overlap = _('labelOverlap');

  // if overlap method or bound defined, request label overlap removal
  overlap = overlap || bound ? {
    separation: _('labelSeparation'),
    method: overlap,
    order: 'datum.index',
    bound: bound ? {
      scale,
      orient,
      tolerance: bound
    } : null
  } : undefined;
  if (update.align !== align) {
    update.align = patch(update.align, align);
  }
  if (update.baseline !== baseline) {
    update.baseline = patch(update.baseline, baseline);
  }
  return guideMark({
    type: TextMark,
    role: AxisLabelRole,
    style: GuideLabelStyle,
    key: Value,
    from: dataRef,
    encode,
    overlap
  }, userEncode);
}

function axisTitle (spec, config, userEncode, dataRef) {
  const _ = vega_parser_module_lookup(spec, config),
    orient = spec.orient,
    sign = getSign(orient, -1, 1);
  let enter, update;
  const encode = {
    enter: enter = {
      opacity: vega_parser_module_zero,
      anchor: encoder(_('titleAnchor', null)),
      align: {
        signal: alignExpr$1
      }
    },
    update: update = extend({}, enter, {
      opacity: vega_parser_module_one,
      text: encoder(spec.title)
    }),
    exit: {
      opacity: vega_parser_module_zero
    }
  };
  const titlePos = {
    signal: `lerp(range("${spec.scale}"), ${anchorExpr(0, 1, 0.5)})`
  };
  update.x = ifX(orient, titlePos);
  update.y = ifY(orient, titlePos);
  enter.angle = ifX(orient, vega_parser_module_zero, mult(sign, 90));
  enter.baseline = ifX(orient, ifTop(orient, vega_parser_module_Bottom, vega_parser_module_Top), {
    value: vega_parser_module_Bottom
  });
  update.angle = enter.angle;
  update.baseline = enter.baseline;
  addEncoders(encode, {
    fill: _('titleColor'),
    fillOpacity: _('titleOpacity'),
    font: _('titleFont'),
    fontSize: _('titleFontSize'),
    fontStyle: _('titleFontStyle'),
    fontWeight: _('titleFontWeight'),
    limit: _('titleLimit'),
    lineHeight: _('titleLineHeight')
  }, {
    // require update
    align: _('titleAlign'),
    angle: _('titleAngle'),
    baseline: _('titleBaseline')
  });
  autoLayout(_, orient, encode, userEncode);
  encode.update.align = patch(encode.update.align, enter.align);
  encode.update.angle = patch(encode.update.angle, enter.angle);
  encode.update.baseline = patch(encode.update.baseline, enter.baseline);
  return guideMark({
    type: TextMark,
    role: AxisTitleRole,
    style: GuideTitleStyle,
    from: dataRef,
    encode
  }, userEncode);
}
function autoLayout(_, orient, encode, userEncode) {
  const auto = (value, dim) => value != null ? (encode.update[dim] = patch(encoder(value), encode.update[dim]), false) : !vega_parser_module_has(dim, userEncode) ? true : false;
  const autoY = auto(_('titleX'), 'x'),
    autoX = auto(_('titleY'), 'y');
  encode.enter.auto = autoX === autoY ? encoder(autoX) : ifX(orient, encoder(autoX), encoder(autoY));
}

function parseAxis (spec, scope) {
  const config = axisConfig(spec, scope),
    encode = spec.encode || {},
    axisEncode = encode.axis || {},
    name = axisEncode.name || undefined,
    interactive = axisEncode.interactive,
    style = axisEncode.style,
    _ = vega_parser_module_lookup(spec, config),
    band = tickBand(_);

  // single-element data source for axis group
  const datum = {
    scale: spec.scale,
    ticks: !!_('ticks'),
    labels: !!_('labels'),
    grid: !!_('grid'),
    domain: !!_('domain'),
    title: spec.title != null
  };
  const dataRef = vega_parser_module_ref(scope.add(vega_parser_module_Collect({}, [datum])));

  // data source for axis ticks
  const ticksRef = vega_parser_module_ref(scope.add(vega_parser_module_AxisTicks({
    scale: scope.scaleRef(spec.scale),
    extra: scope.property(band.extra),
    count: scope.objectProperty(spec.tickCount),
    values: scope.objectProperty(spec.values),
    minstep: scope.property(spec.tickMinStep),
    formatType: scope.property(spec.formatType),
    formatSpecifier: scope.property(spec.format)
  })));

  // generate axis marks
  const children = [];
  let size;

  // include axis gridlines if requested
  if (datum.grid) {
    children.push(axisGrid(spec, config, encode.grid, ticksRef, band));
  }

  // include axis ticks if requested
  if (datum.ticks) {
    size = _('tickSize');
    children.push(axisTicks(spec, config, encode.ticks, ticksRef, size, band));
  }

  // include axis labels if requested
  if (datum.labels) {
    size = datum.ticks ? size : 0;
    children.push(axisLabels(spec, config, encode.labels, ticksRef, size, band));
  }

  // include axis domain path if requested
  if (datum.domain) {
    children.push(axisDomain(spec, config, encode.domain, dataRef));
  }

  // include axis title if defined
  if (datum.title) {
    children.push(axisTitle(spec, config, encode.title, dataRef));
  }

  // parse axis specification
  return parseMark(guideGroup({
    role: vega_parser_module_AxisRole,
    from: dataRef,
    encode: extendEncode(buildAxisEncode(_, spec), axisEncode, vega_parser_module_Skip),
    marks: children,
    aria: _('aria'),
    description: _('description'),
    zindex: _('zindex'),
    name,
    interactive,
    style
  }), scope);
}
function buildAxisEncode(_, spec) {
  const encode = {
    enter: {},
    update: {}
  };
  addEncoders(encode, {
    orient: _('orient'),
    offset: _('offset') || 0,
    position: vega_parser_module_value(spec.position, 0),
    titlePadding: _('titlePadding'),
    minExtent: _('minExtent'),
    maxExtent: _('maxExtent'),
    range: {
      signal: `abs(span(range("${spec.scale}")))`
    },
    translate: _('translate'),
    // accessibility support
    format: spec.format,
    formatType: spec.formatType
  });
  return encode;
}

function parseScope (spec, scope, preprocessed) {
  const signals = vega_util_module_array(spec.signals),
    scales = vega_util_module_array(spec.scales);

  // parse signal definitions, if not already preprocessed
  if (!preprocessed) signals.forEach(_ => parseSignal(_, scope));

  // parse cartographic projection definitions
  vega_util_module_array(spec.projections).forEach(_ => parseProjection(_, scope));

  // initialize scale references
  scales.forEach(_ => initScale(_, scope));

  // parse data sources
  vega_util_module_array(spec.data).forEach(_ => parseData(_, scope));

  // parse scale definitions
  scales.forEach(_ => parseScale(_, scope));

  // parse signal updates
  (preprocessed || signals).forEach(_ => parseSignalUpdates(_, scope));

  // parse axis definitions
  vega_util_module_array(spec.axes).forEach(_ => parseAxis(_, scope));

  // parse mark definitions
  vega_util_module_array(spec.marks).forEach(_ => parseMark(_, scope));

  // parse legend definitions
  vega_util_module_array(spec.legends).forEach(_ => parseLegend(_, scope));

  // parse title, if defined
  if (spec.title) parseTitle(spec.title, scope);

  // parse collected lambda (anonymous) expressions
  scope.parseLambdas();
  return scope;
}

const rootEncode = spec => extendEncode({
  enter: {
    x: {
      value: 0
    },
    y: {
      value: 0
    }
  },
  update: {
    width: {
      signal: 'width'
    },
    height: {
      signal: 'height'
    }
  }
}, spec);
function parseView(spec, scope) {
  const config = scope.config;

  // add scenegraph root
  const root = vega_parser_module_ref(scope.root = scope.add(operator()));

  // parse top-level signal definitions
  const signals = collectSignals(spec, config);
  signals.forEach(_ => parseSignal(_, scope));

  // assign description, event, legend, and locale configuration
  scope.description = spec.description || config.description;
  scope.eventConfig = config.events;
  scope.legends = scope.objectProperty(config.legend && config.legend.layout);
  scope.locale = config.locale;

  // store root group item
  const input = scope.add(vega_parser_module_Collect());

  // encode root group item
  const encode = scope.add(vega_parser_module_Encode(parseEncode(rootEncode(spec.encode), GroupMark, vega_parser_module_FrameRole, spec.style, scope, {
    pulse: vega_parser_module_ref(input)
  })));

  // perform view layout
  const parent = scope.add(vega_parser_module_ViewLayout({
    layout: scope.objectProperty(spec.layout),
    legends: scope.legends,
    autosize: scope.signalRef('autosize'),
    mark: root,
    pulse: vega_parser_module_ref(encode)
  }));
  scope.operators.pop();

  // parse remainder of specification
  scope.pushState(vega_parser_module_ref(encode), vega_parser_module_ref(parent), null);
  parseScope(spec, scope, signals);
  scope.operators.push(parent);

  // bound / render / sieve root item
  let op = scope.add(vega_parser_module_Bound({
    mark: root,
    pulse: vega_parser_module_ref(parent)
  }));
  op = scope.add(vega_parser_module_Render({
    pulse: vega_parser_module_ref(op)
  }));
  op = scope.add(vega_parser_module_Sieve({
    pulse: vega_parser_module_ref(op)
  }));

  // track metadata for root item
  scope.addData('root', new DataScope(scope, input, input, op));
  return scope;
}
function signalObject(name, value) {
  return value && value.signal ? {
    name,
    update: value.signal
  } : {
    name,
    value
  };
}

/**
 * Collect top-level signals, merging values as needed. Signals
 * defined in the config signals arrays are added only if that
 * signal is not explicitly defined in the specification.
 * Built-in signals (autosize, background, padding, width, height)
 * receive special treatment. They are initialized using the
 * top-level spec property, or, if undefined in the spec, using
 * the corresponding top-level config property. If this property
 * is a signal reference object, the signal expression maps to the
 * signal 'update' property. If the spec's top-level signal array
 * contains an entry that matches a built-in signal, that entry
 * will be merged with the built-in specification, potentially
 * overwriting existing 'value' or 'update' properties.
 */
function collectSignals(spec, config) {
  const _ = name => vega_parser_module_value(spec[name], config[name]),
    signals = [signalObject('background', _('background')), signalObject('autosize', parseAutosize(_('autosize'))), signalObject('padding', parsePadding(_('padding'))), signalObject('width', _('width') || 0), signalObject('height', _('height') || 0)],
    pre = signals.reduce((p, s) => (p[s.name] = s, p), {}),
    map = {};

  // add spec signal array
  vega_util_module_array(spec.signals).forEach(s => {
    if (vega_util_module_has(pre, s.name)) {
      // merge if built-in signal
      s = extend(pre[s.name], s);
    } else {
      // otherwise add to signal list
      signals.push(s);
    }
    map[s.name] = s;
  });

  // add config signal array
  vega_util_module_array(config.signals).forEach(s => {
    if (!vega_util_module_has(map, s.name) && !vega_util_module_has(pre, s.name)) {
      // add to signal list if not already defined
      signals.push(s);
    }
  });
  return signals;
}

function vega_parser_module_Scope(config, options) {
  this.config = config || {};
  this.options = options || {};
  this.bindings = [];
  this.field = {};
  this.signals = {};
  this.lambdas = {};
  this.scales = {};
  this.events = {};
  this.data = {};
  this.streams = [];
  this.updates = [];
  this.operators = [];
  this.eventConfig = null;
  this.locale = null;
  this._id = 0;
  this._subid = 0;
  this._nextsub = [0];
  this._parent = [];
  this._encode = [];
  this._lookup = [];
  this._markpath = [];
}
function Subscope(scope) {
  this.config = scope.config;
  this.options = scope.options;
  this.legends = scope.legends;
  this.field = Object.create(scope.field);
  this.signals = Object.create(scope.signals);
  this.lambdas = Object.create(scope.lambdas);
  this.scales = Object.create(scope.scales);
  this.events = Object.create(scope.events);
  this.data = Object.create(scope.data);
  this.streams = [];
  this.updates = [];
  this.operators = [];
  this._id = 0;
  this._subid = ++scope._nextsub[0];
  this._nextsub = scope._nextsub;
  this._parent = scope._parent.slice();
  this._encode = scope._encode.slice();
  this._lookup = scope._lookup.slice();
  this._markpath = scope._markpath;
}
vega_parser_module_Scope.prototype = Subscope.prototype = {
  parse(spec) {
    return parseScope(spec, this);
  },
  fork() {
    return new Subscope(this);
  },
  isSubscope() {
    return this._subid > 0;
  },
  toRuntime() {
    this.finish();
    return {
      description: this.description,
      operators: this.operators,
      streams: this.streams,
      updates: this.updates,
      bindings: this.bindings,
      eventConfig: this.eventConfig,
      locale: this.locale
    };
  },
  id() {
    return (this._subid ? this._subid + ':' : 0) + this._id++;
  },
  add(op) {
    this.operators.push(op);
    op.id = this.id();
    // if pre-registration references exist, resolve them now
    if (op.refs) {
      op.refs.forEach(ref => {
        ref.$ref = op.id;
      });
      op.refs = null;
    }
    return op;
  },
  proxy(op) {
    const vref = op instanceof Entry ? vega_parser_module_ref(op) : op;
    return this.add(vega_parser_module_Proxy({
      value: vref
    }));
  },
  addStream(stream) {
    this.streams.push(stream);
    stream.id = this.id();
    return stream;
  },
  addUpdate(update) {
    this.updates.push(update);
    return update;
  },
  // Apply metadata
  finish() {
    let name, ds;

    // annotate root
    if (this.root) this.root.root = true;

    // annotate signals
    for (name in this.signals) {
      this.signals[name].signal = name;
    }

    // annotate scales
    for (name in this.scales) {
      this.scales[name].scale = name;
    }

    // annotate data sets
    function annotate(op, name, type) {
      let data, list;
      if (op) {
        data = op.data || (op.data = {});
        list = data[name] || (data[name] = []);
        list.push(type);
      }
    }
    for (name in this.data) {
      ds = this.data[name];
      annotate(ds.input, name, 'input');
      annotate(ds.output, name, 'output');
      annotate(ds.values, name, 'values');
      for (const field in ds.index) {
        annotate(ds.index[field], name, 'index:' + field);
      }
    }
    return this;
  },
  // ----

  pushState(encode, parent, lookup) {
    this._encode.push(vega_parser_module_ref(this.add(vega_parser_module_Sieve({
      pulse: encode
    }))));
    this._parent.push(parent);
    this._lookup.push(lookup ? vega_parser_module_ref(this.proxy(lookup)) : null);
    this._markpath.push(-1);
  },
  popState() {
    this._encode.pop();
    this._parent.pop();
    this._lookup.pop();
    this._markpath.pop();
  },
  parent() {
    return peek(this._parent);
  },
  encode() {
    return peek(this._encode);
  },
  lookup() {
    return peek(this._lookup);
  },
  markpath() {
    const p = this._markpath;
    return ++p[p.length - 1];
  },
  // ----

  fieldRef(field, name) {
    if (vega_util_module_isString(field)) return fieldRef$1(field, name);
    if (!field.signal) {
      vega_util_module_error('Unsupported field reference: ' + $(field));
    }
    const s = field.signal;
    let f = this.field[s];
    if (!f) {
      const params = {
        name: this.signalRef(s)
      };
      if (name) params.as = name;
      this.field[s] = f = vega_parser_module_ref(this.add(vega_parser_module_Field(params)));
    }
    return f;
  },
  compareRef(cmp) {
    let signal = false;
    const check = _ => isSignal(_) ? (signal = true, this.signalRef(_.signal)) : isExpr$1(_) ? (signal = true, this.exprRef(_.expr)) : _;
    const fields = vega_util_module_array(cmp.field).map(check),
      orders = vega_util_module_array(cmp.order).map(check);
    return signal ? vega_parser_module_ref(this.add(vega_parser_module_Compare({
      fields: fields,
      orders: orders
    }))) : compareRef(fields, orders);
  },
  keyRef(fields, flat) {
    let signal = false;
    const check = _ => isSignal(_) ? (signal = true, vega_parser_module_ref(sig[_.signal])) : _;
    const sig = this.signals;
    fields = vega_util_module_array(fields).map(check);
    return signal ? vega_parser_module_ref(this.add(vega_parser_module_Key({
      fields: fields,
      flat: flat
    }))) : keyRef(fields, flat);
  },
  sortRef(sort) {
    if (!sort) return sort;

    // including id ensures stable sorting
    const a = aggrField(sort.op, sort.field),
      o = sort.order || Ascending;
    return o.signal ? vega_parser_module_ref(this.add(vega_parser_module_Compare({
      fields: a,
      orders: this.signalRef(o.signal)
    }))) : compareRef(a, o);
  },
  // ----

  event(source, type) {
    const key = source + ':' + type;
    if (!this.events[key]) {
      const id = this.id();
      this.streams.push({
        id: id,
        source: source,
        type: type
      });
      this.events[key] = id;
    }
    return this.events[key];
  },
  // ----

  hasOwnSignal(name) {
    return vega_util_module_has(this.signals, name);
  },
  addSignal(name, value) {
    if (this.hasOwnSignal(name)) {
      vega_util_module_error('Duplicate signal name: ' + $(name));
    }
    const op = value instanceof Entry ? value : this.add(operator(value));
    return this.signals[name] = op;
  },
  getSignal(name) {
    if (!this.signals[name]) {
      vega_util_module_error('Unrecognized signal name: ' + $(name));
    }
    return this.signals[name];
  },
  signalRef(s) {
    if (this.signals[s]) {
      return vega_parser_module_ref(this.signals[s]);
    } else if (!vega_util_module_has(this.lambdas, s)) {
      this.lambdas[s] = this.add(operator(null));
    }
    return vega_parser_module_ref(this.lambdas[s]);
  },
  parseLambdas() {
    const code = Object.keys(this.lambdas);
    for (let i = 0, n = code.length; i < n; ++i) {
      const s = code[i],
        e = vega_functions_module_parser(s, this),
        op = this.lambdas[s];
      op.params = e.$params;
      op.update = e.$expr;
    }
  },
  property(spec) {
    return spec && spec.signal ? this.signalRef(spec.signal) : spec;
  },
  objectProperty(spec) {
    return !spec || !vega_util_module_isObject(spec) ? spec : this.signalRef(spec.signal || propertyLambda(spec));
  },
  exprRef(code, name) {
    const params = {
      expr: vega_functions_module_parser(code, this)
    };
    if (name) params.expr.$name = name;
    return vega_parser_module_ref(this.add(vega_parser_module_Expression(params)));
  },
  addBinding(name, bind) {
    if (!this.bindings) {
      vega_util_module_error('Nested signals do not support binding: ' + $(name));
    }
    this.bindings.push(extend({
      signal: name
    }, bind));
  },
  // ----

  addScaleProj(name, transform) {
    if (vega_util_module_has(this.scales, name)) {
      vega_util_module_error('Duplicate scale or projection name: ' + $(name));
    }
    this.scales[name] = this.add(transform);
  },
  addScale(name, params) {
    this.addScaleProj(name, vega_parser_module_Scale(params));
  },
  addProjection(name, params) {
    this.addScaleProj(name, vega_parser_module_Projection(params));
  },
  getScale(name) {
    if (!this.scales[name]) {
      vega_util_module_error('Unrecognized scale name: ' + $(name));
    }
    return this.scales[name];
  },
  scaleRef(name) {
    return vega_parser_module_ref(this.getScale(name));
  },
  scaleType(name) {
    return this.getScale(name).params.type;
  },
  projectionRef(name) {
    return this.scaleRef(name);
  },
  projectionType(name) {
    return this.scaleType(name);
  },
  // ----

  addData(name, dataScope) {
    if (vega_util_module_has(this.data, name)) {
      vega_util_module_error('Duplicate data set name: ' + $(name));
    }
    return this.data[name] = dataScope;
  },
  getData(name) {
    if (!this.data[name]) {
      vega_util_module_error('Undefined data set name: ' + $(name));
    }
    return this.data[name];
  },
  addDataPipeline(name, entries) {
    if (vega_util_module_has(this.data, name)) {
      vega_util_module_error('Duplicate data set name: ' + $(name));
    }
    return this.addData(name, DataScope.fromEntries(this, entries));
  }
};
function propertyLambda(spec) {
  return (vega_util_module_isArray(spec) ? arrayLambda : objectLambda)(spec);
}
function arrayLambda(array) {
  const n = array.length;
  let code = '[';
  for (let i = 0; i < n; ++i) {
    const value = array[i];
    code += (i > 0 ? ',' : '') + (vega_util_module_isObject(value) ? value.signal || propertyLambda(value) : $(value));
  }
  return code + ']';
}
function objectLambda(obj) {
  let code = '{',
    i = 0,
    key,
    value;
  for (key in obj) {
    value = obj[key];
    code += (++i > 1 ? ',' : '') + $(key) + ':' + (vega_util_module_isObject(value) ? value.signal || propertyLambda(value) : $(value));
  }
  return code + '}';
}

/**
 * Standard configuration defaults for Vega specification parsing.
 * Users can provide their own (sub-)set of these default values
 * by passing in a config object to the top-level parse method.
 */
function defaults () {
  const defaultFont = 'sans-serif',
    defaultSymbolSize = 30,
    defaultStrokeWidth = 2,
    defaultColor = '#4c78a8',
    black = '#000',
    gray = '#888',
    lightGray = '#ddd';
  return {
    // default visualization description
    description: 'Vega visualization',
    // default padding around visualization
    padding: 0,
    // default for automatic sizing; options: 'none', 'pad', 'fit'
    // or provide an object (e.g., {'type': 'pad', 'resize': true})
    autosize: 'pad',
    // default view background color
    // covers the entire view component
    background: null,
    // default event handling configuration
    // preventDefault for view-sourced event types except 'wheel'
    events: {
      defaults: {
        allow: ['wheel']
      }
    },
    // defaults for top-level group marks
    // accepts mark properties (fill, stroke, etc)
    // covers the data rectangle within group width/height
    group: null,
    // defaults for basic mark types
    // each subset accepts mark properties (fill, stroke, etc)
    mark: null,
    arc: {
      fill: defaultColor
    },
    area: {
      fill: defaultColor
    },
    image: null,
    line: {
      stroke: defaultColor,
      strokeWidth: defaultStrokeWidth
    },
    path: {
      stroke: defaultColor
    },
    rect: {
      fill: defaultColor
    },
    rule: {
      stroke: black
    },
    shape: {
      stroke: defaultColor
    },
    symbol: {
      fill: defaultColor,
      size: 64
    },
    text: {
      fill: black,
      font: defaultFont,
      fontSize: 11
    },
    trail: {
      fill: defaultColor,
      size: defaultStrokeWidth
    },
    // style definitions
    style: {
      // axis & legend labels
      'guide-label': {
        fill: black,
        font: defaultFont,
        fontSize: 10
      },
      // axis & legend titles
      'guide-title': {
        fill: black,
        font: defaultFont,
        fontSize: 11,
        fontWeight: 'bold'
      },
      // headers, including chart title
      'group-title': {
        fill: black,
        font: defaultFont,
        fontSize: 13,
        fontWeight: 'bold'
      },
      // chart subtitle
      'group-subtitle': {
        fill: black,
        font: defaultFont,
        fontSize: 12
      },
      // defaults for styled point marks in Vega-Lite
      point: {
        size: defaultSymbolSize,
        strokeWidth: defaultStrokeWidth,
        shape: 'circle'
      },
      circle: {
        size: defaultSymbolSize,
        strokeWidth: defaultStrokeWidth
      },
      square: {
        size: defaultSymbolSize,
        strokeWidth: defaultStrokeWidth,
        shape: 'square'
      },
      // defaults for styled group marks in Vega-Lite
      cell: {
        fill: 'transparent',
        stroke: lightGray
      },
      view: {
        fill: 'transparent'
      }
    },
    // defaults for title
    title: {
      orient: 'top',
      anchor: 'middle',
      offset: 4,
      subtitlePadding: 3
    },
    // defaults for axes
    axis: {
      minExtent: 0,
      maxExtent: 200,
      bandPosition: 0.5,
      domain: true,
      domainWidth: 1,
      domainColor: gray,
      grid: false,
      gridWidth: 1,
      gridColor: lightGray,
      labels: true,
      labelAngle: 0,
      labelLimit: 180,
      labelOffset: 0,
      labelPadding: 2,
      ticks: true,
      tickColor: gray,
      tickOffset: 0,
      tickRound: true,
      tickSize: 5,
      tickWidth: 1,
      titlePadding: 4
    },
    // correction for centering bias
    axisBand: {
      tickOffset: -0.5
    },
    // defaults for cartographic projection
    projection: {
      type: 'mercator'
    },
    // defaults for legends
    legend: {
      orient: 'right',
      padding: 0,
      gridAlign: 'each',
      columnPadding: 10,
      rowPadding: 2,
      symbolDirection: 'vertical',
      gradientDirection: 'vertical',
      gradientLength: 200,
      gradientThickness: 16,
      gradientStrokeColor: lightGray,
      gradientStrokeWidth: 0,
      gradientLabelOffset: 2,
      labelAlign: 'left',
      labelBaseline: 'middle',
      labelLimit: 160,
      labelOffset: 4,
      labelOverlap: true,
      symbolLimit: 30,
      symbolType: 'circle',
      symbolSize: 100,
      symbolOffset: 0,
      symbolStrokeWidth: 1.5,
      symbolBaseFillColor: 'transparent',
      symbolBaseStrokeColor: gray,
      titleLimit: 180,
      titleOrient: 'top',
      titlePadding: 5,
      layout: {
        offset: 18,
        direction: 'horizontal',
        left: {
          direction: 'vertical'
        },
        right: {
          direction: 'vertical'
        }
      }
    },
    // defaults for scale ranges
    range: {
      category: {
        scheme: 'tableau10'
      },
      ordinal: {
        scheme: 'blues'
      },
      heatmap: {
        scheme: 'yellowgreenblue'
      },
      ramp: {
        scheme: 'blues'
      },
      diverging: {
        scheme: 'blueorange',
        extent: [1, 0]
      },
      symbol: ['circle', 'square', 'triangle-up', 'cross', 'diamond', 'triangle-right', 'triangle-down', 'triangle-left']
    }
  };
}

function vega_parser_module_parse (spec, config, options) {
  if (!vega_util_module_isObject(spec)) {
    vega_util_module_error('Input Vega specification must be an object.');
  }
  config = mergeConfig(defaults(), config, spec.config);
  return parseView(spec, new vega_parser_module_Scope(config, options)).toRuntime();
}



;// ../../node_modules/vega/build/vega.module.js





























var vega_module_version = "5.33.0";

// -- Transforms -----

extend(vega_dataflow_module_transforms, vega_transforms_module_namespaceObject, vega_view_transforms_module_namespaceObject, vega_encode_module_namespaceObject, vega_geo_module_namespaceObject, vega_force_module_namespaceObject, vega_label_module_namespaceObject, vega_hierarchy_module_namespaceObject, vega_regression_module_namespaceObject, vega_voronoi_module_namespaceObject, vega_wordcloud_module_namespaceObject, vega_crossfilter_module_namespaceObject);



;// ../../node_modules/vega-interpreter/build/vega-interpreter.module.js


function vega_interpreter_module_adjustSpatial (item, encode, swap) {
  let t;
  if (encode.x2) {
    if (encode.x) {
      if (swap && item.x > item.x2) {
        t = item.x;
        item.x = item.x2;
        item.x2 = t;
      }
      item.width = item.x2 - item.x;
    } else {
      item.x = item.x2 - (item.width || 0);
    }
  }
  if (encode.xc) {
    item.x = item.xc - (item.width || 0) / 2;
  }
  if (encode.y2) {
    if (encode.y) {
      if (swap && item.y > item.y2) {
        t = item.y;
        item.y = item.y2;
        item.y2 = t;
      }
      item.height = item.y2 - item.y;
    } else {
      item.y = item.y2 - (item.height || 0);
    }
  }
  if (encode.yc) {
    item.y = item.yc - (item.height || 0) / 2;
  }
}

var vega_interpreter_module_Constants = {
  NaN: NaN,
  E: Math.E,
  LN2: Math.LN2,
  LN10: Math.LN10,
  LOG2E: Math.LOG2E,
  LOG10E: Math.LOG10E,
  PI: Math.PI,
  SQRT1_2: Math.SQRT1_2,
  SQRT2: Math.SQRT2,
  MIN_VALUE: Number.MIN_VALUE,
  MAX_VALUE: Number.MAX_VALUE
};

var Ops = {
  '*': (a, b) => a * b,
  '+': (a, b) => a + b,
  '-': (a, b) => a - b,
  '/': (a, b) => a / b,
  '%': (a, b) => a % b,
  '>': (a, b) => a > b,
  '<': (a, b) => a < b,
  '<=': (a, b) => a <= b,
  '>=': (a, b) => a >= b,
  '==': (a, b) => a == b,
  '!=': (a, b) => a != b,
  '===': (a, b) => a === b,
  '!==': (a, b) => a !== b,
  '&': (a, b) => a & b,
  '|': (a, b) => a | b,
  '^': (a, b) => a ^ b,
  '<<': (a, b) => a << b,
  '>>': (a, b) => a >> b,
  '>>>': (a, b) => a >>> b
};

var Unary = {
  '+': a => +a,
  '-': a => -a,
  '~': a => ~a,
  '!': a => !a
};

const vega_interpreter_module_slice = Array.prototype.slice;
const vega_interpreter_module_apply = (m, args, cast) => {
  const obj = cast ? cast(args[0]) : args[0];
  return obj[m].apply(obj, vega_interpreter_module_slice.call(args, 1));
};
const vega_interpreter_module_datetime = (y, m, d, H, M, S, ms) => new Date(y, m || 0, d != null ? d : 1, H || 0, M || 0, S || 0, ms || 0);
var vega_interpreter_module_Functions = {
  // math functions
  isNaN: Number.isNaN,
  isFinite: Number.isFinite,
  abs: Math.abs,
  acos: Math.acos,
  asin: Math.asin,
  atan: Math.atan,
  atan2: Math.atan2,
  ceil: Math.ceil,
  cos: Math.cos,
  exp: Math.exp,
  floor: Math.floor,
  log: Math.log,
  max: Math.max,
  min: Math.min,
  pow: Math.pow,
  random: Math.random,
  round: Math.round,
  sin: Math.sin,
  sqrt: Math.sqrt,
  tan: Math.tan,
  clamp: (a, b, c) => Math.max(b, Math.min(c, a)),
  // date functions
  now: Date.now,
  utc: Date.UTC,
  datetime: vega_interpreter_module_datetime,
  date: d => new Date(d).getDate(),
  day: d => new Date(d).getDay(),
  year: d => new Date(d).getFullYear(),
  month: d => new Date(d).getMonth(),
  hours: d => new Date(d).getHours(),
  minutes: d => new Date(d).getMinutes(),
  seconds: d => new Date(d).getSeconds(),
  milliseconds: d => new Date(d).getMilliseconds(),
  time: d => new Date(d).getTime(),
  timezoneoffset: d => new Date(d).getTimezoneOffset(),
  utcdate: d => new Date(d).getUTCDate(),
  utcday: d => new Date(d).getUTCDay(),
  utcyear: d => new Date(d).getUTCFullYear(),
  utcmonth: d => new Date(d).getUTCMonth(),
  utchours: d => new Date(d).getUTCHours(),
  utcminutes: d => new Date(d).getUTCMinutes(),
  utcseconds: d => new Date(d).getUTCSeconds(),
  utcmilliseconds: d => new Date(d).getUTCMilliseconds(),
  // sequence functions
  length: x => x.length,
  join: function () {
    return vega_interpreter_module_apply('join', arguments);
  },
  indexof: function () {
    return vega_interpreter_module_apply('indexOf', arguments);
  },
  lastindexof: function () {
    return vega_interpreter_module_apply('lastIndexOf', arguments);
  },
  slice: function () {
    return vega_interpreter_module_apply('slice', arguments);
  },
  reverse: x => x.slice().reverse(),
  sort: x => x.slice().sort(vega_util_module_ascending),
  // string functions
  parseFloat: parseFloat,
  parseInt: parseInt,
  upper: x => String(x).toUpperCase(),
  lower: x => String(x).toLowerCase(),
  substring: function () {
    return vega_interpreter_module_apply('substring', arguments, String);
  },
  split: function () {
    return vega_interpreter_module_apply('split', arguments, String);
  },
  replace: function () {
    return vega_interpreter_module_apply('replace', arguments, String);
  },
  trim: x => String(x).trim(),
  // Base64 encode/decode
  // Convert binary string to base64-encoded ascii
  btoa: x => btoa(x),
  // Convert base64-encoded ascii to binary string
  atob: x => atob(x),
  // regexp functions
  regexp: RegExp,
  test: (r, t) => RegExp(r).test(t)
};

const EventFunctions = ['view', 'item', 'group', 'xy', 'x', 'y'];
const DisallowedMethods = new Set([Function, eval, setTimeout, setInterval]);
if (typeof setImmediate === 'function') DisallowedMethods.add(setImmediate);
const Visitors = {
  Literal: ($, n) => n.value,
  Identifier: ($, n) => {
    const id = n.name;
    return $.memberDepth > 0 ? id : id === 'datum' ? $.datum : id === 'event' ? $.event : id === 'item' ? $.item : vega_interpreter_module_Constants[id] || $.params['$' + id];
  },
  MemberExpression: ($, n) => {
    const d = !n.computed,
      o = $(n.object);
    if (d) $.memberDepth += 1;
    const p = $(n.property);
    if (d) $.memberDepth -= 1;
    if (DisallowedMethods.has(o[p])) {
      // eslint-disable-next-line no-console
      console.error(`Prevented interpretation of member "${p}" which could lead to insecure code execution`);
      return;
    }
    return o[p];
  },
  CallExpression: ($, n) => {
    const args = n.arguments;
    let name = n.callee.name;

    // handle special internal functions used by encoders
    // re-route to corresponding standard function
    if (name.startsWith('_')) {
      name = name.slice(1);
    }

    // special case "if" due to conditional evaluation of branches
    return name === 'if' ? $(args[0]) ? $(args[1]) : $(args[2]) : ($.fn[name] || vega_interpreter_module_Functions[name]).apply($.fn, args.map($));
  },
  ArrayExpression: ($, n) => n.elements.map($),
  BinaryExpression: ($, n) => Ops[n.operator]($(n.left), $(n.right)),
  UnaryExpression: ($, n) => Unary[n.operator]($(n.argument)),
  ConditionalExpression: ($, n) => $(n.test) ? $(n.consequent) : $(n.alternate),
  LogicalExpression: ($, n) => n.operator === '&&' ? $(n.left) && $(n.right) : $(n.left) || $(n.right),
  ObjectExpression: ($, n) => n.properties.reduce((o, p) => {
    $.memberDepth += 1;
    const k = $(p.key);
    $.memberDepth -= 1;
    if (DisallowedMethods.has($(p.value))) {
      // eslint-disable-next-line no-console
      console.error(`Prevented interpretation of property "${k}" which could lead to insecure code execution`);
    } else {
      o[k] = $(p.value);
    }
    return o;
  }, {})
};
function interpret (ast, fn, params, datum, event, item) {
  const $ = n => Visitors[n.type]($, n);
  $.memberDepth = 0;
  $.fn = Object.create(fn);
  $.params = params;
  $.datum = datum;
  $.event = event;
  $.item = item;

  // route event functions to annotated vega event context
  EventFunctions.forEach(f => $.fn[f] = function () {
    return event.vega[f](...arguments);
  });
  return $(ast);
}

var vega_interpreter_module_expression = {
  /**
   * Parse an expression used to update an operator value.
   */
  operator(ctx, expr) {
    const ast = expr.ast,
      fn = ctx.functions;
    return _ => interpret(ast, fn, _);
  },
  /**
   * Parse an expression provided as an operator parameter value.
   */
  parameter(ctx, expr) {
    const ast = expr.ast,
      fn = ctx.functions;
    return (datum, _) => interpret(ast, fn, _, datum);
  },
  /**
   * Parse an expression applied to an event stream.
   */
  event(ctx, expr) {
    const ast = expr.ast,
      fn = ctx.functions;
    return event => interpret(ast, fn, undefined, undefined, event);
  },
  /**
   * Parse an expression used to handle an event-driven operator update.
   */
  handler(ctx, expr) {
    const ast = expr.ast,
      fn = ctx.functions;
    return (_, event) => {
      const datum = event.item && event.item.datum;
      return interpret(ast, fn, _, datum, event);
    };
  },
  /**
   * Parse an expression that performs visual encoding.
   */
  encode(ctx, encode) {
    const {
        marktype,
        channels
      } = encode,
      fn = ctx.functions,
      swap = marktype === 'group' || marktype === 'image' || marktype === 'rect';
    return (item, _) => {
      const datum = item.datum;
      let m = 0,
        v;
      for (const name in channels) {
        v = interpret(channels[name].ast, fn, _, datum, undefined, item);
        if (item[name] !== v) {
          item[name] = v;
          m = 1;
        }
      }
      if (marktype !== 'rule') {
        vega_interpreter_module_adjustSpatial(item, channels, swap);
      }
      return m;
    };
  }
};



;// ../../node_modules/vega-lite/build/package.json
const package_namespaceObject = {"rE":"5.23.0"};
;// ../../node_modules/vega-lite/build/src/logical.js

function isLogicalOr(op) {
    return util_hasProperty(op, 'or');
}
function isLogicalAnd(op) {
    return util_hasProperty(op, 'and');
}
function isLogicalNot(op) {
    return util_hasProperty(op, 'not');
}
function forEachLeaf(op, fn) {
    if (isLogicalNot(op)) {
        forEachLeaf(op.not, fn);
    }
    else if (isLogicalAnd(op)) {
        for (const subop of op.and) {
            forEachLeaf(subop, fn);
        }
    }
    else if (isLogicalOr(op)) {
        for (const subop of op.or) {
            forEachLeaf(subop, fn);
        }
    }
    else {
        fn(op);
    }
}
function normalizeLogicalComposition(op, normalizer) {
    if (isLogicalNot(op)) {
        return { not: normalizeLogicalComposition(op.not, normalizer) };
    }
    else if (isLogicalAnd(op)) {
        return { and: op.and.map(o => normalizeLogicalComposition(o, normalizer)) };
    }
    else if (isLogicalOr(op)) {
        return { or: op.or.map(o => normalizeLogicalComposition(o, normalizer)) };
    }
    else {
        return normalizer(op);
    }
}
//# sourceMappingURL=logical.js.map
;// ../../node_modules/vega-lite/build/src/util.js


const duplicate = structuredClone;
function never(message) {
    throw new Error(message);
}
/**
 * Creates an object composed of the picked object properties.
 *
 * var object = {'a': 1, 'b': '2', 'c': 3};
 * pick(object, ['a', 'c']);
 * // → {'a': 1, 'c': 3}
 */
// eslint-disable-next-line @typescript-eslint/ban-types
function util_pick(obj, props) {
    const copy = {};
    for (const prop of props) {
        if (vega_util_module_has(obj, prop)) {
            copy[prop] = obj[prop];
        }
    }
    return copy;
}
/**
 * The opposite of _.pick; this method creates an object composed of the own
 * and inherited enumerable string keyed properties of object that are not omitted.
 */
// eslint-disable-next-line @typescript-eslint/ban-types
function omit(obj, props) {
    const copy = { ...obj };
    for (const prop of props) {
        delete copy[prop];
    }
    return copy;
}
/**
 * Monkey patch Set so that `stringify` produces a string representation of sets.
 */
Set.prototype['toJSON'] = function () {
    return `Set(${[...this].map(x => util_stringify(x)).join(',')})`;
};
/**
 * Converts any object to a string of limited size, or a number.
 */
function util_hash(a) {
    if (vega_util_module_isNumber(a)) {
        return a;
    }
    const str = vega_util_module_isString(a) ? a : util_stringify(a);
    // short strings can be used as hash directly, longer strings are hashed to reduce memory usage
    if (str.length < 250) {
        return str;
    }
    // from http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
    let h = 0;
    for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        h = (h << 5) - h + char;
        h = h & h; // Convert to 32bit integer
    }
    return h;
}
function isNullOrFalse(x) {
    return x === false || x === null;
}
function util_contains(array, item) {
    return array.includes(item);
}
/**
 * Returns true if any item returns true.
 */
function some(arr, f) {
    let i = 0;
    for (const [k, a] of arr.entries()) {
        if (f(a, k, i++)) {
            return true;
        }
    }
    return false;
}
/**
 * Returns true if all items return true.
 */
function every(arr, f) {
    let i = 0;
    for (const [k, a] of arr.entries()) {
        if (!f(a, k, i++)) {
            return false;
        }
    }
    return true;
}
/**
 * recursively merges src into dest
 */
function mergeDeep(dest, ...src) {
    for (const s of src) {
        deepMerge_(dest, s ?? {});
    }
    return dest;
}
function deepMerge_(dest, src) {
    for (const property of util_keys(src)) {
        writeConfig(dest, property, src[property], true);
    }
}
function unique(values, f) {
    const results = [];
    const u = {};
    let v;
    for (const val of values) {
        v = f(val);
        if (v in u) {
            continue;
        }
        u[v] = 1;
        results.push(val);
    }
    return results;
}
/**
 * Returns true if the two dictionaries agree. Applies only to defined values.
 */
function isEqual(dict, other) {
    const dictKeys = util_keys(dict);
    const otherKeys = util_keys(other);
    if (dictKeys.length !== otherKeys.length) {
        return false;
    }
    for (const key of dictKeys) {
        if (dict[key] !== other[key]) {
            return false;
        }
    }
    return true;
}
function setEqual(a, b) {
    if (a.size !== b.size) {
        return false;
    }
    for (const e of a) {
        if (!b.has(e)) {
            return false;
        }
    }
    return true;
}
function hasIntersection(a, b) {
    for (const key of a) {
        if (b.has(key)) {
            return true;
        }
    }
    return false;
}
function prefixGenerator(a) {
    const prefixes = new Set();
    for (const x of a) {
        const splitField = splitAccessPath(x);
        // Wrap every element other than the first in `[]`
        const wrappedWithAccessors = splitField.map((y, i) => (i === 0 ? y : `[${y}]`));
        const computedPrefixes = wrappedWithAccessors.map((_, i) => wrappedWithAccessors.slice(0, i + 1).join(''));
        for (const y of computedPrefixes) {
            prefixes.add(y);
        }
    }
    return prefixes;
}
/**
 * Returns true if a and b have an intersection. Also return true if a or b are undefined
 * since this means we don't know what fields a node produces or depends on.
 */
function fieldIntersection(a, b) {
    if (a === undefined || b === undefined) {
        return true;
    }
    return hasIntersection(prefixGenerator(a), prefixGenerator(b));
}
// eslint-disable-next-line @typescript-eslint/ban-types
function isEmpty(obj) {
    return util_keys(obj).length === 0;
}
// This is a stricter version of Object.keys but with better types. See https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208
const util_keys = Object.keys;
// Stricter version from https://github.com/microsoft/TypeScript/issues/51572#issuecomment-1319153323
const vals = Object.values;
// Stricter version from https://github.com/microsoft/TypeScript/issues/51572#issuecomment-1319153323
const util_entries = Object.entries;
function util_isBoolean(b) {
    return b === true || b === false;
}
/**
 * Convert a string into a valid variable name
 */
function varName(s) {
    // Replace non-alphanumeric characters (anything besides a-zA-Z0-9_) with _
    const alphanumericS = s.replace(/\W/g, '_');
    // Add _ if the string has leading numbers.
    return (s.match(/^\d+/) ? '_' : '') + alphanumericS;
}
function logicalExpr(op, cb) {
    if (isLogicalNot(op)) {
        return `!(${logicalExpr(op.not, cb)})`;
    }
    else if (isLogicalAnd(op)) {
        return `(${op.and.map((and) => logicalExpr(and, cb)).join(') && (')})`;
    }
    else if (isLogicalOr(op)) {
        return `(${op.or.map((or) => logicalExpr(or, cb)).join(') || (')})`;
    }
    else {
        return cb(op);
    }
}
/**
 * Delete nested property of an object, and delete the ancestors of the property if they become empty.
 */
function deleteNestedProperty(obj, orderedProps) {
    if (orderedProps.length === 0) {
        return true;
    }
    const prop = orderedProps.shift(); // eslint-disable-line @typescript-eslint/no-non-null-assertion
    if (prop in obj && deleteNestedProperty(obj[prop], orderedProps)) {
        delete obj[prop];
    }
    return isEmpty(obj);
}
function titleCase(s) {
    return s.charAt(0).toUpperCase() + s.substr(1);
}
/**
 * Converts a path to an access path with datum.
 * @param path The field name.
 * @param datum The string to use for `datum`.
 */
function accessPathWithDatum(path, datum = 'datum') {
    const pieces = splitAccessPath(path);
    const prefixes = [];
    for (let i = 1; i <= pieces.length; i++) {
        const prefix = `[${pieces.slice(0, i).map($).join('][')}]`;
        prefixes.push(`${datum}${prefix}`);
    }
    return prefixes.join(' && ');
}
/**
 * Return access with datum to the flattened field.
 *
 * @param path The field name.
 * @param datum The string to use for `datum`.
 */
function flatAccessWithDatum(path, datum = 'datum') {
    return `${datum}[${$(splitAccessPath(path).join('.'))}]`;
}
/**
 * Return access with datum to **an unescaped path**.
 *
 * ```ts
 * console.log(accessWithDatumToUnescapedPath("vega's favorite"))
 * // "datum['vega\\'s favorite']"
 * ```
 *
 * @param path The unescaped path name. E.g., `"a.b"`, `"vega's favorite"`. (Note
 * that the field defs take escaped strings like `"a\\.b"`, `"vega\\'s favorite"`,
 * but this function is for the unescaped field/path)
 */
function accessWithDatumToUnescapedPath(unescapedPath) {
    const singleQuoteEscapedPath = unescapedPath.replaceAll("'", "\\'");
    return `datum['${singleQuoteEscapedPath}']`;
}
function escapePathAccess(string) {
    return string.replace(/(\[|\]|\.|'|")/g, '\\$1');
}
/**
 * Replaces path accesses with access to non-nested field.
 * For example, `foo["bar"].baz` becomes `foo\\.bar\\.baz`.
 */
function replacePathInField(path) {
    return `${splitAccessPath(path).map(escapePathAccess).join('\\.')}`;
}
/**
 * Replace all occurrences of a string with another string.
 *
 * @param string the string to replace in
 * @param find the string to replace
 * @param replacement the replacement
 */
function replaceAll(string, find, replacement) {
    return string.replace(new RegExp(find.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replacement);
}
/**
 * Remove path accesses with access from field.
 * For example, `foo["bar"].baz` becomes `foo.bar.baz`.
 */
function removePathFromField(path) {
    return `${splitAccessPath(path).join('.')}`;
}
/**
 * Count the depth of the path. Returns 1 for fields that are not nested.
 */
function accessPathDepth(path) {
    if (!path) {
        return 0;
    }
    return splitAccessPath(path).length;
}
/**
 * This is a replacement for chained || for numeric properties or properties that respect null so that 0 will be included.
 */
function getFirstDefined(...args) {
    return args.find(a => a !== undefined);
}
// variable used to generate id
let idCounter = 42;
/**
 * Returns a new random id every time it gets called.
 *
 * Has side effect!
 */
function uniqueId(prefix) {
    const id = ++idCounter;
    return prefix ? String(prefix) + id : id;
}
/**
 * Resets the id counter used in uniqueId. This can be useful for testing.
 */
function resetIdCounter() {
    idCounter = 42;
}
function internalField(name) {
    return isInternalField(name) ? name : `__${name}`;
}
function isInternalField(name) {
    return name.startsWith('__');
}
/**
 * Normalize angle to be within [0,360).
 */
function normalizeAngle(angle) {
    if (angle === undefined) {
        return undefined;
    }
    return ((angle % 360) + 360) % 360;
}
/**
 * Returns whether the passed in value is a valid number.
 */
function isNumeric(value) {
    if (vega_util_module_isNumber(value)) {
        return true;
    }
    return !isNaN(value) && !isNaN(parseFloat(value));
}
const clonedProto = Object.getPrototypeOf(structuredClone({}));
/**
 * Compares two values for equality, including arrays and objects.
 *
 * Adapted from https://github.com/epoberezkin/fast-deep-equal.
 */
function util_deepEqual(a, b) {
    if (a === b)
        return true;
    if (a && b && typeof a == 'object' && typeof b == 'object') {
        // compare names to avoid issues with structured clone
        if (a.constructor.name !== b.constructor.name)
            return false;
        let length;
        let i;
        if (Array.isArray(a)) {
            length = a.length;
            if (length != b.length)
                return false;
            for (i = length; i-- !== 0;)
                if (!util_deepEqual(a[i], b[i]))
                    return false;
            return true;
        }
        if (a instanceof Map && b instanceof Map) {
            if (a.size !== b.size)
                return false;
            for (const e of a.entries())
                if (!b.has(e[0]))
                    return false;
            for (const e of a.entries())
                if (!util_deepEqual(e[1], b.get(e[0])))
                    return false;
            return true;
        }
        if (a instanceof Set && b instanceof Set) {
            if (a.size !== b.size)
                return false;
            for (const e of a.entries())
                if (!b.has(e[0]))
                    return false;
            return true;
        }
        if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
            length = a.length;
            if (length != b.length)
                return false;
            for (i = length; i-- !== 0;)
                if (a[i] !== b[i])
                    return false;
            return true;
        }
        if (a.constructor === RegExp)
            return a.source === b.source && a.flags === b.flags;
        // also compare to structured clone prototype
        if (a.valueOf !== Object.prototype.valueOf && a.valueOf !== clonedProto.valueOf)
            return a.valueOf() === b.valueOf();
        if (a.toString !== Object.prototype.toString && a.toString !== clonedProto.toString)
            return a.toString() === b.toString();
        const ks = Object.keys(a);
        length = ks.length;
        if (length !== Object.keys(b).length)
            return false;
        for (i = length; i-- !== 0;)
            if (!Object.prototype.hasOwnProperty.call(b, ks[i]))
                return false;
        for (i = length; i-- !== 0;) {
            const key = ks[i];
            if (!util_deepEqual(a[key], b[key]))
                return false;
        }
        return true;
    }
    // true if both NaN, false otherwise
    return a !== a && b !== b;
}
/**
 * Converts any object to a string representation that can be consumed by humans.
 *
 * Adapted from https://github.com/epoberezkin/fast-json-stable-stringify
 */
function util_stringify(data) {
    const seen = [];
    return (function _stringify(node) {
        if (node && node.toJSON && typeof node.toJSON === 'function') {
            node = node.toJSON();
        }
        if (node === undefined)
            return undefined;
        if (typeof node == 'number')
            return isFinite(node) ? '' + node : 'null';
        if (typeof node !== 'object')
            return JSON.stringify(node);
        let i, out;
        if (Array.isArray(node)) {
            out = '[';
            for (i = 0; i < node.length; i++) {
                if (i)
                    out += ',';
                out += _stringify(node[i]) || 'null';
            }
            return out + ']';
        }
        if (node === null)
            return 'null';
        if (seen.includes(node)) {
            throw new TypeError('Converting circular structure to JSON');
        }
        const seenIndex = seen.push(node) - 1;
        const ks = Object.keys(node).sort();
        out = '';
        for (i = 0; i < ks.length; i++) {
            const key = ks[i];
            const value = _stringify(node[key]);
            if (!value)
                continue;
            if (out)
                out += ',';
            out += JSON.stringify(key) + ':' + value;
        }
        seen.splice(seenIndex, 1);
        return `{${out}}`;
    })(data);
}
/**
 * Check if the input object has the property and it's not undefined.
 *
 * @param object the object
 * @param property the property to search
 * @returns if the object has the property and it's not undefined.
 */
function util_hasProperty(obj, key) {
    return vega_util_module_isObject(obj) && vega_util_module_has(obj, key) && obj[key] !== undefined;
}
//# sourceMappingURL=util.js.map
;// ../../node_modules/vega-lite/build/src/channel.js
/*
 * Constants and utilities for encoding channels (Visual variables)
 * such as 'x', 'y', 'color'.
 */


// Facet
const ROW = 'row';
const COLUMN = 'column';
const FACET = 'facet';
// Position
const channel_X = 'x';
const channel_Y = 'y';
const channel_X2 = 'x2';
const channel_Y2 = 'y2';
// Position Offset
const XOFFSET = 'xOffset';
const YOFFSET = 'yOffset';
// Arc-Position
const RADIUS = 'radius';
const RADIUS2 = 'radius2';
const THETA = 'theta';
const THETA2 = 'theta2';
// Geo Position
const LATITUDE = 'latitude';
const LONGITUDE = 'longitude';
const LATITUDE2 = 'latitude2';
const LONGITUDE2 = 'longitude2';
// Time
const TIME = 'time';
// Mark property with scale
const COLOR = 'color';
const FILL = 'fill';
const STROKE = 'stroke';
const SHAPE = 'shape';
const channel_SIZE = 'size';
const ANGLE = 'angle';
const OPACITY = 'opacity';
const FILLOPACITY = 'fillOpacity';
const STROKEOPACITY = 'strokeOpacity';
const STROKEWIDTH = 'strokeWidth';
const STROKEDASH = 'strokeDash';
// Non-scale channel
const TEXT = 'text';
const ORDER = 'order';
const DETAIL = 'detail';
const KEY = 'key';
const TOOLTIP = 'tooltip';
const HREF = 'href';
const channel_URL = 'url';
const DESCRIPTION = 'description';
const POSITION_CHANNEL_INDEX = {
    x: 1,
    y: 1,
    x2: 1,
    y2: 1
};
const POLAR_POSITION_CHANNEL_INDEX = {
    theta: 1,
    theta2: 1,
    radius: 1,
    radius2: 1
};
function isPolarPositionChannel(c) {
    return vega_util_module_has(POLAR_POSITION_CHANNEL_INDEX, c);
}
const GEO_POSIITON_CHANNEL_INDEX = {
    longitude: 1,
    longitude2: 1,
    latitude: 1,
    latitude2: 1
};
function getPositionChannelFromLatLong(channel) {
    switch (channel) {
        case LATITUDE:
            return 'y';
        case LATITUDE2:
            return 'y2';
        case LONGITUDE:
            return 'x';
        case LONGITUDE2:
            return 'x2';
    }
}
function isGeoPositionChannel(c) {
    return vega_util_module_has(GEO_POSIITON_CHANNEL_INDEX, c);
}
const GEOPOSITION_CHANNELS = util_keys(GEO_POSIITON_CHANNEL_INDEX);
const UNIT_CHANNEL_INDEX = {
    ...POSITION_CHANNEL_INDEX,
    ...POLAR_POSITION_CHANNEL_INDEX,
    ...GEO_POSIITON_CHANNEL_INDEX,
    xOffset: 1,
    yOffset: 1,
    // color
    color: 1,
    fill: 1,
    stroke: 1,
    // time
    time: 1,
    // other non-position with scale
    opacity: 1,
    fillOpacity: 1,
    strokeOpacity: 1,
    strokeWidth: 1,
    strokeDash: 1,
    size: 1,
    angle: 1,
    shape: 1,
    // channels without scales
    order: 1,
    text: 1,
    detail: 1,
    key: 1,
    tooltip: 1,
    href: 1,
    url: 1,
    description: 1
};
function isColorChannel(channel) {
    return channel === COLOR || channel === FILL || channel === STROKE;
}
const FACET_CHANNEL_INDEX = {
    row: 1,
    column: 1,
    facet: 1
};
const FACET_CHANNELS = util_keys(FACET_CHANNEL_INDEX);
const CHANNEL_INDEX = {
    ...UNIT_CHANNEL_INDEX,
    ...FACET_CHANNEL_INDEX
};
const CHANNELS = util_keys(CHANNEL_INDEX);
const { order: _o, detail: _d, tooltip: _tt1, ...SINGLE_DEF_CHANNEL_INDEX } = CHANNEL_INDEX;
const { row: _r, column: _c, facet: _f, ...SINGLE_DEF_UNIT_CHANNEL_INDEX } = SINGLE_DEF_CHANNEL_INDEX;
/**
 * Channels that cannot have an array of channelDef.
 * model.fieldDef, getFieldDef only work for these channels.
 *
 * (The only two channels that can have an array of channelDefs are "detail" and "order".
 * Since there can be multiple fieldDefs for detail and order, getFieldDef/model.fieldDef
 * are not applicable for them. Similarly, selection projection won't work with "detail" and "order".)
 */
const SINGLE_DEF_CHANNELS = util_keys(SINGLE_DEF_CHANNEL_INDEX);
const SINGLE_DEF_UNIT_CHANNELS = util_keys(SINGLE_DEF_UNIT_CHANNEL_INDEX);
function isSingleDefUnitChannel(str) {
    return vega_util_module_has(SINGLE_DEF_UNIT_CHANNEL_INDEX, str);
}
function isChannel(str) {
    return vega_util_module_has(CHANNEL_INDEX, str);
}
const SECONDARY_RANGE_CHANNEL = [channel_X2, channel_Y2, LATITUDE2, LONGITUDE2, THETA2, RADIUS2];
function isSecondaryRangeChannel(c) {
    const main = getMainRangeChannel(c);
    return main !== c;
}
/**
 * Get the main channel for a range channel. E.g. `x` for `x2`.
 */
function getMainRangeChannel(channel) {
    switch (channel) {
        case channel_X2:
            return channel_X;
        case channel_Y2:
            return channel_Y;
        case LATITUDE2:
            return LATITUDE;
        case LONGITUDE2:
            return LONGITUDE;
        case THETA2:
            return THETA;
        case RADIUS2:
            return RADIUS;
    }
    return channel;
}
function getVgPositionChannel(channel) {
    if (isPolarPositionChannel(channel)) {
        switch (channel) {
            case THETA:
                return 'startAngle';
            case THETA2:
                return 'endAngle';
            case RADIUS:
                return 'outerRadius';
            case RADIUS2:
                return 'innerRadius';
        }
    }
    return channel;
}
/**
 * Get the main channel for a range channel. E.g. `x` for `x2`.
 */
function getSecondaryRangeChannel(channel) {
    switch (channel) {
        case channel_X:
            return channel_X2;
        case channel_Y:
            return channel_Y2;
        case LATITUDE:
            return LATITUDE2;
        case LONGITUDE:
            return LONGITUDE2;
        case THETA:
            return THETA2;
        case RADIUS:
            return RADIUS2;
    }
    return undefined;
}
function getSizeChannel(channel) {
    switch (channel) {
        case channel_X:
        case channel_X2:
            return 'width';
        case channel_Y:
        case channel_Y2:
            return 'height';
    }
    return undefined;
}
/**
 * Get the main channel for a range channel. E.g. `x` for `x2`.
 */
function getOffsetChannel(channel) {
    switch (channel) {
        case channel_X:
            return 'xOffset';
        case channel_Y:
            return 'yOffset';
        case channel_X2:
            return 'x2Offset';
        case channel_Y2:
            return 'y2Offset';
        case THETA:
            return 'thetaOffset';
        case RADIUS:
            return 'radiusOffset';
        case THETA2:
            return 'theta2Offset';
        case RADIUS2:
            return 'radius2Offset';
    }
    return undefined;
}
/**
 * Get the main channel for a range channel. E.g. `x` for `x2`.
 */
function getOffsetScaleChannel(channel) {
    switch (channel) {
        case channel_X:
            return 'xOffset';
        case channel_Y:
            return 'yOffset';
    }
    return undefined;
}
function getMainChannelFromOffsetChannel(channel) {
    switch (channel) {
        case 'xOffset':
            return 'x';
        case 'yOffset':
            return 'y';
    }
}
// CHANNELS without COLUMN, ROW
const UNIT_CHANNELS = util_keys(UNIT_CHANNEL_INDEX);
// NONPOSITION_CHANNELS = UNIT_CHANNELS without X, Y, X2, Y2;
const { x: _x, y: _y, 
// x2 and y2 share the same scale as x and y
x2: _x2, y2: _y2, 
//
xOffset: _xo, yOffset: _yo, latitude: _latitude, longitude: _longitude, latitude2: _latitude2, longitude2: _longitude2, theta: _theta, theta2: _theta2, radius: _radius, radius2: _radius2, 
// The rest of unit channels then have scale
...NONPOSITION_CHANNEL_INDEX } = UNIT_CHANNEL_INDEX;
const NONPOSITION_CHANNELS = util_keys(NONPOSITION_CHANNEL_INDEX);
const POSITION_SCALE_CHANNEL_INDEX = {
    x: 1,
    y: 1
};
const POSITION_SCALE_CHANNELS = util_keys(POSITION_SCALE_CHANNEL_INDEX);
function isXorY(channel) {
    return vega_util_module_has(POSITION_SCALE_CHANNEL_INDEX, channel);
}
const POLAR_POSITION_SCALE_CHANNEL_INDEX = {
    theta: 1,
    radius: 1
};
const POLAR_POSITION_SCALE_CHANNELS = util_keys(POLAR_POSITION_SCALE_CHANNEL_INDEX);
function getPositionScaleChannel(sizeType) {
    return sizeType === 'width' ? channel_X : channel_Y;
}
const OFFSET_SCALE_CHANNEL_INDEX = { xOffset: 1, yOffset: 1 };
const OFFSET_SCALE_CHANNELS = util_keys(OFFSET_SCALE_CHANNEL_INDEX);
function isXorYOffset(channel) {
    return vega_util_module_has(OFFSET_SCALE_CHANNEL_INDEX, channel);
}
const TIME_SCALE_CHANNEL_INDEX = {
    time: 1
};
const TIME_SCALE_CHANNELS = util_keys(TIME_SCALE_CHANNEL_INDEX);
function isTime(channel) {
    return channel in TIME_SCALE_CHANNEL_INDEX;
}
// NON_POSITION_SCALE_CHANNEL = SCALE_CHANNELS without position / offset
const { 
// x2 and y2 share the same scale as x and y
// text and tooltip have format instead of scale,
// href has neither format, nor scale
text: _t, tooltip: _tt, href: _hr, url: _u, description: _al, 
// detail and order have no scale
detail: _dd, key: _k, order: _oo, ...NONPOSITION_SCALE_CHANNEL_INDEX } = NONPOSITION_CHANNEL_INDEX;
const NONPOSITION_SCALE_CHANNELS = util_keys(NONPOSITION_SCALE_CHANNEL_INDEX);
function isNonPositionScaleChannel(channel) {
    return vega_util_module_has(NONPOSITION_CHANNEL_INDEX, channel);
}
/**
 * @returns whether Vega supports legends for a particular channel
 */
function supportLegend(channel) {
    switch (channel) {
        case COLOR:
        case FILL:
        case STROKE:
        case channel_SIZE:
        case SHAPE:
        case OPACITY:
        case STROKEWIDTH:
        case STROKEDASH:
            return true;
        case FILLOPACITY:
        case STROKEOPACITY:
        case ANGLE:
        case TIME:
            return false;
    }
}
// Declare SCALE_CHANNEL_INDEX
const SCALE_CHANNEL_INDEX = {
    ...POSITION_SCALE_CHANNEL_INDEX,
    ...POLAR_POSITION_SCALE_CHANNEL_INDEX,
    ...OFFSET_SCALE_CHANNEL_INDEX,
    ...NONPOSITION_SCALE_CHANNEL_INDEX
};
/** List of channels with scales */
const SCALE_CHANNELS = util_keys(SCALE_CHANNEL_INDEX);
function isScaleChannel(channel) {
    return vega_util_module_has(SCALE_CHANNEL_INDEX, channel);
}
/**
 * Return whether a channel supports a particular mark type.
 * @param channel  channel name
 * @param mark the mark type
 * @return whether the mark supports the channel
 */
function supportMark(channel, mark) {
    return getSupportedMark(channel)[mark];
}
const ALL_MARKS = {
    // all marks
    arc: 'always',
    area: 'always',
    bar: 'always',
    circle: 'always',
    geoshape: 'always',
    image: 'always',
    line: 'always',
    rule: 'always',
    point: 'always',
    rect: 'always',
    square: 'always',
    trail: 'always',
    text: 'always',
    tick: 'always'
};
const { geoshape: _g, ...ALL_MARKS_EXCEPT_GEOSHAPE } = ALL_MARKS;
/**
 * Return a dictionary showing whether a channel supports mark type.
 * @param channel
 * @return A dictionary mapping mark types to 'always', 'binned', or undefined
 */
function getSupportedMark(channel) {
    switch (channel) {
        case COLOR:
        case FILL:
        case STROKE:
        // falls through
        case DESCRIPTION:
        case DETAIL:
        case KEY:
        case TOOLTIP:
        case HREF:
        case ORDER: // TODO: revise (order might not support rect, which is not stackable?)
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
        case STROKEWIDTH:
        // falls through
        case FACET:
        case ROW: // falls through
        case COLUMN:
            return ALL_MARKS;
        case channel_X:
        case channel_Y:
        case XOFFSET:
        case YOFFSET:
        case LATITUDE:
        case LONGITUDE:
        case TIME:
            // all marks except geoshape. geoshape does not use X, Y -- it uses a projection
            return ALL_MARKS_EXCEPT_GEOSHAPE;
        case channel_X2:
        case channel_Y2:
        case LATITUDE2:
        case LONGITUDE2:
            return {
                area: 'always',
                bar: 'always',
                image: 'always',
                rect: 'always',
                rule: 'always',
                circle: 'binned',
                point: 'binned',
                square: 'binned',
                tick: 'binned',
                line: 'binned',
                trail: 'binned'
            };
        case channel_SIZE:
            return {
                point: 'always',
                tick: 'always',
                rule: 'always',
                circle: 'always',
                square: 'always',
                bar: 'always',
                text: 'always',
                line: 'always',
                trail: 'always'
            };
        case STROKEDASH:
            return {
                line: 'always',
                point: 'always',
                tick: 'always',
                rule: 'always',
                circle: 'always',
                square: 'always',
                bar: 'always',
                geoshape: 'always'
            };
        case SHAPE:
            return { point: 'always', geoshape: 'always' };
        case TEXT:
            return { text: 'always' };
        case ANGLE:
            return { point: 'always', square: 'always', text: 'always' };
        case channel_URL:
            return { image: 'always' };
        case THETA:
            return { text: 'always', arc: 'always' };
        case RADIUS:
            return { text: 'always', arc: 'always' };
        case THETA2:
        case RADIUS2:
            return { arc: 'always' };
    }
}
function rangeType(channel) {
    switch (channel) {
        case channel_X:
        case channel_Y:
        case THETA:
        case RADIUS:
        case XOFFSET:
        case YOFFSET:
        case channel_SIZE:
        case ANGLE:
        case STROKEWIDTH:
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
        case TIME:
        // X2 and Y2 use X and Y scales, so they similarly have continuous range. [falls through]
        case channel_X2:
        case channel_Y2:
        case THETA2:
        case RADIUS2:
            return undefined;
        case FACET:
        case ROW:
        case COLUMN:
        case SHAPE:
        case STROKEDASH:
        // TEXT, TOOLTIP, URL, and HREF have no scale but have discrete output [falls through]
        case TEXT:
        case TOOLTIP:
        case HREF:
        case channel_URL:
        case DESCRIPTION:
            return 'discrete';
        // Color can be either continuous or discrete, depending on scale type.
        case COLOR:
        case FILL:
        case STROKE:
            return 'flexible';
        // No scale, no range type.
        case LATITUDE:
        case LONGITUDE:
        case LATITUDE2:
        case LONGITUDE2:
        case DETAIL:
        case KEY:
        case ORDER:
            return undefined;
    }
}
//# sourceMappingURL=channel.js.map
;// ../../node_modules/vega-lite/build/src/aggregate.js


const AGGREGATE_OP_INDEX = {
    argmax: 1,
    argmin: 1,
    average: 1,
    count: 1,
    distinct: 1,
    exponential: 1,
    exponentialb: 1,
    product: 1,
    max: 1,
    mean: 1,
    median: 1,
    min: 1,
    missing: 1,
    q1: 1,
    q3: 1,
    ci0: 1,
    ci1: 1,
    stderr: 1,
    stdev: 1,
    stdevp: 1,
    sum: 1,
    valid: 1,
    values: 1,
    variance: 1,
    variancep: 1
};
const MULTIDOMAIN_SORT_OP_INDEX = {
    count: 1,
    min: 1,
    max: 1
};
function isArgminDef(a) {
    return util_hasProperty(a, 'argmin');
}
function isArgmaxDef(a) {
    return util_hasProperty(a, 'argmax');
}
function isAggregateOp(a) {
    return vega_util_module_isString(a) && vega_util_module_has(AGGREGATE_OP_INDEX, a);
}
const COUNTING_OPS = new Set([
    'count',
    'valid',
    'missing',
    'distinct'
]);
function isCountingAggregateOp(aggregate) {
    return vega_util_module_isString(aggregate) && COUNTING_OPS.has(aggregate);
}
function isMinMaxOp(aggregate) {
    return vega_util_module_isString(aggregate) && util_contains(['min', 'max'], aggregate);
}
/** Additive-based aggregation operations. These can be applied to stack. */
const SUM_OPS = new Set([
    'count',
    'sum',
    'distinct',
    'valid',
    'missing'
]);
/**
 * Aggregation operators that always produce values within the range [domainMin, domainMax].
 */
const SHARED_DOMAIN_OPS = new Set([
    'mean',
    'average',
    'median',
    'q1',
    'q3',
    'min',
    'max'
]);
//# sourceMappingURL=aggregate.js.map
;// ../../node_modules/vega-lite/build/src/bin.js




/**
 * Create a key for the bin configuration. Not for prebinned bin.
 */
function binToString(bin) {
    if (isBoolean(bin)) {
        bin = normalizeBin(bin, undefined);
    }
    return ('bin' +
        util_keys(bin)
            .map(p => (isParameterExtent(bin[p]) ? varName(`_${p}_${util_entries(bin[p])}`) : varName(`_${p}_${bin[p]}`)))
            .join(''));
}
/**
 * Vega-Lite should bin the data.
 */
function isBinning(bin) {
    return bin === true || (isBinParams(bin) && !bin.binned);
}
/**
 * The data is already binned and so Vega-Lite should not bin it again.
 */
function isBinned(bin) {
    return bin === 'binned' || (isBinParams(bin) && bin.binned === true);
}
function isBinParams(bin) {
    return vega_util_module_isObject(bin);
}
function isParameterExtent(extent) {
    return util_hasProperty(extent, 'param');
}
function autoMaxBins(channel) {
    switch (channel) {
        case ROW:
        case COLUMN:
        case channel_SIZE:
        case COLOR:
        case FILL:
        case STROKE:
        case STROKEWIDTH:
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
        // Facets and Size shouldn't have too many bins
        // We choose 6 like shape to simplify the rule [falls through]
        case SHAPE:
            return 6; // Vega's "shape" has 6 distinct values
        case STROKEDASH:
            return 4; // We only provide 5 different stroke dash values (but 4 is more effective)
        default:
            return 10;
    }
}
//# sourceMappingURL=bin.js.map
;// ../../node_modules/vega-lite/build/src/expr.js


function isExprRef(o) {
    return util_hasProperty(o, 'expr');
}
function replaceExprRef(index, { level } = { level: 0 }) {
    const props = util_keys(index || {});
    const newIndex = {};
    for (const prop of props) {
        newIndex[prop] = level === 0 ? signalRefOrValue(index[prop]) : replaceExprRef(index[prop], { level: level - 1 });
    }
    return newIndex;
}
//# sourceMappingURL=expr.js.map
;// ../../node_modules/vega-lite/build/src/title.js


function extractTitleConfig(titleConfig) {
    const { 
    // These are non-mark title config that need to be hardcoded
    anchor, frame, offset, orient, angle, limit, 
    // color needs to be redirect to fill
    color, 
    // subtitle properties
    subtitleColor, subtitleFont, subtitleFontSize, subtitleFontStyle, subtitleFontWeight, subtitleLineHeight, subtitlePadding, 
    // The rest are mark config.
    ...rest } = titleConfig;
    const titleMarkConfig = {
        ...rest,
        ...(color ? { fill: color } : {})
    };
    // These are non-mark title config that need to be hardcoded
    const nonMarkTitleProperties = {
        ...(anchor ? { anchor } : {}),
        ...(frame ? { frame } : {}),
        ...(offset ? { offset } : {}),
        ...(orient ? { orient } : {}),
        ...(angle !== undefined ? { angle } : {}),
        ...(limit !== undefined ? { limit } : {})
    };
    // subtitle part can stay in config.title since header titles do not use subtitle
    const subtitle = {
        ...(subtitleColor ? { subtitleColor } : {}),
        ...(subtitleFont ? { subtitleFont } : {}),
        ...(subtitleFontSize ? { subtitleFontSize } : {}),
        ...(subtitleFontStyle ? { subtitleFontStyle } : {}),
        ...(subtitleFontWeight ? { subtitleFontWeight } : {}),
        ...(subtitleLineHeight ? { subtitleLineHeight } : {}),
        ...(subtitlePadding ? { subtitlePadding } : {})
    };
    const subtitleMarkConfig = util_pick(titleConfig, ['align', 'baseline', 'dx', 'dy', 'limit']);
    return { titleMarkConfig, subtitleMarkConfig, nonMarkTitleProperties, subtitle };
}
function isText(v) {
    return vega_util_module_isString(v) || (vega_util_module_isArray(v) && vega_util_module_isString(v[0]));
}
//# sourceMappingURL=title.js.map
;// ../../node_modules/vega-lite/build/src/vega.schema.js


function isSignalRef(o) {
    return util_hasProperty(o, 'signal');
}
function isVgRangeStep(range) {
    return util_hasProperty(range, 'step');
}
function isDataRefUnionedDomain(domain) {
    if (!vega_util_module_isArray(domain)) {
        return util_hasProperty(domain, 'fields') && !util_hasProperty(domain, 'data');
    }
    return false;
}
function isFieldRefUnionDomain(domain) {
    if (!vega_util_module_isArray(domain)) {
        return util_hasProperty(domain, 'fields') && util_hasProperty(domain, 'data');
    }
    return false;
}
function isDataRefDomain(domain) {
    if (!vega_util_module_isArray(domain)) {
        return util_hasProperty(domain, 'field') && util_hasProperty(domain, 'data');
    }
    return false;
}
const VG_MARK_CONFIG_INDEX = {
    aria: 1,
    description: 1,
    ariaRole: 1,
    ariaRoleDescription: 1,
    blend: 1,
    opacity: 1,
    fill: 1,
    fillOpacity: 1,
    stroke: 1,
    strokeCap: 1,
    strokeWidth: 1,
    strokeOpacity: 1,
    strokeDash: 1,
    strokeDashOffset: 1,
    strokeJoin: 1,
    strokeOffset: 1,
    strokeMiterLimit: 1,
    startAngle: 1,
    endAngle: 1,
    padAngle: 1,
    innerRadius: 1,
    outerRadius: 1,
    size: 1,
    shape: 1,
    interpolate: 1,
    tension: 1,
    orient: 1,
    align: 1,
    baseline: 1,
    text: 1,
    dir: 1,
    dx: 1,
    dy: 1,
    ellipsis: 1,
    limit: 1,
    radius: 1,
    theta: 1,
    angle: 1,
    font: 1,
    fontSize: 1,
    fontWeight: 1,
    fontStyle: 1,
    lineBreak: 1,
    lineHeight: 1,
    cursor: 1,
    href: 1,
    tooltip: 1,
    cornerRadius: 1,
    cornerRadiusTopLeft: 1,
    cornerRadiusTopRight: 1,
    cornerRadiusBottomLeft: 1,
    cornerRadiusBottomRight: 1,
    aspect: 1,
    width: 1,
    height: 1,
    url: 1,
    smooth: 1
    // commented below are vg channel that do not have mark config.
    // x: 1,
    // y: 1,
    // x2: 1,
    // y2: 1,
    // xc'|'yc'
    // clip: 1,
    // path: 1,
    // url: 1,
};
const VG_MARK_CONFIGS = util_keys(VG_MARK_CONFIG_INDEX);
const VG_MARK_INDEX = {
    arc: 1,
    area: 1,
    group: 1,
    image: 1,
    line: 1,
    path: 1,
    rect: 1,
    rule: 1,
    shape: 1,
    symbol: 1,
    text: 1,
    trail: 1
};
// Vega's cornerRadius channels.
const VG_CORNERRADIUS_CHANNELS = [
    'cornerRadius',
    'cornerRadiusTopLeft',
    'cornerRadiusTopRight',
    'cornerRadiusBottomLeft',
    'cornerRadiusBottomRight'
];
//# sourceMappingURL=vega.schema.js.map
;// ../../node_modules/vega-lite/build/src/compile/common.js






const BIN_RANGE_DELIMITER = ' \u2013 ';
function signalOrValueRefWithCondition(val) {
    const condition = vega_util_module_isArray(val.condition)
        ? val.condition.map(conditionalSignalRefOrValue)
        : conditionalSignalRefOrValue(val.condition);
    return {
        ...signalRefOrValue(val),
        condition
    };
}
function signalRefOrValue(value) {
    if (isExprRef(value)) {
        const { expr, ...rest } = value;
        return { signal: expr, ...rest };
    }
    return value;
}
function conditionalSignalRefOrValue(value) {
    if (isExprRef(value)) {
        const { expr, ...rest } = value;
        return { signal: expr, ...rest };
    }
    return value;
}
function signalOrValueRef(value) {
    if (isExprRef(value)) {
        const { expr, ...rest } = value;
        return { signal: expr, ...rest };
    }
    if (isSignalRef(value)) {
        return value;
    }
    return value !== undefined ? { value } : undefined;
}
function exprFromSignalRefOrValue(ref) {
    if (isSignalRef(ref)) {
        return ref.signal;
    }
    return $(ref);
}
function exprFromValueRefOrSignalRef(ref) {
    if (isSignalRef(ref)) {
        return ref.signal;
    }
    return $(ref.value);
}
function signalOrStringValue(v) {
    if (isSignalRef(v)) {
        return v.signal;
    }
    return v == null ? null : $(v);
}
function applyMarkConfig(e, model, propsList) {
    for (const property of propsList) {
        const value = getMarkConfig(property, model.markDef, model.config);
        if (value !== undefined) {
            e[property] = signalOrValueRef(value);
        }
    }
    return e;
}
function getStyles(mark) {
    return [].concat(mark.type, mark.style ?? []);
}
function getMarkPropOrConfig(channel, mark, config, opt = {}) {
    const { vgChannel, ignoreVgConfig } = opt;
    if (vgChannel && util_hasProperty(mark, vgChannel)) {
        return mark[vgChannel];
    }
    else if (mark[channel] !== undefined) {
        return mark[channel];
    }
    else if (ignoreVgConfig && (!vgChannel || vgChannel === channel)) {
        return undefined;
    }
    return getMarkConfig(channel, mark, config, opt);
}
/**
 * Return property value from style or mark specific config property if exists.
 * Otherwise, return general mark specific config.
 */
function getMarkConfig(channel, mark, config, { vgChannel } = {}) {
    const cfg = getMarkStyleConfig(channel, mark, config.style);
    return getFirstDefined(
    // style config has highest precedence
    vgChannel ? cfg : undefined, cfg, 
    // then mark-specific config
    vgChannel ? config[mark.type][vgChannel] : undefined, config[mark.type][channel], // Need to cast because MarkDef doesn't perfectly match with AnyMarkConfig, but if the type isn't available, we'll get nothing here, which is fine
    // If there is vgChannel, skip vl channel.
    // For example, vl size for text is vg fontSize, but config.mark.size is only for point size.
    vgChannel ? config.mark[vgChannel] : config.mark[channel] // Need to cast for the same reason as above
    );
}
function getMarkStyleConfig(prop, mark, styleConfigIndex) {
    return getStyleConfig(prop, getStyles(mark), styleConfigIndex);
}
function getStyleConfig(p, styles, styleConfigIndex) {
    styles = vega_util_module_array(styles);
    let value;
    for (const style of styles) {
        const styleConfig = styleConfigIndex[style];
        if (util_hasProperty(styleConfig, p)) {
            value = styleConfig[p];
        }
    }
    return value;
}
/**
 * Return Vega sort parameters (tuple of field and order).
 */
function sortParams(orderDef, fieldRefOption) {
    return vega_util_module_array(orderDef).reduce((s, orderChannelDef) => {
        s.field.push(vgField(orderChannelDef, fieldRefOption));
        s.order.push(orderChannelDef.sort ?? 'ascending');
        return s;
    }, { field: [], order: [] });
}
function mergeTitleFieldDefs(f1, f2) {
    const merged = [...f1];
    f2.forEach(fdToMerge => {
        for (const fieldDef1 of merged) {
            // If already exists, no need to append to merged array
            if (util_deepEqual(fieldDef1, fdToMerge)) {
                return;
            }
        }
        merged.push(fdToMerge);
    });
    return merged;
}
function mergeTitle(title1, title2) {
    if (util_deepEqual(title1, title2) || !title2) {
        // if titles are the same or title2 is falsy
        return title1;
    }
    else if (!title1) {
        // if title1 is falsy
        return title2;
    }
    else {
        return [...vega_util_module_array(title1), ...vega_util_module_array(title2)].join(', ');
    }
}
function mergeTitleComponent(v1, v2) {
    const v1Val = v1.value;
    const v2Val = v2.value;
    if (v1Val == null || v2Val === null) {
        return {
            explicit: v1.explicit,
            value: null
        };
    }
    else if ((isText(v1Val) || isSignalRef(v1Val)) && (isText(v2Val) || isSignalRef(v2Val))) {
        return {
            explicit: v1.explicit,
            value: mergeTitle(v1Val, v2Val)
        };
    }
    else if (isText(v1Val) || isSignalRef(v1Val)) {
        return {
            explicit: v1.explicit,
            value: v1Val
        };
    }
    else if (isText(v2Val) || isSignalRef(v2Val)) {
        return {
            explicit: v1.explicit,
            value: v2Val
        };
    }
    else if (!isText(v1Val) && !isSignalRef(v1Val) && !isText(v2Val) && !isSignalRef(v2Val)) {
        return {
            explicit: v1.explicit,
            value: mergeTitleFieldDefs(v1Val, v2Val)
        };
    }
    /* istanbul ignore next: Condition should not happen -- only for warning in development. */
    throw new Error('It should never reach here');
}
//# sourceMappingURL=common.js.map
;// ../../node_modules/vega-lite/build/src/log/message.js
/**
 * Collection of all Vega-Lite Error Messages
 */



function invalidSpec(spec) {
    return `Invalid specification ${util_stringify(spec)}. Make sure the specification includes at least one of the following properties: "mark", "layer", "facet", "hconcat", "vconcat", "concat", or "repeat".`;
}
// FIT
const FIT_NON_SINGLE = 'Autosize "fit" only works for single views and layered views.';
function containerSizeNonSingle(name) {
    const uName = name == 'width' ? 'Width' : 'Height';
    return `${uName} "container" only works for single views and layered views.`;
}
function containerSizeNotCompatibleWithAutosize(name) {
    const uName = name == 'width' ? 'Width' : 'Height';
    const fitDirection = name == 'width' ? 'x' : 'y';
    return `${uName} "container" only works well with autosize "fit" or "fit-${fitDirection}".`;
}
function droppingFit(channel) {
    return channel
        ? `Dropping "fit-${channel}" because spec has discrete ${getSizeChannel(channel)}.`
        : `Dropping "fit" because spec has discrete size.`;
}
// VIEW SIZE
function unknownField(channel) {
    return `Unknown field for ${channel}. Cannot calculate view size.`;
}
// SELECTION
function cannotProjectOnChannelWithoutField(channel) {
    return `Cannot project a selection on encoding channel "${channel}", which has no field.`;
}
function cannotProjectAggregate(channel, aggregate) {
    return `Cannot project a selection on encoding channel "${channel}" as it uses an aggregate function ("${aggregate}").`;
}
function nearestNotSupportForContinuous(mark) {
    return `The "nearest" transform is not supported for ${mark} marks.`;
}
function selectionNotSupported(mark) {
    return `Selection not supported for ${mark} yet.`;
}
function selectionNotFound(name) {
    return `Cannot find a selection named "${name}".`;
}
const SCALE_BINDINGS_CONTINUOUS = 'Scale bindings are currently only supported for scales with unbinned, continuous domains.';
const SEQUENTIAL_SCALE_DEPRECATED = 'Sequntial scales are deprecated. The available quantitative scale type values are linear, log, pow, sqrt, symlog, time and utc';
const LEGEND_BINDINGS_MUST_HAVE_PROJECTION = 'Legend bindings are only supported for selections over an individual field or encoding channel.';
function cannotLookupVariableParameter(name) {
    return `Lookups can only be performed on selection parameters. "${name}" is a variable parameter.`;
}
function noSameUnitLookup(name) {
    return (`Cannot define and lookup the "${name}" selection in the same view. ` +
        `Try moving the lookup into a second, layered view?`);
}
const NEEDS_SAME_SELECTION = 'The same selection must be used to override scale domains in a layered view.';
const INTERVAL_INITIALIZED_WITH_POS = 'Interval selections should be initialized using "x", "y", "longitude", or "latitude" keys.';
// REPEAT
function noSuchRepeatedValue(field) {
    return `Unknown repeated value "${field}".`;
}
function columnsNotSupportByRowCol(type) {
    return `The "columns" property cannot be used when "${type}" has nested row/column.`;
}
const MULTIPLE_TIMER_ANIMATION_SELECTION = 'Multiple timer selections in one unit spec are not supported. Ignoring all but the first.';
const MULTI_VIEW_ANIMATION_UNSUPPORTED = 'Animation involving facet, layer, or concat is currently unsupported.';
function selectionAsScaleDomainWithoutField(field) {
    return ('A "field" or "encoding" must be specified when using a selection as a scale domain. ' +
        `Using "field": ${$(field)}.`);
}
function selectionAsScaleDomainWrongEncodings(encodings, encoding, extent, field) {
    return ((!encodings.length ? 'No ' : 'Multiple ') +
        `matching ${$(encoding)} encoding found for selection ${$(extent.param)}. ` +
        `Using "field": ${$(field)}.`);
}
// CONCAT / REPEAT
const CONCAT_CANNOT_SHARE_AXIS = 'Axes cannot be shared in concatenated or repeated views yet (https://github.com/vega/vega-lite/issues/2415).';
// DATA
function unrecognizedParse(p) {
    return `Unrecognized parse "${p}".`;
}
function differentParse(field, local, ancestor) {
    return `An ancestor parsed field "${field}" as ${ancestor} but a child wants to parse the field as ${local}.`;
}
const ADD_SAME_CHILD_TWICE = 'Attempt to add the same child twice.';
// TRANSFORMS
function invalidTransformIgnored(transform) {
    return `Ignoring an invalid transform: ${util_stringify(transform)}.`;
}
const NO_FIELDS_NEEDS_AS = 'If "from.fields" is not specified, "as" has to be a string that specifies the key to be used for the data from the secondary source.';
// ENCODING & FACET
function customFormatTypeNotAllowed(channel) {
    return `Config.customFormatTypes is not true, thus custom format type and format for channel ${channel} are dropped.`;
}
function projectionOverridden(opt) {
    const { parentProjection, projection } = opt;
    return `Layer's shared projection ${util_stringify(parentProjection)} is overridden by a child projection ${util_stringify(projection)}.`;
}
const REPLACE_ANGLE_WITH_THETA = 'Arc marks uses theta channel rather than angle, replacing angle with theta.';
function offsetNestedInsideContinuousPositionScaleDropped(mainChannel) {
    return `${mainChannel}Offset dropped because ${mainChannel} is continuous`;
}
function primitiveChannelDef(channel, type, value) {
    return `Channel ${channel} is a ${type}. Converted to {value: ${util_stringify(value)}}.`;
}
function invalidFieldType(type) {
    return `Invalid field type "${type}".`;
}
function invalidFieldTypeForCountAggregate(type, aggregate) {
    return `Invalid field type "${type}" for aggregate: "${aggregate}", using "quantitative" instead.`;
}
function invalidAggregate(aggregate) {
    return `Invalid aggregation operator "${aggregate}".`;
}
function missingFieldType(channel, newType) {
    return `Missing type for channel "${channel}", using "${newType}" instead.`;
}
function droppingColor(type, opt) {
    const { fill, stroke } = opt;
    return `Dropping color ${type} as the plot also has ${fill && stroke ? 'fill and stroke' : fill ? 'fill' : 'stroke'}.`;
}
function relativeBandSizeNotSupported(sizeChannel) {
    return `Position range does not support relative band size for ${sizeChannel}.`;
}
function emptyFieldDef(fieldDef, channel) {
    return `Dropping ${util_stringify(fieldDef)} from channel "${channel}" since it does not contain any data field, datum, value, or signal.`;
}
const LINE_WITH_VARYING_SIZE = 'Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.';
function incompatibleChannel(channel, markOrFacet, when) {
    return `${channel} dropped as it is incompatible with "${markOrFacet}"${when ? ` when ${when}` : ''}.`;
}
function offsetEncodingScaleIgnored(channel) {
    return `${channel} encoding has no scale, so specified scale is ignored.`;
}
function invalidEncodingChannel(channel) {
    return `${channel}-encoding is dropped as ${channel} is not a valid encoding channel.`;
}
function channelShouldBeDiscrete(channel) {
    return `${channel} encoding should be discrete (ordinal / nominal / binned).`;
}
function channelShouldBeDiscreteOrDiscretizing(channel) {
    return `${channel} encoding should be discrete (ordinal / nominal / binned) or use a discretizing scale (e.g. threshold).`;
}
function facetChannelDropped(channels) {
    return `Facet encoding dropped as ${channels.join(' and ')} ${channels.length > 1 ? 'are' : 'is'} also specified.`;
}
function discreteChannelCannotEncode(channel, type) {
    return `Using discrete channel "${channel}" to encode "${type}" field can be misleading as it does not encode ${type === 'ordinal' ? 'order' : 'magnitude'}.`;
}
// MARK
function rangeMarkAlignmentCannotBeExpression(align) {
    return `The ${align} for range marks cannot be an expression`;
}
function lineWithRange(hasX2, hasY2) {
    const channels = hasX2 && hasY2 ? 'x2 and y2' : hasX2 ? 'x2' : 'y2';
    return `Line mark is for continuous lines and thus cannot be used with ${channels}. We will use the rule mark (line segments) instead.`;
}
function orientOverridden(original, actual) {
    return `Specified orient "${original}" overridden with "${actual}".`;
}
// SCALE
const CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN = 'Custom domain scale cannot be unioned with default field-based domain.';
function cannotUseScalePropertyWithNonColor(prop) {
    return `Cannot use the scale property "${prop}" with non-color channel.`;
}
function cannotUseRelativeBandSizeWithNonBandScale(scaleType) {
    return `Cannot use the relative band size with ${scaleType} scale.`;
}
function unaggregateDomainHasNoEffectForRawField(fieldDef) {
    return `Using unaggregated domain with raw field has no effect (${util_stringify(fieldDef)}).`;
}
function unaggregateDomainWithNonSharedDomainOp(aggregate) {
    return `Unaggregated domain not applicable for "${aggregate}" since it produces values outside the origin domain of the source data.`;
}
function unaggregatedDomainWithLogScale(fieldDef) {
    return `Unaggregated domain is currently unsupported for log scale (${util_stringify(fieldDef)}).`;
}
function cannotApplySizeToNonOrientedMark(mark) {
    return `Cannot apply size to non-oriented mark "${mark}".`;
}
function scaleTypeNotWorkWithChannel(channel, scaleType, defaultScaleType) {
    return `Channel "${channel}" does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`;
}
function scaleTypeNotWorkWithFieldDef(scaleType, defaultScaleType) {
    return `FieldDef does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`;
}
function scalePropertyNotWorkWithScaleType(scaleType, propName, channel) {
    return `${channel}-scale's "${propName}" is dropped as it does not work with ${scaleType} scale.`;
}
function scaleTypeNotWorkWithMark(mark, scaleType) {
    return `Scale type "${scaleType}" does not work with mark "${mark}".`;
}
function stepDropped(channel) {
    return `The step for "${channel}" is dropped because the ${channel === 'width' ? 'x' : 'y'} is continuous.`;
}
function mergeConflictingProperty(property, propertyOf, v1, v2) {
    return `Conflicting ${propertyOf.toString()} property "${property.toString()}" (${util_stringify(v1)} and ${util_stringify(v2)}). Using ${util_stringify(v1)}.`;
}
function mergeConflictingDomainProperty(property, propertyOf, v1, v2) {
    return `Conflicting ${propertyOf.toString()} property "${property.toString()}" (${util_stringify(v1)} and ${util_stringify(v2)}). Using the union of the two domains.`;
}
function independentScaleMeansIndependentGuide(channel) {
    return `Setting the scale to be independent for "${channel}" means we also have to set the guide (axis or legend) to be independent.`;
}
function domainSortDropped(sort) {
    return `Dropping sort property ${util_stringify(sort)} as unioned domains only support boolean or op "count", "min", and "max".`;
}
const MORE_THAN_ONE_SORT = 'Domains that should be unioned has conflicting sort properties. Sort will be set to true.';
const FACETED_INDEPENDENT_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect.';
const FACETED_INDEPENDENT_SAME_FIELDS_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect.';
const FACETED_INDEPENDENT_SAME_SOURCE = 'Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.';
// AXIS
const INVALID_CHANNEL_FOR_AXIS = 'Invalid channel for axis.';
// STACK
function cannotStackRangedMark(channel) {
    return `Cannot stack "${channel}" if there is already "${channel}2".`;
}
function stackNonLinearScale(scaleType) {
    return `Stack is applied to a non-linear scale (${scaleType}).`;
}
function stackNonSummativeAggregate(aggregate) {
    return `Stacking is applied even though the aggregate function is non-summative ("${aggregate}").`;
}
// TIMEUNIT
function invalidTimeUnit(unitName, value) {
    return `Invalid ${unitName}: ${util_stringify(value)}.`;
}
function droppedDay(d) {
    return `Dropping day from datetime ${util_stringify(d)} as day cannot be combined with other units.`;
}
function errorBarCenterAndExtentAreNotNeeded(center, extent) {
    return `${extent ? 'extent ' : ''}${extent && center ? 'and ' : ''}${center ? 'center ' : ''}${extent && center ? 'are ' : 'is '}not needed when data are aggregated.`;
}
function errorBarCenterIsUsedWithWrongExtent(center, extent, mark) {
    return `${center} is not usually used with ${extent} for ${mark}.`;
}
function errorBarContinuousAxisHasCustomizedAggregate(aggregate, compositeMark) {
    return `Continuous axis should not have customized aggregation function ${aggregate}; ${compositeMark} already agregates the axis.`;
}
function errorBand1DNotSupport(property) {
    return `1D error band does not support ${property}.`;
}
// CHANNEL
function channelRequiredForBinned(channel) {
    return `Channel ${channel} is required for "binned" bin.`;
}
function channelShouldNotBeUsedForBinned(channel) {
    return `Channel ${channel} should not be used with "binned" bin.`;
}
function domainRequiredForThresholdScale(channel) {
    return `Domain for ${channel} is required for threshold scale.`;
}
//# sourceMappingURL=message.js.map
;// ../../node_modules/vega-lite/build/src/log/index.js
/**
 * Vega-Lite's singleton logger utility.
 */
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _LocalLogger_level;


/**
 * Main (default) Vega Logger instance for Vega-Lite.
 */
const main = logger(vega_util_module_Warn);
let current = main;
/**
 * Logger tool for checking if the code throws correct warning.
 */
class LocalLogger {
    constructor() {
        this.warns = [];
        this.infos = [];
        this.debugs = [];
        _LocalLogger_level.set(this, Warn);
    }
    level(_) {
        if (_) {
            __classPrivateFieldSet(this, _LocalLogger_level, _, "f");
            return this;
        }
        return __classPrivateFieldGet(this, _LocalLogger_level, "f");
    }
    warn(...args) {
        if (__classPrivateFieldGet(this, _LocalLogger_level, "f") >= Warn)
            this.warns.push(...args);
        return this;
    }
    info(...args) {
        if (__classPrivateFieldGet(this, _LocalLogger_level, "f") >= Info)
            this.infos.push(...args);
        return this;
    }
    debug(...args) {
        if (__classPrivateFieldGet(this, _LocalLogger_level, "f") >= Debug)
            this.debugs.push(...args);
        return this;
    }
    error(...args) {
        if (__classPrivateFieldGet(this, _LocalLogger_level, "f") >= ErrorLevel)
            throw Error(...args);
        return this;
    }
}
_LocalLogger_level = new WeakMap();
function log_wrap(f) {
    return () => {
        current = new LocalLogger();
        f(current);
        log_reset();
    };
}
/**
 * Set the singleton logger to be a custom logger.
 */
function log_set(newLogger) {
    current = newLogger;
    return current;
}
/**
 * Reset the main logger to use the default Vega Logger.
 */
function log_reset() {
    current = main;
    return current;
}
function log_error(...args) {
    current.error(...args);
}
function log_warn(...args) {
    current.warn(...args);
}
function log_info(...args) {
    current.info(...args);
}
function log_debug(...args) {
    current.debug(...args);
}
//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/datetime.js
// DateTime definition object




function isDateTime(o) {
    if (o && vega_util_module_isObject(o)) {
        for (const part of TIMEUNIT_PARTS) {
            if (util_hasProperty(o, part)) {
                return true;
            }
        }
    }
    return false;
}
const MONTHS = [
    'january',
    'february',
    'march',
    'april',
    'may',
    'june',
    'july',
    'august',
    'september',
    'october',
    'november',
    'december'
];
const SHORT_MONTHS = MONTHS.map(m => m.substr(0, 3));
const DAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
const SHORT_DAYS = DAYS.map(d => d.substr(0, 3));
function normalizeQuarter(q) {
    if (isNumeric(q)) {
        q = +q;
    }
    if (vega_util_module_isNumber(q)) {
        if (q > 4) {
            log_warn(invalidTimeUnit('quarter', q));
        }
        // We accept 1-based quarter, so need to readjust to 0-based quarter
        return q - 1;
    }
    else {
        // Invalid quarter
        throw new Error(invalidTimeUnit('quarter', q));
    }
}
function normalizeMonth(m) {
    if (isNumeric(m)) {
        m = +m;
    }
    if (vega_util_module_isNumber(m)) {
        // We accept 1-based month, so need to readjust to 0-based month
        return m - 1;
    }
    else {
        const lowerM = m.toLowerCase();
        const monthIndex = MONTHS.indexOf(lowerM);
        if (monthIndex !== -1) {
            return monthIndex; // 0 for january, ...
        }
        const shortM = lowerM.substr(0, 3);
        const shortMonthIndex = SHORT_MONTHS.indexOf(shortM);
        if (shortMonthIndex !== -1) {
            return shortMonthIndex;
        }
        // Invalid month
        throw new Error(invalidTimeUnit('month', m));
    }
}
function normalizeDay(d) {
    if (isNumeric(d)) {
        d = +d;
    }
    if (vega_util_module_isNumber(d)) {
        // mod so that this can be both 0-based where 0 = sunday
        // and 1-based where 7=sunday
        return d % 7;
    }
    else {
        const lowerD = d.toLowerCase();
        const dayIndex = DAYS.indexOf(lowerD);
        if (dayIndex !== -1) {
            return dayIndex; // 0 for january, ...
        }
        const shortD = lowerD.substr(0, 3);
        const shortDayIndex = SHORT_DAYS.indexOf(shortD);
        if (shortDayIndex !== -1) {
            return shortDayIndex;
        }
        // Invalid day
        throw new Error(invalidTimeUnit('day', d));
    }
}
/**
 * @param d the date.
 * @param normalize whether to normalize quarter, month, day. This should probably be true if d is a DateTime.
 * @returns array of date time parts [year, month, day, hours, minutes, seconds, milliseconds]
 */
function dateTimeParts(d, normalize) {
    const parts = [];
    if (normalize && d.day !== undefined) {
        if (util_keys(d).length > 1) {
            log_warn(droppedDay(d));
            d = duplicate(d);
            delete d.day;
        }
    }
    if (d.year !== undefined) {
        parts.push(d.year);
    }
    else {
        // Just like Vega's timeunit transform, set default year to 2012, so domain conversion will be compatible with Vega
        // Note: 2012 is a leap year (and so the date February 29 is respected) that begins on a Sunday (and so days of the week will order properly at the beginning of the year).
        parts.push(2012);
    }
    if (d.month !== undefined) {
        const month = normalize ? normalizeMonth(d.month) : d.month;
        parts.push(month);
    }
    else if (d.quarter !== undefined) {
        const quarter = normalize ? normalizeQuarter(d.quarter) : d.quarter;
        parts.push(vega_util_module_isNumber(quarter) ? quarter * 3 : `${quarter}*3`);
    }
    else {
        parts.push(0); // months start at zero in JS
    }
    if (d.date !== undefined) {
        parts.push(d.date);
    }
    else if (d.day !== undefined) {
        // HACK: Day only works as a standalone unit
        // This is only correct because we always set year to 2006 for day
        const day = normalize ? normalizeDay(d.day) : d.day;
        parts.push(vega_util_module_isNumber(day) ? day + 1 : `${day}+1`);
    }
    else {
        parts.push(1); // Date starts at 1 in JS
    }
    // Note: can't use TimeUnit enum here as importing it will create
    // circular dependency problem!
    for (const timeUnit of ['hours', 'minutes', 'seconds', 'milliseconds']) {
        const unit = d[timeUnit];
        parts.push(typeof unit === 'undefined' ? 0 : unit);
    }
    return parts;
}
/**
 * Return Vega expression for a date time.
 *
 * @param d the date time.
 * @returns the Vega expression.
 */
function dateTimeToExpr(d) {
    const parts = dateTimeParts(d, true);
    const string = parts.join(', ');
    if (d.utc) {
        return `utc(${string})`;
    }
    else {
        return `datetime(${string})`;
    }
}
/**
 * Return Vega expression for a date time expression.
 *
 * @param d the internal date time object with expression.
 * @returns the Vega expression.
 */
function dateTimeExprToExpr(d) {
    const parts = dateTimeParts(d, false);
    const string = parts.join(', ');
    if (d.utc) {
        return `utc(${string})`;
    }
    else {
        return `datetime(${string})`;
    }
}
/**
 * @param d the date time.
 * @returns the timestamp.
 */
function dateTimeToTimestamp(d) {
    const parts = dateTimeParts(d, true);
    if (d.utc) {
        return +new Date(Date.UTC(...parts));
    }
    else {
        return +new Date(...parts);
    }
}
//# sourceMappingURL=datetime.js.map
;// ../../node_modules/vega-lite/build/src/timeunit.js




/** Time Unit that only corresponds to only one part of Date objects. */
const LOCAL_SINGLE_TIMEUNIT_INDEX = {
    year: 1,
    quarter: 1,
    month: 1,
    week: 1,
    day: 1,
    dayofyear: 1,
    date: 1,
    hours: 1,
    minutes: 1,
    seconds: 1,
    milliseconds: 1
};
const TIMEUNIT_PARTS = util_keys(LOCAL_SINGLE_TIMEUNIT_INDEX);
function isLocalSingleTimeUnit(timeUnit) {
    return vega_util_module_has(LOCAL_SINGLE_TIMEUNIT_INDEX, timeUnit);
}
const UTC_SINGLE_TIMEUNIT_INDEX = {
    utcyear: 1,
    utcquarter: 1,
    utcmonth: 1,
    utcweek: 1,
    utcday: 1,
    utcdayofyear: 1,
    utcdate: 1,
    utchours: 1,
    utcminutes: 1,
    utcseconds: 1,
    utcmilliseconds: 1
};
const LOCAL_MULTI_TIMEUNIT_INDEX = {
    yearquarter: 1,
    yearquartermonth: 1,
    yearmonth: 1,
    yearmonthdate: 1,
    yearmonthdatehours: 1,
    yearmonthdatehoursminutes: 1,
    yearmonthdatehoursminutesseconds: 1,
    yearweek: 1,
    yearweekday: 1,
    yearweekdayhours: 1,
    yearweekdayhoursminutes: 1,
    yearweekdayhoursminutesseconds: 1,
    yeardayofyear: 1,
    quartermonth: 1,
    monthdate: 1,
    monthdatehours: 1,
    monthdatehoursminutes: 1,
    monthdatehoursminutesseconds: 1,
    weekday: 1,
    weekdayhours: 1,
    weekdayhoursminutes: 1,
    weekdayhoursminutesseconds: 1,
    dayhours: 1,
    dayhoursminutes: 1,
    dayhoursminutesseconds: 1,
    hoursminutes: 1,
    hoursminutesseconds: 1,
    minutesseconds: 1,
    secondsmilliseconds: 1
};
const BINNED_LOCAL_TIMEUNIT_INDEX = {
    binnedyear: 1,
    binnedyearquarter: 1,
    binnedyearquartermonth: 1,
    binnedyearmonth: 1,
    binnedyearmonthdate: 1,
    binnedyearmonthdatehours: 1,
    binnedyearmonthdatehoursminutes: 1,
    binnedyearmonthdatehoursminutesseconds: 1,
    binnedyearweek: 1,
    binnedyearweekday: 1,
    binnedyearweekdayhours: 1,
    binnedyearweekdayhoursminutes: 1,
    binnedyearweekdayhoursminutesseconds: 1,
    binnedyeardayofyear: 1
};
const BINNED_UTC_TIMEUNIT_INDEX = {
    binnedutcyear: 1,
    binnedutcyearquarter: 1,
    binnedutcyearquartermonth: 1,
    binnedutcyearmonth: 1,
    binnedutcyearmonthdate: 1,
    binnedutcyearmonthdatehours: 1,
    binnedutcyearmonthdatehoursminutes: 1,
    binnedutcyearmonthdatehoursminutesseconds: 1,
    binnedutcyearweek: 1,
    binnedutcyearweekday: 1,
    binnedutcyearweekdayhours: 1,
    binnedutcyearweekdayhoursminutes: 1,
    binnedutcyearweekdayhoursminutesseconds: 1,
    binnedutcyeardayofyear: 1
};
const BINNED_TIMEUNIT_INDEX = {
    ...BINNED_LOCAL_TIMEUNIT_INDEX,
    ...BINNED_UTC_TIMEUNIT_INDEX
};
function isBinnedTimeUnit(timeUnit) {
    if (vega_util_module_isObject(timeUnit)) {
        return timeUnit.binned;
    }
    return isBinnedTimeUnitString(timeUnit);
}
function isBinnedTimeUnitString(timeUnit) {
    return timeUnit && timeUnit.startsWith('binned');
}
const UTC_MULTI_TIMEUNIT_INDEX = {
    utcyearquarter: 1,
    utcyearquartermonth: 1,
    utcyearmonth: 1,
    utcyearmonthdate: 1,
    utcyearmonthdatehours: 1,
    utcyearmonthdatehoursminutes: 1,
    utcyearmonthdatehoursminutesseconds: 1,
    utcyearweek: 1,
    utcyearweekday: 1,
    utcyearweekdayhours: 1,
    utcyearweekdayhoursminutes: 1,
    utcyearweekdayhoursminutesseconds: 1,
    utcyeardayofyear: 1,
    utcquartermonth: 1,
    utcmonthdate: 1,
    utcmonthdatehours: 1,
    utcmonthdatehoursminutes: 1,
    utcmonthdatehoursminutesseconds: 1,
    utcweekday: 1,
    utcweekdayhours: 1,
    utcweekdayhoursminutes: 1,
    utcweekdayhoursminutesseconds: 1,
    utcdayhours: 1,
    utcdayhoursminutes: 1,
    utcdayhoursminutesseconds: 1,
    utchoursminutes: 1,
    utchoursminutesseconds: 1,
    utcminutesseconds: 1,
    utcsecondsmilliseconds: 1
};
function isUTCTimeUnit(t) {
    return t.startsWith('utc');
}
function getLocalTimeUnitFromUTCTimeUnit(t) {
    return t.substring(3);
}
// In order of increasing specificity
const VEGALITE_TIMEFORMAT = {
    'year-month': '%b %Y ',
    'year-month-date': '%b %d, %Y '
};
function getTimeUnitParts(timeUnit) {
    return TIMEUNIT_PARTS.filter(part => containsTimeUnit(timeUnit, part));
}
function getSmallestTimeUnitPart(timeUnit) {
    const parts = getTimeUnitParts(timeUnit);
    return parts[parts.length - 1];
}
/** Returns true if fullTimeUnit contains the timeUnit, false otherwise. */
function containsTimeUnit(fullTimeUnit, timeUnit) {
    const index = fullTimeUnit.indexOf(timeUnit);
    if (index < 0) {
        return false;
    }
    // exclude milliseconds
    if (index > 0 && timeUnit === 'seconds' && fullTimeUnit.charAt(index - 1) === 'i') {
        return false;
    }
    // exclude dayofyear
    if (fullTimeUnit.length > index + 3 && timeUnit === 'day' && fullTimeUnit.charAt(index + 3) === 'o') {
        return false;
    }
    if (index > 0 && timeUnit === 'year' && fullTimeUnit.charAt(index - 1) === 'f') {
        return false;
    }
    return true;
}
/**
 * Returns Vega expression for a given timeUnit and fieldRef
 */
function timeunit_fieldExpr(fullTimeUnit, field, { end } = { end: false }) {
    const fieldRef = accessPathWithDatum(field);
    const utc = isUTCTimeUnit(fullTimeUnit) ? 'utc' : '';
    function func(timeUnit) {
        if (timeUnit === 'quarter') {
            // quarter starting at 0 (0,3,6,9).
            return `(${utc}quarter(${fieldRef})-1)`;
        }
        else {
            return `${utc}${timeUnit}(${fieldRef})`;
        }
    }
    let lastTimeUnit;
    const dateExpr = {};
    for (const part of TIMEUNIT_PARTS) {
        if (containsTimeUnit(fullTimeUnit, part)) {
            dateExpr[part] = func(part);
            lastTimeUnit = part;
        }
    }
    if (end) {
        dateExpr[lastTimeUnit] += '+1';
    }
    return dateTimeExprToExpr(dateExpr);
}
function timeUnitSpecifierExpression(timeUnit) {
    if (!timeUnit) {
        return undefined;
    }
    const timeUnitParts = getTimeUnitParts(timeUnit);
    return `timeUnitSpecifier(${util_stringify(timeUnitParts)}, ${util_stringify(VEGALITE_TIMEFORMAT)})`;
}
/**
 * Returns the signal expression used for axis labels for a time unit.
 */
function formatExpression(timeUnit, field, isUTCScale) {
    if (!timeUnit) {
        return undefined;
    }
    const expr = timeUnitSpecifierExpression(timeUnit);
    // We only use utcFormat for utc scale
    // For utc time units, the data is already converted as a part of timeUnit transform.
    // Thus, utc time units should use timeFormat to avoid shifting the time twice.
    const utc = isUTCScale || isUTCTimeUnit(timeUnit);
    return `${utc ? 'utc' : 'time'}Format(${field}, ${expr})`;
}
function normalizeTimeUnit(timeUnit) {
    if (!timeUnit) {
        return undefined;
    }
    let params;
    if (vega_util_module_isString(timeUnit)) {
        if (isBinnedTimeUnitString(timeUnit)) {
            params = {
                unit: timeUnit.substring(6),
                binned: true
            };
        }
        else {
            params = {
                unit: timeUnit
            };
        }
    }
    else if (vega_util_module_isObject(timeUnit)) {
        params = {
            ...timeUnit,
            ...(timeUnit.unit ? { unit: timeUnit.unit } : {})
        };
    }
    if (isUTCTimeUnit(params.unit)) {
        params.utc = true;
        params.unit = getLocalTimeUnitFromUTCTimeUnit(params.unit);
    }
    return params;
}
function timeUnitToString(tu) {
    const { utc, ...rest } = normalizeTimeUnit(tu);
    if (rest.unit) {
        return ((utc ? 'utc' : '') +
            util_keys(rest)
                .map(p => varName(`${p === 'unit' ? '' : `_${p}_`}${rest[p]}`))
                .join(''));
    }
    else {
        // when maxbins is specified instead of units
        return ((utc ? 'utc' : '') +
            'timeunit' +
            util_keys(rest)
                .map(p => varName(`_${p}_${rest[p]}`))
                .join(''));
    }
}
function durationExpr(timeUnit, wrap = x => x) {
    const normalizedTimeUnit = normalizeTimeUnit(timeUnit);
    const smallestUnitPart = getSmallestTimeUnitPart(normalizedTimeUnit.unit);
    if (smallestUnitPart && smallestUnitPart !== 'day') {
        const startDate = {
            year: 2001, // pick a non-leap year
            month: 1,
            date: 1,
            hours: 0,
            minutes: 0,
            seconds: 0,
            milliseconds: 0
        };
        const { step, part } = getDateTimePartAndStep(smallestUnitPart, normalizedTimeUnit.step);
        const endDate = {
            ...startDate,
            [part]: +startDate[part] + step
        };
        // Calculate timestamp duration for the smallest unit listed
        return `${wrap(dateTimeToExpr(endDate))} - ${wrap(dateTimeToExpr(startDate))}`;
    }
    return undefined;
}
const DATE_PARTS = {
    year: 1,
    month: 1,
    date: 1,
    hours: 1,
    minutes: 1,
    seconds: 1,
    milliseconds: 1
};
function isDatePart(timeUnit) {
    return vega_util_module_has(DATE_PARTS, timeUnit);
}
function getDateTimePartAndStep(timeUnit, step = 1) {
    if (isDatePart(timeUnit)) {
        return { part: timeUnit, step };
    }
    switch (timeUnit) {
        case 'day':
        case 'dayofyear':
            return { part: 'date', step };
        case 'quarter':
            return { part: 'month', step: step * 3 };
        case 'week':
            return { part: 'date', step: step * 7 };
    }
}
//# sourceMappingURL=timeunit.js.map
;// ../../node_modules/vega-lite/build/src/predicate.js






function isSelectionPredicate(predicate) {
    return util_hasProperty(predicate, 'param');
}
function isFieldEqualPredicate(predicate) {
    return !!predicate?.field && predicate.equal !== undefined;
}
function isFieldLTPredicate(predicate) {
    return !!predicate?.field && predicate.lt !== undefined;
}
function isFieldLTEPredicate(predicate) {
    return !!predicate?.field && predicate.lte !== undefined;
}
function isFieldGTPredicate(predicate) {
    return !!predicate?.field && predicate.gt !== undefined;
}
function isFieldGTEPredicate(predicate) {
    return !!predicate?.field && predicate.gte !== undefined;
}
function isFieldRangePredicate(predicate) {
    if (predicate?.field) {
        if (vega_util_module_isArray(predicate.range) && predicate.range.length === 2) {
            return true;
        }
        else if (isSignalRef(predicate.range)) {
            return true;
        }
    }
    return false;
}
function isFieldOneOfPredicate(predicate) {
    return (!!predicate?.field && (vega_util_module_isArray(predicate.oneOf) || vega_util_module_isArray(predicate.in)) // backward compatibility
    );
}
function isFieldValidPredicate(predicate) {
    return !!predicate?.field && predicate.valid !== undefined;
}
function isFieldPredicate(predicate) {
    return (isFieldOneOfPredicate(predicate) ||
        isFieldEqualPredicate(predicate) ||
        isFieldRangePredicate(predicate) ||
        isFieldLTPredicate(predicate) ||
        isFieldGTPredicate(predicate) ||
        isFieldLTEPredicate(predicate) ||
        isFieldGTEPredicate(predicate));
}
function predicateValueExpr(v, timeUnit) {
    return valueExpr(v, { timeUnit, wrapTime: true });
}
function predicateValuesExpr(vals, timeUnit) {
    return vals.map(v => predicateValueExpr(v, timeUnit));
}
// This method is used by Voyager. Do not change its behavior without changing Voyager.
function fieldFilterExpression(predicate, useInRange = true) {
    const { field } = predicate;
    const normalizedTimeUnit = normalizeTimeUnit(predicate.timeUnit);
    const { unit, binned } = normalizedTimeUnit || {};
    const rawFieldExpr = vgField(predicate, { expr: 'datum' });
    const fieldExpr = unit
        ? // For timeUnit, cast into integer with time() so we can use ===, inrange, indexOf to compare values directly.
            // TODO: We calculate timeUnit on the fly here. Consider if we would like to consolidate this with timeUnit pipeline
            // TODO: support utc
            `time(${!binned ? timeunit_fieldExpr(unit, field) : rawFieldExpr})`
        : rawFieldExpr;
    if (isFieldEqualPredicate(predicate)) {
        return `${fieldExpr}===${predicateValueExpr(predicate.equal, unit)}`;
    }
    else if (isFieldLTPredicate(predicate)) {
        const upper = predicate.lt;
        return `${fieldExpr}<${predicateValueExpr(upper, unit)}`;
    }
    else if (isFieldGTPredicate(predicate)) {
        const lower = predicate.gt;
        return `${fieldExpr}>${predicateValueExpr(lower, unit)}`;
    }
    else if (isFieldLTEPredicate(predicate)) {
        const upper = predicate.lte;
        return `${fieldExpr}<=${predicateValueExpr(upper, unit)}`;
    }
    else if (isFieldGTEPredicate(predicate)) {
        const lower = predicate.gte;
        return `${fieldExpr}>=${predicateValueExpr(lower, unit)}`;
    }
    else if (isFieldOneOfPredicate(predicate)) {
        return `indexof([${predicateValuesExpr(predicate.oneOf, unit).join(',')}], ${fieldExpr}) !== -1`;
    }
    else if (isFieldValidPredicate(predicate)) {
        return fieldValidPredicate(fieldExpr, predicate.valid);
    }
    else if (isFieldRangePredicate(predicate)) {
        const { range } = replaceExprRef(predicate);
        const lower = isSignalRef(range) ? { signal: `${range.signal}[0]` } : range[0];
        const upper = isSignalRef(range) ? { signal: `${range.signal}[1]` } : range[1];
        if (lower !== null && upper !== null && useInRange) {
            return ('inrange(' + fieldExpr + ', [' + predicateValueExpr(lower, unit) + ', ' + predicateValueExpr(upper, unit) + '])');
        }
        const exprs = [];
        if (lower !== null) {
            exprs.push(`${fieldExpr} >= ${predicateValueExpr(lower, unit)}`);
        }
        if (upper !== null) {
            exprs.push(`${fieldExpr} <= ${predicateValueExpr(upper, unit)}`);
        }
        return exprs.length > 0 ? exprs.join(' && ') : 'true';
    }
    /* istanbul ignore next: it should never reach here */
    throw new Error(`Invalid field predicate: ${util_stringify(predicate)}`);
}
function fieldValidPredicate(fieldExpr, valid = true) {
    if (valid) {
        return `isValid(${fieldExpr}) && isFinite(+${fieldExpr})`;
    }
    else {
        return `!isValid(${fieldExpr}) || !isFinite(+${fieldExpr})`;
    }
}
function normalizePredicate(f) {
    if (isFieldPredicate(f) && f.timeUnit) {
        return {
            ...f,
            timeUnit: normalizeTimeUnit(f.timeUnit)
        };
    }
    return f;
}
//# sourceMappingURL=predicate.js.map
;// ../../node_modules/vega-lite/build/src/type.js


/**
 * Data type based on level of measurement
 */
const type_Type = {
    quantitative: 'quantitative',
    ordinal: 'ordinal',
    temporal: 'temporal',
    nominal: 'nominal',
    geojson: 'geojson'
};
function isType(t) {
    return hasOwnProperty(type_Type, t);
}
function type_isContinuous(type) {
    return type === 'quantitative' || type === 'temporal';
}
function type_isDiscrete(type) {
    return type === 'ordinal' || type === 'nominal';
}
const QUANTITATIVE = type_Type.quantitative;
const ORDINAL = type_Type.ordinal;
const TEMPORAL = type_Type.temporal;
const NOMINAL = type_Type.nominal;
const GEOJSON = type_Type.geojson;
const TYPES = util_keys(type_Type);
/**
 * Get full, lowercase type name for a given type.
 * @param  type
 * @return Full type name.
 */
function getFullName(type) {
    if (type) {
        type = type.toLowerCase();
        switch (type) {
            case 'q':
            case QUANTITATIVE:
                return 'quantitative';
            case 't':
            case TEMPORAL:
                return 'temporal';
            case 'o':
            case ORDINAL:
                return 'ordinal';
            case 'n':
            case NOMINAL:
                return 'nominal';
            case GEOJSON:
                return 'geojson';
        }
    }
    // If we get invalid input, return undefined type.
    return undefined;
}
//# sourceMappingURL=type.js.map
;// ../../node_modules/vega-lite/build/src/scale.js






const ScaleType = {
    // Continuous - Quantitative
    LINEAR: 'linear',
    LOG: 'log',
    POW: 'pow',
    SQRT: 'sqrt',
    SYMLOG: 'symlog',
    IDENTITY: 'identity',
    SEQUENTIAL: 'sequential',
    // Continuous - Time
    TIME: 'time',
    UTC: 'utc',
    // Discretizing scales
    QUANTILE: 'quantile',
    QUANTIZE: 'quantize',
    THRESHOLD: 'threshold',
    BIN_ORDINAL: 'bin-ordinal',
    // Discrete scales
    ORDINAL: 'ordinal',
    POINT: 'point',
    BAND: 'band'
};
/**
 * Index for scale categories -- only scale of the same categories can be merged together.
 * Current implementation is trying to be conservative and avoid merging scale type that might not work together
 */
const SCALE_CATEGORY_INDEX = {
    linear: 'numeric',
    log: 'numeric',
    pow: 'numeric',
    sqrt: 'numeric',
    symlog: 'numeric',
    identity: 'numeric',
    sequential: 'numeric',
    time: 'time',
    utc: 'time',
    ordinal: 'ordinal',
    'bin-ordinal': 'bin-ordinal', // TODO: should bin-ordinal support merging with other
    point: 'ordinal-position',
    band: 'ordinal-position',
    quantile: 'discretizing',
    quantize: 'discretizing',
    threshold: 'discretizing'
};
const SCALE_TYPES = util_keys(SCALE_CATEGORY_INDEX);
/**
 * Whether the two given scale types can be merged together.
 */
function scaleCompatible(scaleType1, scaleType2) {
    const scaleCategory1 = SCALE_CATEGORY_INDEX[scaleType1];
    const scaleCategory2 = SCALE_CATEGORY_INDEX[scaleType2];
    return (scaleCategory1 === scaleCategory2 ||
        (scaleCategory1 === 'ordinal-position' && scaleCategory2 === 'time') ||
        (scaleCategory2 === 'ordinal-position' && scaleCategory1 === 'time'));
}
/**
 * Index for scale precedence -- high score = higher priority for merging.
 */
const SCALE_PRECEDENCE_INDEX = {
    // numeric
    linear: 0,
    log: 1,
    pow: 1,
    sqrt: 1,
    symlog: 1,
    identity: 1,
    sequential: 1,
    // time
    time: 0,
    utc: 0,
    // ordinal-position -- these have higher precedence than continuous scales as they support more types of data
    point: 10,
    band: 11, // band has higher precedence as it is better for interaction
    // non grouped types
    ordinal: 0,
    'bin-ordinal': 0,
    quantile: 0,
    quantize: 0,
    threshold: 0
};
/**
 * Return scale categories -- only scale of the same categories can be merged together.
 */
function scaleTypePrecedence(scaleType) {
    return SCALE_PRECEDENCE_INDEX[scaleType];
}
const QUANTITATIVE_SCALES = new Set([
    'linear',
    'log',
    'pow',
    'sqrt',
    'symlog'
]);
const CONTINUOUS_TO_CONTINUOUS_SCALES = new Set([
    ...QUANTITATIVE_SCALES,
    'time',
    'utc'
]);
function isQuantitative(type) {
    return QUANTITATIVE_SCALES.has(type);
}
const CONTINUOUS_TO_DISCRETE_SCALES = new Set([
    'quantile',
    'quantize',
    'threshold'
]);
const CONTINUOUS_DOMAIN_SCALES = new Set([
    ...CONTINUOUS_TO_CONTINUOUS_SCALES,
    ...CONTINUOUS_TO_DISCRETE_SCALES,
    'sequential',
    'identity'
]);
const DISCRETE_DOMAIN_SCALES = new Set([
    'ordinal',
    'bin-ordinal',
    'point',
    'band'
]);
const TIME_SCALE_TYPES = new Set(['time', 'utc']);
function hasDiscreteDomain(type) {
    return DISCRETE_DOMAIN_SCALES.has(type);
}
function hasContinuousDomain(type) {
    return CONTINUOUS_DOMAIN_SCALES.has(type);
}
function isContinuousToContinuous(type) {
    return CONTINUOUS_TO_CONTINUOUS_SCALES.has(type);
}
function isContinuousToDiscrete(type) {
    return CONTINUOUS_TO_DISCRETE_SCALES.has(type);
}
const defaultScaleConfig = {
    pointPadding: 0.5,
    barBandPaddingInner: 0.1,
    rectBandPaddingInner: 0,
    tickBandPaddingInner: 0.25,
    bandWithNestedOffsetPaddingInner: 0.2,
    bandWithNestedOffsetPaddingOuter: 0.2,
    minBandSize: 2,
    minFontSize: 8,
    maxFontSize: 40,
    minOpacity: 0.3,
    maxOpacity: 0.8,
    // FIXME: revise if these *can* become ratios of width/height step
    minSize: 4, // Point size is area. For square point, 9 = 3 pixel ^ 2, not too small!
    minStrokeWidth: 1,
    maxStrokeWidth: 4,
    quantileCount: 4,
    quantizeCount: 4,
    zero: true,
    framesPerSecond: 2,
    animationDuration: 5
};
function isExtendedScheme(scheme) {
    return !vega_util_module_isString(scheme) && util_hasProperty(scheme, 'name');
}
function isParameterDomain(domain) {
    return util_hasProperty(domain, 'param');
}
function isDomainUnionWith(domain) {
    return util_hasProperty(domain, 'unionWith');
}
function isFieldRange(range) {
    return vega_util_module_isObject(range) && 'field' in range;
}
const SCALE_PROPERTY_INDEX = {
    type: 1,
    domain: 1,
    domainMax: 1,
    domainMin: 1,
    domainMid: 1,
    domainRaw: 1,
    align: 1,
    range: 1,
    rangeMax: 1,
    rangeMin: 1,
    scheme: 1,
    bins: 1,
    // Other properties
    reverse: 1,
    round: 1,
    // quantitative / time
    clamp: 1,
    nice: 1,
    // quantitative
    base: 1,
    exponent: 1,
    constant: 1,
    interpolate: 1,
    zero: 1, // zero depends on domain
    // band/point
    padding: 1,
    paddingInner: 1,
    paddingOuter: 1
};
const SCALE_PROPERTIES = util_keys(SCALE_PROPERTY_INDEX);
const { type: scale_type, domain: scale_domain, range: scale_range, rangeMax, rangeMin, scheme: scale_scheme, ...NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTY_INDEX } = SCALE_PROPERTY_INDEX;
const NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES = util_keys(NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTY_INDEX);
function scaleTypeSupportProperty(scaleType, propName) {
    switch (propName) {
        case 'type':
        case 'domain':
        case 'reverse':
        case 'range':
            return true;
        case 'scheme':
        case 'interpolate':
            return !['point', 'band', 'identity'].includes(scaleType);
        case 'bins':
            return !['point', 'band', 'identity', 'ordinal'].includes(scaleType);
        case 'round':
            return isContinuousToContinuous(scaleType) || scaleType === 'band' || scaleType === 'point';
        case 'padding':
        case 'rangeMin':
        case 'rangeMax':
            return isContinuousToContinuous(scaleType) || ['point', 'band'].includes(scaleType);
        case 'paddingOuter':
        case 'align':
            return ['point', 'band'].includes(scaleType);
        case 'paddingInner':
            return scaleType === 'band';
        case 'domainMax':
        case 'domainMid':
        case 'domainMin':
        case 'domainRaw':
        case 'clamp':
            return isContinuousToContinuous(scaleType);
        case 'nice':
            return isContinuousToContinuous(scaleType) || scaleType === 'quantize' || scaleType === 'threshold';
        case 'exponent':
            return scaleType === 'pow';
        case 'base':
            return scaleType === 'log';
        case 'constant':
            return scaleType === 'symlog';
        case 'zero':
            return (hasContinuousDomain(scaleType) &&
                !util_contains([
                    'log', // log scale cannot have zero value
                    'time',
                    'utc', // zero is not meaningful for time
                    'threshold', // threshold requires custom domain so zero does not matter
                    'quantile' // quantile depends on distribution so zero does not matter
                ], scaleType));
    }
}
/**
 * Returns undefined if the input channel supports the input scale property name
 */
function channelScalePropertyIncompatability(channel, propName) {
    switch (propName) {
        case 'interpolate':
        case 'scheme':
        case 'domainMid':
            if (!isColorChannel(channel)) {
                return cannotUseScalePropertyWithNonColor(propName);
            }
            return undefined;
        case 'align':
        case 'type':
        case 'bins':
        case 'domain':
        case 'domainMax':
        case 'domainMin':
        case 'domainRaw':
        case 'range':
        case 'base':
        case 'exponent':
        case 'constant':
        case 'nice':
        case 'padding':
        case 'paddingInner':
        case 'paddingOuter':
        case 'rangeMax':
        case 'rangeMin':
        case 'reverse':
        case 'round':
        case 'clamp':
        case 'zero':
            return undefined; // GOOD!
    }
}
function scaleTypeSupportDataType(specifiedType, fieldDefType) {
    if (util_contains([ORDINAL, NOMINAL], fieldDefType)) {
        return specifiedType === undefined || hasDiscreteDomain(specifiedType);
    }
    else if (fieldDefType === TEMPORAL) {
        return util_contains([ScaleType.TIME, ScaleType.UTC, undefined], specifiedType);
    }
    else if (fieldDefType === QUANTITATIVE) {
        return isQuantitative(specifiedType) || isContinuousToDiscrete(specifiedType) || specifiedType === undefined;
    }
    return true;
}
function channelSupportScaleType(channel, scaleType, hasNestedOffsetScale = false) {
    if (!isScaleChannel(channel)) {
        return false;
    }
    switch (channel) {
        case channel_X:
        case channel_Y:
        case XOFFSET:
        case YOFFSET:
        case THETA:
        case RADIUS:
            if (isContinuousToContinuous(scaleType)) {
                return true;
            }
            else if (scaleType === 'band') {
                return true;
            }
            else if (scaleType === 'point') {
                /*
                  Point scale can't be use if the position has a nested offset scale
                  because if there is a nested scale, then it's band.
                */
                return !hasNestedOffsetScale;
            }
            return false;
        case TIME:
            return util_contains(['linear', 'band'], scaleType);
        case channel_SIZE: // TODO: size and opacity can support ordinal with more modification
        case STROKEWIDTH:
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
        case ANGLE:
            // Although it generally doesn't make sense to use band with size and opacity,
            // it can also work since we use band: 0.5 to get midpoint.
            return (isContinuousToContinuous(scaleType) ||
                isContinuousToDiscrete(scaleType) ||
                util_contains(['band', 'point', 'ordinal'], scaleType));
        case COLOR:
        case FILL:
        case STROKE:
            return scaleType !== 'band'; // band does not make sense with color
        case STROKEDASH:
        case SHAPE:
            return scaleType === 'ordinal' || isContinuousToDiscrete(scaleType);
    }
}
//# sourceMappingURL=scale.js.map
;// ../../node_modules/vega-lite/build/src/invalid.js

function isScaleInvalidDataIncludeAsValue(invalidDataMode) {
    return vega_util_module_isObject(invalidDataMode) && 'value' in invalidDataMode;
}
//# sourceMappingURL=invalid.js.map
;// ../../node_modules/vega-lite/build/src/mark.js


/**
 * All types of primitive marks.
 */
const mark_Mark = {
    arc: 'arc',
    area: 'area',
    bar: 'bar',
    image: 'image',
    line: 'line',
    point: 'point',
    rect: 'rect',
    rule: 'rule',
    text: 'text',
    tick: 'tick',
    trail: 'trail',
    circle: 'circle',
    square: 'square',
    geoshape: 'geoshape'
};
const ARC = mark_Mark.arc;
const AREA = mark_Mark.area;
const BAR = mark_Mark.bar;
const IMAGE = mark_Mark.image;
const LINE = mark_Mark.line;
const POINT = mark_Mark.point;
const RECT = mark_Mark.rect;
const RULE = mark_Mark.rule;
const mark_TEXT = mark_Mark.text;
const TICK = mark_Mark.tick;
const TRAIL = mark_Mark.trail;
const CIRCLE = mark_Mark.circle;
const SQUARE = mark_Mark.square;
const GEOSHAPE = mark_Mark.geoshape;
function isMark(m) {
    return hasOwnProperty(mark_Mark, m);
}
const PATH_MARKS = (/* unused pure expression or super */ null && (['line', 'area', 'trail']));
function isPathMark(m) {
    return ['line', 'area', 'trail'].includes(m);
}
function isRectBasedMark(m) {
    return ['rect', 'bar', 'image', 'arc', 'tick' /* arc is rect/interval in polar coordinate */].includes(m);
}
const PRIMITIVE_MARKS = new Set(util_keys(mark_Mark));
function isMarkDef(mark) {
    return util_hasProperty(mark, 'type');
}
function isPrimitiveMark(mark) {
    const markType = isMarkDef(mark) ? mark.type : mark;
    return PRIMITIVE_MARKS.has(markType);
}
const STROKE_CONFIG = [
    'stroke',
    'strokeWidth',
    'strokeDash',
    'strokeDashOffset',
    'strokeOpacity',
    'strokeJoin',
    'strokeMiterLimit'
];
const FILL_CONFIG = ['fill', 'fillOpacity'];
const FILL_STROKE_CONFIG = [...STROKE_CONFIG, ...FILL_CONFIG];
const VL_ONLY_MARK_CONFIG_INDEX = {
    color: 1,
    filled: 1,
    invalid: 1,
    order: 1,
    radius2: 1,
    theta2: 1,
    timeUnitBandSize: 1,
    timeUnitBandPosition: 1
};
const VL_ONLY_MARK_CONFIG_PROPERTIES = util_keys(VL_ONLY_MARK_CONFIG_INDEX);
const VL_ONLY_RECT_CONFIG = [
    'binSpacing',
    'continuousBandSize',
    'discreteBandSize',
    'minBandSize'
];
const VL_ONLY_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX = {
    area: ['line', 'point'],
    bar: VL_ONLY_RECT_CONFIG,
    rect: VL_ONLY_RECT_CONFIG,
    line: ['point'],
    tick: ['bandSize', 'thickness', ...VL_ONLY_RECT_CONFIG]
};
const defaultMarkConfig = {
    color: '#4c78a8',
    invalid: 'break-paths-show-path-domains',
    timeUnitBandSize: 1
};
const MARK_CONFIG_INDEX = {
    mark: 1,
    arc: 1,
    area: 1,
    bar: 1,
    circle: 1,
    image: 1,
    line: 1,
    point: 1,
    rect: 1,
    rule: 1,
    square: 1,
    text: 1,
    tick: 1,
    trail: 1,
    geoshape: 1
};
const MARK_CONFIGS = util_keys(MARK_CONFIG_INDEX);
function isRelativeBandSize(o) {
    return util_hasProperty(o, 'band');
}
const BAR_CORNER_RADIUS_INDEX = {
    horizontal: ['cornerRadiusTopRight', 'cornerRadiusBottomRight'],
    vertical: ['cornerRadiusTopLeft', 'cornerRadiusTopRight']
};
const DEFAULT_RECT_BAND_SIZE = 5;
const defaultRectConfig = {
    binSpacing: 0,
    continuousBandSize: DEFAULT_RECT_BAND_SIZE,
    minBandSize: 0.25,
    timeUnitBandPosition: 0.5
};
const defaultBarConfig = {
    ...defaultRectConfig,
    binSpacing: 1
};
const defaultTickConfig = {
    ...defaultRectConfig,
    thickness: 1
};
function getMarkType(m) {
    return isMarkDef(m) ? m.type : m;
}
//# sourceMappingURL=mark.js.map
;// ../../node_modules/vega-lite/build/src/compile/invalid/normalizeInvalidDataMode.js
function normalizeInvalidDataMode(mode, { isPath }) {
    if (mode === undefined || mode === 'break-paths-show-path-domains') {
        return isPath ? 'break-paths-show-domains' : 'filter';
    }
    else if (mode === null) {
        return 'show';
    }
    return mode;
}
//# sourceMappingURL=normalizeInvalidDataMode.js.map
;// ../../node_modules/vega-lite/build/src/compile/invalid/ScaleInvalidDataMode.js




function getScaleInvalidDataMode({ markDef, config, scaleChannel, scaleType, isCountAggregate }) {
    if (!scaleType || !hasContinuousDomain(scaleType) || isCountAggregate) {
        // - Discrete scales can always display null as another category
        // - Count cannot output null values
        return 'always-valid';
    }
    const invalidMode = normalizeInvalidDataMode(getMarkPropOrConfig('invalid', markDef, config), {
        isPath: isPathMark(markDef.type)
    });
    const scaleOutputForInvalid = config.scale?.invalid?.[scaleChannel];
    if (scaleOutputForInvalid !== undefined) {
        // Regardless of the current invalid mode, if the channel has a default value, we consider the field valid.
        return 'show';
    }
    return invalidMode;
}
function shouldBreakPath(mode) {
    return mode === 'break-paths-filter-domains' || mode === 'break-paths-show-domains';
}
//# sourceMappingURL=ScaleInvalidDataMode.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/scaledZeroOrMinOrMax.js
function scaledZeroOrMinOrMax({ scaleName, scale, mode }) {
    const domain = `domain('${scaleName}')`;
    if (!scale || !scaleName) {
        return undefined;
    }
    const min = `${domain}[0]`;
    const max = `peek(${domain})`; // peek = the last item of the array
    // If there is a scale (and hence its name)
    const domainHasZero = scale.domainHasZero();
    // zeroOrMin or zeroOrMax mode
    if (domainHasZero === 'definitely') {
        return {
            scale: scaleName,
            value: 0
        };
    }
    else if (domainHasZero === 'maybe') {
        const nonZeroValue = mode === 'zeroOrMin' ? min : max;
        return { signal: `scale('${scaleName}', inrange(0, ${domain}) ? 0 : ${nonZeroValue})` };
    }
    else {
        // domainHasZero === 'definitely-not'
        return { signal: `scale('${scaleName}', ${mode === 'zeroOrMin' ? min : max})` };
    }
}
//# sourceMappingURL=scaledZeroOrMinOrMax.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/invalid.js







function getConditionalValueRefForIncludingInvalidValue({ scaleChannel, channelDef, scale, scaleName, markDef, config }) {
    const scaleType = scale?.get('type');
    const fieldDef = getFieldDef(channelDef);
    const isCountAggregate = isCountingAggregateOp(fieldDef?.aggregate);
    const invalidDataMode = getScaleInvalidDataMode({
        scaleChannel,
        markDef,
        config,
        scaleType,
        isCountAggregate
    });
    if (fieldDef && invalidDataMode === 'show') {
        const includeAs = config.scale.invalid?.[scaleChannel] ?? 'zero-or-min';
        return {
            test: fieldValidPredicate(vgField(fieldDef, { expr: 'datum' }), false),
            ...refForInvalidValues(includeAs, scale, scaleName)
        };
    }
    return undefined;
}
function refForInvalidValues(includeAs, scale, scaleName) {
    if (isScaleInvalidDataIncludeAsValue(includeAs)) {
        const { value } = includeAs;
        return isSignalRef(value) ? { signal: value.signal } : { value };
    }
    return scaledZeroOrMinOrMax({
        scale,
        scaleName,
        mode: 'zeroOrMin'
    });
}
//# sourceMappingURL=invalid.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/valueref.js













function midPointRefWithPositionInvalidTest(params) {
    const { channel, channelDef, markDef, scale, scaleName, config } = params;
    const scaleChannel = getMainRangeChannel(channel);
    const mainRef = midPoint(params);
    const valueRefForIncludingInvalid = getConditionalValueRefForIncludingInvalidValue({
        scaleChannel,
        channelDef,
        scale,
        scaleName,
        markDef,
        config
    });
    return valueRefForIncludingInvalid !== undefined ? [valueRefForIncludingInvalid, mainRef] : mainRef;
}
function datumDefToExpr(datumDef) {
    const { datum } = datumDef;
    if (isDateTime(datum)) {
        return dateTimeToExpr(datum);
    }
    return `${util_stringify(datum)}`;
}
function valueRefForFieldOrDatumDef(fieldDef, scaleName, opt, encode) {
    const ref = {};
    if (scaleName) {
        ref.scale = scaleName;
    }
    if (isDatumDef(fieldDef)) {
        const { datum } = fieldDef;
        if (isDateTime(datum)) {
            ref.signal = dateTimeToExpr(datum);
        }
        else if (isSignalRef(datum)) {
            ref.signal = datum.signal;
        }
        else if (isExprRef(datum)) {
            ref.signal = datum.expr;
        }
        else {
            ref.value = datum;
        }
    }
    else {
        ref.field = vgField(fieldDef, opt);
    }
    if (encode) {
        const { offset, band } = encode;
        if (offset) {
            ref.offset = offset;
        }
        if (band) {
            ref.band = band;
        }
    }
    return ref;
}
/**
 * Signal that returns the middle of a bin from start and end field. Should only be used with x and y.
 */
function interpolatedSignalRef({ scaleName, fieldOrDatumDef, fieldOrDatumDef2, offset, startSuffix, endSuffix = 'end', bandPosition = 0.5 }) {
    const expr = !isSignalRef(bandPosition) && 0 < bandPosition && bandPosition < 1 ? 'datum' : undefined;
    const start = vgField(fieldOrDatumDef, { expr, suffix: startSuffix });
    const end = fieldOrDatumDef2 !== undefined
        ? vgField(fieldOrDatumDef2, { expr })
        : vgField(fieldOrDatumDef, { suffix: endSuffix, expr });
    const ref = {};
    if (bandPosition === 0 || bandPosition === 1) {
        ref.scale = scaleName;
        const field = bandPosition === 0 ? start : end;
        ref.field = field;
    }
    else {
        const datum = isSignalRef(bandPosition)
            ? `(1-${bandPosition.signal}) * ${start} + ${bandPosition.signal} * ${end}`
            : `${1 - bandPosition} * ${start} + ${bandPosition} * ${end}`;
        ref.signal = `scale("${scaleName}", ${datum})`;
    }
    if (offset) {
        ref.offset = offset;
    }
    return ref;
}
function binSizeExpr({ scaleName, fieldDef }) {
    const start = vgField(fieldDef, { expr: 'datum' });
    const end = vgField(fieldDef, { expr: 'datum', suffix: 'end' });
    return `abs(scale("${scaleName}", ${end}) - scale("${scaleName}", ${start}))`;
}
/**
 * @returns {VgValueRef} Value Ref for xc / yc or mid point for other channels.
 */
function midPoint({ channel, channelDef, channel2Def, markDef, config, scaleName, scale, stack, offset, defaultRef, bandPosition }) {
    // TODO: datum support
    if (channelDef) {
        /* istanbul ignore else */
        if (isFieldOrDatumDef(channelDef)) {
            const scaleType = scale?.get('type');
            if (isTypedFieldDef(channelDef)) {
                bandPosition ?? (bandPosition = getBandPosition({
                    fieldDef: channelDef,
                    fieldDef2: channel2Def,
                    markDef,
                    config
                }));
                const { bin, timeUnit, type } = channelDef;
                if (isBinning(bin) || (bandPosition && timeUnit && type === TEMPORAL)) {
                    // Use middle only for x an y to place marks in the center between start and end of the bin range.
                    // We do not use the mid point for other channels (e.g. size) so that properties of legends and marks match.
                    if (stack?.impute) {
                        // For stack, we computed bin_mid so we can impute.
                        return valueRefForFieldOrDatumDef(channelDef, scaleName, { binSuffix: 'mid' }, { offset });
                    }
                    if (bandPosition && !hasDiscreteDomain(scaleType)) {
                        // if band = 0, no need to call interpolation
                        // For non-stack, we can just calculate bin mid on the fly using signal.
                        return interpolatedSignalRef({ scaleName, fieldOrDatumDef: channelDef, bandPosition, offset });
                    }
                    return valueRefForFieldOrDatumDef(channelDef, scaleName, binRequiresRange(channelDef, channel) ? { binSuffix: 'range' } : {}, {
                        offset
                    });
                }
                else if (isBinned(bin)) {
                    if (isFieldDef(channel2Def)) {
                        return interpolatedSignalRef({
                            scaleName,
                            fieldOrDatumDef: channelDef,
                            fieldOrDatumDef2: channel2Def,
                            bandPosition,
                            offset
                        });
                    }
                    else {
                        const channel2 = channel === channel_X ? channel_X2 : channel_Y2;
                        log_warn(channelRequiredForBinned(channel2));
                    }
                }
            }
            return valueRefForFieldOrDatumDef(channelDef, scaleName, hasDiscreteDomain(scaleType) ? { binSuffix: 'range' } : {}, // no need for bin suffix if there is no scale
            {
                offset,
                // For band, to get mid point, need to offset by half of the band
                band: scaleType === 'band' ? (bandPosition ?? channelDef.bandPosition ?? 0.5) : undefined
            });
        }
        else if (isValueDef(channelDef)) {
            const value = channelDef.value;
            const offsetMixins = offset ? { offset } : {};
            return { ...widthHeightValueOrSignalRef(channel, value), ...offsetMixins };
        }
        // If channelDef is neither field def or value def, it's a condition-only def.
        // In such case, we will use default ref.
    }
    if (vega_util_module_isFunction(defaultRef)) {
        defaultRef = defaultRef();
    }
    if (defaultRef) {
        // for non-position, ref could be undefined.
        return {
            ...defaultRef,
            // only include offset when it is non-zero (zero = no offset)
            ...(offset ? { offset } : {})
        };
    }
    return defaultRef;
}
/**
 * Convert special "width" and "height" values in Vega-Lite into Vega value ref.
 */
function widthHeightValueOrSignalRef(channel, value) {
    if (util_contains(['x', 'x2'], channel) && value === 'width') {
        return { field: { group: 'width' } };
    }
    else if (util_contains(['y', 'y2'], channel) && value === 'height') {
        return { field: { group: 'height' } };
    }
    return signalOrValueRef(value);
}
//# sourceMappingURL=valueref.js.map
;// ../../node_modules/vega-lite/build/src/compile/format.js










function isCustomFormatType(formatType) {
    return formatType && formatType !== 'number' && formatType !== 'time';
}
function customFormatExpr(formatType, field, format) {
    return `${formatType}(${field}${format ? `, ${util_stringify(format)}` : ''})`;
}
const format_BIN_RANGE_DELIMITER = ' \u2013 ';
function formatSignalRef({ fieldOrDatumDef, format, formatType, expr, normalizeStack, config }) {
    if (isCustomFormatType(formatType)) {
        return formatCustomType({
            fieldOrDatumDef,
            format,
            formatType,
            expr,
            config
        });
    }
    const field = fieldToFormat(fieldOrDatumDef, expr, normalizeStack);
    const type = channelDefType(fieldOrDatumDef);
    if (format === undefined && formatType === undefined && config.customFormatTypes) {
        if (type === 'quantitative') {
            if (normalizeStack && config.normalizedNumberFormatType)
                return formatCustomType({
                    fieldOrDatumDef,
                    format: config.normalizedNumberFormat,
                    formatType: config.normalizedNumberFormatType,
                    expr,
                    config
                });
            if (config.numberFormatType) {
                return formatCustomType({
                    fieldOrDatumDef,
                    format: config.numberFormat,
                    formatType: config.numberFormatType,
                    expr,
                    config
                });
            }
        }
        if (type === 'temporal' &&
            config.timeFormatType &&
            isFieldDef(fieldOrDatumDef) &&
            fieldOrDatumDef.timeUnit === undefined) {
            return formatCustomType({
                fieldOrDatumDef,
                format: config.timeFormat,
                formatType: config.timeFormatType,
                expr,
                config
            });
        }
    }
    if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef)) {
        const signal = timeFormatExpression({
            field,
            timeUnit: isFieldDef(fieldOrDatumDef) ? normalizeTimeUnit(fieldOrDatumDef.timeUnit)?.unit : undefined,
            format,
            formatType: config.timeFormatType,
            rawTimeFormat: config.timeFormat,
            isUTCScale: isScaleFieldDef(fieldOrDatumDef) && fieldOrDatumDef.scale?.type === ScaleType.UTC
        });
        return signal ? { signal } : undefined;
    }
    format = numberFormat({ type, specifiedFormat: format, config, normalizeStack });
    if (isFieldDef(fieldOrDatumDef) && isBinning(fieldOrDatumDef.bin)) {
        const endField = vgField(fieldOrDatumDef, { expr, binSuffix: 'end' });
        return {
            signal: binFormatExpression(field, endField, format, formatType, config)
        };
    }
    else if (format || channelDefType(fieldOrDatumDef) === 'quantitative') {
        return {
            signal: `${formatExpr(field, format)}`
        };
    }
    else {
        return { signal: `isValid(${field}) ? ${field} : ""+${field}` };
    }
}
function fieldToFormat(fieldOrDatumDef, expr, normalizeStack) {
    if (isFieldDef(fieldOrDatumDef)) {
        if (normalizeStack) {
            return `${vgField(fieldOrDatumDef, { expr, suffix: 'end' })}-${vgField(fieldOrDatumDef, {
                expr,
                suffix: 'start'
            })}`;
        }
        else {
            return vgField(fieldOrDatumDef, { expr });
        }
    }
    else {
        return datumDefToExpr(fieldOrDatumDef);
    }
}
function formatCustomType({ fieldOrDatumDef, format, formatType, expr, normalizeStack, config, field }) {
    field ?? (field = fieldToFormat(fieldOrDatumDef, expr, normalizeStack));
    if (field !== 'datum.value' && // For axis/legend, we can't correctly know the end of the bin from `datum`
        isFieldDef(fieldOrDatumDef) &&
        isBinning(fieldOrDatumDef.bin)) {
        const endField = vgField(fieldOrDatumDef, { expr, binSuffix: 'end' });
        return {
            signal: binFormatExpression(field, endField, format, formatType, config)
        };
    }
    return { signal: customFormatExpr(formatType, field, format) };
}
function guideFormat(fieldOrDatumDef, type, format, formatType, config, omitTimeFormatConfig // axis doesn't use config.timeFormat
) {
    if (vega_util_module_isString(formatType) && isCustomFormatType(formatType)) {
        return undefined; // handled in encode block
    }
    else if (format === undefined && formatType === undefined && config.customFormatTypes) {
        if (channelDefType(fieldOrDatumDef) === 'quantitative') {
            if (config.normalizedNumberFormatType &&
                isPositionFieldOrDatumDef(fieldOrDatumDef) &&
                fieldOrDatumDef.stack === 'normalize') {
                return undefined; // handled in encode block
            }
            if (config.numberFormatType) {
                return undefined; // handled in encode block
            }
        }
    }
    if (isPositionFieldOrDatumDef(fieldOrDatumDef) &&
        fieldOrDatumDef.stack === 'normalize' &&
        config.normalizedNumberFormat) {
        return numberFormat({
            type: 'quantitative',
            config,
            normalizeStack: true
        });
    }
    if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef)) {
        const timeUnit = isFieldDef(fieldOrDatumDef) ? normalizeTimeUnit(fieldOrDatumDef.timeUnit)?.unit : undefined;
        if (timeUnit === undefined && config.customFormatTypes && config.timeFormatType) {
            return undefined; // hanlded in encode block
        }
        return format_timeFormat({ specifiedFormat: format, timeUnit, config, omitTimeFormatConfig });
    }
    return numberFormat({ type, specifiedFormat: format, config });
}
function guideFormatType(formatType, fieldOrDatumDef, scaleType) {
    if (formatType && (isSignalRef(formatType) || formatType === 'number' || formatType === 'time')) {
        return formatType;
    }
    if (isFieldOrDatumDefForTimeFormat(fieldOrDatumDef) && scaleType !== 'time' && scaleType !== 'utc') {
        return isFieldDef(fieldOrDatumDef) && normalizeTimeUnit(fieldOrDatumDef?.timeUnit)?.utc ? 'utc' : 'time';
    }
    return undefined;
}
/**
 * Returns number format for a fieldDef.
 */
function numberFormat({ type, specifiedFormat, config, normalizeStack }) {
    // Specified format in axis/legend has higher precedence than fieldDef.format
    if (vega_util_module_isString(specifiedFormat)) {
        return specifiedFormat;
    }
    if (type === QUANTITATIVE) {
        // we only apply the default if the field is quantitative
        return normalizeStack ? config.normalizedNumberFormat : config.numberFormat;
    }
    return undefined;
}
/**
 * Returns time format for a fieldDef for use in guides.
 */
function format_timeFormat({ specifiedFormat, timeUnit, config, omitTimeFormatConfig }) {
    if (specifiedFormat) {
        return specifiedFormat;
    }
    if (timeUnit) {
        return {
            signal: timeUnitSpecifierExpression(timeUnit)
        };
    }
    return omitTimeFormatConfig ? undefined : config.timeFormat;
}
function formatExpr(field, format) {
    return `format(${field}, "${format || ''}")`;
}
function binNumberFormatExpr(field, format, formatType, config) {
    if (isCustomFormatType(formatType)) {
        return customFormatExpr(formatType, field, format);
    }
    return formatExpr(field, (vega_util_module_isString(format) ? format : undefined) ?? config.numberFormat);
}
function binFormatExpression(startField, endField, format, formatType, config) {
    if (format === undefined && formatType === undefined && config.customFormatTypes && config.numberFormatType) {
        return binFormatExpression(startField, endField, config.numberFormat, config.numberFormatType, config);
    }
    const start = binNumberFormatExpr(startField, format, formatType, config);
    const end = binNumberFormatExpr(endField, format, formatType, config);
    return `${fieldValidPredicate(startField, false)} ? "null" : ${start} + "${format_BIN_RANGE_DELIMITER}" + ${end}`;
}
/**
 * Returns the time expression used for axis/legend labels or text mark for a temporal field
 */
function timeFormatExpression({ field, timeUnit, format, formatType, rawTimeFormat, isUTCScale }) {
    if (!timeUnit || format) {
        // If there is no time unit, or if user explicitly specifies format for axis/legend/text.
        if (!timeUnit && formatType) {
            return `${formatType}(${field}, '${format}')`;
        }
        format = vega_util_module_isString(format) ? format : rawTimeFormat; // only use provided timeFormat if there is no timeUnit.
        return `${isUTCScale ? 'utc' : 'time'}Format(${field}, '${format}')`;
    }
    else {
        return formatExpression(timeUnit, field, isUTCScale);
    }
}
//# sourceMappingURL=format.js.map
;// ../../node_modules/vega-lite/build/src/sort.js


const DEFAULT_SORT_OP = 'min';
const SORT_BY_CHANNEL_INDEX = {
    x: 1,
    y: 1,
    color: 1,
    fill: 1,
    stroke: 1,
    strokeWidth: 1,
    size: 1,
    shape: 1,
    fillOpacity: 1,
    strokeOpacity: 1,
    opacity: 1,
    text: 1
};
function isSortByChannel(c) {
    return vega_util_module_has(SORT_BY_CHANNEL_INDEX, c);
}
function isSortByEncoding(sort) {
    return util_hasProperty(sort, 'encoding');
}
function isSortField(sort) {
    return sort && (sort.op === 'count' || util_hasProperty(sort, 'field'));
}
function isSortArray(sort) {
    return sort && vega_util_module_isArray(sort);
}
//# sourceMappingURL=sort.js.map
;// ../../node_modules/vega-lite/build/src/spec/facet.js

function isFacetMapping(f) {
    return util_hasProperty(f, 'row') || util_hasProperty(f, 'column');
}
function isFacetFieldDef(channelDef) {
    return util_hasProperty(channelDef, 'header');
}
function isFacetSpec(spec) {
    return util_hasProperty(spec, 'facet');
}
//# sourceMappingURL=facet.js.map
;// ../../node_modules/vega-lite/build/src/channeldef.js

















function isConditionalParameter(c) {
    return util_hasProperty(c, 'param');
}
function isRepeatRef(field) {
    return !vega_util_module_isString(field) && util_hasProperty(field, 'repeat');
}
function toFieldDefBase(fieldDef) {
    const { field, timeUnit, bin, aggregate } = fieldDef;
    return {
        ...(timeUnit ? { timeUnit } : {}),
        ...(bin ? { bin } : {}),
        ...(aggregate ? { aggregate } : {}),
        field
    };
}
function isSortableFieldDef(fieldDef) {
    return util_hasProperty(fieldDef, 'sort');
}
function getBandPosition({ fieldDef, fieldDef2, markDef: mark, config }) {
    if (isFieldOrDatumDef(fieldDef) && fieldDef.bandPosition !== undefined) {
        return fieldDef.bandPosition;
    }
    if (isFieldDef(fieldDef)) {
        const { timeUnit, bin } = fieldDef;
        if (timeUnit && !fieldDef2) {
            return getMarkConfig('timeUnitBandPosition', mark, config);
        }
        else if (isBinning(bin)) {
            return 0.5;
        }
    }
    return undefined;
}
function getBandSize({ channel, fieldDef, fieldDef2, markDef: mark, config, scaleType, useVlSizeChannel }) {
    const sizeChannel = getSizeChannel(channel);
    const size = getMarkPropOrConfig(useVlSizeChannel ? 'size' : sizeChannel, mark, config, {
        vgChannel: sizeChannel
    });
    if (size !== undefined) {
        return size;
    }
    if (isFieldDef(fieldDef)) {
        const { timeUnit, bin } = fieldDef;
        if (timeUnit && !fieldDef2) {
            return { band: getMarkConfig('timeUnitBandSize', mark, config) };
        }
        else if (isBinning(bin) && !hasDiscreteDomain(scaleType)) {
            return { band: 1 };
        }
    }
    if (isRectBasedMark(mark.type)) {
        if (scaleType) {
            if (hasDiscreteDomain(scaleType)) {
                return config[mark.type]?.discreteBandSize || { band: 1 };
            }
            else {
                return config[mark.type]?.continuousBandSize;
            }
        }
        return config[mark.type]?.discreteBandSize;
    }
    return undefined;
}
function hasBandEnd(fieldDef, fieldDef2, markDef, config) {
    if (isBinning(fieldDef.bin) || (fieldDef.timeUnit && isTypedFieldDef(fieldDef) && fieldDef.type === 'temporal')) {
        // Need to check bandPosition because non-rect marks (e.g., point) with timeUnit
        // doesn't have to use bandEnd if there is no bandPosition.
        return getBandPosition({ fieldDef, fieldDef2, markDef, config }) !== undefined;
    }
    return false;
}
function isOrderOnlyDef(orderDef) {
    return util_hasProperty(orderDef, 'sort') && !util_hasProperty(orderDef, 'field');
}
function isConditionalDef(channelDef) {
    return util_hasProperty(channelDef, 'condition');
}
/**
 * Return if a channelDef is a ConditionalValueDef with ConditionFieldDef
 */
function hasConditionalFieldDef(channelDef) {
    const condition = channelDef?.['condition'];
    return !!condition && !vega_util_module_isArray(condition) && isFieldDef(condition);
}
function hasConditionalFieldOrDatumDef(channelDef) {
    const condition = channelDef?.['condition'];
    return !!condition && !vega_util_module_isArray(condition) && isFieldOrDatumDef(condition);
}
function hasConditionalValueDef(channelDef) {
    const condition = channelDef?.['condition'];
    return !!condition && (vega_util_module_isArray(condition) || isValueDef(condition));
}
function isFieldDef(channelDef) {
    return util_hasProperty(channelDef, 'field') || channelDef?.aggregate === 'count';
}
function channelDefType(channelDef) {
    return channelDef?.['type'];
}
function isDatumDef(channelDef) {
    return util_hasProperty(channelDef, 'datum');
}
function isContinuousFieldOrDatumDef(cd) {
    // TODO: make datum support DateTime object
    return (isTypedFieldDef(cd) && !channeldef_isDiscrete(cd)) || isNumericDataDef(cd);
}
function isUnbinnedQuantitativeFieldOrDatumDef(cd) {
    // TODO: make datum support DateTime object
    return (isTypedFieldDef(cd) && cd.type === 'quantitative' && !cd.bin) || isNumericDataDef(cd);
}
function isNumericDataDef(cd) {
    return isDatumDef(cd) && vega_util_module_isNumber(cd.datum);
}
function isFieldOrDatumDef(channelDef) {
    return isFieldDef(channelDef) || isDatumDef(channelDef);
}
function isTypedFieldDef(channelDef) {
    return (channelDef &&
        (util_hasProperty(channelDef, 'field') || channelDef['aggregate'] === 'count') &&
        util_hasProperty(channelDef, 'type'));
}
function isValueDef(channelDef) {
    return util_hasProperty(channelDef, 'value');
}
function isScaleFieldDef(channelDef) {
    return util_hasProperty(channelDef, 'scale') || util_hasProperty(channelDef, 'sort');
}
function isPositionFieldOrDatumDef(channelDef) {
    return util_hasProperty(channelDef, 'axis') || util_hasProperty(channelDef, 'stack') || util_hasProperty(channelDef, 'impute');
}
function isMarkPropFieldOrDatumDef(channelDef) {
    return util_hasProperty(channelDef, 'legend');
}
function isStringFieldOrDatumDef(channelDef) {
    return util_hasProperty(channelDef, 'format') || util_hasProperty(channelDef, 'formatType');
}
function toStringFieldDef(fieldDef) {
    // omit properties that don't exist in string field defs
    return omit(fieldDef, ['legend', 'axis', 'header', 'scale']);
}
function isOpFieldDef(fieldDef) {
    return util_hasProperty(fieldDef, 'op');
}
/**
 * Get a Vega field reference from a Vega-Lite field def.
 */
function vgField(fieldDef, opt = {}) {
    let field = fieldDef.field;
    const prefix = opt.prefix;
    let suffix = opt.suffix;
    let argAccessor = ''; // for accessing argmin/argmax field at the end without getting escaped
    if (isCount(fieldDef)) {
        field = internalField('count');
    }
    else {
        let fn;
        if (!opt.nofn) {
            if (isOpFieldDef(fieldDef)) {
                fn = fieldDef.op;
            }
            else {
                const { bin, aggregate, timeUnit } = fieldDef;
                if (isBinning(bin)) {
                    fn = binToString(bin);
                    suffix = (opt.binSuffix ?? '') + (opt.suffix ?? '');
                }
                else if (aggregate) {
                    if (isArgmaxDef(aggregate)) {
                        argAccessor = `["${field}"]`;
                        field = `argmax_${aggregate.argmax}`;
                    }
                    else if (isArgminDef(aggregate)) {
                        argAccessor = `["${field}"]`;
                        field = `argmin_${aggregate.argmin}`;
                    }
                    else {
                        fn = String(aggregate);
                    }
                }
                else if (timeUnit && !isBinnedTimeUnit(timeUnit)) {
                    fn = timeUnitToString(timeUnit);
                    suffix = ((!['range', 'mid'].includes(opt.binSuffix) && opt.binSuffix) || '') + (opt.suffix ?? '');
                }
            }
        }
        if (fn) {
            field = field ? `${fn}_${field}` : fn;
        }
    }
    if (suffix) {
        field = `${field}_${suffix}`;
    }
    if (prefix) {
        field = `${prefix}_${field}`;
    }
    if (opt.forAs) {
        return removePathFromField(field);
    }
    else if (opt.expr) {
        // Expression to access flattened field. No need to escape dots.
        return flatAccessWithDatum(field, opt.expr) + argAccessor;
    }
    else {
        // We flattened all fields so paths should have become dot.
        return replacePathInField(field) + argAccessor;
    }
}
function channeldef_isDiscrete(def) {
    switch (def.type) {
        case 'nominal':
        case 'ordinal':
        case 'geojson':
            return true;
        case 'quantitative':
            return isFieldDef(def) && !!def.bin;
        case 'temporal':
            return false;
    }
    throw new Error(invalidFieldType(def.type));
}
function channeldef_isDiscretizing(def) {
    return isScaleFieldDef(def) && isContinuousToDiscrete(def.scale?.type);
}
function isCount(fieldDef) {
    return fieldDef.aggregate === 'count';
}
function verbalTitleFormatter(fieldDef, config) {
    const { field, bin, timeUnit, aggregate } = fieldDef;
    if (aggregate === 'count') {
        return config.countTitle;
    }
    else if (isBinning(bin)) {
        return `${field} (binned)`;
    }
    else if (timeUnit && !isBinnedTimeUnit(timeUnit)) {
        const unit = normalizeTimeUnit(timeUnit)?.unit;
        if (unit) {
            return `${field} (${getTimeUnitParts(unit).join('-')})`;
        }
    }
    else if (aggregate) {
        if (isArgmaxDef(aggregate)) {
            return `${field} for max ${aggregate.argmax}`;
        }
        else if (isArgminDef(aggregate)) {
            return `${field} for min ${aggregate.argmin}`;
        }
        else {
            return `${titleCase(aggregate)} of ${field}`;
        }
    }
    return field;
}
function functionalTitleFormatter(fieldDef) {
    const { aggregate, bin, timeUnit, field } = fieldDef;
    if (isArgmaxDef(aggregate)) {
        return `${field} for argmax(${aggregate.argmax})`;
    }
    else if (isArgminDef(aggregate)) {
        return `${field} for argmin(${aggregate.argmin})`;
    }
    const timeUnitParams = timeUnit && !isBinnedTimeUnit(timeUnit) ? normalizeTimeUnit(timeUnit) : undefined;
    const fn = aggregate || timeUnitParams?.unit || (timeUnitParams?.maxbins && 'timeunit') || (isBinning(bin) && 'bin');
    return fn ? `${fn.toUpperCase()}(${field})` : field;
}
const defaultTitleFormatter = (fieldDef, config) => {
    switch (config.fieldTitle) {
        case 'plain':
            return fieldDef.field;
        case 'functional':
            return functionalTitleFormatter(fieldDef);
        default:
            return verbalTitleFormatter(fieldDef, config);
    }
};
let titleFormatter = defaultTitleFormatter;
function setTitleFormatter(formatter) {
    titleFormatter = formatter;
}
function resetTitleFormatter() {
    setTitleFormatter(defaultTitleFormatter);
}
function channeldef_title(fieldOrDatumDef, config, { allowDisabling, includeDefault = true }) {
    const guideTitle = getGuide(fieldOrDatumDef)?.title;
    if (!isFieldDef(fieldOrDatumDef)) {
        return guideTitle ?? fieldOrDatumDef.title;
    }
    const fieldDef = fieldOrDatumDef;
    const def = includeDefault ? defaultTitle(fieldDef, config) : undefined;
    if (allowDisabling) {
        return getFirstDefined(guideTitle, fieldDef.title, def);
    }
    else {
        return guideTitle ?? fieldDef.title ?? def;
    }
}
function getGuide(fieldDef) {
    if (isPositionFieldOrDatumDef(fieldDef) && fieldDef.axis) {
        return fieldDef.axis;
    }
    else if (isMarkPropFieldOrDatumDef(fieldDef) && fieldDef.legend) {
        return fieldDef.legend;
    }
    else if (isFacetFieldDef(fieldDef) && fieldDef.header) {
        return fieldDef.header;
    }
    return undefined;
}
function defaultTitle(fieldDef, config) {
    return titleFormatter(fieldDef, config);
}
function getFormatMixins(fieldDef) {
    if (isStringFieldOrDatumDef(fieldDef)) {
        const { format, formatType } = fieldDef;
        return { format, formatType };
    }
    else {
        const guide = getGuide(fieldDef) ?? {};
        const { format, formatType } = guide;
        return { format, formatType };
    }
}
function defaultType(fieldDef, channel) {
    switch (channel) {
        case 'latitude':
        case 'longitude':
            return 'quantitative';
        case 'row':
        case 'column':
        case 'facet':
        case 'shape':
        case 'strokeDash':
            return 'nominal';
        case 'order':
            return 'ordinal';
    }
    if (isSortableFieldDef(fieldDef) && vega_util_module_isArray(fieldDef.sort)) {
        return 'ordinal';
    }
    const { aggregate, bin, timeUnit } = fieldDef;
    if (timeUnit) {
        return 'temporal';
    }
    if (bin || (aggregate && !isArgmaxDef(aggregate) && !isArgminDef(aggregate))) {
        return 'quantitative';
    }
    if (isScaleFieldDef(fieldDef) && fieldDef.scale?.type) {
        switch (SCALE_CATEGORY_INDEX[fieldDef.scale.type]) {
            case 'numeric':
            case 'discretizing':
                return 'quantitative';
            case 'time':
                return 'temporal';
        }
    }
    return 'nominal';
}
/**
 * Returns the fieldDef -- either from the outer channelDef or from the condition of channelDef.
 * @param channelDef
 */
function getFieldDef(channelDef) {
    if (isFieldDef(channelDef)) {
        return channelDef;
    }
    else if (hasConditionalFieldDef(channelDef)) {
        return channelDef.condition;
    }
    return undefined;
}
function getFieldOrDatumDef(channelDef) {
    if (isFieldOrDatumDef(channelDef)) {
        return channelDef;
    }
    else if (hasConditionalFieldOrDatumDef(channelDef)) {
        return channelDef.condition;
    }
    return undefined;
}
/**
 * Convert type to full, lowercase type, or augment the fieldDef with a default type if missing.
 */
function initChannelDef(channelDef, channel, config, opt = {}) {
    if (vega_util_module_isString(channelDef) || vega_util_module_isNumber(channelDef) || isBoolean(channelDef)) {
        const primitiveType = vega_util_module_isString(channelDef) ? 'string' : vega_util_module_isNumber(channelDef) ? 'number' : 'boolean';
        log_warn(primitiveChannelDef(channel, primitiveType, channelDef));
        return { value: channelDef };
    }
    // If a fieldDef contains a field, we need type.
    if (isFieldOrDatumDef(channelDef)) {
        return initFieldOrDatumDef(channelDef, channel, config, opt);
    }
    else if (hasConditionalFieldOrDatumDef(channelDef)) {
        return {
            ...channelDef,
            // Need to cast as normalizeFieldDef normally return FieldDef, but here we know that it is definitely Condition<FieldDef>
            condition: initFieldOrDatumDef(channelDef.condition, channel, config, opt)
        };
    }
    return channelDef;
}
function initFieldOrDatumDef(fd, channel, config, opt) {
    if (isStringFieldOrDatumDef(fd)) {
        const { format, formatType, ...rest } = fd;
        if (isCustomFormatType(formatType) && !config.customFormatTypes) {
            log_warn(customFormatTypeNotAllowed(channel));
            return initFieldOrDatumDef(rest, channel, config, opt);
        }
    }
    else {
        const guideType = isPositionFieldOrDatumDef(fd)
            ? 'axis'
            : isMarkPropFieldOrDatumDef(fd)
                ? 'legend'
                : isFacetFieldDef(fd)
                    ? 'header'
                    : null;
        if (guideType && fd[guideType]) {
            const { format, formatType, ...newGuide } = fd[guideType];
            if (isCustomFormatType(formatType) && !config.customFormatTypes) {
                log_warn(customFormatTypeNotAllowed(channel));
                return initFieldOrDatumDef({ ...fd, [guideType]: newGuide }, channel, config, opt);
            }
        }
    }
    if (isFieldDef(fd)) {
        return initFieldDef(fd, channel, opt);
    }
    return initDatumDef(fd);
}
function initDatumDef(datumDef) {
    let type = datumDef['type'];
    if (type) {
        return datumDef;
    }
    const { datum } = datumDef;
    type = vega_util_module_isNumber(datum) ? 'quantitative' : vega_util_module_isString(datum) ? 'nominal' : isDateTime(datum) ? 'temporal' : undefined;
    return { ...datumDef, type };
}
function initFieldDef(fd, channel, { compositeMark = false } = {}) {
    const { aggregate, timeUnit, bin, field } = fd;
    const fieldDef = { ...fd };
    // Drop invalid aggregate
    if (!compositeMark && aggregate && !isAggregateOp(aggregate) && !isArgmaxDef(aggregate) && !isArgminDef(aggregate)) {
        log_warn(invalidAggregate(aggregate));
        delete fieldDef.aggregate;
    }
    // Normalize Time Unit
    if (timeUnit) {
        fieldDef.timeUnit = normalizeTimeUnit(timeUnit);
    }
    if (field) {
        fieldDef.field = `${field}`;
    }
    // Normalize bin
    if (isBinning(bin)) {
        fieldDef.bin = normalizeBin(bin, channel);
    }
    if (isBinned(bin) && !isXorY(channel)) {
        log_warn(channelShouldNotBeUsedForBinned(channel));
    }
    // Normalize Type
    if (isTypedFieldDef(fieldDef)) {
        const { type } = fieldDef;
        const fullType = getFullName(type);
        if (type !== fullType) {
            // convert short type to full type
            fieldDef.type = fullType;
        }
        if (type !== 'quantitative') {
            if (isCountingAggregateOp(aggregate)) {
                log_warn(invalidFieldTypeForCountAggregate(type, aggregate));
                fieldDef.type = 'quantitative';
            }
        }
    }
    else if (!isSecondaryRangeChannel(channel)) {
        // If type is empty / invalid, then augment with default type
        const newType = defaultType(fieldDef, channel);
        fieldDef['type'] = newType;
    }
    if (isTypedFieldDef(fieldDef)) {
        const { compatible, warning } = channelCompatibility(fieldDef, channel) || {};
        if (compatible === false) {
            log_warn(warning);
        }
    }
    if (isSortableFieldDef(fieldDef) && vega_util_module_isString(fieldDef.sort)) {
        const { sort } = fieldDef;
        if (isSortByChannel(sort)) {
            return {
                ...fieldDef,
                sort: { encoding: sort }
            };
        }
        const sub = sort.substring(1);
        if (sort.charAt(0) === '-' && isSortByChannel(sub)) {
            return {
                ...fieldDef,
                sort: { encoding: sub, order: 'descending' }
            };
        }
    }
    if (isFacetFieldDef(fieldDef)) {
        const { header } = fieldDef;
        if (header) {
            const { orient, ...rest } = header;
            if (orient) {
                return {
                    ...fieldDef,
                    header: {
                        ...rest,
                        labelOrient: header.labelOrient || orient,
                        titleOrient: header.titleOrient || orient
                    }
                };
            }
        }
    }
    return fieldDef;
}
function normalizeBin(bin, channel) {
    if (isBoolean(bin)) {
        return { maxbins: autoMaxBins(channel) };
    }
    else if (bin === 'binned') {
        return {
            binned: true
        };
    }
    else if (!bin.maxbins && !bin.step) {
        return { ...bin, maxbins: autoMaxBins(channel) };
    }
    else {
        return bin;
    }
}
const COMPATIBLE = { compatible: true };
function channelCompatibility(fieldDef, channel) {
    const type = fieldDef.type;
    if (type === 'geojson' && channel !== 'shape') {
        return {
            compatible: false,
            warning: `Channel ${channel} should not be used with a geojson data.`
        };
    }
    switch (channel) {
        case ROW:
        case COLUMN:
        case FACET:
            if (!channeldef_isDiscrete(fieldDef)) {
                return {
                    compatible: false,
                    warning: channelShouldBeDiscrete(channel)
                };
            }
            return COMPATIBLE;
        case channel_X:
        case channel_Y:
        case XOFFSET:
        case YOFFSET:
        case COLOR:
        case FILL:
        case STROKE:
        case TEXT:
        case DETAIL:
        case KEY:
        case TOOLTIP:
        case HREF:
        case channel_URL:
        case ANGLE:
        case THETA:
        case RADIUS:
        case DESCRIPTION:
            return COMPATIBLE;
        case LONGITUDE:
        case LONGITUDE2:
        case LATITUDE:
        case LATITUDE2:
            if (type !== QUANTITATIVE) {
                return {
                    compatible: false,
                    warning: `Channel ${channel} should be used with a quantitative field only, not ${fieldDef.type} field.`
                };
            }
            return COMPATIBLE;
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
        case STROKEWIDTH:
        case channel_SIZE:
        case THETA2:
        case RADIUS2:
        case channel_X2:
        case channel_Y2:
        case TIME:
            if (type === 'nominal' && !fieldDef['sort']) {
                return {
                    compatible: false,
                    warning: `Channel ${channel} should not be used with an unsorted discrete field.`
                };
            }
            return COMPATIBLE;
        case SHAPE:
        case STROKEDASH:
            if (!channeldef_isDiscrete(fieldDef) && !channeldef_isDiscretizing(fieldDef)) {
                return {
                    compatible: false,
                    warning: channelShouldBeDiscreteOrDiscretizing(channel)
                };
            }
            return COMPATIBLE;
        case ORDER:
            if (fieldDef.type === 'nominal' && !('sort' in fieldDef)) {
                return {
                    compatible: false,
                    warning: `Channel order is inappropriate for nominal field, which has no inherent order.`
                };
            }
            return COMPATIBLE;
    }
}
/**
 * Check if the field def uses a time format or does not use any format but is temporal
 * (this does not cover field defs that are temporal but use a number format).
 */
function isFieldOrDatumDefForTimeFormat(fieldOrDatumDef) {
    const { formatType } = getFormatMixins(fieldOrDatumDef);
    return formatType === 'time' || (!formatType && isTemporalFieldDef(fieldOrDatumDef));
}
/**
 * Check if field def has type `temporal`. If you want to also cover field defs that use a time format, use `isFieldOrDatumDefForTimeFormat`.
 */
function isTemporalFieldDef(def) {
    return def && (def['type'] === 'temporal' || (isFieldDef(def) && !!def.timeUnit));
}
/**
 * Getting a value associated with a fielddef.
 * Convert the value to Vega expression if applicable (for datetime object, or string if the field def is temporal or has timeUnit)
 */
function valueExpr(v, { timeUnit, type, wrapTime, undefinedIfExprNotRequired }) {
    const unit = timeUnit && normalizeTimeUnit(timeUnit)?.unit;
    let isTime = unit || type === 'temporal';
    let expr;
    if (isExprRef(v)) {
        expr = v.expr;
    }
    else if (isSignalRef(v)) {
        expr = v.signal;
    }
    else if (isDateTime(v)) {
        isTime = true;
        expr = dateTimeToExpr(v);
    }
    else if (vega_util_module_isString(v) || vega_util_module_isNumber(v)) {
        if (isTime) {
            expr = `datetime(${util_stringify(v)})`;
            if (isLocalSingleTimeUnit(unit)) {
                // for single timeUnit, we will use dateTimeToExpr to convert number/string to match the timeUnit
                if ((vega_util_module_isNumber(v) && v < 10000) || (vega_util_module_isString(v) && isNaN(Date.parse(v)))) {
                    expr = dateTimeToExpr({ [unit]: v });
                }
            }
        }
    }
    if (expr) {
        return wrapTime && isTime ? `time(${expr})` : expr;
    }
    // number or boolean or normal string
    return undefinedIfExprNotRequired ? undefined : util_stringify(v);
}
/**
 * Standardize value array -- convert each value to Vega expression if applicable
 */
function valueArray(fieldOrDatumDef, values) {
    const { type } = fieldOrDatumDef;
    return values.map(v => {
        const timeUnit = isFieldDef(fieldOrDatumDef) && !isBinnedTimeUnit(fieldOrDatumDef.timeUnit) ? fieldOrDatumDef.timeUnit : undefined;
        const expr = valueExpr(v, {
            timeUnit,
            type,
            undefinedIfExprNotRequired: true
        });
        // return signal for the expression if we need an expression
        if (expr !== undefined) {
            return { signal: expr };
        }
        // otherwise just return the original value
        return v;
    });
}
/**
 * Checks whether a fieldDef for a particular channel requires a computed bin range.
 */
function binRequiresRange(fieldDef, channel) {
    if (!isBinning(fieldDef.bin)) {
        console.warn('Only call this method for binned field defs.');
        return false;
    }
    // We need the range only when the user explicitly forces a binned field to be use discrete scale. In this case, bin range is used in axis and legend labels.
    // We could check whether the axis or legend exists (not disabled) but that seems overkill.
    return isScaleChannel(channel) && ['ordinal', 'nominal'].includes(fieldDef.type);
}
//# sourceMappingURL=channeldef.js.map
;// ../../node_modules/vega-lite/build/src/axis.js


const CONDITIONAL_AXIS_PROP_INDEX = {
    labelAlign: {
        part: 'labels',
        vgProp: 'align'
    },
    labelBaseline: {
        part: 'labels',
        vgProp: 'baseline'
    },
    labelColor: {
        part: 'labels',
        vgProp: 'fill'
    },
    labelFont: {
        part: 'labels',
        vgProp: 'font'
    },
    labelFontSize: {
        part: 'labels',
        vgProp: 'fontSize'
    },
    labelFontStyle: {
        part: 'labels',
        vgProp: 'fontStyle'
    },
    labelFontWeight: {
        part: 'labels',
        vgProp: 'fontWeight'
    },
    labelOpacity: {
        part: 'labels',
        vgProp: 'opacity'
    },
    labelOffset: null,
    labelPadding: null, // There is no fixed vgProp for tickSize, need to use signal.
    gridColor: {
        part: 'grid',
        vgProp: 'stroke'
    },
    gridDash: {
        part: 'grid',
        vgProp: 'strokeDash'
    },
    gridDashOffset: {
        part: 'grid',
        vgProp: 'strokeDashOffset'
    },
    gridOpacity: {
        part: 'grid',
        vgProp: 'opacity'
    },
    gridWidth: {
        part: 'grid',
        vgProp: 'strokeWidth'
    },
    tickColor: {
        part: 'ticks',
        vgProp: 'stroke'
    },
    tickDash: {
        part: 'ticks',
        vgProp: 'strokeDash'
    },
    tickDashOffset: {
        part: 'ticks',
        vgProp: 'strokeDashOffset'
    },
    tickOpacity: {
        part: 'ticks',
        vgProp: 'opacity'
    },
    tickSize: null, // There is no fixed vgProp for tickSize, need to use signal.
    tickWidth: {
        part: 'ticks',
        vgProp: 'strokeWidth'
    }
};
function isConditionalAxisValue(v) {
    return v?.condition;
}
const AXIS_PARTS = ['domain', 'grid', 'labels', 'ticks', 'title'];
/**
 * A dictionary listing whether a certain axis property is applicable for only main axes or only grid axes.
 */
const AXIS_PROPERTY_TYPE = {
    grid: 'grid',
    gridCap: 'grid',
    gridColor: 'grid',
    gridDash: 'grid',
    gridDashOffset: 'grid',
    gridOpacity: 'grid',
    gridScale: 'grid',
    gridWidth: 'grid',
    orient: 'main',
    bandPosition: 'both', // Need to be applied to grid axis too, so the grid will align with ticks.
    aria: 'main',
    description: 'main',
    domain: 'main',
    domainCap: 'main',
    domainColor: 'main',
    domainDash: 'main',
    domainDashOffset: 'main',
    domainOpacity: 'main',
    domainWidth: 'main',
    format: 'main',
    formatType: 'main',
    labelAlign: 'main',
    labelAngle: 'main',
    labelBaseline: 'main',
    labelBound: 'main',
    labelColor: 'main',
    labelFlush: 'main',
    labelFlushOffset: 'main',
    labelFont: 'main',
    labelFontSize: 'main',
    labelFontStyle: 'main',
    labelFontWeight: 'main',
    labelLimit: 'main',
    labelLineHeight: 'main',
    labelOffset: 'main',
    labelOpacity: 'main',
    labelOverlap: 'main',
    labelPadding: 'main',
    labels: 'main',
    labelSeparation: 'main',
    maxExtent: 'main',
    minExtent: 'main',
    offset: 'both',
    position: 'main',
    tickCap: 'main',
    tickColor: 'main',
    tickDash: 'main',
    tickDashOffset: 'main',
    tickMinStep: 'both',
    tickOffset: 'both', // Need to be applied to grid axis too, so the grid will align with ticks.
    tickOpacity: 'main',
    tickRound: 'both', // Apply rounding to grid and ticks so they are aligned.
    ticks: 'main',
    tickSize: 'main',
    tickWidth: 'both',
    title: 'main',
    titleAlign: 'main',
    titleAnchor: 'main',
    titleAngle: 'main',
    titleBaseline: 'main',
    titleColor: 'main',
    titleFont: 'main',
    titleFontSize: 'main',
    titleFontStyle: 'main',
    titleFontWeight: 'main',
    titleLimit: 'main',
    titleLineHeight: 'main',
    titleOpacity: 'main',
    titlePadding: 'main',
    titleX: 'main',
    titleY: 'main',
    encode: 'both', // we hide this in Vega-Lite
    scale: 'both',
    tickBand: 'both',
    tickCount: 'both',
    tickExtra: 'both',
    translate: 'both',
    values: 'both',
    zindex: 'both' // this is actually set afterward, so it doesn't matter
};
const COMMON_AXIS_PROPERTIES_INDEX = {
    orient: 1, // other things can depend on orient
    aria: 1,
    bandPosition: 1,
    description: 1,
    domain: 1,
    domainCap: 1,
    domainColor: 1,
    domainDash: 1,
    domainDashOffset: 1,
    domainOpacity: 1,
    domainWidth: 1,
    format: 1,
    formatType: 1,
    grid: 1,
    gridCap: 1,
    gridColor: 1,
    gridDash: 1,
    gridDashOffset: 1,
    gridOpacity: 1,
    gridWidth: 1,
    labelAlign: 1,
    labelAngle: 1,
    labelBaseline: 1,
    labelBound: 1,
    labelColor: 1,
    labelFlush: 1,
    labelFlushOffset: 1,
    labelFont: 1,
    labelFontSize: 1,
    labelFontStyle: 1,
    labelFontWeight: 1,
    labelLimit: 1,
    labelLineHeight: 1,
    labelOffset: 1,
    labelOpacity: 1,
    labelOverlap: 1,
    labelPadding: 1,
    labels: 1,
    labelSeparation: 1,
    maxExtent: 1,
    minExtent: 1,
    offset: 1,
    position: 1,
    tickBand: 1,
    tickCap: 1,
    tickColor: 1,
    tickCount: 1,
    tickDash: 1,
    tickDashOffset: 1,
    tickExtra: 1,
    tickMinStep: 1,
    tickOffset: 1,
    tickOpacity: 1,
    tickRound: 1,
    ticks: 1,
    tickSize: 1,
    tickWidth: 1,
    title: 1,
    titleAlign: 1,
    titleAnchor: 1,
    titleAngle: 1,
    titleBaseline: 1,
    titleColor: 1,
    titleFont: 1,
    titleFontSize: 1,
    titleFontStyle: 1,
    titleFontWeight: 1,
    titleLimit: 1,
    titleLineHeight: 1,
    titleOpacity: 1,
    titlePadding: 1,
    titleX: 1,
    titleY: 1,
    translate: 1,
    values: 1,
    zindex: 1
};
const AXIS_PROPERTIES_INDEX = {
    ...COMMON_AXIS_PROPERTIES_INDEX,
    style: 1,
    labelExpr: 1,
    encoding: 1
};
function isAxisProperty(prop) {
    return vega_util_module_has(AXIS_PROPERTIES_INDEX, prop);
}
// Export for dependent projects
const AXIS_PROPERTIES = util_keys(AXIS_PROPERTIES_INDEX);
const AXIS_CONFIGS_INDEX = {
    axis: 1,
    axisBand: 1,
    axisBottom: 1,
    axisDiscrete: 1,
    axisLeft: 1,
    axisPoint: 1,
    axisQuantitative: 1,
    axisRight: 1,
    axisTemporal: 1,
    axisTop: 1,
    axisX: 1,
    axisXBand: 1,
    axisXDiscrete: 1,
    axisXPoint: 1,
    axisXQuantitative: 1,
    axisXTemporal: 1,
    axisY: 1,
    axisYBand: 1,
    axisYDiscrete: 1,
    axisYPoint: 1,
    axisYQuantitative: 1,
    axisYTemporal: 1
};
const AXIS_CONFIGS = util_keys(AXIS_CONFIGS_INDEX);
//# sourceMappingURL=axis.js.map
;// ../../node_modules/vega-lite/build/src/spec/unit.js

function isUnitSpec(spec) {
    return util_hasProperty(spec, 'mark');
}
//# sourceMappingURL=unit.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/base.js


class CompositeMarkNormalizer {
    constructor(name, run) {
        this.name = name;
        this.run = run;
    }
    hasMatchingType(spec) {
        if (isUnitSpec(spec)) {
            return getMarkType(spec.mark) === this.name;
        }
        return false;
    }
}
//# sourceMappingURL=base.js.map
;// ../../node_modules/vega-lite/build/src/encoding.js










function channelHasField(encoding, channel) {
    const channelDef = encoding && encoding[channel];
    if (channelDef) {
        if (vega_util_module_isArray(channelDef)) {
            return some(channelDef, fieldDef => !!fieldDef.field);
        }
        else {
            return isFieldDef(channelDef) || hasConditionalFieldDef(channelDef);
        }
    }
    return false;
}
function channelHasFieldOrDatum(encoding, channel) {
    const channelDef = encoding && encoding[channel];
    if (channelDef) {
        if (vega_util_module_isArray(channelDef)) {
            return some(channelDef, fieldDef => !!fieldDef.field);
        }
        else {
            return isFieldDef(channelDef) || isDatumDef(channelDef) || hasConditionalFieldOrDatumDef(channelDef);
        }
    }
    return false;
}
function channelHasNestedOffsetScale(encoding, channel) {
    if (isXorY(channel)) {
        const fieldDef = encoding[channel];
        if ((isFieldDef(fieldDef) || isDatumDef(fieldDef)) &&
            (type_isDiscrete(fieldDef.type) || (isFieldDef(fieldDef) && fieldDef.timeUnit))) {
            const offsetChannel = getOffsetScaleChannel(channel);
            return channelHasFieldOrDatum(encoding, offsetChannel);
        }
    }
    return false;
}
function isAggregate(encoding) {
    return some(CHANNELS, channel => {
        if (channelHasField(encoding, channel)) {
            const channelDef = encoding[channel];
            if (vega_util_module_isArray(channelDef)) {
                return some(channelDef, fieldDef => !!fieldDef.aggregate);
            }
            else {
                const fieldDef = getFieldDef(channelDef);
                return fieldDef && !!fieldDef.aggregate;
            }
        }
        return false;
    });
}
function extractTransformsFromEncoding(oldEncoding, config) {
    const groupby = [];
    const bins = [];
    const timeUnits = [];
    const aggregate = [];
    const encoding = {};
    forEach(oldEncoding, (channelDef, channel) => {
        // Extract potential embedded transformations along with remaining properties
        if (isFieldDef(channelDef)) {
            const { field, aggregate: aggOp, bin, timeUnit, ...remaining } = channelDef;
            if (aggOp || timeUnit || bin) {
                const guide = getGuide(channelDef);
                const isTitleDefined = guide?.title;
                let newField = vgField(channelDef, { forAs: true });
                const newFieldDef = {
                    // Only add title if it doesn't exist
                    ...(isTitleDefined ? [] : { title: channeldef_title(channelDef, config, { allowDisabling: true }) }),
                    ...remaining,
                    // Always overwrite field
                    field: newField
                };
                if (aggOp) {
                    let op;
                    if (isArgmaxDef(aggOp)) {
                        op = 'argmax';
                        newField = vgField({ op: 'argmax', field: aggOp.argmax }, { forAs: true });
                        newFieldDef.field = `${newField}.${field}`;
                    }
                    else if (isArgminDef(aggOp)) {
                        op = 'argmin';
                        newField = vgField({ op: 'argmin', field: aggOp.argmin }, { forAs: true });
                        newFieldDef.field = `${newField}.${field}`;
                    }
                    else if (aggOp !== 'boxplot' && aggOp !== 'errorbar' && aggOp !== 'errorband') {
                        op = aggOp;
                    }
                    if (op) {
                        const aggregateEntry = {
                            op,
                            as: newField
                        };
                        if (field) {
                            aggregateEntry.field = field;
                        }
                        aggregate.push(aggregateEntry);
                    }
                }
                else {
                    groupby.push(newField);
                    if (isTypedFieldDef(channelDef) && isBinning(bin)) {
                        bins.push({ bin, field, as: newField });
                        // Add additional groupbys for range and end of bins
                        groupby.push(vgField(channelDef, { binSuffix: 'end' }));
                        if (binRequiresRange(channelDef, channel)) {
                            groupby.push(vgField(channelDef, { binSuffix: 'range' }));
                        }
                        // Create accompanying 'x2' or 'y2' field if channel is 'x' or 'y' respectively
                        if (isXorY(channel)) {
                            const secondaryChannel = {
                                field: `${newField}_end`
                            };
                            encoding[`${channel}2`] = secondaryChannel;
                        }
                        newFieldDef.bin = 'binned';
                        if (!isSecondaryRangeChannel(channel)) {
                            newFieldDef['type'] = QUANTITATIVE;
                        }
                    }
                    else if (timeUnit && !isBinnedTimeUnit(timeUnit)) {
                        timeUnits.push({
                            timeUnit,
                            field,
                            as: newField
                        });
                        // define the format type for later compilation
                        const formatType = isTypedFieldDef(channelDef) && channelDef.type !== TEMPORAL && 'time';
                        if (formatType) {
                            if (channel === TEXT || channel === TOOLTIP) {
                                newFieldDef['formatType'] = formatType;
                            }
                            else if (isNonPositionScaleChannel(channel)) {
                                newFieldDef['legend'] = {
                                    formatType,
                                    ...newFieldDef['legend']
                                };
                            }
                            else if (isXorY(channel)) {
                                newFieldDef['axis'] = {
                                    formatType,
                                    ...newFieldDef['axis']
                                };
                            }
                        }
                    }
                }
                // now the field should refer to post-transformed field instead
                encoding[channel] = newFieldDef;
            }
            else {
                groupby.push(field);
                encoding[channel] = oldEncoding[channel];
            }
        }
        else {
            // For value def / signal ref / datum def, just copy
            encoding[channel] = oldEncoding[channel];
        }
    });
    return {
        bins,
        timeUnits,
        aggregate,
        groupby,
        encoding
    };
}
function markChannelCompatible(encoding, channel, mark) {
    const markSupported = supportMark(channel, mark);
    if (!markSupported) {
        return false;
    }
    else if (markSupported === 'binned') {
        const primaryFieldDef = encoding[channel === channel_X2 ? channel_X : channel_Y];
        // circle, point, square and tick only support x2/y2 when their corresponding x/y fieldDef
        // has "binned" data and thus need x2/y2 to specify the bin-end field.
        if (isFieldDef(primaryFieldDef) && isFieldDef(encoding[channel]) && isBinned(primaryFieldDef.bin)) {
            return true;
        }
        else {
            return false;
        }
    }
    return true;
}
function initEncoding(encoding, mark, filled, config) {
    const normalizedEncoding = {};
    for (const key of util_keys(encoding)) {
        if (!isChannel(key)) {
            // Drop invalid channel
            log_warn(invalidEncodingChannel(key));
        }
    }
    for (let channel of UNIT_CHANNELS) {
        if (!encoding[channel]) {
            continue;
        }
        const channelDef = encoding[channel];
        if (isXorYOffset(channel)) {
            const mainChannel = getMainChannelFromOffsetChannel(channel);
            const positionDef = normalizedEncoding[mainChannel];
            if (isFieldDef(positionDef)) {
                if (type_isContinuous(positionDef.type)) {
                    if (isFieldDef(channelDef) && !positionDef.timeUnit) {
                        // TODO: nesting continuous field instead continuous field should
                        // behave like offsetting the data in data domain
                        log_warn(offsetNestedInsideContinuousPositionScaleDropped(mainChannel));
                        continue;
                    }
                }
            }
        }
        if (channel === 'angle' && mark === 'arc' && !encoding.theta) {
            log_warn(REPLACE_ANGLE_WITH_THETA);
            channel = THETA;
        }
        if (!markChannelCompatible(encoding, channel, mark)) {
            // Drop unsupported channel
            log_warn(incompatibleChannel(channel, mark));
            continue;
        }
        // Drop line's size if the field is aggregated.
        if (channel === channel_SIZE && mark === 'line') {
            const fieldDef = getFieldDef(encoding[channel]);
            if (fieldDef?.aggregate) {
                log_warn(LINE_WITH_VARYING_SIZE);
                continue;
            }
        }
        // Drop color if either fill or stroke is specified
        if (channel === COLOR && (filled ? 'fill' in encoding : 'stroke' in encoding)) {
            log_warn(droppingColor('encoding', { fill: 'fill' in encoding, stroke: 'stroke' in encoding }));
            continue;
        }
        if (channel === DETAIL ||
            (channel === ORDER && !vega_util_module_isArray(channelDef) && !isValueDef(channelDef)) ||
            (channel === TOOLTIP && vega_util_module_isArray(channelDef))) {
            if (channelDef) {
                if (channel === ORDER) {
                    const def = encoding[channel];
                    if (isOrderOnlyDef(def)) {
                        normalizedEncoding[channel] = def;
                        continue;
                    }
                }
                // Array of fieldDefs for detail channel (or production rule)
                normalizedEncoding[channel] = vega_util_module_array(channelDef).reduce((defs, fieldDef) => {
                    if (!isFieldDef(fieldDef)) {
                        log_warn(emptyFieldDef(fieldDef, channel));
                    }
                    else {
                        defs.push(initFieldDef(fieldDef, channel));
                    }
                    return defs;
                }, []);
            }
        }
        else {
            if (channel === TOOLTIP && channelDef === null) {
                // Preserve null so we can use it to disable tooltip
                normalizedEncoding[channel] = null;
            }
            else if (!isFieldDef(channelDef) &&
                !isDatumDef(channelDef) &&
                !isValueDef(channelDef) &&
                !isConditionalDef(channelDef) &&
                !isSignalRef(channelDef)) {
                log_warn(emptyFieldDef(channelDef, channel));
                continue;
            }
            normalizedEncoding[channel] = initChannelDef(channelDef, channel, config);
        }
    }
    return normalizedEncoding;
}
/**
 * For composite marks, we have to call initChannelDef during init so we can infer types earlier.
 */
function normalizeEncoding(encoding, config) {
    const normalizedEncoding = {};
    for (const channel of util_keys(encoding)) {
        const newChannelDef = initChannelDef(encoding[channel], channel, config, { compositeMark: true });
        normalizedEncoding[channel] = newChannelDef;
    }
    return normalizedEncoding;
}
function fieldDefs(encoding) {
    const arr = [];
    for (const channel of util_keys(encoding)) {
        if (channelHasField(encoding, channel)) {
            const channelDef = encoding[channel];
            const channelDefArray = vega_util_module_array(channelDef);
            for (const def of channelDefArray) {
                if (isFieldDef(def)) {
                    arr.push(def);
                }
                else if (hasConditionalFieldDef(def)) {
                    arr.push(def.condition);
                }
            }
        }
    }
    return arr;
}
function forEach(mapping, f, thisArg) {
    if (!mapping) {
        return;
    }
    for (const channel of util_keys(mapping)) {
        const el = mapping[channel];
        if (vega_util_module_isArray(el)) {
            for (const channelDef of el) {
                f.call(thisArg, channelDef, channel);
            }
        }
        else {
            f.call(thisArg, el, channel);
        }
    }
}
function encoding_reduce(mapping, f, init, thisArg) {
    if (!mapping) {
        return init;
    }
    return util_keys(mapping).reduce((r, channel) => {
        const map = mapping[channel];
        if (vega_util_module_isArray(map)) {
            return map.reduce((r1, channelDef) => {
                return f.call(thisArg, r1, channelDef, channel);
            }, r);
        }
        else {
            return f.call(thisArg, r, map, channel);
        }
    }, init);
}
/**
 * Returns list of path grouping fields for the given encoding
 */
function pathGroupingFields(mark, encoding) {
    return util_keys(encoding).reduce((details, channel) => {
        switch (channel) {
            // x, y, x2, y2, lat, long, lat1, long2, order, tooltip, href, aria label, cursor should not cause lines to group
            case channel_X:
            case channel_Y:
            case HREF:
            case DESCRIPTION:
            case channel_URL:
            case channel_X2:
            case channel_Y2:
            case XOFFSET:
            case YOFFSET:
            case THETA:
            case THETA2:
            case RADIUS:
            case RADIUS2:
            case TIME:
            // falls through
            case LATITUDE:
            case LONGITUDE:
            case LATITUDE2:
            case LONGITUDE2:
            // TODO: case 'cursor':
            // text, shape, shouldn't be a part of line/trail/area [falls through]
            case TEXT:
            case SHAPE:
            case ANGLE:
            // falls through
            // tooltip fields should not be added to group by [falls through]
            case TOOLTIP:
                return details;
            case ORDER:
                // order should not group line / trail
                if (mark === 'line' || mark === 'trail') {
                    return details;
                }
            // but order should group area for stacking (falls through)
            case DETAIL:
            case KEY: {
                const channelDef = encoding[channel];
                if (vega_util_module_isArray(channelDef) || isFieldDef(channelDef)) {
                    for (const fieldDef of vega_util_module_array(channelDef)) {
                        if (!fieldDef.aggregate) {
                            details.push(vgField(fieldDef, {}));
                        }
                    }
                }
                return details;
            }
            case channel_SIZE:
                if (mark === 'trail') {
                    // For trail, size should not group trail lines.
                    return details;
                }
            // For line, size should group lines.
            // falls through
            case COLOR:
            case FILL:
            case STROKE:
            case OPACITY:
            case FILLOPACITY:
            case STROKEOPACITY:
            case STROKEDASH:
            case STROKEWIDTH: {
                // TODO strokeDashOffset:
                // falls through
                const fieldDef = getFieldDef(encoding[channel]);
                if (fieldDef && !fieldDef.aggregate) {
                    details.push(vgField(fieldDef, {}));
                }
                return details;
            }
        }
    }, []);
}
//# sourceMappingURL=encoding.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/common.js








function filterTooltipWithAggregatedField(oldEncoding) {
    const { tooltip, ...filteredEncoding } = oldEncoding;
    if (!tooltip) {
        return { filteredEncoding };
    }
    let customTooltipWithAggregatedField;
    let customTooltipWithoutAggregatedField;
    if (vega_util_module_isArray(tooltip)) {
        for (const t of tooltip) {
            if (t.aggregate) {
                if (!customTooltipWithAggregatedField) {
                    customTooltipWithAggregatedField = [];
                }
                customTooltipWithAggregatedField.push(t);
            }
            else {
                if (!customTooltipWithoutAggregatedField) {
                    customTooltipWithoutAggregatedField = [];
                }
                customTooltipWithoutAggregatedField.push(t);
            }
        }
        if (customTooltipWithAggregatedField) {
            filteredEncoding.tooltip = customTooltipWithAggregatedField;
        }
    }
    else {
        if (tooltip.aggregate) {
            filteredEncoding.tooltip = tooltip;
        }
        else {
            customTooltipWithoutAggregatedField = tooltip;
        }
    }
    if (vega_util_module_isArray(customTooltipWithoutAggregatedField) && customTooltipWithoutAggregatedField.length === 1) {
        customTooltipWithoutAggregatedField = customTooltipWithoutAggregatedField[0];
    }
    return { customTooltipWithoutAggregatedField, filteredEncoding };
}
function getCompositeMarkTooltip(tooltipSummary, continuousAxisChannelDef, encodingWithoutContinuousAxis, withFieldName = true) {
    if ('tooltip' in encodingWithoutContinuousAxis) {
        return { tooltip: encodingWithoutContinuousAxis.tooltip };
    }
    const fiveSummaryTooltip = tooltipSummary.map(({ fieldPrefix, titlePrefix }) => {
        const mainTitle = withFieldName ? ` of ${getTitle(continuousAxisChannelDef)}` : '';
        return {
            field: fieldPrefix + continuousAxisChannelDef.field,
            type: continuousAxisChannelDef.type,
            title: isSignalRef(titlePrefix) ? { signal: `${titlePrefix}"${escape(mainTitle)}"` } : titlePrefix + mainTitle
        };
    });
    const tooltipFieldDefs = fieldDefs(encodingWithoutContinuousAxis).map(toStringFieldDef);
    return {
        tooltip: [
            ...fiveSummaryTooltip,
            // need to cast because TextFieldDef supports fewer types of bin
            ...unique(tooltipFieldDefs, util_hash)
        ]
    };
}
function getTitle(continuousAxisChannelDef) {
    const { title, field } = continuousAxisChannelDef;
    return getFirstDefined(title, field);
}
function makeCompositeAggregatePartFactory(compositeMarkDef, continuousAxis, continuousAxisChannelDef, sharedEncoding, compositeMarkConfig) {
    const { scale, axis } = continuousAxisChannelDef;
    return ({ partName, mark, positionPrefix, endPositionPrefix = undefined, extraEncoding = {} }) => {
        const title = getTitle(continuousAxisChannelDef);
        return partLayerMixins(compositeMarkDef, partName, compositeMarkConfig, {
            mark, // TODO better remove this method and just have mark as a parameter of the method
            encoding: {
                [continuousAxis]: {
                    field: `${positionPrefix}_${continuousAxisChannelDef.field}`,
                    type: continuousAxisChannelDef.type,
                    ...(title !== undefined ? { title } : {}),
                    ...(scale !== undefined ? { scale } : {}),
                    ...(axis !== undefined ? { axis } : {})
                },
                ...(vega_util_module_isString(endPositionPrefix)
                    ? {
                        [`${continuousAxis}2`]: {
                            field: `${endPositionPrefix}_${continuousAxisChannelDef.field}`
                        }
                    }
                    : {}),
                ...sharedEncoding,
                ...extraEncoding
            }
        });
    };
}
function partLayerMixins(markDef, part, compositeMarkConfig, partBaseSpec) {
    const { clip, color, opacity } = markDef;
    const mark = markDef.type;
    if (markDef[part] || (markDef[part] === undefined && compositeMarkConfig[part])) {
        return [
            {
                ...partBaseSpec,
                mark: {
                    ...compositeMarkConfig[part],
                    ...(clip ? { clip } : {}),
                    ...(color ? { color } : {}),
                    ...(opacity ? { opacity } : {}),
                    ...(isMarkDef(partBaseSpec.mark) ? partBaseSpec.mark : { type: partBaseSpec.mark }),
                    style: `${mark}-${String(part)}`,
                    ...(isBoolean(markDef[part]) ? {} : markDef[part])
                }
            }
        ];
    }
    return [];
}
function compositeMarkContinuousAxis(spec, orient, compositeMark) {
    const { encoding } = spec;
    const continuousAxis = orient === 'vertical' ? 'y' : 'x';
    const continuousAxisChannelDef = encoding[continuousAxis]; // Safe to cast because if x is not continuous fielddef, the orient would not be horizontal.
    const continuousAxisChannelDef2 = encoding[`${continuousAxis}2`];
    const continuousAxisChannelDefError = encoding[`${continuousAxis}Error`];
    const continuousAxisChannelDefError2 = encoding[`${continuousAxis}Error2`];
    return {
        continuousAxisChannelDef: filterAggregateFromChannelDef(continuousAxisChannelDef, compositeMark),
        continuousAxisChannelDef2: filterAggregateFromChannelDef(continuousAxisChannelDef2, compositeMark),
        continuousAxisChannelDefError: filterAggregateFromChannelDef(continuousAxisChannelDefError, compositeMark),
        continuousAxisChannelDefError2: filterAggregateFromChannelDef(continuousAxisChannelDefError2, compositeMark),
        continuousAxis
    };
}
function filterAggregateFromChannelDef(continuousAxisChannelDef, compositeMark) {
    if (continuousAxisChannelDef?.aggregate) {
        const { aggregate, ...continuousAxisWithoutAggregate } = continuousAxisChannelDef;
        if (aggregate !== compositeMark) {
            log_warn(errorBarContinuousAxisHasCustomizedAggregate(aggregate, compositeMark));
        }
        return continuousAxisWithoutAggregate;
    }
    else {
        return continuousAxisChannelDef;
    }
}
function compositeMarkOrient(spec, compositeMark) {
    const { mark, encoding } = spec;
    const { x, y } = encoding;
    if (isMarkDef(mark) && mark.orient) {
        return mark.orient;
    }
    if (isContinuousFieldOrDatumDef(x)) {
        // x is continuous
        if (isContinuousFieldOrDatumDef(y)) {
            // both x and y are continuous
            const xAggregate = isFieldDef(x) && x.aggregate;
            const yAggregate = isFieldDef(y) && y.aggregate;
            if (!xAggregate && yAggregate === compositeMark) {
                return 'vertical';
            }
            else if (!yAggregate && xAggregate === compositeMark) {
                return 'horizontal';
            }
            else if (xAggregate === compositeMark && yAggregate === compositeMark) {
                throw new Error('Both x and y cannot have aggregate');
            }
            else {
                if (isFieldOrDatumDefForTimeFormat(y) && !isFieldOrDatumDefForTimeFormat(x)) {
                    // y is temporal but x is not
                    return 'horizontal';
                }
                // default orientation for two continuous
                return 'vertical';
            }
        }
        return 'horizontal';
    }
    else if (isContinuousFieldOrDatumDef(y)) {
        // y is continuous but x is not
        return 'vertical';
    }
    else {
        // Neither x nor y is continuous.
        throw new Error(`Need a valid continuous axis for ${compositeMark}s`);
    }
}
//# sourceMappingURL=common.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/boxplot.js








const BOXPLOT = 'boxplot';
const BOXPLOT_PARTS = ['box', 'median', 'outliers', 'rule', 'ticks'];
const boxPlotNormalizer = new CompositeMarkNormalizer(BOXPLOT, normalizeBoxPlot);
function getBoxPlotType(extent) {
    if (vega_util_module_isNumber(extent)) {
        return 'tukey';
    }
    // Ham: If we ever want to, we could add another extent syntax `{kIQR: number}` for the original [Q1-k*IQR, Q3+k*IQR] whisker and call this boxPlotType = `kIQR`. However, I'm not exposing this for now.
    return extent;
}
function normalizeBoxPlot(spec, { config }) {
    // Need to initEncoding first so we can infer type
    spec = {
        ...spec,
        encoding: normalizeEncoding(spec.encoding, config)
    };
    const { mark, encoding: _encoding, params, projection: _p, ...outerSpec } = spec;
    const markDef = isMarkDef(mark) ? mark : { type: mark };
    // TODO(https://github.com/vega/vega-lite/issues/3702): add selection support
    if (params) {
        log_warn(selectionNotSupported('boxplot'));
    }
    const extent = markDef.extent ?? config.boxplot.extent;
    const sizeValue = getMarkPropOrConfig('size', markDef, // TODO: https://github.com/vega/vega-lite/issues/6245
    config);
    const invalid = markDef.invalid;
    const boxPlotType = getBoxPlotType(extent);
    const { bins, timeUnits, transform, continuousAxisChannelDef, continuousAxis, groupby, aggregate, encodingWithoutContinuousAxis, ticksOrient, boxOrient, customTooltipWithoutAggregatedField } = boxParams(spec, extent, config);
    const aliasedFieldName = removePathFromField(continuousAxisChannelDef.field);
    const { color, size, ...encodingWithoutSizeColorAndContinuousAxis } = encodingWithoutContinuousAxis;
    const makeBoxPlotPart = (sharedEncoding) => {
        return makeCompositeAggregatePartFactory(markDef, continuousAxis, continuousAxisChannelDef, sharedEncoding, config.boxplot);
    };
    const makeBoxPlotExtent = makeBoxPlotPart(encodingWithoutSizeColorAndContinuousAxis);
    const makeBoxPlotBox = makeBoxPlotPart(encodingWithoutContinuousAxis);
    const defaultBoxColor = (vega_util_module_isObject(config.boxplot.box) ? config.boxplot.box.color : config.mark.color) || '#4c78a8';
    const makeBoxPlotMidTick = makeBoxPlotPart({
        ...encodingWithoutSizeColorAndContinuousAxis,
        ...(size ? { size } : {}),
        color: {
            condition: {
                test: `${accessWithDatumToUnescapedPath(`lower_box_${continuousAxisChannelDef.field}`)} >= ${accessWithDatumToUnescapedPath(`upper_box_${continuousAxisChannelDef.field}`)}`,
                ...(color || { value: defaultBoxColor })
            }
        }
    });
    const fiveSummaryTooltipEncoding = getCompositeMarkTooltip([
        { fieldPrefix: boxPlotType === 'min-max' ? 'upper_whisker_' : 'max_', titlePrefix: 'Max' },
        { fieldPrefix: 'upper_box_', titlePrefix: 'Q3' },
        { fieldPrefix: 'mid_box_', titlePrefix: 'Median' },
        { fieldPrefix: 'lower_box_', titlePrefix: 'Q1' },
        { fieldPrefix: boxPlotType === 'min-max' ? 'lower_whisker_' : 'min_', titlePrefix: 'Min' }
    ], continuousAxisChannelDef, encodingWithoutContinuousAxis);
    // ## Whisker Layers
    const endTick = { type: 'tick', color: 'black', opacity: 1, orient: ticksOrient, invalid, aria: false };
    const whiskerTooltipEncoding = boxPlotType === 'min-max'
        ? fiveSummaryTooltipEncoding // for min-max, show five-summary tooltip for whisker
        : // for tukey / k-IQR, just show upper/lower-whisker
            getCompositeMarkTooltip([
                { fieldPrefix: 'upper_whisker_', titlePrefix: 'Upper Whisker' },
                { fieldPrefix: 'lower_whisker_', titlePrefix: 'Lower Whisker' }
            ], continuousAxisChannelDef, encodingWithoutContinuousAxis);
    const whiskerLayers = [
        ...makeBoxPlotExtent({
            partName: 'rule',
            mark: { type: 'rule', invalid, aria: false },
            positionPrefix: 'lower_whisker',
            endPositionPrefix: 'lower_box',
            extraEncoding: whiskerTooltipEncoding
        }),
        ...makeBoxPlotExtent({
            partName: 'rule',
            mark: { type: 'rule', invalid, aria: false },
            positionPrefix: 'upper_box',
            endPositionPrefix: 'upper_whisker',
            extraEncoding: whiskerTooltipEncoding
        }),
        ...makeBoxPlotExtent({
            partName: 'ticks',
            mark: endTick,
            positionPrefix: 'lower_whisker',
            extraEncoding: whiskerTooltipEncoding
        }),
        ...makeBoxPlotExtent({
            partName: 'ticks',
            mark: endTick,
            positionPrefix: 'upper_whisker',
            extraEncoding: whiskerTooltipEncoding
        })
    ];
    // ## Box Layers
    // TODO: support hiding certain mark parts
    const boxLayers = [
        ...(boxPlotType !== 'tukey' ? whiskerLayers : []),
        ...makeBoxPlotBox({
            partName: 'box',
            mark: {
                type: 'bar',
                ...(sizeValue ? { size: sizeValue } : {}),
                orient: boxOrient,
                invalid,
                ariaRoleDescription: 'box'
            },
            positionPrefix: 'lower_box',
            endPositionPrefix: 'upper_box',
            extraEncoding: fiveSummaryTooltipEncoding
        }),
        ...makeBoxPlotMidTick({
            partName: 'median',
            mark: {
                type: 'tick',
                invalid,
                ...(vega_util_module_isObject(config.boxplot.median) && config.boxplot.median.color ? { color: config.boxplot.median.color } : {}),
                ...(sizeValue ? { size: sizeValue } : {}),
                orient: ticksOrient,
                aria: false
            },
            positionPrefix: 'mid_box',
            extraEncoding: fiveSummaryTooltipEncoding
        })
    ];
    if (boxPlotType === 'min-max') {
        return {
            ...outerSpec,
            transform: (outerSpec.transform ?? []).concat(transform),
            layer: boxLayers
        };
    }
    // Tukey Box Plot
    const lowerBoxExpr = accessWithDatumToUnescapedPath(`lower_box_${continuousAxisChannelDef.field}`);
    const upperBoxExpr = accessWithDatumToUnescapedPath(`upper_box_${continuousAxisChannelDef.field}`);
    const iqrExpr = `(${upperBoxExpr} - ${lowerBoxExpr})`;
    const lowerWhiskerExpr = `${lowerBoxExpr} - ${extent} * ${iqrExpr}`;
    const upperWhiskerExpr = `${upperBoxExpr} + ${extent} * ${iqrExpr}`;
    const fieldExpr = accessWithDatumToUnescapedPath(continuousAxisChannelDef.field);
    const joinaggregateTransform = {
        joinaggregate: boxParamsQuartiles(continuousAxisChannelDef.field),
        groupby
    };
    const filteredWhiskerSpec = {
        transform: [
            {
                filter: `(${lowerWhiskerExpr} <= ${fieldExpr}) && (${fieldExpr} <= ${upperWhiskerExpr})`
            },
            {
                aggregate: [
                    {
                        op: 'min',
                        field: continuousAxisChannelDef.field,
                        as: `lower_whisker_${aliasedFieldName}`
                    },
                    {
                        op: 'max',
                        field: continuousAxisChannelDef.field,
                        as: `upper_whisker_${aliasedFieldName}`
                    },
                    // preserve lower_box / upper_box
                    {
                        op: 'min',
                        field: `lower_box_${continuousAxisChannelDef.field}`,
                        as: `lower_box_${aliasedFieldName}`
                    },
                    {
                        op: 'max',
                        field: `upper_box_${continuousAxisChannelDef.field}`,
                        as: `upper_box_${aliasedFieldName}`
                    },
                    ...aggregate
                ],
                groupby
            }
        ],
        layer: whiskerLayers
    };
    const { tooltip, ...encodingWithoutSizeColorContinuousAxisAndTooltip } = encodingWithoutSizeColorAndContinuousAxis;
    const { scale, axis } = continuousAxisChannelDef;
    const title = getTitle(continuousAxisChannelDef);
    const axisWithoutTitle = omit(axis, ['title']);
    const outlierLayersMixins = partLayerMixins(markDef, 'outliers', config.boxplot, {
        transform: [{ filter: `(${fieldExpr} < ${lowerWhiskerExpr}) || (${fieldExpr} > ${upperWhiskerExpr})` }],
        mark: 'point',
        encoding: {
            [continuousAxis]: {
                field: continuousAxisChannelDef.field,
                type: continuousAxisChannelDef.type,
                ...(title !== undefined ? { title } : {}),
                ...(scale !== undefined ? { scale } : {}),
                // add axis without title since we already added the title above
                ...(isEmpty(axisWithoutTitle) ? {} : { axis: axisWithoutTitle })
            },
            ...encodingWithoutSizeColorContinuousAxisAndTooltip,
            ...(color ? { color } : {}),
            ...(customTooltipWithoutAggregatedField ? { tooltip: customTooltipWithoutAggregatedField } : {})
        }
    })[0];
    let filteredLayersMixins;
    const filteredLayersMixinsTransforms = [...bins, ...timeUnits, joinaggregateTransform];
    if (outlierLayersMixins) {
        filteredLayersMixins = {
            transform: filteredLayersMixinsTransforms,
            layer: [outlierLayersMixins, filteredWhiskerSpec]
        };
    }
    else {
        filteredLayersMixins = filteredWhiskerSpec;
        filteredLayersMixins.transform.unshift(...filteredLayersMixinsTransforms);
    }
    return {
        ...outerSpec,
        layer: [
            filteredLayersMixins,
            {
                // boxplot
                transform,
                layer: boxLayers
            }
        ]
    };
}
function boxParamsQuartiles(continousAxisField) {
    const aliasedFieldName = removePathFromField(continousAxisField);
    return [
        {
            op: 'q1',
            field: continousAxisField,
            as: `lower_box_${aliasedFieldName}`
        },
        {
            op: 'q3',
            field: continousAxisField,
            as: `upper_box_${aliasedFieldName}`
        }
    ];
}
function boxParams(spec, extent, config) {
    const orient = compositeMarkOrient(spec, BOXPLOT);
    const { continuousAxisChannelDef, continuousAxis } = compositeMarkContinuousAxis(spec, orient, BOXPLOT);
    const continuousFieldName = continuousAxisChannelDef.field;
    const aliasedFieldName = removePathFromField(continuousFieldName);
    const boxPlotType = getBoxPlotType(extent);
    const boxplotSpecificAggregate = [
        ...boxParamsQuartiles(continuousFieldName),
        {
            op: 'median',
            field: continuousFieldName,
            as: `mid_box_${aliasedFieldName}`
        },
        {
            op: 'min',
            field: continuousFieldName,
            as: (boxPlotType === 'min-max' ? 'lower_whisker_' : 'min_') + aliasedFieldName
        },
        {
            op: 'max',
            field: continuousFieldName,
            as: (boxPlotType === 'min-max' ? 'upper_whisker_' : 'max_') + aliasedFieldName
        }
    ];
    const postAggregateCalculates = boxPlotType === 'min-max' || boxPlotType === 'tukey'
        ? []
        : [
            // This is for the  original k-IQR, which we do not expose
            {
                calculate: `${accessWithDatumToUnescapedPath(`upper_box_${aliasedFieldName}`)} - ${accessWithDatumToUnescapedPath(`lower_box_${aliasedFieldName}`)}`,
                as: `iqr_${aliasedFieldName}`
            },
            {
                calculate: `min(${accessWithDatumToUnescapedPath(`upper_box_${aliasedFieldName}`)} + ${accessWithDatumToUnescapedPath(`iqr_${aliasedFieldName}`)} * ${extent}, ${accessWithDatumToUnescapedPath(`max_${aliasedFieldName}`)})`,
                as: `upper_whisker_${aliasedFieldName}`
            },
            {
                calculate: `max(${accessWithDatumToUnescapedPath(`lower_box_${aliasedFieldName}`)} - ${accessWithDatumToUnescapedPath(`iqr_${aliasedFieldName}`)} * ${extent}, ${accessWithDatumToUnescapedPath(`min_${aliasedFieldName}`)})`,
                as: `lower_whisker_${aliasedFieldName}`
            }
        ];
    const { [continuousAxis]: oldContinuousAxisChannelDef, ...oldEncodingWithoutContinuousAxis } = spec.encoding;
    const { customTooltipWithoutAggregatedField, filteredEncoding } = filterTooltipWithAggregatedField(oldEncodingWithoutContinuousAxis);
    const { bins, timeUnits, aggregate, groupby, encoding: encodingWithoutContinuousAxis } = extractTransformsFromEncoding(filteredEncoding, config);
    const ticksOrient = orient === 'vertical' ? 'horizontal' : 'vertical';
    const boxOrient = orient;
    const transform = [
        ...bins,
        ...timeUnits,
        {
            aggregate: [...aggregate, ...boxplotSpecificAggregate],
            groupby
        },
        ...postAggregateCalculates
    ];
    return {
        bins,
        timeUnits,
        transform,
        groupby,
        aggregate,
        continuousAxisChannelDef,
        continuousAxis,
        encodingWithoutContinuousAxis,
        ticksOrient,
        boxOrient,
        customTooltipWithoutAggregatedField
    };
}
//# sourceMappingURL=boxplot.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/errorbar.js







const ERRORBAR = 'errorbar';
const ERRORBAR_PARTS = ['ticks', 'rule'];
const errorBarNormalizer = new CompositeMarkNormalizer(ERRORBAR, normalizeErrorBar);
function normalizeErrorBar(spec, { config }) {
    // Need to initEncoding first so we can infer type
    spec = {
        ...spec,
        encoding: normalizeEncoding(spec.encoding, config)
    };
    const { transform, continuousAxisChannelDef, continuousAxis, encodingWithoutContinuousAxis, ticksOrient, markDef, outerSpec, tooltipEncoding } = errorBarParams(spec, ERRORBAR, config);
    delete encodingWithoutContinuousAxis.size;
    const makeErrorBarPart = makeCompositeAggregatePartFactory(markDef, continuousAxis, continuousAxisChannelDef, encodingWithoutContinuousAxis, config.errorbar);
    const thickness = markDef.thickness;
    const size = markDef.size;
    const tick = {
        type: 'tick',
        orient: ticksOrient,
        aria: false,
        ...(thickness !== undefined ? { thickness } : {}),
        ...(size !== undefined ? { size } : {})
    };
    const layer = [
        ...makeErrorBarPart({
            partName: 'ticks',
            mark: tick,
            positionPrefix: 'lower',
            extraEncoding: tooltipEncoding
        }),
        ...makeErrorBarPart({
            partName: 'ticks',
            mark: tick,
            positionPrefix: 'upper',
            extraEncoding: tooltipEncoding
        }),
        ...makeErrorBarPart({
            partName: 'rule',
            mark: {
                type: 'rule',
                ariaRoleDescription: 'errorbar',
                ...(thickness !== undefined ? { size: thickness } : {})
            },
            positionPrefix: 'lower',
            endPositionPrefix: 'upper',
            extraEncoding: tooltipEncoding
        })
    ];
    return {
        ...outerSpec,
        transform,
        ...(layer.length > 1 ? { layer } : { ...layer[0] })
    };
}
function errorBarOrientAndInputType(spec, compositeMark) {
    const { encoding } = spec;
    if (errorBarIsInputTypeRaw(encoding)) {
        return {
            orient: compositeMarkOrient(spec, compositeMark),
            inputType: 'raw'
        };
    }
    const isTypeAggregatedUpperLower = errorBarIsInputTypeAggregatedUpperLower(encoding);
    const isTypeAggregatedError = errorBarIsInputTypeAggregatedError(encoding);
    const x = encoding.x;
    const y = encoding.y;
    if (isTypeAggregatedUpperLower) {
        // type is aggregated-upper-lower
        if (isTypeAggregatedError) {
            throw new Error(`${compositeMark} cannot be both type aggregated-upper-lower and aggregated-error`);
        }
        const x2 = encoding.x2;
        const y2 = encoding.y2;
        if (isFieldOrDatumDef(x2) && isFieldOrDatumDef(y2)) {
            // having both x, x2 and y, y2
            throw new Error(`${compositeMark} cannot have both x2 and y2`);
        }
        else if (isFieldOrDatumDef(x2)) {
            if (isContinuousFieldOrDatumDef(x)) {
                // having x, x2 quantitative and field y, y2 are not specified
                return { orient: 'horizontal', inputType: 'aggregated-upper-lower' };
            }
            else {
                // having x, x2 that are not both quantitative
                throw new Error(`Both x and x2 have to be quantitative in ${compositeMark}`);
            }
        }
        else if (isFieldOrDatumDef(y2)) {
            // y2 is a FieldDef
            if (isContinuousFieldOrDatumDef(y)) {
                // having y, y2 quantitative and field x, x2 are not specified
                return { orient: 'vertical', inputType: 'aggregated-upper-lower' };
            }
            else {
                // having y, y2 that are not both quantitative
                throw new Error(`Both y and y2 have to be quantitative in ${compositeMark}`);
            }
        }
        throw new Error('No ranged axis');
    }
    else {
        // type is aggregated-error
        const xError = encoding.xError;
        const xError2 = encoding.xError2;
        const yError = encoding.yError;
        const yError2 = encoding.yError2;
        if (isFieldOrDatumDef(xError2) && !isFieldOrDatumDef(xError)) {
            // having xError2 without xError
            throw new Error(`${compositeMark} cannot have xError2 without xError`);
        }
        if (isFieldOrDatumDef(yError2) && !isFieldOrDatumDef(yError)) {
            // having yError2 without yError
            throw new Error(`${compositeMark} cannot have yError2 without yError`);
        }
        if (isFieldOrDatumDef(xError) && isFieldOrDatumDef(yError)) {
            // having both xError and yError
            throw new Error(`${compositeMark} cannot have both xError and yError with both are quantiative`);
        }
        else if (isFieldOrDatumDef(xError)) {
            if (isContinuousFieldOrDatumDef(x)) {
                // having x and xError that are all quantitative
                return { orient: 'horizontal', inputType: 'aggregated-error' };
            }
            else {
                // having x, xError, and xError2 that are not all quantitative
                throw new Error('All x, xError, and xError2 (if exist) have to be quantitative');
            }
        }
        else if (isFieldOrDatumDef(yError)) {
            if (isContinuousFieldOrDatumDef(y)) {
                // having y and yError that are all quantitative
                return { orient: 'vertical', inputType: 'aggregated-error' };
            }
            else {
                // having y, yError, and yError2 that are not all quantitative
                throw new Error('All y, yError, and yError2 (if exist) have to be quantitative');
            }
        }
        throw new Error('No ranged axis');
    }
}
function errorBarIsInputTypeRaw(encoding) {
    return ((isFieldOrDatumDef(encoding.x) || isFieldOrDatumDef(encoding.y)) &&
        !isFieldOrDatumDef(encoding.x2) &&
        !isFieldOrDatumDef(encoding.y2) &&
        !isFieldOrDatumDef(encoding.xError) &&
        !isFieldOrDatumDef(encoding.xError2) &&
        !isFieldOrDatumDef(encoding.yError) &&
        !isFieldOrDatumDef(encoding.yError2));
}
function errorBarIsInputTypeAggregatedUpperLower(encoding) {
    return isFieldOrDatumDef(encoding.x2) || isFieldOrDatumDef(encoding.y2);
}
function errorBarIsInputTypeAggregatedError(encoding) {
    return (isFieldOrDatumDef(encoding.xError) ||
        isFieldOrDatumDef(encoding.xError2) ||
        isFieldOrDatumDef(encoding.yError) ||
        isFieldOrDatumDef(encoding.yError2));
}
function errorBarParams(spec, compositeMark, config) {
    // TODO: use selection
    const { mark, encoding, params, projection: _p, ...outerSpec } = spec;
    const markDef = isMarkDef(mark) ? mark : { type: mark };
    // TODO(https://github.com/vega/vega-lite/issues/3702): add selection support
    if (params) {
        log_warn(selectionNotSupported(compositeMark));
    }
    const { orient, inputType } = errorBarOrientAndInputType(spec, compositeMark);
    const { continuousAxisChannelDef, continuousAxisChannelDef2, continuousAxisChannelDefError, continuousAxisChannelDefError2, continuousAxis } = compositeMarkContinuousAxis(spec, orient, compositeMark);
    const { errorBarSpecificAggregate, postAggregateCalculates, tooltipSummary, tooltipTitleWithFieldName } = errorBarAggregationAndCalculation(markDef, continuousAxisChannelDef, continuousAxisChannelDef2, continuousAxisChannelDefError, continuousAxisChannelDefError2, inputType, compositeMark, config);
    const { [continuousAxis]: oldContinuousAxisChannelDef, [continuousAxis === 'x' ? 'x2' : 'y2']: oldContinuousAxisChannelDef2, [continuousAxis === 'x' ? 'xError' : 'yError']: oldContinuousAxisChannelDefError, [continuousAxis === 'x' ? 'xError2' : 'yError2']: oldContinuousAxisChannelDefError2, ...oldEncodingWithoutContinuousAxis } = encoding;
    const { bins, timeUnits, aggregate: oldAggregate, groupby: oldGroupBy, encoding: encodingWithoutContinuousAxis } = extractTransformsFromEncoding(oldEncodingWithoutContinuousAxis, config);
    const aggregate = [...oldAggregate, ...errorBarSpecificAggregate];
    const groupby = inputType !== 'raw' ? [] : oldGroupBy;
    const tooltipEncoding = getCompositeMarkTooltip(tooltipSummary, continuousAxisChannelDef, encodingWithoutContinuousAxis, tooltipTitleWithFieldName);
    return {
        transform: [
            ...(outerSpec.transform ?? []),
            ...bins,
            ...timeUnits,
            ...(aggregate.length === 0 ? [] : [{ aggregate, groupby }]),
            ...postAggregateCalculates
        ],
        groupby,
        continuousAxisChannelDef,
        continuousAxis,
        encodingWithoutContinuousAxis,
        ticksOrient: orient === 'vertical' ? 'horizontal' : 'vertical',
        markDef,
        outerSpec,
        tooltipEncoding
    };
}
function errorBarAggregationAndCalculation(markDef, continuousAxisChannelDef, continuousAxisChannelDef2, continuousAxisChannelDefError, continuousAxisChannelDefError2, inputType, compositeMark, config) {
    let errorBarSpecificAggregate = [];
    let postAggregateCalculates = [];
    const continuousFieldName = continuousAxisChannelDef.field;
    let tooltipSummary;
    let tooltipTitleWithFieldName = false;
    if (inputType === 'raw') {
        const center = markDef.center
            ? markDef.center
            : markDef.extent
                ? markDef.extent === 'iqr'
                    ? 'median'
                    : 'mean'
                : config.errorbar.center;
        const extent = markDef.extent ? markDef.extent : center === 'mean' ? 'stderr' : 'iqr';
        if ((center === 'median') !== (extent === 'iqr')) {
            log_warn(errorBarCenterIsUsedWithWrongExtent(center, extent, compositeMark));
        }
        if (extent === 'stderr' || extent === 'stdev') {
            errorBarSpecificAggregate = [
                { op: extent, field: continuousFieldName, as: `extent_${continuousFieldName}` },
                { op: center, field: continuousFieldName, as: `center_${continuousFieldName}` }
            ];
            postAggregateCalculates = [
                {
                    calculate: `${accessWithDatumToUnescapedPath(`center_${continuousFieldName}`)} + ${accessWithDatumToUnescapedPath(`extent_${continuousFieldName}`)}`,
                    as: `upper_${continuousFieldName}`
                },
                {
                    calculate: `${accessWithDatumToUnescapedPath(`center_${continuousFieldName}`)} - ${accessWithDatumToUnescapedPath(`extent_${continuousFieldName}`)}`,
                    as: `lower_${continuousFieldName}`
                }
            ];
            tooltipSummary = [
                { fieldPrefix: 'center_', titlePrefix: titleCase(center) },
                { fieldPrefix: 'upper_', titlePrefix: getTitlePrefix(center, extent, '+') },
                { fieldPrefix: 'lower_', titlePrefix: getTitlePrefix(center, extent, '-') }
            ];
            tooltipTitleWithFieldName = true;
        }
        else {
            let centerOp;
            let lowerExtentOp;
            let upperExtentOp;
            if (extent === 'ci') {
                centerOp = 'mean';
                lowerExtentOp = 'ci0';
                upperExtentOp = 'ci1';
            }
            else {
                centerOp = 'median';
                lowerExtentOp = 'q1';
                upperExtentOp = 'q3';
            }
            errorBarSpecificAggregate = [
                { op: lowerExtentOp, field: continuousFieldName, as: `lower_${continuousFieldName}` },
                { op: upperExtentOp, field: continuousFieldName, as: `upper_${continuousFieldName}` },
                { op: centerOp, field: continuousFieldName, as: `center_${continuousFieldName}` }
            ];
            tooltipSummary = [
                {
                    fieldPrefix: 'upper_',
                    titlePrefix: channeldef_title({ field: continuousFieldName, aggregate: upperExtentOp, type: 'quantitative' }, config, {
                        allowDisabling: false
                    })
                },
                {
                    fieldPrefix: 'lower_',
                    titlePrefix: channeldef_title({ field: continuousFieldName, aggregate: lowerExtentOp, type: 'quantitative' }, config, {
                        allowDisabling: false
                    })
                },
                {
                    fieldPrefix: 'center_',
                    titlePrefix: channeldef_title({ field: continuousFieldName, aggregate: centerOp, type: 'quantitative' }, config, {
                        allowDisabling: false
                    })
                }
            ];
        }
    }
    else {
        if (markDef.center || markDef.extent) {
            log_warn(errorBarCenterAndExtentAreNotNeeded(markDef.center, markDef.extent));
        }
        if (inputType === 'aggregated-upper-lower') {
            tooltipSummary = [];
            postAggregateCalculates = [
                {
                    calculate: accessWithDatumToUnescapedPath(continuousAxisChannelDef2.field),
                    as: `upper_${continuousFieldName}`
                },
                { calculate: accessWithDatumToUnescapedPath(continuousFieldName), as: `lower_${continuousFieldName}` }
            ];
        }
        else if (inputType === 'aggregated-error') {
            tooltipSummary = [{ fieldPrefix: '', titlePrefix: continuousFieldName }];
            postAggregateCalculates = [
                {
                    calculate: `${accessWithDatumToUnescapedPath(continuousFieldName)} + ${accessWithDatumToUnescapedPath(continuousAxisChannelDefError.field)}`,
                    as: `upper_${continuousFieldName}`
                }
            ];
            if (continuousAxisChannelDefError2) {
                postAggregateCalculates.push({
                    calculate: `${accessWithDatumToUnescapedPath(continuousFieldName)} + ${accessWithDatumToUnescapedPath(continuousAxisChannelDefError2.field)}`,
                    as: `lower_${continuousFieldName}`
                });
            }
            else {
                postAggregateCalculates.push({
                    calculate: `${accessWithDatumToUnescapedPath(continuousFieldName)} - ${accessWithDatumToUnescapedPath(continuousAxisChannelDefError.field)}`,
                    as: `lower_${continuousFieldName}`
                });
            }
        }
        for (const postAggregateCalculate of postAggregateCalculates) {
            tooltipSummary.push({
                fieldPrefix: postAggregateCalculate.as.substring(0, 6),
                titlePrefix: replaceAll(replaceAll(postAggregateCalculate.calculate, "datum['", ''), "']", '')
            });
        }
    }
    return { postAggregateCalculates, errorBarSpecificAggregate, tooltipSummary, tooltipTitleWithFieldName };
}
function getTitlePrefix(center, extent, operation) {
    return `${titleCase(center)} ${operation} ${extent}`;
}
//# sourceMappingURL=errorbar.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/errorband.js





const ERRORBAND = 'errorband';
const ERRORBAND_PARTS = ['band', 'borders'];
const errorBandNormalizer = new CompositeMarkNormalizer(ERRORBAND, normalizeErrorBand);
function normalizeErrorBand(spec, { config }) {
    // Need to initEncoding first so we can infer type
    spec = {
        ...spec,
        encoding: normalizeEncoding(spec.encoding, config)
    };
    const { transform, continuousAxisChannelDef, continuousAxis, encodingWithoutContinuousAxis, markDef, outerSpec, tooltipEncoding } = errorBarParams(spec, ERRORBAND, config);
    const errorBandDef = markDef;
    const makeErrorBandPart = makeCompositeAggregatePartFactory(errorBandDef, continuousAxis, continuousAxisChannelDef, encodingWithoutContinuousAxis, config.errorband);
    const is2D = spec.encoding.x !== undefined && spec.encoding.y !== undefined;
    let bandMark = { type: is2D ? 'area' : 'rect' };
    let bordersMark = { type: is2D ? 'line' : 'rule' };
    const interpolate = {
        ...(errorBandDef.interpolate ? { interpolate: errorBandDef.interpolate } : {}),
        ...(errorBandDef.tension && errorBandDef.interpolate ? { tension: errorBandDef.tension } : {})
    };
    if (is2D) {
        bandMark = {
            ...bandMark,
            ...interpolate,
            ariaRoleDescription: 'errorband'
        };
        bordersMark = {
            ...bordersMark,
            ...interpolate,
            aria: false
        };
    }
    else if (errorBandDef.interpolate) {
        log_warn(errorBand1DNotSupport('interpolate'));
    }
    else if (errorBandDef.tension) {
        log_warn(errorBand1DNotSupport('tension'));
    }
    return {
        ...outerSpec,
        transform,
        layer: [
            ...makeErrorBandPart({
                partName: 'band',
                mark: bandMark,
                positionPrefix: 'lower',
                endPositionPrefix: 'upper',
                extraEncoding: tooltipEncoding
            }),
            ...makeErrorBandPart({
                partName: 'borders',
                mark: bordersMark,
                positionPrefix: 'lower',
                extraEncoding: tooltipEncoding
            }),
            ...makeErrorBandPart({
                partName: 'borders',
                mark: bordersMark,
                positionPrefix: 'upper',
                extraEncoding: tooltipEncoding
            })
        ]
    };
}
//# sourceMappingURL=errorband.js.map
;// ../../node_modules/vega-lite/build/src/compositemark/index.js





/**
 * Registry index for all composite mark's normalizer
 */
const compositeMarkRegistry = {};
function compositemark_add(mark, run, parts) {
    const normalizer = new CompositeMarkNormalizer(mark, run);
    compositeMarkRegistry[mark] = { normalizer, parts };
}
function compositemark_remove(mark) {
    delete compositeMarkRegistry[mark];
}
function getAllCompositeMarks() {
    return util_keys(compositeMarkRegistry);
}
compositemark_add(BOXPLOT, normalizeBoxPlot, BOXPLOT_PARTS);
compositemark_add(ERRORBAR, normalizeErrorBar, ERRORBAR_PARTS);
compositemark_add(ERRORBAND, normalizeErrorBand, ERRORBAND_PARTS);
//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/guide.js
const VL_ONLY_LEGEND_CONFIG = [
    'gradientHorizontalMaxLength',
    'gradientHorizontalMinLength',
    'gradientVerticalMaxLength',
    'gradientVerticalMinLength',
    'unselectedOpacity'
];
//# sourceMappingURL=guide.js.map
;// ../../node_modules/vega-lite/build/src/header.js

const HEADER_TITLE_PROPERTIES_MAP = {
    titleAlign: 'align',
    titleAnchor: 'anchor',
    titleAngle: 'angle',
    titleBaseline: 'baseline',
    titleColor: 'color',
    titleFont: 'font',
    titleFontSize: 'fontSize',
    titleFontStyle: 'fontStyle',
    titleFontWeight: 'fontWeight',
    titleLimit: 'limit',
    titleLineHeight: 'lineHeight',
    titleOrient: 'orient',
    titlePadding: 'offset'
};
const HEADER_LABEL_PROPERTIES_MAP = {
    labelAlign: 'align',
    labelAnchor: 'anchor',
    labelAngle: 'angle',
    labelBaseline: 'baseline',
    labelColor: 'color',
    labelFont: 'font',
    labelFontSize: 'fontSize',
    labelFontStyle: 'fontStyle',
    labelFontWeight: 'fontWeight',
    labelLimit: 'limit',
    labelLineHeight: 'lineHeight',
    labelOrient: 'orient',
    labelPadding: 'offset'
};
const HEADER_TITLE_PROPERTIES = util_keys(HEADER_TITLE_PROPERTIES_MAP);
const HEADER_LABEL_PROPERTIES = util_keys(HEADER_LABEL_PROPERTIES_MAP);
const HEADER_CONFIGS_INDEX = {
    header: 1,
    headerRow: 1,
    headerColumn: 1,
    headerFacet: 1
};
const HEADER_CONFIGS = util_keys(HEADER_CONFIGS_INDEX);
//# sourceMappingURL=header.js.map
;// ../../node_modules/vega-lite/build/src/legend.js

const LEGEND_SCALE_CHANNELS = [
    'size',
    'shape',
    'fill',
    'stroke',
    'strokeDash',
    'strokeWidth',
    'opacity'
];
const defaultLegendConfig = {
    gradientHorizontalMaxLength: 200,
    gradientHorizontalMinLength: 100,
    gradientVerticalMaxLength: 200,
    gradientVerticalMinLength: 64, // This is Vega's minimum.
    unselectedOpacity: 0.35
};
const COMMON_LEGEND_PROPERTY_INDEX = {
    aria: 1,
    clipHeight: 1,
    columnPadding: 1,
    columns: 1,
    cornerRadius: 1,
    description: 1,
    direction: 1,
    fillColor: 1,
    format: 1,
    formatType: 1,
    gradientLength: 1,
    gradientOpacity: 1,
    gradientStrokeColor: 1,
    gradientStrokeWidth: 1,
    gradientThickness: 1,
    gridAlign: 1,
    labelAlign: 1,
    labelBaseline: 1,
    labelColor: 1,
    labelFont: 1,
    labelFontSize: 1,
    labelFontStyle: 1,
    labelFontWeight: 1,
    labelLimit: 1,
    labelOffset: 1,
    labelOpacity: 1,
    labelOverlap: 1,
    labelPadding: 1,
    labelSeparation: 1,
    legendX: 1,
    legendY: 1,
    offset: 1,
    orient: 1,
    padding: 1,
    rowPadding: 1,
    strokeColor: 1,
    symbolDash: 1,
    symbolDashOffset: 1,
    symbolFillColor: 1,
    symbolLimit: 1,
    symbolOffset: 1,
    symbolOpacity: 1,
    symbolSize: 1,
    symbolStrokeColor: 1,
    symbolStrokeWidth: 1,
    symbolType: 1,
    tickCount: 1,
    tickMinStep: 1,
    title: 1,
    titleAlign: 1,
    titleAnchor: 1,
    titleBaseline: 1,
    titleColor: 1,
    titleFont: 1,
    titleFontSize: 1,
    titleFontStyle: 1,
    titleFontWeight: 1,
    titleLimit: 1,
    titleLineHeight: 1,
    titleOpacity: 1,
    titleOrient: 1,
    titlePadding: 1,
    type: 1,
    values: 1,
    zindex: 1
};
const LEGEND_PROPERTIES = util_keys(COMMON_LEGEND_PROPERTY_INDEX);
//# sourceMappingURL=legend.js.map
;// ../../node_modules/vega-lite/build/src/selection.js

const SELECTION_ID = '_vgsid_';
const defaultConfig = {
    point: {
        on: 'click',
        fields: [SELECTION_ID],
        toggle: 'event.shiftKey',
        resolve: 'global',
        clear: 'dblclick'
    },
    interval: {
        on: '[pointerdown, window:pointerup] > window:pointermove!',
        encodings: ['x', 'y'],
        translate: '[pointerdown, window:pointerup] > window:pointermove!',
        zoom: 'wheel!',
        mark: { fill: '#333', fillOpacity: 0.125, stroke: 'white' },
        resolve: 'global',
        clear: 'dblclick'
    }
};
function isLegendBinding(bind) {
    return bind === 'legend' || !!bind?.legend;
}
function isLegendStreamBinding(bind) {
    return isLegendBinding(bind) && vega_util_module_isObject(bind);
}
function isSelectionParameter(param) {
    return !!param?.['select'];
}
//# sourceMappingURL=selection.js.map
;// ../../node_modules/vega-lite/build/src/parameter.js

function assembleParameterSignals(params) {
    const signals = [];
    for (const param of params || []) {
        // Selection parameters are handled separately via assembleSelectionTopLevelSignals
        // and assembleSignals methods registered on the Model.
        if (isSelectionParameter(param))
            continue;
        const { expr, bind, ...rest } = param;
        if (bind && expr) {
            // Vega's InitSignal -- apply expr to "init"
            const signal = {
                ...rest,
                bind,
                init: expr
            };
            signals.push(signal);
        }
        else {
            const signal = {
                ...rest,
                ...(expr ? { update: expr } : {}),
                ...(bind ? { bind } : {})
            };
            signals.push(signal);
        }
    }
    return signals;
}
//# sourceMappingURL=parameter.js.map
;// ../../node_modules/vega-lite/build/src/spec/concat.js

function isAnyConcatSpec(spec) {
    return isVConcatSpec(spec) || isHConcatSpec(spec) || isConcatSpec(spec);
}
function isConcatSpec(spec) {
    return util_hasProperty(spec, 'concat');
}
function isVConcatSpec(spec) {
    return util_hasProperty(spec, 'vconcat');
}
function isHConcatSpec(spec) {
    return util_hasProperty(spec, 'hconcat');
}
//# sourceMappingURL=concat.js.map
;// ../../node_modules/vega-lite/build/src/spec/base.js




function getStepFor({ step, offsetIsDiscrete }) {
    if (offsetIsDiscrete) {
        return step.for ?? 'offset';
    }
    else {
        return 'position';
    }
}
function isStep(size) {
    return util_hasProperty(size, 'step');
}
function isFrameMixins(o) {
    return util_hasProperty(o, 'view') || util_hasProperty(o, 'width') || util_hasProperty(o, 'height');
}
const DEFAULT_SPACING = 20;
const COMPOSITION_LAYOUT_INDEX = {
    align: 1,
    bounds: 1,
    center: 1,
    columns: 1,
    spacing: 1
};
const COMPOSITION_LAYOUT_PROPERTIES = util_keys(COMPOSITION_LAYOUT_INDEX);
function extractCompositionLayout(spec, specType, config) {
    const compositionConfig = config[specType];
    const layout = {};
    // Apply config first
    const { spacing: spacingConfig, columns } = compositionConfig;
    if (spacingConfig !== undefined) {
        layout.spacing = spacingConfig;
    }
    if (columns !== undefined) {
        if ((isFacetSpec(spec) && !isFacetMapping(spec.facet)) || isConcatSpec(spec)) {
            layout.columns = columns;
        }
    }
    if (isVConcatSpec(spec)) {
        layout.columns = 1;
    }
    // Then copy properties from the spec
    for (const prop of COMPOSITION_LAYOUT_PROPERTIES) {
        if (spec[prop] !== undefined) {
            if (prop === 'spacing') {
                const spacing = spec[prop];
                layout[prop] = vega_util_module_isNumber(spacing)
                    ? spacing
                    : {
                        row: spacing.row ?? spacingConfig,
                        column: spacing.column ?? spacingConfig
                    };
            }
            else {
                layout[prop] = spec[prop];
            }
        }
    }
    return layout;
}
//# sourceMappingURL=base.js.map
;// ../../node_modules/vega-lite/build/src/config.js
















function getViewConfigContinuousSize(viewConfig, channel) {
    return viewConfig[channel] ?? viewConfig[channel === 'width' ? 'continuousWidth' : 'continuousHeight']; // get width/height for backwards compatibility
}
function getViewConfigDiscreteStep(viewConfig, channel) {
    const size = getViewConfigDiscreteSize(viewConfig, channel);
    return isStep(size) ? size.step : DEFAULT_STEP;
}
function getViewConfigDiscreteSize(viewConfig, channel) {
    const size = viewConfig[channel] ?? viewConfig[channel === 'width' ? 'discreteWidth' : 'discreteHeight']; // get width/height for backwards compatibility
    return getFirstDefined(size, { step: viewConfig.step });
}
const DEFAULT_STEP = 20;
const defaultViewConfig = {
    continuousWidth: 200,
    continuousHeight: 200,
    step: DEFAULT_STEP
};
function isVgScheme(rangeScheme) {
    return hasProperty(rangeScheme, 'scheme');
}
const config_defaultConfig = {
    background: 'white',
    padding: 5,
    timeFormat: '%b %d, %Y',
    countTitle: 'Count of Records',
    view: defaultViewConfig,
    mark: defaultMarkConfig,
    arc: {},
    area: {},
    bar: defaultBarConfig,
    circle: {},
    geoshape: {},
    image: {},
    line: {},
    point: {},
    rect: defaultRectConfig,
    rule: { color: 'black' }, // Need this to override default color in mark config
    square: {},
    text: { color: 'black' }, // Need this to override default color in mark config
    tick: defaultTickConfig,
    trail: {},
    boxplot: {
        size: 14,
        extent: 1.5,
        box: {},
        median: { color: 'white' },
        outliers: {},
        rule: {},
        ticks: null
    },
    errorbar: {
        center: 'mean',
        rule: true,
        ticks: false
    },
    errorband: {
        band: {
            opacity: 0.3
        },
        borders: false
    },
    scale: defaultScaleConfig,
    projection: {},
    legend: defaultLegendConfig,
    header: { titlePadding: 10, labelPadding: 10 },
    headerColumn: {},
    headerRow: {},
    headerFacet: {},
    selection: defaultConfig,
    style: {},
    title: {},
    facet: { spacing: DEFAULT_SPACING },
    concat: { spacing: DEFAULT_SPACING },
    normalizedNumberFormat: '.0%'
};
// Tableau10 color palette, copied from `vegaScale.scheme('tableau10')`
const tab10 = [
    '#4c78a8',
    '#f58518',
    '#e45756',
    '#72b7b2',
    '#54a24b',
    '#eeca3b',
    '#b279a2',
    '#ff9da6',
    '#9d755d',
    '#bab0ac'
];
const DEFAULT_FONT_SIZE = {
    text: 11,
    guideLabel: 10,
    guideTitle: 11,
    groupTitle: 13,
    groupSubtitle: 12
};
const DEFAULT_COLOR = {
    blue: tab10[0],
    orange: tab10[1],
    red: tab10[2],
    teal: tab10[3],
    green: tab10[4],
    yellow: tab10[5],
    purple: tab10[6],
    pink: tab10[7],
    brown: tab10[8],
    gray0: '#000',
    gray1: '#111',
    gray2: '#222',
    gray3: '#333',
    gray4: '#444',
    gray5: '#555',
    gray6: '#666',
    gray7: '#777',
    gray8: '#888',
    gray9: '#999',
    gray10: '#aaa',
    gray11: '#bbb',
    gray12: '#ccc',
    gray13: '#ddd',
    gray14: '#eee',
    gray15: '#fff'
};
function colorSignalConfig(color = {}) {
    return {
        signals: [
            {
                name: 'color',
                value: vega_util_module_isObject(color) ? { ...DEFAULT_COLOR, ...color } : DEFAULT_COLOR
            }
        ],
        mark: { color: { signal: 'color.blue' } },
        rule: { color: { signal: 'color.gray0' } },
        text: {
            color: { signal: 'color.gray0' }
        },
        style: {
            'guide-label': {
                fill: { signal: 'color.gray0' }
            },
            'guide-title': {
                fill: { signal: 'color.gray0' }
            },
            'group-title': {
                fill: { signal: 'color.gray0' }
            },
            'group-subtitle': {
                fill: { signal: 'color.gray0' }
            },
            cell: {
                stroke: { signal: 'color.gray8' }
            }
        },
        axis: {
            domainColor: { signal: 'color.gray13' },
            gridColor: { signal: 'color.gray8' },
            tickColor: { signal: 'color.gray13' }
        },
        range: {
            category: [
                { signal: 'color.blue' },
                { signal: 'color.orange' },
                { signal: 'color.red' },
                { signal: 'color.teal' },
                { signal: 'color.green' },
                { signal: 'color.yellow' },
                { signal: 'color.purple' },
                { signal: 'color.pink' },
                { signal: 'color.brown' },
                { signal: 'color.grey8' }
            ]
        }
    };
}
function fontSizeSignalConfig(fontSize) {
    return {
        signals: [
            {
                name: 'fontSize',
                value: vega_util_module_isObject(fontSize) ? { ...DEFAULT_FONT_SIZE, ...fontSize } : DEFAULT_FONT_SIZE
            }
        ],
        text: {
            fontSize: { signal: 'fontSize.text' }
        },
        style: {
            'guide-label': {
                fontSize: { signal: 'fontSize.guideLabel' }
            },
            'guide-title': {
                fontSize: { signal: 'fontSize.guideTitle' }
            },
            'group-title': {
                fontSize: { signal: 'fontSize.groupTitle' }
            },
            'group-subtitle': {
                fontSize: { signal: 'fontSize.groupSubtitle' }
            }
        }
    };
}
function fontConfig(font) {
    return {
        text: { font },
        style: {
            'guide-label': { font },
            'guide-title': { font },
            'group-title': { font },
            'group-subtitle': { font }
        }
    };
}
function getAxisConfigInternal(axisConfig) {
    const props = util_keys(axisConfig || {});
    const axisConfigInternal = {};
    for (const prop of props) {
        const val = axisConfig[prop];
        axisConfigInternal[prop] = isConditionalAxisValue(val)
            ? signalOrValueRefWithCondition(val)
            : signalRefOrValue(val);
    }
    return axisConfigInternal;
}
function getStyleConfigInternal(styleConfig) {
    const props = util_keys(styleConfig);
    const styleConfigInternal = {};
    for (const prop of props) {
        // We need to cast to cheat a bit here since styleConfig can be either mark config or axis config
        styleConfigInternal[prop] = getAxisConfigInternal(styleConfig[prop]);
    }
    return styleConfigInternal;
}
const configPropsWithExpr = [
    ...MARK_CONFIGS,
    ...AXIS_CONFIGS,
    ...HEADER_CONFIGS,
    'background',
    'padding',
    'legend',
    'lineBreak',
    'scale',
    'style',
    'title',
    'view'
];
/**
 * Merge specified config with default config and config for the `color` flag,
 * then replace all expressions with signals
 */
function initConfig(specifiedConfig = {}) {
    const { color, font, fontSize, selection, ...restConfig } = specifiedConfig;
    const mergedConfig = mergeConfig({}, duplicate(config_defaultConfig), font ? fontConfig(font) : {}, color ? colorSignalConfig(color) : {}, fontSize ? fontSizeSignalConfig(fontSize) : {}, restConfig || {});
    // mergeConfig doesn't recurse and overrides object values.
    if (selection) {
        writeConfig(mergedConfig, 'selection', selection, true);
    }
    const outputConfig = omit(mergedConfig, configPropsWithExpr);
    for (const prop of ['background', 'lineBreak', 'padding']) {
        if (mergedConfig[prop]) {
            outputConfig[prop] = signalRefOrValue(mergedConfig[prop]);
        }
    }
    for (const markConfigType of MARK_CONFIGS) {
        if (mergedConfig[markConfigType]) {
            // FIXME: outputConfig[markConfigType] expects that types are replaced recursively but replaceExprRef only replaces one level deep
            outputConfig[markConfigType] = replaceExprRef(mergedConfig[markConfigType]);
        }
    }
    for (const axisConfigType of AXIS_CONFIGS) {
        if (mergedConfig[axisConfigType]) {
            outputConfig[axisConfigType] = getAxisConfigInternal(mergedConfig[axisConfigType]);
        }
    }
    for (const headerConfigType of HEADER_CONFIGS) {
        if (mergedConfig[headerConfigType]) {
            outputConfig[headerConfigType] = replaceExprRef(mergedConfig[headerConfigType]);
        }
    }
    if (mergedConfig.legend) {
        outputConfig.legend = replaceExprRef(mergedConfig.legend);
    }
    if (mergedConfig.scale) {
        const { invalid, ...otherScaleConfig } = mergedConfig.scale;
        const newScaleInvalid = replaceExprRef(invalid, { level: 1 });
        outputConfig.scale = {
            ...replaceExprRef(otherScaleConfig),
            ...(util_keys(newScaleInvalid).length > 0 ? { invalid: newScaleInvalid } : {})
        };
    }
    if (mergedConfig.style) {
        outputConfig.style = getStyleConfigInternal(mergedConfig.style);
    }
    if (mergedConfig.title) {
        outputConfig.title = replaceExprRef(mergedConfig.title);
    }
    if (mergedConfig.view) {
        outputConfig.view = replaceExprRef(mergedConfig.view);
    }
    return outputConfig;
}
const MARK_STYLES = new Set(['view', ...PRIMITIVE_MARKS]);
const VL_ONLY_CONFIG_PROPERTIES = [
    'color',
    'fontSize',
    'background', // We apply background to the spec directly.
    'padding',
    'facet',
    'concat',
    'numberFormat',
    'numberFormatType',
    'normalizedNumberFormat',
    'normalizedNumberFormatType',
    'timeFormat',
    'countTitle',
    'header',
    'axisQuantitative',
    'axisTemporal',
    'axisDiscrete',
    'axisPoint',
    'axisXBand',
    'axisXPoint',
    'axisXDiscrete',
    'axisXQuantitative',
    'axisXTemporal',
    'axisYBand',
    'axisYPoint',
    'axisYDiscrete',
    'axisYQuantitative',
    'axisYTemporal',
    'scale',
    'selection',
    'overlay' // FIXME: Redesign and unhide this
];
const VL_ONLY_ALL_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX = {
    view: ['continuousWidth', 'continuousHeight', 'discreteWidth', 'discreteHeight', 'step'],
    ...VL_ONLY_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX
};
function stripAndRedirectConfig(config) {
    config = duplicate(config);
    for (const prop of VL_ONLY_CONFIG_PROPERTIES) {
        delete config[prop];
    }
    if (config.axis) {
        // delete condition axis config
        for (const prop in config.axis) {
            if (isConditionalAxisValue(config.axis[prop])) {
                delete config.axis[prop];
            }
        }
    }
    if (config.legend) {
        for (const prop of VL_ONLY_LEGEND_CONFIG) {
            delete config.legend[prop];
        }
    }
    // Remove Vega-Lite only generic mark config
    if (config.mark) {
        for (const prop of VL_ONLY_MARK_CONFIG_PROPERTIES) {
            delete config.mark[prop];
        }
        if (config.mark.tooltip && vega_util_module_isObject(config.mark.tooltip)) {
            delete config.mark.tooltip;
        }
    }
    if (config.params) {
        config.signals = (config.signals || []).concat(assembleParameterSignals(config.params));
        delete config.params;
    }
    for (const markType of MARK_STYLES) {
        // Remove Vega-Lite-only mark config
        for (const prop of VL_ONLY_MARK_CONFIG_PROPERTIES) {
            delete config[markType][prop];
        }
        // Remove Vega-Lite only mark-specific config
        const vlOnlyMarkSpecificConfigs = VL_ONLY_ALL_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX[markType];
        if (vlOnlyMarkSpecificConfigs) {
            for (const prop of vlOnlyMarkSpecificConfigs) {
                delete config[markType][prop];
            }
        }
        // Redirect mark config to config.style so that mark config only affect its own mark type
        // without affecting other marks that share the same underlying Vega marks.
        // For example, config.rect should not affect bar marks.
        redirectConfigToStyleConfig(config, markType);
    }
    for (const m of getAllCompositeMarks()) {
        // Clean up the composite mark config as we don't need them in the output specs anymore
        delete config[m];
    }
    redirectTitleConfig(config);
    // Remove empty config objects.
    for (const prop in config) {
        // @ts-ignore
        if (vega_util_module_isObject(config[prop]) && isEmpty(config[prop])) {
            // @ts-ignore
            delete config[prop];
        }
    }
    return isEmpty(config) ? undefined : config;
}
/**
 *
 * Redirect config.title -- so that title config do not affect header labels,
 * which also uses `title` directive to implement.
 *
 * For subtitle configs in config.title, keep them in config.title as header titles never have subtitles.
 */
function redirectTitleConfig(config) {
    const { titleMarkConfig, subtitleMarkConfig, subtitle } = extractTitleConfig(config.title);
    // set config.style if title/subtitleMarkConfig is not an empty object
    if (!isEmpty(titleMarkConfig)) {
        config.style['group-title'] = {
            ...config.style['group-title'],
            ...titleMarkConfig // config.title has higher precedence than config.style.group-title in Vega
        };
    }
    if (!isEmpty(subtitleMarkConfig)) {
        config.style['group-subtitle'] = {
            ...config.style['group-subtitle'],
            ...subtitleMarkConfig
        };
    }
    // subtitle part can stay in config.title since header titles do not use subtitle
    if (!isEmpty(subtitle)) {
        config.title = subtitle;
    }
    else {
        delete config.title;
    }
}
function redirectConfigToStyleConfig(config, prop, // string = composite mark
toProp, compositeMarkPart) {
    const propConfig = compositeMarkPart
        ? config[prop][compositeMarkPart]
        : config[prop];
    if (prop === 'view') {
        toProp = 'cell'; // View's default style is "cell"
    }
    const style = {
        ...propConfig,
        ...config.style[toProp ?? prop]
    };
    // set config.style if it is not an empty object
    if (!isEmpty(style)) {
        config.style[toProp ?? prop] = style;
    }
    if (!compositeMarkPart) {
        // For composite mark, so don't delete the whole config yet as we have to do multiple redirections.
        delete config[prop];
    }
}
//# sourceMappingURL=config.js.map
;// ../../node_modules/vega-lite/build/src/spec/layer.js

function isLayerSpec(spec) {
    return util_hasProperty(spec, 'layer');
}
//# sourceMappingURL=layer.js.map
;// ../../node_modules/vega-lite/build/src/spec/repeat.js


function isRepeatSpec(spec) {
    return util_hasProperty(spec, 'repeat');
}
function isLayerRepeatSpec(spec) {
    return !vega_util_module_isArray(spec.repeat) && util_hasProperty(spec.repeat, 'layer');
}
//# sourceMappingURL=repeat.js.map
;// ../../node_modules/vega-lite/build/src/spec/index.js





//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/spec/map.js






class SpecMapper {
    map(spec, params) {
        if (isFacetSpec(spec)) {
            return this.mapFacet(spec, params);
        }
        else if (isRepeatSpec(spec)) {
            return this.mapRepeat(spec, params);
        }
        else if (isHConcatSpec(spec)) {
            return this.mapHConcat(spec, params);
        }
        else if (isVConcatSpec(spec)) {
            return this.mapVConcat(spec, params);
        }
        else if (isConcatSpec(spec)) {
            return this.mapConcat(spec, params);
        }
        else {
            return this.mapLayerOrUnit(spec, params);
        }
    }
    mapLayerOrUnit(spec, params) {
        if (isLayerSpec(spec)) {
            return this.mapLayer(spec, params);
        }
        else if (isUnitSpec(spec)) {
            return this.mapUnit(spec, params);
        }
        throw new Error(invalidSpec(spec));
    }
    mapLayer(spec, params) {
        return {
            ...spec,
            layer: spec.layer.map(subspec => this.mapLayerOrUnit(subspec, params))
        };
    }
    mapHConcat(spec, params) {
        return {
            ...spec,
            hconcat: spec.hconcat.map(subspec => this.map(subspec, params))
        };
    }
    mapVConcat(spec, params) {
        return {
            ...spec,
            vconcat: spec.vconcat.map(subspec => this.map(subspec, params))
        };
    }
    mapConcat(spec, params) {
        const { concat, ...rest } = spec;
        return {
            ...rest,
            concat: concat.map(subspec => this.map(subspec, params))
        };
    }
    mapFacet(spec, params) {
        return {
            // as any is required here since TS cannot infer that FO may only be FieldName or Field, but not RepeatRef
            ...spec,
            // TODO: remove "any" once we support all facet listed in https://github.com/vega/vega-lite/issues/2760
            spec: this.map(spec.spec, params)
        };
    }
    mapRepeat(spec, params) {
        return {
            ...spec,
            // as any is required here since TS cannot infer that the output type satisfies the input type
            spec: this.map(spec.spec, params)
        };
    }
}
//# sourceMappingURL=map.js.map
;// ../../node_modules/vega-lite/build/src/stack.js








const STACK_OFFSET_INDEX = {
    zero: 1,
    center: 1,
    normalize: 1
};
function isStackOffset(s) {
    return vega_util_module_has(STACK_OFFSET_INDEX, s);
}
const STACKABLE_MARKS = new Set([ARC, BAR, AREA, RULE, POINT, CIRCLE, SQUARE, LINE, mark_TEXT, TICK]);
const STACK_BY_DEFAULT_MARKS = new Set([BAR, AREA, ARC]);
function isUnbinnedQuantitative(channelDef) {
    return isFieldDef(channelDef) && channelDefType(channelDef) === 'quantitative' && !channelDef.bin;
}
function potentialStackedChannel(encoding, x, { orient, type: mark }) {
    const y = x === 'x' ? 'y' : 'radius';
    const isCartesianBarOrArea = x === 'x' && ['bar', 'area'].includes(mark);
    const xDef = encoding[x];
    const yDef = encoding[y];
    if (isFieldDef(xDef) && isFieldDef(yDef)) {
        if (isUnbinnedQuantitative(xDef) && isUnbinnedQuantitative(yDef)) {
            if (xDef.stack) {
                return x;
            }
            else if (yDef.stack) {
                return y;
            }
            const xAggregate = isFieldDef(xDef) && !!xDef.aggregate;
            const yAggregate = isFieldDef(yDef) && !!yDef.aggregate;
            // if there is no explicit stacking, only apply stack if there is only one aggregate for x or y
            if (xAggregate !== yAggregate) {
                return xAggregate ? x : y;
            }
            if (isCartesianBarOrArea) {
                if (orient === 'vertical') {
                    return y;
                }
                else if (orient === 'horizontal') {
                    return x;
                }
            }
        }
        else if (isUnbinnedQuantitative(xDef)) {
            return x;
        }
        else if (isUnbinnedQuantitative(yDef)) {
            return y;
        }
    }
    else if (isUnbinnedQuantitative(xDef)) {
        if (isCartesianBarOrArea && orient === 'vertical') {
            return undefined;
        }
        return x;
    }
    else if (isUnbinnedQuantitative(yDef)) {
        if (isCartesianBarOrArea && orient === 'horizontal') {
            return undefined;
        }
        return y;
    }
    return undefined;
}
function getDimensionChannel(channel) {
    switch (channel) {
        case 'x':
            return 'y';
        case 'y':
            return 'x';
        case 'theta':
            return 'radius';
        case 'radius':
            return 'theta';
    }
}
function stack(m, encoding) {
    const markDef = isMarkDef(m) ? m : { type: m };
    const mark = markDef.type;
    // Should have stackable mark
    if (!STACKABLE_MARKS.has(mark)) {
        return null;
    }
    // Run potential stacked twice, one for Cartesian and another for Polar,
    // so text marks can be stacked in any of the coordinates.
    // Note: The logic here is not perfectly correct.  If we want to support stacked dot plots where each dot is a pie chart with label, we have to change the stack logic here to separate Cartesian stacking for polar stacking.
    // However, since we probably never want to do that, let's just note the limitation here.
    const fieldChannel = potentialStackedChannel(encoding, 'x', markDef) || potentialStackedChannel(encoding, 'theta', markDef);
    if (!fieldChannel) {
        return null;
    }
    const stackedFieldDef = encoding[fieldChannel];
    const stackedField = isFieldDef(stackedFieldDef) ? vgField(stackedFieldDef, {}) : undefined;
    const dimensionChannel = getDimensionChannel(fieldChannel);
    const groupbyChannels = [];
    const groupbyFields = new Set();
    if (encoding[dimensionChannel]) {
        const dimensionDef = encoding[dimensionChannel];
        const dimensionField = isFieldDef(dimensionDef) ? vgField(dimensionDef, {}) : undefined;
        if (dimensionField && dimensionField !== stackedField) {
            // avoid grouping by the stacked field
            groupbyChannels.push(dimensionChannel);
            groupbyFields.add(dimensionField);
        }
    }
    const dimensionOffsetChannel = dimensionChannel === 'x' ? 'xOffset' : 'yOffset';
    const dimensionOffsetDef = encoding[dimensionOffsetChannel];
    const dimensionOffsetField = isFieldDef(dimensionOffsetDef) ? vgField(dimensionOffsetDef, {}) : undefined;
    if (dimensionOffsetField && dimensionOffsetField !== stackedField) {
        // avoid grouping by the stacked field
        groupbyChannels.push(dimensionOffsetChannel);
        groupbyFields.add(dimensionOffsetField);
    }
    // If the dimension has offset, don't stack anymore
    // Should have grouping level of detail that is different from the dimension field
    const stackBy = NONPOSITION_CHANNELS.reduce((sc, channel) => {
        // Ignore tooltip in stackBy (https://github.com/vega/vega-lite/issues/4001)
        if (channel !== 'tooltip' && channelHasField(encoding, channel)) {
            const channelDef = encoding[channel];
            for (const cDef of vega_util_module_array(channelDef)) {
                const fieldDef = getFieldDef(cDef);
                if (fieldDef.aggregate) {
                    continue;
                }
                // Check whether the channel's field is identical to x/y's field or if the channel is a repeat
                const f = vgField(fieldDef, {});
                if (
                // if fielddef is a repeat, just include it in the stack by
                !f ||
                    // otherwise, the field must be different from the groupBy fields.
                    !groupbyFields.has(f)) {
                    sc.push({ channel, fieldDef });
                }
            }
        }
        return sc;
    }, []);
    // Automatically determine offset
    let offset;
    if (stackedFieldDef.stack !== undefined) {
        if (isBoolean(stackedFieldDef.stack)) {
            offset = stackedFieldDef.stack ? 'zero' : null;
        }
        else {
            offset = stackedFieldDef.stack;
        }
    }
    else if (STACK_BY_DEFAULT_MARKS.has(mark)) {
        offset = 'zero';
    }
    if (!offset || !isStackOffset(offset)) {
        return null;
    }
    if (isAggregate(encoding) && stackBy.length === 0) {
        return null;
    }
    // warn when stacking non-linear
    if (stackedFieldDef?.scale?.type && stackedFieldDef?.scale?.type !== ScaleType.LINEAR) {
        if (stackedFieldDef?.stack) {
            log_warn(stackNonLinearScale(stackedFieldDef.scale.type));
        }
    }
    // Check if it is a ranged mark
    if (isFieldOrDatumDef(encoding[getSecondaryRangeChannel(fieldChannel)])) {
        if (stackedFieldDef.stack !== undefined) {
            log_warn(cannotStackRangedMark(fieldChannel));
        }
        return null;
    }
    // Warn if stacking non-summative aggregate
    if (isFieldDef(stackedFieldDef) &&
        stackedFieldDef.aggregate &&
        !SUM_OPS.has(stackedFieldDef.aggregate)) {
        log_warn(stackNonSummativeAggregate(stackedFieldDef.aggregate));
    }
    return {
        groupbyChannels,
        groupbyFields,
        fieldChannel,
        impute: stackedFieldDef.impute === null ? false : isPathMark(mark),
        stackBy,
        offset
    };
}
//# sourceMappingURL=stack.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/init.js









function initMarkdef(originalMarkDef, encoding, config) {
    // FIXME: markDef expects that exprRefs are replaced recursively but replaceExprRef only replaces the top level
    const markDef = replaceExprRef(originalMarkDef);
    // set orient, which can be overridden by rules as sometimes the specified orient is invalid.
    const specifiedOrient = getMarkPropOrConfig('orient', markDef, config);
    markDef.orient = orient(markDef.type, encoding, specifiedOrient);
    if (specifiedOrient !== undefined && specifiedOrient !== markDef.orient) {
        log_warn(orientOverridden(markDef.orient, specifiedOrient));
    }
    if (markDef.type === 'bar' && markDef.orient) {
        const cornerRadiusEnd = getMarkPropOrConfig('cornerRadiusEnd', markDef, config);
        if (cornerRadiusEnd !== undefined) {
            const newProps = (markDef.orient === 'horizontal' && encoding.x2) || (markDef.orient === 'vertical' && encoding.y2)
                ? ['cornerRadius']
                : BAR_CORNER_RADIUS_INDEX[markDef.orient];
            for (const newProp of newProps) {
                markDef[newProp] = cornerRadiusEnd;
            }
            if (markDef.cornerRadiusEnd !== undefined) {
                delete markDef.cornerRadiusEnd; // no need to keep the original cap cornerRadius
            }
        }
    }
    // set opacity and filled if not specified in mark config
    const specifiedOpacity = getMarkPropOrConfig('opacity', markDef, config);
    const specifiedfillOpacity = getMarkPropOrConfig('fillOpacity', markDef, config);
    if (specifiedOpacity === undefined && specifiedfillOpacity === undefined) {
        markDef.opacity = opacity(markDef.type, encoding);
    }
    // set cursor, which should be pointer if href channel is present unless otherwise specified
    const specifiedCursor = getMarkPropOrConfig('cursor', markDef, config);
    if (specifiedCursor === undefined) {
        markDef.cursor = init_cursor(markDef, encoding, config);
    }
    return markDef;
}
function init_cursor(markDef, encoding, config) {
    if (encoding.href || markDef.href || getMarkPropOrConfig('href', markDef, config)) {
        return 'pointer';
    }
    return markDef.cursor;
}
function opacity(mark, encoding) {
    if (util_contains([POINT, TICK, CIRCLE, SQUARE], mark)) {
        // point-based marks
        if (!isAggregate(encoding)) {
            return 0.7;
        }
    }
    return undefined;
}
function defaultFilled(markDef, config, { graticule }) {
    if (graticule) {
        return false;
    }
    const filledConfig = getMarkConfig('filled', markDef, config);
    const mark = markDef.type;
    return getFirstDefined(filledConfig, mark !== POINT && mark !== LINE && mark !== RULE);
}
function orient(mark, encoding, specifiedOrient) {
    switch (mark) {
        case POINT:
        case CIRCLE:
        case SQUARE:
        case mark_TEXT:
        case RECT:
        case IMAGE:
            // orient is meaningless for these marks.
            return undefined;
    }
    const { x, y, x2, y2 } = encoding;
    switch (mark) {
        case BAR:
            if (isFieldDef(x) && (isBinned(x.bin) || (isFieldDef(y) && y.aggregate && !x.aggregate))) {
                return 'vertical';
            }
            if (isFieldDef(y) && (isBinned(y.bin) || (isFieldDef(x) && x.aggregate && !y.aggregate))) {
                return 'horizontal';
            }
            if (y2 || x2) {
                // Ranged bar does not always have clear orientation, so we allow overriding
                if (specifiedOrient) {
                    return specifiedOrient;
                }
                // If y is range and x is non-range, non-bin Q
                if (!x2) {
                    if ((isFieldDef(x) && x.type === QUANTITATIVE && !isBinning(x.bin)) || isNumericDataDef(x)) {
                        if (isFieldDef(y) && isBinned(y.bin)) {
                            return 'horizontal';
                        }
                    }
                    return 'vertical';
                }
                // If x is range and y is non-range, non-bin Q
                if (!y2) {
                    if ((isFieldDef(y) && y.type === QUANTITATIVE && !isBinning(y.bin)) || isNumericDataDef(y)) {
                        if (isFieldDef(x) && isBinned(x.bin)) {
                            return 'vertical';
                        }
                    }
                    return 'horizontal';
                }
            }
        // falls through
        case RULE:
            // return undefined for line segment rule and bar with both axis ranged
            // we have to ignore the case that the data are already binned
            if (x2 && !(isFieldDef(x) && isBinned(x.bin)) && y2 && !(isFieldDef(y) && isBinned(y.bin))) {
                return undefined;
            }
        // falls through
        case AREA:
            // If there are range for both x and y, y (vertical) has higher precedence.
            if (y2) {
                if (isFieldDef(y) && isBinned(y.bin)) {
                    return 'horizontal';
                }
                else {
                    return 'vertical';
                }
            }
            else if (x2) {
                if (isFieldDef(x) && isBinned(x.bin)) {
                    return 'vertical';
                }
                else {
                    return 'horizontal';
                }
            }
            else if (mark === RULE) {
                if (x && !y) {
                    return 'vertical';
                }
                else if (y && !x) {
                    return 'horizontal';
                }
            }
        // falls through
        case LINE:
        case TICK: {
            const xIsMeasure = isUnbinnedQuantitativeFieldOrDatumDef(x);
            const yIsMeasure = isUnbinnedQuantitativeFieldOrDatumDef(y);
            if (specifiedOrient) {
                return specifiedOrient;
            }
            else if (xIsMeasure && !yIsMeasure) {
                // Tick is opposite to bar, line, area
                return mark !== 'tick' ? 'horizontal' : 'vertical';
            }
            else if (!xIsMeasure && yIsMeasure) {
                // Tick is opposite to bar, line, area
                return mark !== 'tick' ? 'vertical' : 'horizontal';
            }
            else if (xIsMeasure && yIsMeasure) {
                return 'vertical';
            }
            else {
                const xIsTemporal = isTypedFieldDef(x) && x.type === TEMPORAL;
                const yIsTemporal = isTypedFieldDef(y) && y.type === TEMPORAL;
                // x: T, y: N --> vertical tick
                if (xIsTemporal && !yIsTemporal) {
                    return 'vertical';
                }
                else if (!xIsTemporal && yIsTemporal) {
                    return 'horizontal';
                }
            }
            return undefined;
        }
    }
    return 'vertical';
}
//# sourceMappingURL=init.js.map
;// ../../node_modules/vega-lite/build/src/normalize/pathoverlay.js







function dropLineAndPoint(markDef) {
    const { point: _point, line: _line, ...mark } = markDef;
    return util_keys(mark).length > 1 ? mark : mark.type;
}
function dropLineAndPointFromConfig(config) {
    for (const mark of ['line', 'area', 'rule', 'trail']) {
        if (config[mark]) {
            config = {
                ...config,
                // TODO: remove as any
                [mark]: omit(config[mark], ['point', 'line'])
            };
        }
    }
    return config;
}
function getPointOverlay(markDef, markConfig = {}, encoding) {
    if (markDef.point === 'transparent') {
        return { opacity: 0 };
    }
    else if (markDef.point) {
        // truthy : true or object
        return vega_util_module_isObject(markDef.point) ? markDef.point : {};
    }
    else if (markDef.point !== undefined) {
        // false or null
        return null;
    }
    else {
        // undefined (not disabled)
        if (markConfig.point || encoding.shape) {
            // enable point overlay if config[mark].point is truthy or if encoding.shape is provided
            return vega_util_module_isObject(markConfig.point) ? markConfig.point : {};
        }
        // markDef.point is defined as falsy
        return undefined;
    }
}
function getLineOverlay(markDef, markConfig = {}) {
    if (markDef.line) {
        // true or object
        return markDef.line === true ? {} : markDef.line;
    }
    else if (markDef.line !== undefined) {
        // false or null
        return null;
    }
    else {
        // undefined (not disabled)
        if (markConfig.line) {
            // enable line overlay if config[mark].line is truthy
            return markConfig.line === true ? {} : markConfig.line;
        }
        // markDef.point is defined as falsy
        return undefined;
    }
}
class PathOverlayNormalizer {
    constructor() {
        this.name = 'path-overlay';
    }
    hasMatchingType(spec, config) {
        if (isUnitSpec(spec)) {
            const { mark, encoding } = spec;
            const markDef = isMarkDef(mark) ? mark : { type: mark };
            switch (markDef.type) {
                case 'line':
                case 'rule':
                case 'trail':
                    return !!getPointOverlay(markDef, config[markDef.type], encoding);
                case 'area':
                    return (
                    // false / null are also included as we want to remove the properties
                    !!getPointOverlay(markDef, config[markDef.type], encoding) ||
                        !!getLineOverlay(markDef, config[markDef.type]));
            }
        }
        return false;
    }
    run(spec, normParams, normalize) {
        const { config } = normParams;
        const { params, projection, mark, name, encoding: e, ...outerSpec } = spec;
        // Need to call normalizeEncoding because we need the inferred types to correctly determine stack
        const encoding = normalizeEncoding(e, config);
        const markDef = isMarkDef(mark) ? mark : { type: mark };
        const pointOverlay = getPointOverlay(markDef, config[markDef.type], encoding);
        const lineOverlay = markDef.type === 'area' && getLineOverlay(markDef, config[markDef.type]);
        const layer = [
            {
                name,
                ...(params ? { params } : {}),
                mark: dropLineAndPoint({
                    // TODO: extract this 0.7 to be shared with default opacity for point/tick/...
                    ...(markDef.type === 'area' && markDef.opacity === undefined && markDef.fillOpacity === undefined
                        ? { opacity: 0.7 }
                        : {}),
                    ...markDef
                }),
                // drop shape from encoding as this might be used to trigger point overlay
                encoding: omit(encoding, ['shape'])
            }
        ];
        // FIXME: determine rules for applying selections.
        // Need to copy stack config to overlayed layer
        // FIXME: normalizer shouldn't call `initMarkdef`, a method from an init phase.
        const stackProps = stack(initMarkdef(markDef, encoding, config), encoding);
        let overlayEncoding = encoding;
        if (stackProps) {
            const { fieldChannel: stackFieldChannel, offset } = stackProps;
            overlayEncoding = {
                ...encoding,
                [stackFieldChannel]: {
                    ...encoding[stackFieldChannel],
                    ...(offset ? { stack: offset } : {})
                }
            };
        }
        // overlay line layer should be on the edge of area but passing y2/x2 makes
        // it as "rule" mark so that it draws unwanted vertical/horizontal lines.
        // point overlay also should not have y2/x2 as it does not support.
        overlayEncoding = omit(overlayEncoding, ['y2', 'x2']);
        if (lineOverlay) {
            layer.push({
                ...(projection ? { projection } : {}),
                mark: {
                    type: 'line',
                    ...util_pick(markDef, ['clip', 'interpolate', 'tension', 'tooltip']),
                    ...lineOverlay
                },
                encoding: overlayEncoding
            });
        }
        if (pointOverlay) {
            layer.push({
                ...(projection ? { projection } : {}),
                mark: {
                    type: 'point',
                    opacity: 1,
                    filled: true,
                    ...util_pick(markDef, ['clip', 'tooltip']),
                    ...pointOverlay
                },
                encoding: overlayEncoding
            });
        }
        return normalize({
            ...outerSpec,
            layer
        }, {
            ...normParams,
            config: dropLineAndPointFromConfig(config)
        });
    }
}
//# sourceMappingURL=pathoverlay.js.map
;// ../../node_modules/vega-lite/build/src/normalize/repeater.js






function replaceRepeaterInFacet(facet, repeater) {
    if (!repeater) {
        return facet;
    }
    if (isFacetMapping(facet)) {
        return replaceRepeaterInMapping(facet, repeater);
    }
    return replaceRepeaterInFieldDef(facet, repeater);
}
function replaceRepeaterInEncoding(encoding, repeater) {
    if (!repeater) {
        return encoding;
    }
    return replaceRepeaterInMapping(encoding, repeater);
}
/**
 * Replaces repeated value and returns if the repeated value is valid.
 */
function replaceRepeatInProp(prop, o, repeater) {
    const val = o[prop];
    if (isRepeatRef(val)) {
        if (val.repeat in repeater) {
            return { ...o, [prop]: repeater[val.repeat] };
        }
        else {
            log_warn(noSuchRepeatedValue(val.repeat));
            return undefined;
        }
    }
    return o;
}
/**
 * Replace repeater values in a field def with the concrete field name.
 */
function replaceRepeaterInFieldDef(fieldDef, repeater) {
    fieldDef = replaceRepeatInProp('field', fieldDef, repeater);
    if (fieldDef === undefined) {
        // the field def should be ignored
        return undefined;
    }
    else if (fieldDef === null) {
        return null;
    }
    if (isSortableFieldDef(fieldDef) && isSortField(fieldDef.sort)) {
        const sort = replaceRepeatInProp('field', fieldDef.sort, repeater);
        fieldDef = {
            ...fieldDef,
            ...(sort ? { sort } : {})
        };
    }
    return fieldDef;
}
function replaceRepeaterInFieldOrDatumDef(def, repeater) {
    if (isFieldDef(def)) {
        return replaceRepeaterInFieldDef(def, repeater);
    }
    else {
        const datumDef = replaceRepeatInProp('datum', def, repeater);
        if (datumDef !== def && !datumDef.type) {
            datumDef.type = 'nominal';
        }
        return datumDef;
    }
}
function replaceRepeaterInChannelDef(channelDef, repeater) {
    if (isFieldOrDatumDef(channelDef)) {
        const fd = replaceRepeaterInFieldOrDatumDef(channelDef, repeater);
        if (fd) {
            return fd;
        }
        else if (isConditionalDef(channelDef)) {
            return { condition: channelDef.condition };
        }
    }
    else {
        if (hasConditionalFieldOrDatumDef(channelDef)) {
            const fd = replaceRepeaterInFieldOrDatumDef(channelDef.condition, repeater);
            if (fd) {
                return {
                    ...channelDef,
                    condition: fd
                };
            }
            else {
                const { condition, ...channelDefWithoutCondition } = channelDef;
                return channelDefWithoutCondition;
            }
        }
        return channelDef;
    }
    return undefined;
}
function replaceRepeaterInMapping(mapping, repeater) {
    const out = {};
    for (const channel in mapping) {
        if (util_hasProperty(mapping, channel)) {
            const channelDef = mapping[channel];
            if (vega_util_module_isArray(channelDef)) {
                // array cannot have condition
                out[channel] = channelDef // somehow we need to cast it here
                    .map(cd => replaceRepeaterInChannelDef(cd, repeater))
                    .filter(cd => cd);
            }
            else {
                const cd = replaceRepeaterInChannelDef(channelDef, repeater);
                if (cd !== undefined) {
                    out[channel] = cd;
                }
            }
        }
    }
    return out;
}
//# sourceMappingURL=repeater.js.map
;// ../../node_modules/vega-lite/build/src/normalize/ruleforrangedline.js







class RuleForRangedLineNormalizer {
    constructor() {
        this.name = 'RuleForRangedLine';
    }
    hasMatchingType(spec) {
        if (isUnitSpec(spec)) {
            const { encoding, mark } = spec;
            if (mark === 'line' || (isMarkDef(mark) && mark.type === 'line')) {
                for (const channel of SECONDARY_RANGE_CHANNEL) {
                    const mainChannel = getMainRangeChannel(channel);
                    const mainChannelDef = encoding[mainChannel];
                    if (encoding[channel]) {
                        if ((isFieldDef(mainChannelDef) && !isBinned(mainChannelDef.bin)) || isDatumDef(mainChannelDef)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
    run(spec, params, normalize) {
        const { encoding, mark } = spec;
        log_warn(lineWithRange(!!encoding.x2, !!encoding.y2));
        return normalize({
            ...spec,
            mark: vega_util_module_isObject(mark) ? { ...mark, type: 'rule' } : 'rule'
        }, params);
    }
}
//# sourceMappingURL=ruleforrangedline.js.map
;// ../../node_modules/vega-lite/build/src/normalize/core.js

















class CoreNormalizer extends SpecMapper {
    constructor() {
        super(...arguments);
        this.nonFacetUnitNormalizers = [
            boxPlotNormalizer,
            errorBarNormalizer,
            errorBandNormalizer,
            new PathOverlayNormalizer(),
            new RuleForRangedLineNormalizer()
        ];
    }
    map(spec, params) {
        // Special handling for a faceted unit spec as it can return a facet spec, not just a layer or unit spec like a normal unit spec.
        if (isUnitSpec(spec)) {
            const hasRow = channelHasField(spec.encoding, ROW);
            const hasColumn = channelHasField(spec.encoding, COLUMN);
            const hasFacet = channelHasField(spec.encoding, FACET);
            if (hasRow || hasColumn || hasFacet) {
                return this.mapFacetedUnit(spec, params);
            }
        }
        return super.map(spec, params);
    }
    // This is for normalizing non-facet unit
    mapUnit(spec, params) {
        const { parentEncoding, parentProjection } = params;
        const encoding = replaceRepeaterInEncoding(spec.encoding, params.repeater);
        const specWithReplacedEncoding = {
            ...spec,
            ...(spec.name ? { name: [params.repeaterPrefix, spec.name].filter(n => n).join('_') } : {}),
            ...(encoding ? { encoding } : {})
        };
        if (parentEncoding || parentProjection) {
            return this.mapUnitWithParentEncodingOrProjection(specWithReplacedEncoding, params);
        }
        const normalizeLayerOrUnit = this.mapLayerOrUnit.bind(this);
        for (const unitNormalizer of this.nonFacetUnitNormalizers) {
            if (unitNormalizer.hasMatchingType(specWithReplacedEncoding, params.config)) {
                return unitNormalizer.run(specWithReplacedEncoding, params, normalizeLayerOrUnit);
            }
        }
        return specWithReplacedEncoding;
    }
    mapRepeat(spec, params) {
        if (isLayerRepeatSpec(spec)) {
            return this.mapLayerRepeat(spec, params);
        }
        else {
            return this.mapNonLayerRepeat(spec, params);
        }
    }
    mapLayerRepeat(spec, params) {
        const { repeat, spec: childSpec, ...rest } = spec;
        const { row, column, layer } = repeat;
        const { repeater = {}, repeaterPrefix = '' } = params;
        if (row || column) {
            return this.mapRepeat({
                ...spec,
                repeat: {
                    ...(row ? { row } : {}),
                    ...(column ? { column } : {})
                },
                spec: {
                    repeat: { layer },
                    spec: childSpec
                }
            }, params);
        }
        else {
            return {
                ...rest,
                layer: layer.map(layerValue => {
                    const childRepeater = {
                        ...repeater,
                        layer: layerValue
                    };
                    const childName = `${(childSpec.name ? `${childSpec.name}_` : '') + repeaterPrefix}child__layer_${varName(layerValue)}`;
                    const child = this.mapLayerOrUnit(childSpec, { ...params, repeater: childRepeater, repeaterPrefix: childName });
                    child.name = childName;
                    return child;
                })
            };
        }
    }
    mapNonLayerRepeat(spec, params) {
        const { repeat, spec: childSpec, data, ...remainingProperties } = spec;
        if (!vega_util_module_isArray(repeat) && spec.columns) {
            // is repeat with row/column
            spec = omit(spec, ['columns']);
            log_warn(columnsNotSupportByRowCol('repeat'));
        }
        const concat = [];
        const { repeater = {}, repeaterPrefix = '' } = params;
        const row = (!vega_util_module_isArray(repeat) && repeat.row) || [repeater ? repeater.row : null];
        const column = (!vega_util_module_isArray(repeat) && repeat.column) || [repeater ? repeater.column : null];
        const repeatValues = (vega_util_module_isArray(repeat) && repeat) || [repeater ? repeater.repeat : null];
        // cross product
        for (const repeatValue of repeatValues) {
            for (const rowValue of row) {
                for (const columnValue of column) {
                    const childRepeater = {
                        repeat: repeatValue,
                        row: rowValue,
                        column: columnValue,
                        layer: repeater.layer
                    };
                    const childName = (childSpec.name ? `${childSpec.name}_` : '') +
                        repeaterPrefix +
                        'child__' +
                        (vega_util_module_isArray(repeat)
                            ? `${varName(repeatValue)}`
                            : (repeat.row ? `row_${varName(rowValue)}` : '') +
                                (repeat.column ? `column_${varName(columnValue)}` : ''));
                    const child = this.map(childSpec, { ...params, repeater: childRepeater, repeaterPrefix: childName });
                    child.name = childName;
                    // we move data up
                    concat.push(omit(child, ['data']));
                }
            }
        }
        const columns = vega_util_module_isArray(repeat) ? spec.columns : repeat.column ? repeat.column.length : 1;
        return {
            data: childSpec.data ?? data, // data from child spec should have precedence
            align: 'all',
            ...remainingProperties,
            columns,
            concat
        };
    }
    mapFacet(spec, params) {
        const { facet } = spec;
        if (isFacetMapping(facet) && spec.columns) {
            // is facet with row/column
            spec = omit(spec, ['columns']);
            log_warn(columnsNotSupportByRowCol('facet'));
        }
        return super.mapFacet(spec, params);
    }
    mapUnitWithParentEncodingOrProjection(spec, params) {
        const { encoding, projection } = spec;
        const { parentEncoding, parentProjection, config } = params;
        const mergedProjection = mergeProjection({ parentProjection, projection });
        const mergedEncoding = mergeEncoding({
            parentEncoding,
            encoding: replaceRepeaterInEncoding(encoding, params.repeater)
        });
        return this.mapUnit({
            ...spec,
            ...(mergedProjection ? { projection: mergedProjection } : {}),
            ...(mergedEncoding ? { encoding: mergedEncoding } : {})
        }, { config });
    }
    mapFacetedUnit(spec, normParams) {
        // New encoding in the inside spec should not contain row / column
        // as row/column should be moved to facet
        const { row, column, facet, ...encoding } = spec.encoding;
        // Mark and encoding should be moved into the inner spec
        const { mark, width, projection, height, view, params, encoding: _, ...outerSpec } = spec;
        const { facetMapping, layout } = this.getFacetMappingAndLayout({ row, column, facet }, normParams);
        const newEncoding = replaceRepeaterInEncoding(encoding, normParams.repeater);
        return this.mapFacet({
            ...outerSpec,
            ...layout,
            // row / column has higher precedence than facet
            facet: facetMapping,
            spec: {
                ...(width ? { width } : {}),
                ...(height ? { height } : {}),
                ...(view ? { view } : {}),
                ...(projection ? { projection } : {}),
                mark,
                encoding: newEncoding,
                ...(params ? { params } : {})
            }
        }, normParams);
    }
    getFacetMappingAndLayout(facets, params) {
        const { row, column, facet } = facets;
        if (row || column) {
            if (facet) {
                log_warn(facetChannelDropped([...(row ? [ROW] : []), ...(column ? [COLUMN] : [])]));
            }
            const facetMapping = {};
            const layout = {};
            for (const channel of [ROW, COLUMN]) {
                const def = facets[channel];
                if (def) {
                    const { align, center, spacing, columns, ...defWithoutLayout } = def;
                    facetMapping[channel] = defWithoutLayout;
                    for (const prop of ['align', 'center', 'spacing']) {
                        if (def[prop] !== undefined) {
                            layout[prop] ?? (layout[prop] = {});
                            layout[prop][channel] = def[prop];
                        }
                    }
                }
            }
            return { facetMapping, layout };
        }
        else {
            const { align, center, spacing, columns, ...facetMapping } = facet;
            return {
                facetMapping: replaceRepeaterInFacet(facetMapping, params.repeater),
                layout: {
                    ...(align ? { align } : {}),
                    ...(center ? { center } : {}),
                    ...(spacing ? { spacing } : {}),
                    ...(columns ? { columns } : {})
                }
            };
        }
    }
    mapLayer(spec, { parentEncoding, parentProjection, ...otherParams }) {
        // Special handling for extended layer spec
        const { encoding, projection, ...rest } = spec;
        const params = {
            ...otherParams,
            parentEncoding: mergeEncoding({ parentEncoding, encoding, layer: true }),
            parentProjection: mergeProjection({ parentProjection, projection })
        };
        return super.mapLayer({
            ...rest,
            ...(spec.name ? { name: [params.repeaterPrefix, spec.name].filter(n => n).join('_') } : {})
        }, params);
    }
}
function mergeEncoding({ parentEncoding, encoding = {}, layer }) {
    let merged = {};
    if (parentEncoding) {
        const channels = new Set([...util_keys(parentEncoding), ...util_keys(encoding)]);
        for (const channel of channels) {
            const channelDef = encoding[channel];
            const parentChannelDef = parentEncoding[channel];
            if (isFieldOrDatumDef(channelDef)) {
                // Field/Datum Def can inherit properties from its parent
                // Note that parentChannelDef doesn't have to be a field/datum def if the channelDef is already one.
                const mergedChannelDef = {
                    ...parentChannelDef,
                    ...channelDef
                };
                merged[channel] = mergedChannelDef;
            }
            else if (hasConditionalFieldOrDatumDef(channelDef)) {
                merged[channel] = {
                    ...channelDef,
                    condition: {
                        ...parentChannelDef,
                        ...channelDef.condition
                    }
                };
            }
            else if (channelDef || channelDef === null) {
                merged[channel] = channelDef;
            }
            else if (layer ||
                isValueDef(parentChannelDef) ||
                isSignalRef(parentChannelDef) ||
                isFieldOrDatumDef(parentChannelDef) ||
                vega_util_module_isArray(parentChannelDef)) {
                merged[channel] = parentChannelDef;
            }
        }
    }
    else {
        merged = encoding;
    }
    return !merged || isEmpty(merged) ? undefined : merged;
}
function mergeProjection(opt) {
    const { parentProjection, projection } = opt;
    if (parentProjection && projection) {
        log_warn(projectionOverridden({ parentProjection, projection }));
    }
    return projection ?? parentProjection;
}
//# sourceMappingURL=core.js.map
;// ../../node_modules/vega-lite/build/src/transform.js



function isFilter(t) {
    return util_hasProperty(t, 'filter');
}
function isImputeSequence(t) {
    return util_hasProperty(t, 'stop');
}
function isLookup(t) {
    return util_hasProperty(t, 'lookup');
}
function isLookupData(from) {
    return util_hasProperty(from, 'data');
}
function isLookupSelection(from) {
    return util_hasProperty(from, 'param');
}
function isPivot(t) {
    return util_hasProperty(t, 'pivot');
}
function isDensity(t) {
    return util_hasProperty(t, 'density');
}
function transform_isQuantile(t) {
    return util_hasProperty(t, 'quantile');
}
function isRegression(t) {
    return util_hasProperty(t, 'regression');
}
function isLoess(t) {
    return util_hasProperty(t, 'loess');
}
function isSample(t) {
    return util_hasProperty(t, 'sample');
}
function isWindow(t) {
    return util_hasProperty(t, 'window');
}
function isJoinAggregate(t) {
    return util_hasProperty(t, 'joinaggregate');
}
function isFlatten(t) {
    return util_hasProperty(t, 'flatten');
}
function isCalculate(t) {
    return util_hasProperty(t, 'calculate');
}
function isBin(t) {
    return util_hasProperty(t, 'bin');
}
function isImpute(t) {
    return util_hasProperty(t, 'impute');
}
function isTimeUnit(t) {
    return util_hasProperty(t, 'timeUnit');
}
function transform_isAggregate(t) {
    return util_hasProperty(t, 'aggregate');
}
function isStack(t) {
    return util_hasProperty(t, 'stack');
}
function isFold(t) {
    return util_hasProperty(t, 'fold');
}
function isExtent(t) {
    return util_hasProperty(t, 'extent') && !util_hasProperty(t, 'density') && !util_hasProperty(t, 'regression');
}
function normalizeTransform(transform) {
    return transform.map(t => {
        if (isFilter(t)) {
            return {
                filter: normalizeLogicalComposition(t.filter, normalizePredicate)
            };
        }
        return t;
    });
}
//# sourceMappingURL=transform.js.map
;// ../../node_modules/vega-lite/build/src/normalize/selectioncompat.js







class SelectionCompatibilityNormalizer extends SpecMapper {
    map(spec, normParams) {
        normParams.emptySelections ?? (normParams.emptySelections = {});
        normParams.selectionPredicates ?? (normParams.selectionPredicates = {});
        spec = normalizeTransforms(spec, normParams);
        return super.map(spec, normParams);
    }
    mapLayerOrUnit(spec, normParams) {
        spec = normalizeTransforms(spec, normParams);
        if (spec.encoding) {
            const encoding = {};
            for (const [channel, enc] of util_entries(spec.encoding)) {
                encoding[channel] = normalizeChannelDef(enc, normParams);
            }
            spec = { ...spec, encoding };
        }
        return super.mapLayerOrUnit(spec, normParams);
    }
    mapUnit(spec, normParams) {
        const { selection, ...rest } = spec;
        if (selection) {
            return {
                ...rest,
                params: util_entries(selection).map(([name, selDef]) => {
                    const { init: value, bind, empty, ...select } = selDef;
                    if (select.type === 'single') {
                        select.type = 'point';
                        select.toggle = false;
                    }
                    else if (select.type === 'multi') {
                        select.type = 'point';
                    }
                    // Propagate emptiness forwards and backwards
                    normParams.emptySelections[name] = empty !== 'none';
                    for (const pred of vals(normParams.selectionPredicates[name] ?? {})) {
                        pred.empty = empty !== 'none';
                    }
                    return { name, value, select, bind };
                })
            };
        }
        return spec;
    }
}
function normalizeTransforms(spec, normParams) {
    const { transform: tx, ...rest } = spec;
    if (tx) {
        const transform = tx.map((t) => {
            if (isFilter(t)) {
                return { filter: selectioncompat_normalizePredicate(t, normParams) };
            }
            else if (isBin(t) && isBinParams(t.bin)) {
                return {
                    ...t,
                    bin: normalizeBinExtent(t.bin)
                };
            }
            else if (isLookup(t)) {
                const { selection: param, ...from } = t.from;
                return param
                    ? {
                        ...t,
                        from: { param, ...from }
                    }
                    : t;
            }
            return t;
        });
        return { ...rest, transform };
    }
    return spec;
}
function normalizeChannelDef(obj, normParams) {
    const enc = duplicate(obj);
    if (isFieldDef(enc) && isBinParams(enc.bin)) {
        enc.bin = normalizeBinExtent(enc.bin);
    }
    if (isScaleFieldDef(enc) && enc.scale?.domain?.selection) {
        const { selection: param, ...domain } = enc.scale.domain;
        enc.scale.domain = { ...domain, ...(param ? { param } : {}) };
    }
    if (isConditionalDef(enc)) {
        if (vega_util_module_isArray(enc.condition)) {
            enc.condition = enc.condition.map((c) => {
                const { selection, param, test, ...cond } = c;
                return param ? c : { ...cond, test: selectioncompat_normalizePredicate(c, normParams) };
            });
        }
        else {
            const { selection, param, test, ...cond } = normalizeChannelDef(enc.condition, normParams);
            enc.condition = param
                ? enc.condition
                : {
                    ...cond,
                    test: selectioncompat_normalizePredicate(enc.condition, normParams)
                };
        }
    }
    return enc;
}
function normalizeBinExtent(bin) {
    const ext = bin.extent;
    if (ext?.selection) {
        const { selection: param, ...rest } = ext;
        return { ...bin, extent: { ...rest, param } };
    }
    return bin;
}
function selectioncompat_normalizePredicate(op, normParams) {
    // Normalize old compositions of selection names (e.g., selection: {and: ["one", "two"]})
    const normalizeSelectionComposition = (o) => {
        return normalizeLogicalComposition(o, param => {
            var _a;
            const empty = normParams.emptySelections[param] ?? true;
            const pred = { param, empty };
            (_a = normParams.selectionPredicates)[param] ?? (_a[param] = []);
            normParams.selectionPredicates[param].push(pred);
            return pred;
        });
    };
    return op.selection
        ? normalizeSelectionComposition(op.selection)
        : normalizeLogicalComposition(op.test || op.filter, o => o.selection ? normalizeSelectionComposition(o.selection) : o);
}
//# sourceMappingURL=selectioncompat.js.map
;// ../../node_modules/vega-lite/build/src/normalize/toplevelselection.js




class TopLevelSelectionsNormalizer extends SpecMapper {
    map(spec, normParams) {
        const selections = normParams.selections ?? [];
        if (spec.params && !isUnitSpec(spec)) {
            const params = [];
            for (const param of spec.params) {
                if (isSelectionParameter(param)) {
                    selections.push(param);
                }
                else {
                    params.push(param);
                }
            }
            spec.params = params;
        }
        normParams.selections = selections;
        return super.map(spec, normParams);
    }
    mapUnit(spec, normParams) {
        const selections = normParams.selections;
        if (!selections || !selections.length)
            return spec;
        const path = (normParams.path ?? []).concat(spec.name);
        const params = [];
        for (const selection of selections) {
            // By default, apply selections to all unit views.
            if (!selection.views || !selection.views.length) {
                params.push(selection);
            }
            else {
                for (const view of selection.views) {
                    // view is either a specific unit name, or a partial path through the spec tree.
                    if ((vega_util_module_isString(view) && (view === spec.name || path.includes(view))) ||
                        (vega_util_module_isArray(view) &&
                            // logic for backwards compatibility with view paths before we had unique names
                            // @ts-ignore
                            view.map(v => path.indexOf(v)).every((v, i, arr) => v !== -1 && (i === 0 || v > arr[i - 1])))) {
                        params.push(selection);
                    }
                }
            }
        }
        if (params.length)
            spec.params = params;
        return spec;
    }
}
for (const method of ['mapFacet', 'mapRepeat', 'mapHConcat', 'mapVConcat', 'mapLayer']) {
    const proto = TopLevelSelectionsNormalizer.prototype[method];
    TopLevelSelectionsNormalizer.prototype[method] = function (spec, params) {
        return proto.call(this, spec, addSpecNameToParams(spec, params));
    };
}
function addSpecNameToParams(spec, params) {
    return spec.name
        ? {
            ...params,
            path: (params.path ?? []).concat(spec.name)
        }
        : params;
}
//# sourceMappingURL=toplevelselection.js.map
;// ../../node_modules/vega-lite/build/src/normalize/index.js








function normalize_normalize(spec, config) {
    if (config === undefined) {
        config = initConfig(spec.config);
    }
    const normalizedSpec = normalizeGenericSpec(spec, config);
    const { width, height } = spec;
    const autosize = normalizeAutoSize(normalizedSpec, { width, height, autosize: spec.autosize }, config);
    return {
        ...normalizedSpec,
        ...(autosize ? { autosize } : {})
    };
}
const coreNormalizer = new CoreNormalizer();
const selectionCompatNormalizer = new SelectionCompatibilityNormalizer();
const topLevelSelectionNormalizer = new TopLevelSelectionsNormalizer();
/**
 * Decompose extended unit specs into composition of pure unit specs.
 * And push top-level selection definitions down to unit specs.
 */
function normalizeGenericSpec(spec, config = {}) {
    const normParams = { config };
    return topLevelSelectionNormalizer.map(coreNormalizer.map(selectionCompatNormalizer.map(spec, normParams), normParams), normParams);
}
function _normalizeAutoSize(autosize) {
    return vega_util_module_isString(autosize) ? { type: autosize } : (autosize ?? {});
}
/**
 * Normalize autosize and deal with width or height == "container".
 */
function normalizeAutoSize(spec, sizeInfo, config) {
    let { width, height } = sizeInfo;
    const isFitCompatible = isUnitSpec(spec) || isLayerSpec(spec);
    const autosizeDefault = {};
    if (!isFitCompatible) {
        // If spec is not compatible with autosize == "fit", discard width/height == container
        if (width == 'container') {
            log_warn(containerSizeNonSingle('width'));
            width = undefined;
        }
        if (height == 'container') {
            log_warn(containerSizeNonSingle('height'));
            height = undefined;
        }
    }
    else {
        // Default autosize parameters to fit when width/height is "container"
        if (width == 'container' && height == 'container') {
            autosizeDefault.type = 'fit';
            autosizeDefault.contains = 'padding';
        }
        else if (width == 'container') {
            autosizeDefault.type = 'fit-x';
            autosizeDefault.contains = 'padding';
        }
        else if (height == 'container') {
            autosizeDefault.type = 'fit-y';
            autosizeDefault.contains = 'padding';
        }
    }
    const autosize = {
        type: 'pad',
        ...autosizeDefault,
        ...(config ? _normalizeAutoSize(config.autosize) : {}),
        ..._normalizeAutoSize(spec.autosize)
    };
    if (autosize.type === 'fit' && !isFitCompatible) {
        log_warn(FIT_NON_SINGLE);
        autosize.type = 'pad';
    }
    if (width == 'container' && !(autosize.type == 'fit' || autosize.type == 'fit-x')) {
        log_warn(containerSizeNotCompatibleWithAutosize('width'));
    }
    if (height == 'container' && !(autosize.type == 'fit' || autosize.type == 'fit-y')) {
        log_warn(containerSizeNotCompatibleWithAutosize('height'));
    }
    // Delete autosize property if it's Vega's default
    if (util_deepEqual(autosize, { type: 'pad' })) {
        return undefined;
    }
    return autosize;
}
//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/spec/toplevel.js


function isFitType(autoSizeType) {
    return ['fit', 'fit-x', 'fit-y'].includes(autoSizeType);
}
function getFitType(sizeType) {
    return sizeType ? `fit-${getPositionScaleChannel(sizeType)}` : 'fit';
}
const TOP_LEVEL_PROPERTIES = [
    'background',
    'padding'
    // We do not include "autosize" here as it is supported by only unit and layer specs and thus need to be normalized
];
function extractTopLevelProperties(t, includeParams) {
    const o = {};
    for (const p of TOP_LEVEL_PROPERTIES) {
        if (t && t[p] !== undefined) {
            o[p] = signalRefOrValue(t[p]);
        }
    }
    if (includeParams) {
        o.params = t.params;
    }
    return o;
}
//# sourceMappingURL=toplevel.js.map
;// ../../node_modules/vega-lite/build/src/compile/split.js


/**
 * Generic class for storing properties that are explicitly specified
 * and implicitly determined by the compiler.
 * This is important for scale/axis/legend merging as
 * we want to prioritize properties that users explicitly specified.
 */
// eslint-disable-next-line @typescript-eslint/ban-types
class Split {
    constructor(explicit = {}, implicit = {}) {
        this.explicit = explicit;
        this.implicit = implicit;
    }
    clone() {
        return new Split(duplicate(this.explicit), duplicate(this.implicit));
    }
    combine() {
        return {
            ...this.explicit, // Explicit properties comes first
            ...this.implicit
        };
    }
    get(key) {
        // Explicit has higher precedence
        return getFirstDefined(this.explicit[key], this.implicit[key]);
    }
    getWithExplicit(key) {
        // Explicit has higher precedence
        if (this.explicit[key] !== undefined) {
            return { explicit: true, value: this.explicit[key] };
        }
        else if (this.implicit[key] !== undefined) {
            return { explicit: false, value: this.implicit[key] };
        }
        return { explicit: false, value: undefined };
    }
    setWithExplicit(key, { value, explicit }) {
        if (value !== undefined) {
            this.set(key, value, explicit);
        }
    }
    set(key, value, explicit) {
        delete this[explicit ? 'implicit' : 'explicit'][key];
        this[explicit ? 'explicit' : 'implicit'][key] = value;
        return this;
    }
    copyKeyFromSplit(key, { explicit, implicit }) {
        // Explicit has higher precedence
        if (explicit[key] !== undefined) {
            this.set(key, explicit[key], true);
        }
        else if (implicit[key] !== undefined) {
            this.set(key, implicit[key], false);
        }
    }
    copyKeyFromObject(key, s) {
        // Explicit has higher precedence
        if (s[key] !== undefined) {
            this.set(key, s[key], true);
        }
    }
    /**
     * Merge split object into this split object. Properties from the other split
     * overwrite properties from this split.
     */
    copyAll(other) {
        for (const key of util_keys(other.combine())) {
            const val = other.getWithExplicit(key);
            this.setWithExplicit(key, val);
        }
    }
}
function makeExplicit(value) {
    return {
        explicit: true,
        value
    };
}
function makeImplicit(value) {
    return {
        explicit: false,
        value
    };
}
function tieBreakByComparing(compare) {
    return (v1, v2, property, propertyOf) => {
        const diff = compare(v1.value, v2.value);
        if (diff > 0) {
            return v1;
        }
        else if (diff < 0) {
            return v2;
        }
        return defaultTieBreaker(v1, v2, property, propertyOf);
    };
}
function defaultTieBreaker(v1, v2, property, propertyOf) {
    if (v1.explicit && v2.explicit) {
        log_warn(mergeConflictingProperty(property, propertyOf, v1.value, v2.value));
    }
    // If equal score, prefer v1.
    return v1;
}
function mergeValuesWithExplicit(v1, v2, property, propertyOf, tieBreaker = defaultTieBreaker) {
    if (v1 === undefined || v1.value === undefined) {
        // For first run
        return v2;
    }
    if (v1.explicit && !v2.explicit) {
        return v1;
    }
    else if (v2.explicit && !v1.explicit) {
        return v2;
    }
    else if (util_deepEqual(v1.value, v2.value)) {
        return v1;
    }
    else {
        return tieBreaker(v1, v2, property, propertyOf);
    }
}
//# sourceMappingURL=split.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/index.js

/**
 * Class to track interesting properties (see https://15721.courses.cs.cmu.edu/spring2016/papers/graefe-ieee1995.pdf)
 * about how fields have been parsed or whether they have been derived in a transform. We use this to not parse the
 * same field again (or differently).
 */
class AncestorParse extends Split {
    constructor(explicit = {}, implicit = {}, parseNothing = false) {
        super(explicit, implicit);
        this.explicit = explicit;
        this.implicit = implicit;
        this.parseNothing = parseNothing;
    }
    clone() {
        const clone = super.clone();
        clone.parseNothing = this.parseNothing;
        return clone;
    }
}
//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/data.js

function isUrlData(data) {
    return util_hasProperty(data, 'url');
}
function isInlineData(data) {
    return util_hasProperty(data, 'values');
}
function isNamedData(data) {
    return util_hasProperty(data, 'name') && !isUrlData(data) && !isInlineData(data) && !isGenerator(data);
}
function isGenerator(data) {
    return data && (isSequenceGenerator(data) || isSphereGenerator(data) || isGraticuleGenerator(data));
}
function isSequenceGenerator(data) {
    return util_hasProperty(data, 'sequence');
}
function isSphereGenerator(data) {
    return util_hasProperty(data, 'sphere');
}
function isGraticuleGenerator(data) {
    return util_hasProperty(data, 'graticule');
}
var DataSourceType;
(function (DataSourceType) {
    DataSourceType[DataSourceType["Raw"] = 0] = "Raw";
    /** Main data source for marks */
    DataSourceType[DataSourceType["Main"] = 1] = "Main";
    DataSourceType[DataSourceType["Row"] = 2] = "Row";
    DataSourceType[DataSourceType["Column"] = 3] = "Column";
    DataSourceType[DataSourceType["Lookup"] = 4] = "Lookup";
    /** Pre-filter-invalid data source for scale domains */
    DataSourceType[DataSourceType["PreFilterInvalid"] = 5] = "PreFilterInvalid";
    /** Post-filter-invalid data source for scale domains */
    DataSourceType[DataSourceType["PostFilterInvalid"] = 6] = "PostFilterInvalid";
})(DataSourceType || (DataSourceType = {}));
//# sourceMappingURL=data.js.map
;// ../../node_modules/vega-lite/build/src/compile/invalid/datasources.js


function getDataSourcesForHandlingInvalidValues({ invalid, isPath }) {
    const normalizedInvalid = normalizeInvalidDataMode(invalid, { isPath });
    switch (normalizedInvalid) {
        case 'filter':
            // Both marks and scales use post-filter data
            return {
                marks: 'exclude-invalid-values',
                scales: 'exclude-invalid-values'
            };
        case 'break-paths-show-domains':
            return {
                // Path-based marks use pre-filter data so we know to skip these invalid points in the path.
                // For non-path based marks, we skip by not showing them at all.
                marks: isPath ? 'include-invalid-values' : 'exclude-invalid-values',
                scales: 'include-invalid-values'
            };
        case 'break-paths-filter-domains':
            // For path marks, the marks will use unfiltered data (and skip points). But we need a separate data sources to feed the domain.
            // For non-path marks, we can use the filtered data for both marks and scales.
            return {
                marks: isPath ? 'include-invalid-values' : 'exclude-invalid-values',
                // Unlike 'break-paths-show-domains', 'break-paths-filter-domains' uses post-filter data to feed scale.
                scales: 'exclude-invalid-values'
            };
        case 'show':
            return {
                marks: 'include-invalid-values',
                scales: 'include-invalid-values'
            };
    }
}
function getScaleDataSourceForHandlingInvalidValues(props) {
    const { marks, scales } = getDataSourcesForHandlingInvalidValues(props);
    if (marks === scales) {
        // If both marks and scales use the same data, there is only the main data source.
        return DataSourceType.Main;
    }
    // If marks and scales use differetnt data, return the pre/post-filter data source accordingly.
    return scales === 'include-invalid-values' ? DataSourceType.PreFilterInvalid : DataSourceType.PostFilterInvalid;
}
//# sourceMappingURL=datasources.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/dataflow.js


/**
 * A node in the dataflow tree.
 */
class DataFlowNode {
    constructor(parent, debugName) {
        this.debugName = debugName;
        this._children = [];
        this._parent = null;
        if (parent) {
            this.parent = parent;
        }
    }
    /**
     * Clone this node with a deep copy but don't clone links to children or parents.
     */
    clone() {
        throw new Error('Cannot clone node');
    }
    get parent() {
        return this._parent;
    }
    /**
     * Set the parent of the node and also add this node to the parent's children.
     */
    set parent(parent) {
        this._parent = parent;
        if (parent) {
            parent.addChild(this);
        }
    }
    get children() {
        return this._children;
    }
    numChildren() {
        return this._children.length;
    }
    addChild(child, loc) {
        // do not add the same child twice
        if (this._children.includes(child)) {
            log_warn(ADD_SAME_CHILD_TWICE);
            return;
        }
        if (loc !== undefined) {
            this._children.splice(loc, 0, child);
        }
        else {
            this._children.push(child);
        }
    }
    removeChild(oldChild) {
        const loc = this._children.indexOf(oldChild);
        this._children.splice(loc, 1);
        return loc;
    }
    /**
     * Remove node from the dataflow.
     */
    remove() {
        let loc = this._parent.removeChild(this);
        for (const child of this._children) {
            // do not use the set method because we want to insert at a particular location
            child._parent = this._parent;
            this._parent.addChild(child, loc++);
        }
    }
    /**
     * Insert another node as a parent of this node.
     */
    insertAsParentOf(other) {
        const parent = other.parent;
        parent.removeChild(this);
        this.parent = parent;
        other.parent = this;
    }
    swapWithParent() {
        const parent = this._parent;
        const newParent = parent.parent;
        // reconnect the children
        for (const child of this._children) {
            child.parent = parent;
        }
        // remove old links
        this._children = []; // equivalent to removing every child link one by one
        parent.removeChild(this);
        const loc = parent.parent.removeChild(parent);
        // swap two nodes but maintain order in children
        this._parent = newParent;
        newParent.addChild(this, loc);
        parent.parent = this;
    }
}
class OutputNode extends DataFlowNode {
    clone() {
        const cloneObj = new this.constructor();
        cloneObj.debugName = `clone_${this.debugName}`;
        cloneObj._source = this._source;
        cloneObj._name = `clone_${this._name}`;
        cloneObj.type = this.type;
        cloneObj.refCounts = this.refCounts;
        cloneObj.refCounts[cloneObj._name] = 0;
        return cloneObj;
    }
    /**
     * @param source The name of the source. Will change in assemble.
     * @param type The type of the output node.
     * @param refCounts A global ref counter map.
     */
    constructor(parent, source, type, refCounts) {
        super(parent, source);
        this.type = type;
        this.refCounts = refCounts;
        this._source = this._name = source;
        if (this.refCounts && !(this._name in this.refCounts)) {
            this.refCounts[this._name] = 0;
        }
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return new Set();
    }
    hash() {
        if (this._hash === undefined) {
            this._hash = `Output ${uniqueId()}`;
        }
        return this._hash;
    }
    /**
     * Request the datasource name and increase the ref counter.
     *
     * During the parsing phase, this will return the simple name such as 'main' or 'raw'.
     * It is crucial to request the name from an output node to mark it as a required node.
     * If nobody ever requests the name, this datasource will not be instantiated in the assemble phase.
     *
     * In the assemble phase, this will return the correct name.
     */
    getSource() {
        this.refCounts[this._name]++;
        return this._source;
    }
    isRequired() {
        return !!this.refCounts[this._name];
    }
    setSource(source) {
        this._source = source;
    }
}
//# sourceMappingURL=dataflow.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/timeunit.js







function isTimeUnitTransformComponent(timeUnitComponent) {
    return timeUnitComponent.as !== undefined;
}
function offsetAs(field) {
    return `${field}_end`;
}
class TimeUnitNode extends DataFlowNode {
    clone() {
        return new TimeUnitNode(null, duplicate(this.timeUnits));
    }
    constructor(parent, timeUnits) {
        super(parent);
        this.timeUnits = timeUnits;
    }
    static makeFromEncoding(parent, model) {
        const formula = model.reduceFieldDef((timeUnitComponent, fieldDef, channel) => {
            const { field, timeUnit } = fieldDef;
            if (timeUnit) {
                let component;
                if (isBinnedTimeUnit(timeUnit)) {
                    // For binned time unit, only produce end if the mark is a rect-based mark (rect, bar, image, arc), which needs "range".
                    if (isUnitModel(model)) {
                        const { mark, markDef, config } = model;
                        const bandPosition = getBandPosition({ fieldDef, markDef, config });
                        if (isRectBasedMark(mark) || !!bandPosition) {
                            component = {
                                timeUnit: normalizeTimeUnit(timeUnit),
                                field
                            };
                        }
                    }
                }
                else {
                    component = {
                        as: vgField(fieldDef, { forAs: true }),
                        field,
                        timeUnit
                    };
                }
                if (isUnitModel(model)) {
                    const { mark, markDef, config } = model;
                    const bandPosition = getBandPosition({ fieldDef, markDef, config });
                    if (isRectBasedMark(mark) && isXorY(channel) && bandPosition !== 0.5) {
                        component.rectBandPosition = bandPosition;
                    }
                }
                if (component) {
                    timeUnitComponent[util_hash(component)] = component;
                }
            }
            return timeUnitComponent;
        }, {});
        if (isEmpty(formula)) {
            return null;
        }
        return new TimeUnitNode(parent, formula);
    }
    static makeFromTransform(parent, t) {
        const { timeUnit, ...other } = { ...t };
        const normalizedTimeUnit = normalizeTimeUnit(timeUnit);
        const component = {
            ...other,
            timeUnit: normalizedTimeUnit
        };
        return new TimeUnitNode(parent, {
            [util_hash(component)]: component
        });
    }
    /**
     * Merge together TimeUnitNodes assigning the children of `other` to `this`
     * and removing `other`.
     */
    merge(other) {
        this.timeUnits = { ...this.timeUnits };
        // if the same hash happen twice, merge
        for (const key in other.timeUnits) {
            if (!this.timeUnits[key]) {
                // copy if it's not a duplicate
                this.timeUnits[key] = other.timeUnits[key];
            }
        }
        for (const child of other.children) {
            other.removeChild(child);
            child.parent = this;
        }
        other.remove();
    }
    /**
     * Remove time units coming from the other node.
     */
    removeFormulas(fields) {
        const newFormula = {};
        for (const [key, timeUnitComponent] of util_entries(this.timeUnits)) {
            const fieldAs = isTimeUnitTransformComponent(timeUnitComponent)
                ? timeUnitComponent.as
                : `${timeUnitComponent.field}_end`;
            if (!fields.has(fieldAs)) {
                newFormula[key] = timeUnitComponent;
            }
        }
        this.timeUnits = newFormula;
    }
    producedFields() {
        return new Set(vals(this.timeUnits).map(f => {
            return isTimeUnitTransformComponent(f) ? f.as : offsetAs(f.field);
        }));
    }
    dependentFields() {
        return new Set(vals(this.timeUnits).map(f => f.field));
    }
    hash() {
        return `TimeUnit ${util_hash(this.timeUnits)}`;
    }
    assemble() {
        const transforms = [];
        for (const f of vals(this.timeUnits)) {
            const { rectBandPosition } = f;
            const normalizedTimeUnit = normalizeTimeUnit(f.timeUnit);
            if (isTimeUnitTransformComponent(f)) {
                const { field, as } = f;
                const { unit, utc, ...params } = normalizedTimeUnit;
                const startEnd = [as, `${as}_end`];
                transforms.push({
                    field: replacePathInField(field),
                    type: 'timeunit',
                    ...(unit ? { units: getTimeUnitParts(unit) } : {}),
                    ...(utc ? { timezone: 'utc' } : {}),
                    ...params,
                    as: startEnd
                });
                transforms.push(...offsetedRectFormulas(startEnd, rectBandPosition, normalizedTimeUnit));
            }
            else if (f) {
                const { field: escapedField } = f;
                // since this is a expression, we want the unescaped field name
                const field = escapedField.replaceAll('\\.', '.');
                const expr = offsetExpr({ timeUnit: normalizedTimeUnit, field });
                const endAs = offsetAs(field);
                transforms.push({
                    type: 'formula',
                    expr,
                    as: endAs
                });
                transforms.push(...offsetedRectFormulas([field, endAs], rectBandPosition, normalizedTimeUnit));
            }
        }
        return transforms;
    }
}
const OFFSETTED_RECT_START_SUFFIX = 'offsetted_rect_start';
const OFFSETTED_RECT_END_SUFFIX = 'offsetted_rect_end';
function offsetExpr({ timeUnit, field, reverse }) {
    const { unit, utc } = timeUnit;
    const smallestUnit = getSmallestTimeUnitPart(unit);
    const { part, step } = getDateTimePartAndStep(smallestUnit, timeUnit.step);
    const offsetFn = utc ? 'utcOffset' : 'timeOffset';
    const expr = `${offsetFn}('${part}', ${accessWithDatumToUnescapedPath(field)}, ${reverse ? -step : step})`;
    return expr;
}
function offsetedRectFormulas([startField, endField], rectBandPosition, timeUnit) {
    if (rectBandPosition !== undefined && rectBandPosition !== 0.5) {
        const startExpr = accessWithDatumToUnescapedPath(startField);
        const endExpr = accessWithDatumToUnescapedPath(endField);
        return [
            {
                type: 'formula',
                expr: interpolateExpr([
                    offsetExpr({
                        timeUnit,
                        field: startField,
                        reverse: true
                    }),
                    startExpr
                ], rectBandPosition + 0.5),
                as: `${startField}_${OFFSETTED_RECT_START_SUFFIX}`
            },
            {
                type: 'formula',
                expr: interpolateExpr([startExpr, endExpr], rectBandPosition + 0.5),
                as: `${startField}_${OFFSETTED_RECT_END_SUFFIX}`
            }
        ];
    }
    return [];
}
function interpolateExpr([start, end], fraction) {
    return `${1 - fraction} * ${start} + ${fraction} * ${end}`;
}
//# sourceMappingURL=timeunit.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/project.js









const TUPLE_FIELDS = '_tuple_fields';
class SelectionProjectionComponent {
    constructor(...items) {
        this.items = items;
        this.hasChannel = {};
        this.hasField = {};
        this.hasSelectionId = false;
    }
}
const project_project = {
    defined: () => {
        return true; // This transform handles its own defaults, so always run parse.
    },
    parse: (model, selCmpt, selDef) => {
        const name = selCmpt.name;
        const proj = (selCmpt.project ?? (selCmpt.project = new SelectionProjectionComponent()));
        const parsed = {};
        const timeUnits = {};
        const signals = new Set();
        const signalName = (p, range) => {
            const suffix = range === 'visual' ? p.channel : p.field;
            let sg = varName(`${name}_${suffix}`);
            for (let counter = 1; signals.has(sg); counter++) {
                sg = varName(`${name}_${suffix}_${counter}`);
            }
            signals.add(sg);
            return { [range]: sg };
        };
        const type = selCmpt.type;
        const cfg = model.config.selection[type];
        const init = selDef.value !== undefined
            ? vega_util_module_array(selDef.value)
            : null;
        // If no explicit projection (either fields or encodings) is specified, set some defaults.
        // If an initial value is set, try to infer projections.
        let { fields, encodings } = (vega_util_module_isObject(selDef.select) ? selDef.select : {});
        if (!fields && !encodings && init) {
            for (const initVal of init) {
                // initVal may be a scalar value to smoothen varParam -> pointSelection gradient.
                if (!vega_util_module_isObject(initVal)) {
                    continue;
                }
                for (const key of util_keys(initVal)) {
                    if (isSingleDefUnitChannel(key)) {
                        (encodings || (encodings = [])).push(key);
                    }
                    else {
                        if (type === 'interval') {
                            log_warn(INTERVAL_INITIALIZED_WITH_POS);
                            encodings = cfg.encodings;
                        }
                        else {
                            (fields ?? (fields = [])).push(key);
                        }
                    }
                }
            }
        }
        // If no initial value is specified, use the default configuration.
        // We break this out as a separate if block (instead of an else condition)
        // to account for unprojected point selections that have scalar initial values
        if (!fields && !encodings) {
            encodings = cfg.encodings;
            if ('fields' in cfg) {
                fields = cfg.fields;
            }
        }
        for (const channel of encodings ?? []) {
            const fieldDef = model.fieldDef(channel);
            if (fieldDef) {
                let field = fieldDef.field;
                if (fieldDef.aggregate) {
                    log_warn(cannotProjectAggregate(channel, fieldDef.aggregate));
                    continue;
                }
                else if (!field) {
                    log_warn(cannotProjectOnChannelWithoutField(channel));
                    continue;
                }
                if (fieldDef.timeUnit && !isBinnedTimeUnit(fieldDef.timeUnit)) {
                    field = model.vgField(channel);
                    // Construct TimeUnitComponents which will be combined into a
                    // TimeUnitNode. This node may need to be inserted into the
                    // dataflow if the selection is used across views that do not
                    // have these time units defined.
                    const component = {
                        timeUnit: fieldDef.timeUnit,
                        as: field,
                        field: fieldDef.field
                    };
                    timeUnits[util_hash(component)] = component;
                }
                // Prevent duplicate projections on the same field.
                // TODO: what if the same field is bound to multiple channels (e.g., SPLOM diag).
                if (!parsed[field]) {
                    // Determine whether the tuple will store enumerated or ranged values.
                    // Interval selections store ranges for continuous scales, and enumerations otherwise.
                    // Single/multi selections store ranges for binned fields, and enumerations otherwise.
                    const tplType = type === 'interval' &&
                        isScaleChannel(channel) &&
                        hasContinuousDomain(model.getScaleComponent(channel).get('type'))
                        ? 'R'
                        : fieldDef.bin
                            ? 'R-RE'
                            : 'E';
                    const p = { field, channel, type: tplType, index: proj.items.length };
                    p.signals = { ...signalName(p, 'data'), ...signalName(p, 'visual') };
                    proj.items.push((parsed[field] = p));
                    proj.hasField[field] = parsed[field];
                    proj.hasSelectionId = proj.hasSelectionId || field === SELECTION_ID;
                    if (isGeoPositionChannel(channel)) {
                        p.geoChannel = channel;
                        p.channel = getPositionChannelFromLatLong(channel);
                        proj.hasChannel[p.channel] = parsed[field];
                    }
                    else {
                        proj.hasChannel[channel] = parsed[field];
                    }
                }
            }
            else {
                log_warn(cannotProjectOnChannelWithoutField(channel));
            }
        }
        for (const field of fields ?? []) {
            if (proj.hasField[field])
                continue;
            const p = { type: 'E', field, index: proj.items.length };
            p.signals = { ...signalName(p, 'data') };
            proj.items.push(p);
            proj.hasField[field] = p;
            proj.hasSelectionId = proj.hasSelectionId || field === SELECTION_ID;
        }
        if (init) {
            selCmpt.init = init.map((v) => {
                // Selections can be initialized either with a full object that maps projections to values
                // or scalar values to smoothen the abstraction gradient from variable params to point selections.
                return proj.items.map(p => vega_util_module_isObject(v) ? (v[p.geoChannel || p.channel] !== undefined ? v[p.geoChannel || p.channel] : v[p.field]) : v);
            });
        }
        if (!isEmpty(timeUnits)) {
            proj.timeUnit = new TimeUnitNode(null, timeUnits);
        }
    },
    signals: (model, selCmpt, allSignals) => {
        const name = selCmpt.name + TUPLE_FIELDS;
        const hasSignal = allSignals.filter(s => s.name === name);
        return hasSignal.length > 0 || selCmpt.project.hasSelectionId
            ? allSignals
            : allSignals.concat({
                name,
                value: selCmpt.project.items.map(assembleProjection)
            });
    }
};
/* harmony default export */ const selection_project = (project_project);
//# sourceMappingURL=project.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/point.js







const CURR = '_curr';
const ANIM_VALUE = 'anim_value';
const ANIM_CLOCK = 'anim_clock';
const EASED_ANIM_CLOCK = 'eased_anim_clock';
const MIN_EXTENT = 'min_extent';
const MAX_RANGE_EXTENT = 'max_range_extent';
const LAST_TICK = 'last_tick_at';
const IS_PLAYING = 'is_playing';
const THROTTLE = (1 / 60) * 1000; // 60 FPS
const animationSignals = (selectionName, scaleName) => {
    return [
        // timer signals
        {
            name: EASED_ANIM_CLOCK,
            // update: 'easeLinear(anim_clock / max_range_extent) * max_range_extent'
            update: ANIM_CLOCK // TODO: replace with above once easing functions are implemented in vega-functions
        },
        // scale signals
        // TODO(jzong): uncomment commented signals below when implementing interpolation
        { name: `${selectionName}_domain`, init: `domain('${scaleName}')` },
        { name: MIN_EXTENT, init: `extent(${selectionName}_domain)[0]` },
        // {name: 'max_extent', init: `extent(${selectionName}_domain)[1]`},
        { name: MAX_RANGE_EXTENT, init: `extent(range('${scaleName}'))[1]` },
        // {name: 't_index', update: `indexof(${selectionName}_domain, anim_value)`},
        { name: ANIM_VALUE, update: `invert('${scaleName}', ${EASED_ANIM_CLOCK})` }
    ];
};
const point_point = {
    defined: selCmpt => selCmpt.type === 'point',
    topLevelSignals: (model, selCmpt, signals) => {
        if (isTimerSelection(selCmpt)) {
            signals = signals.concat([
                {
                    name: ANIM_CLOCK,
                    init: '0',
                    on: [
                        {
                            events: { type: 'timer', throttle: THROTTLE },
                            update: `${IS_PLAYING} ? (${ANIM_CLOCK} + (now() - ${LAST_TICK}) > ${MAX_RANGE_EXTENT} ? 0 : ${ANIM_CLOCK} + (now() - ${LAST_TICK})) : ${ANIM_CLOCK}`
                        }
                    ]
                },
                {
                    name: LAST_TICK,
                    init: 'now()',
                    on: [{ events: [{ signal: ANIM_CLOCK }, { signal: IS_PLAYING }], update: 'now()' }]
                },
                {
                    name: IS_PLAYING,
                    init: 'true'
                }
            ]);
        }
        return signals;
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const fieldsSg = name + TUPLE_FIELDS;
        const project = selCmpt.project;
        const datum = '(item().isVoronoi ? datum.datum : datum)';
        // Only add a discrete selection to the store if a datum is present _and_
        // the interaction isn't occurring on a group mark. This guards against
        // polluting interactive state with invalid values in faceted displays
        // as the group marks are also data-driven. We force the update to account
        // for constant null states but varying toggles (e.g., shift-click in
        // whitespace followed by a click in whitespace; the store should only
        // be cleared on the second click).
        const brushes = vals(model.component.selection ?? {})
            .reduce((acc, cmpt) => {
            return cmpt.type === 'interval' ? acc.concat(cmpt.name + BRUSH) : acc;
        }, [])
            .map(b => `indexof(item().mark.name, '${b}') < 0`)
            .join(' && ');
        const test = `datum && item().mark.marktype !== 'group' && indexof(item().mark.role, 'legend') < 0${brushes ? ` && ${brushes}` : ''}`;
        let update = `unit: ${unitName(model)}, `;
        if (selCmpt.project.hasSelectionId) {
            update += `${SELECTION_ID}: ${datum}[${$(SELECTION_ID)}]`;
        }
        else if (isTimerSelection(selCmpt)) {
            update += `fields: ${fieldsSg}, values: [${ANIM_VALUE} ? ${ANIM_VALUE} : ${MIN_EXTENT}]`;
        }
        else {
            const values = project.items
                .map(p => {
                const fieldDef = model.fieldDef(p.channel);
                // Binned fields should capture extents, for a range test against the raw field.
                return fieldDef?.bin
                    ? `[${datum}[${$(model.vgField(p.channel, {}))}], ` +
                        `${datum}[${$(model.vgField(p.channel, { binSuffix: 'end' }))}]]`
                    : `${datum}[${$(p.field)}]`;
            })
                .join(', ');
            update += `fields: ${fieldsSg}, values: [${values}]`;
        }
        if (isTimerSelection(selCmpt)) {
            // timer event: selection is for animation
            return signals.concat(animationSignals(selCmpt.name, model.scaleName(TIME)), [
                {
                    name: name + TUPLE,
                    on: [
                        {
                            events: [{ signal: EASED_ANIM_CLOCK }, { signal: ANIM_VALUE }],
                            update: `{${update}}`,
                            force: true
                        }
                    ]
                }
            ]);
        }
        else {
            const events = selCmpt.events;
            return signals.concat([
                {
                    name: name + TUPLE,
                    on: events
                        ? [
                            {
                                events,
                                update: `${test} ? {${update}} : null`,
                                force: true
                            }
                        ]
                        : []
                }
            ]);
        }
    }
};
/* harmony default export */ const selection_point = (point_point);
//# sourceMappingURL=point.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/assemble.js











function assembleProjection(proj) {
    const { signals, hasLegend, index, ...rest } = proj;
    rest.field = replacePathInField(rest.field);
    return rest;
}
function assembleInit(init, isExpr = true, wrap = vega_util_module_identity) {
    if (vega_util_module_isArray(init)) {
        const assembled = init.map(v => assembleInit(v, isExpr, wrap));
        return isExpr ? `[${assembled.join(', ')}]` : assembled;
    }
    else if (isDateTime(init)) {
        if (isExpr) {
            return wrap(dateTimeToExpr(init));
        }
        else {
            return wrap(dateTimeToTimestamp(init));
        }
    }
    return isExpr ? wrap(util_stringify(init)) : init;
}
function assembleUnitSelectionSignals(model, signals) {
    for (const selCmpt of vals(model.component.selection ?? {})) {
        const name = selCmpt.name;
        let modifyExpr = `${name}${TUPLE}, ${selCmpt.resolve === 'global' ? 'true' : `{unit: ${unitName(model)}}`}`;
        for (const c of selectionCompilers) {
            if (!c.defined(selCmpt))
                continue;
            if (c.signals)
                signals = c.signals(model, selCmpt, signals);
            if (c.modifyExpr)
                modifyExpr = c.modifyExpr(model, selCmpt, modifyExpr);
        }
        signals.push({
            name: name + MODIFY,
            on: [
                {
                    events: { signal: selCmpt.name + TUPLE },
                    update: `modify(${$(selCmpt.name + STORE)}, ${modifyExpr})`
                }
            ]
        });
    }
    return cleanupEmptyOnArray(signals);
}
function assembleFacetSignals(model, signals) {
    if (model.component.selection && util_keys(model.component.selection).length) {
        const name = $(model.getName('cell'));
        signals.unshift({
            name: 'facet',
            value: {},
            on: [
                {
                    events: eventSelector('pointermove', 'scope'),
                    update: `isTuple(facet) ? facet : group(${name}).datum`
                }
            ]
        });
    }
    return cleanupEmptyOnArray(signals);
}
function assembleTopLevelSignals(model, signals) {
    let hasSelections = false;
    for (const selCmpt of vals(model.component.selection ?? {})) {
        const name = selCmpt.name;
        const store = $(name + STORE);
        const hasSg = signals.filter(s => s.name === name);
        if (hasSg.length === 0) {
            const resolve = selCmpt.resolve === 'global' ? 'union' : selCmpt.resolve;
            const isPoint = selCmpt.type === 'point' ? ', true, true)' : ')';
            signals.push({
                name: selCmpt.name,
                update: `${VL_SELECTION_RESOLVE}(${store}, ${$(resolve)}${isPoint}`
            });
        }
        hasSelections = true;
        for (const c of selectionCompilers) {
            if (c.defined(selCmpt) && c.topLevelSignals) {
                signals = c.topLevelSignals(model, selCmpt, signals);
            }
        }
    }
    if (hasSelections) {
        const hasUnit = signals.filter(s => s.name === 'unit');
        if (hasUnit.length === 0) {
            signals.unshift({
                name: 'unit',
                value: {},
                on: [{ events: 'pointermove', update: 'isTuple(group()) ? group() : unit' }]
            });
        }
    }
    return cleanupEmptyOnArray(signals);
}
function assembleUnitSelectionData(model, data) {
    const selectionData = [];
    const animationData = [];
    const unit = unitName(model, { escape: false });
    for (const selCmpt of vals(model.component.selection ?? {})) {
        const store = { name: selCmpt.name + STORE };
        if (selCmpt.project.hasSelectionId) {
            store.transform = [{ type: 'collect', sort: { field: SELECTION_ID } }];
        }
        if (selCmpt.init) {
            const fields = selCmpt.project.items.map(assembleProjection);
            store.values = selCmpt.project.hasSelectionId
                ? selCmpt.init.map(i => ({ unit, [SELECTION_ID]: assembleInit(i, false)[0] }))
                : selCmpt.init.map(i => ({ unit, fields, values: assembleInit(i, false) }));
        }
        const contains = [...selectionData, ...data].filter(d => d.name === selCmpt.name + STORE);
        if (!contains.length) {
            selectionData.push(store);
        }
        if (isTimerSelection(selCmpt) && data.length) {
            // TODO(jzong): eventually uncomment this stuff when we want to support multi-view
            // const sourceName =
            //   model.parent && model.parent.type !== 'unit' // facet, layer, or concat
            //     ? model.parent.lookupDataSource(model.parent.getDataName(DataSourceType.Main))
            //     : model.lookupDataSource(model.getDataName(DataSourceType.Main));
            const sourceName = model.lookupDataSource(model.getDataName(DataSourceType.Main));
            const sourceData = data.find(d => d.name === sourceName);
            // find the filter transform for the current selection
            const sourceDataFilter = sourceData.transform.find(t => t.type === 'filter' && t.expr.includes('vlSelectionTest'));
            if (sourceDataFilter) {
                // remove it from the original dataset
                sourceData.transform = sourceData.transform.filter(t => t !== sourceDataFilter);
                // create dataset to hold current animation frame
                const currentFrame = {
                    name: sourceData.name + CURR,
                    source: sourceData.name,
                    transform: [sourceDataFilter] // add the selection filter to the animation dataset
                };
                animationData.push(currentFrame);
            }
        }
    }
    return selectionData.concat(data, animationData);
}
function assembleUnitSelectionMarks(model, marks) {
    for (const selCmpt of vals(model.component.selection ?? {})) {
        for (const c of selectionCompilers) {
            if (c.defined(selCmpt) && c.marks) {
                marks = c.marks(model, selCmpt, marks);
            }
        }
    }
    return marks;
}
function assembleLayerSelectionMarks(model, marks) {
    for (const child of model.children) {
        if (isUnitModel(child)) {
            marks = assembleUnitSelectionMarks(child, marks);
        }
    }
    return marks;
}
function assembleSelectionScaleDomain(model, extent, scaleCmpt, domain) {
    const parsedExtent = parseSelectionExtent(model, extent.param, extent);
    return {
        signal: hasContinuousDomain(scaleCmpt.get('type')) && vega_util_module_isArray(domain) && domain[0] > domain[1]
            ? `isValid(${parsedExtent}) && reverse(${parsedExtent})`
            : parsedExtent
    };
}
function cleanupEmptyOnArray(signals) {
    return signals.map(s => {
        if (s.on && !s.on.length)
            delete s.on;
        return s;
    });
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/scales.js







const scaleBindings = {
    defined: selCmpt => {
        return selCmpt.type === 'interval' && selCmpt.resolve === 'global' && selCmpt.bind && selCmpt.bind === 'scales';
    },
    parse: (model, selCmpt) => {
        const bound = (selCmpt.scales = []);
        for (const proj of selCmpt.project.items) {
            const channel = proj.channel;
            if (!isScaleChannel(channel)) {
                continue;
            }
            const scale = model.getScaleComponent(channel);
            const scaleType = scale ? scale.get('type') : undefined;
            if (scaleType == 'sequential') {
                log_warn(SEQUENTIAL_SCALE_DEPRECATED);
            }
            if (!scale || !hasContinuousDomain(scaleType)) {
                log_warn(SCALE_BINDINGS_CONTINUOUS);
                continue;
            }
            scale.set('selectionExtent', { param: selCmpt.name, field: proj.field }, true);
            bound.push(proj);
        }
    },
    topLevelSignals: (model, selCmpt, signals) => {
        const bound = selCmpt.scales.filter(proj => signals.filter(s => s.name === proj.signals.data).length === 0);
        // Top-level signals are only needed for multiview displays and if this
        // view's top-level signals haven't already been generated.
        if (!model.parent || isTopLevelLayer(model) || bound.length === 0) {
            return signals;
        }
        // vlSelectionResolve does not account for the behavior of bound scales in
        // multiview displays. Each unit view adds a tuple to the store, but the
        // state of the selection is the unit selection most recently updated. This
        // state is captured by the top-level signals that we insert and "push
        // outer" to from within the units. We need to reassemble this state into
        // the top-level named signal, except no single selCmpt has a global view.
        const namedSg = signals.find(s => s.name === selCmpt.name);
        let update = namedSg.update;
        if (update.includes(VL_SELECTION_RESOLVE)) {
            namedSg.update = `{${bound
                .map(proj => `${$(replacePathInField(proj.field))}: ${proj.signals.data}`)
                .join(', ')}}`;
        }
        else {
            for (const proj of bound) {
                const mapping = `${$(replacePathInField(proj.field))}: ${proj.signals.data}`;
                if (!update.includes(mapping)) {
                    update = `${update.substring(0, update.length - 1)}, ${mapping}}`;
                }
            }
            namedSg.update = update;
        }
        return signals.concat(bound.map(proj => ({ name: proj.signals.data })));
    },
    signals: (model, selCmpt, signals) => {
        // Nested signals need only push to top-level signals with multiview displays.
        if (model.parent && !isTopLevelLayer(model)) {
            for (const proj of selCmpt.scales) {
                const signal = signals.find(s => s.name === proj.signals.data);
                signal.push = 'outer';
                delete signal.value;
                delete signal.update;
            }
        }
        return signals;
    }
};
/* harmony default export */ const selection_scales = (scaleBindings);
function scales_domain(model, channel) {
    const scale = $(model.scaleName(channel));
    return `domain(${scale})`;
}
function isTopLevelLayer(model) {
    return model.parent && isLayerModel(model.parent) && (!model.parent.parent || isTopLevelLayer(model.parent.parent));
}
//# sourceMappingURL=scales.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/interval.js












const BRUSH = '_brush';
const SCALE_TRIGGER = '_scale_trigger';
const GEO_INIT_TICK = 'geo_interval_init_tick'; // Workaround for https://github.com/vega/vega/issues/3481
const INIT = '_init';
const interval_CENTER = '_center';
const interval_interval = {
    defined: selCmpt => selCmpt.type === 'interval',
    parse: (model, selCmpt, selDef) => {
        var _a;
        if (model.hasProjection) {
            const def = { ...(vega_util_module_isObject(selDef.select) ? selDef.select : {}) };
            def.fields = [SELECTION_ID];
            if (!def.encodings) {
                // Remap default x/y projection
                def.encodings = selDef.value ? util_keys(selDef.value) : [LONGITUDE, LATITUDE];
            }
            selDef.select = { type: 'interval', ...def };
        }
        if (selCmpt.translate && !selection_scales.defined(selCmpt)) {
            const filterExpr = `!event.item || event.item.mark.name !== ${$(selCmpt.name + BRUSH)}`;
            for (const evt of selCmpt.events) {
                if (!evt.between) {
                    log_warn(`${evt} is not an ordered event stream for interval selections.`);
                    continue;
                }
                const filters = vega_util_module_array(((_a = evt.between[0]).filter ?? (_a.filter = [])));
                if (!filters.includes(filterExpr)) {
                    filters.push(filterExpr);
                }
            }
        }
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const tupleSg = name + TUPLE;
        const channels = vals(selCmpt.project.hasChannel).filter(p => p.channel === channel_X || p.channel === channel_Y);
        const init = selCmpt.init ? selCmpt.init[0] : null;
        signals.push(...channels.reduce((arr, proj) => arr.concat(channelSignals(model, selCmpt, proj, init && init[proj.index])), []));
        if (!model.hasProjection) {
            // Proxy scale reactions to ensure that an infinite loop doesn't occur
            // when an interval selection filter touches the scale.
            if (!selection_scales.defined(selCmpt)) {
                const triggerSg = name + SCALE_TRIGGER;
                const scaleTriggers = channels.map(proj => {
                    const channel = proj.channel;
                    const { data: dname, visual: vname } = proj.signals;
                    const scaleName = $(model.scaleName(channel));
                    const scaleType = model.getScaleComponent(channel).get('type');
                    const toNum = hasContinuousDomain(scaleType) ? '+' : '';
                    return (`(!isArray(${dname}) || ` +
                        `(${toNum}invert(${scaleName}, ${vname})[0] === ${toNum}${dname}[0] && ` +
                        `${toNum}invert(${scaleName}, ${vname})[1] === ${toNum}${dname}[1]))`);
                });
                if (scaleTriggers.length) {
                    signals.push({
                        name: triggerSg,
                        value: {},
                        on: [
                            {
                                events: channels.map(proj => ({ scale: model.scaleName(proj.channel) })),
                                update: scaleTriggers.join(' && ') + ` ? ${triggerSg} : {}`
                            }
                        ]
                    });
                }
            }
            // Only add an interval to the store if it has valid data extents. Data extents
            // are set to null if pixel extents are equal to account for intervals over
            // ordinal/nominal domains which, when inverted, will still produce a valid datum.
            const dataSignals = channels.map(proj => proj.signals.data);
            const update = `unit: ${unitName(model)}, fields: ${name + TUPLE_FIELDS}, values`;
            return signals.concat({
                name: tupleSg,
                ...(init ? { init: `{${update}: ${assembleInit(init)}}` } : {}),
                ...(dataSignals.length
                    ? {
                        on: [
                            {
                                events: [{ signal: dataSignals.join(' || ') }], // Prevents double invocation, see https://github.com/vega/vega/issues/1672.
                                update: `${dataSignals.join(' && ')} ? {${update}: [${dataSignals}]} : null`
                            }
                        ]
                    }
                    : {})
            });
        }
        else {
            const projection = $(model.projectionName());
            const centerSg = model.projectionName() + interval_CENTER;
            const { x, y } = selCmpt.project.hasChannel;
            const xvname = x && x.signals.visual;
            const yvname = y && y.signals.visual;
            const xinit = x ? init && init[x.index] : `${centerSg}[0]`;
            const yinit = y ? init && init[y.index] : `${centerSg}[1]`;
            const sizeSg = (layout) => model.getSizeSignalRef(layout).signal;
            const bbox = `[` +
                `[${xvname ? xvname + '[0]' : '0'}, ${yvname ? yvname + '[0]' : '0'}],` +
                `[${xvname ? xvname + '[1]' : sizeSg('width')}, ` +
                `${yvname ? yvname + '[1]' : sizeSg('height')}]` +
                `]`;
            if (init) {
                signals.unshift({
                    name: name + INIT,
                    init: `[scale(${projection}, [${x ? xinit[0] : xinit}, ${y ? yinit[0] : yinit}]), ` +
                        `scale(${projection}, [${x ? xinit[1] : xinit}, ${y ? yinit[1] : yinit}])]`
                });
                if (!x || !y) {
                    // If initializing a uni-dimensional brush, use the center of the view to determine the other coord
                    const hasCenterSg = signals.find(s => s.name === centerSg);
                    if (!hasCenterSg) {
                        signals.unshift({
                            name: centerSg,
                            update: `invert(${projection}, [${sizeSg('width')}/2, ${sizeSg('height')}/2])`
                        });
                    }
                }
            }
            const intersect = `intersect(${bbox}, {markname: ${$(model.getName('marks'))}}, unit.mark)`;
            const base = `{unit: ${unitName(model)}}`;
            const update = `vlSelectionTuples(${intersect}, ${base})`;
            const visualSignals = channels.map(proj => proj.signals.visual);
            return signals.concat({
                name: tupleSg,
                on: [
                    {
                        events: [
                            ...(visualSignals.length ? [{ signal: visualSignals.join(' || ') }] : []),
                            ...(init ? [{ signal: GEO_INIT_TICK }] : [])
                        ],
                        update
                    }
                ]
            });
        }
    },
    topLevelSignals: (model, selCmpt, signals) => {
        if (isUnitModel(model) && model.hasProjection && selCmpt.init) {
            // Workaround for https://github.com/vega/vega/issues/3481
            // The scenegraph isn't populated on the first pulse. So we use a timer signal
            // to re-pulse the dataflow as soon as possible. We return an object to ensure
            // this only occurs once.
            const hasTick = signals.filter(s => s.name === GEO_INIT_TICK);
            if (!hasTick.length) {
                signals.unshift({
                    name: GEO_INIT_TICK,
                    value: null,
                    on: [
                        {
                            events: 'timer{1}',
                            update: `${GEO_INIT_TICK} === null ? {} : ${GEO_INIT_TICK}`
                        }
                    ]
                });
            }
        }
        return signals;
    },
    marks: (model, selCmpt, marks) => {
        const name = selCmpt.name;
        const { x, y } = selCmpt.project.hasChannel;
        const xvname = x?.signals.visual;
        const yvname = y?.signals.visual;
        const store = `data(${$(selCmpt.name + STORE)})`;
        // Do not add a brush if we're binding to scales
        // or we don't have a valid interval projection
        if (selection_scales.defined(selCmpt) || (!x && !y)) {
            return marks;
        }
        const update = {
            x: x !== undefined ? { signal: `${xvname}[0]` } : { value: 0 },
            y: y !== undefined ? { signal: `${yvname}[0]` } : { value: 0 },
            x2: x !== undefined ? { signal: `${xvname}[1]` } : { field: { group: 'width' } },
            y2: y !== undefined ? { signal: `${yvname}[1]` } : { field: { group: 'height' } }
        };
        // If the selection is resolved to global, only a single interval is in
        // the store. Wrap brush mark's encodings with a production rule to test
        // this based on the `unit` property. Hide the brush mark if it corresponds
        // to a unit different from the one in the store.
        if (selCmpt.resolve === 'global') {
            for (const key of util_keys(update)) {
                update[key] = [
                    {
                        test: `${store}.length && ${store}[0].unit === ${unitName(model)}`,
                        ...update[key]
                    },
                    { value: 0 }
                ];
            }
        }
        // Two brush marks ensure that fill colors and other aesthetic choices do
        // not interefere with the core marks, but that the brushed region can still
        // be interacted with (e.g., dragging it around).
        const { fill, fillOpacity, cursor, ...stroke } = selCmpt.mark;
        const vgStroke = util_keys(stroke).reduce((def, k) => {
            def[k] = [
                {
                    test: [
                        x !== undefined && `${xvname}[0] !== ${xvname}[1]`,
                        y !== undefined && `${yvname}[0] !== ${yvname}[1]`
                    ]
                        .filter(t => t)
                        .join(' && '),
                    value: stroke[k]
                },
                { value: null }
            ];
            return def;
        }, {});
        // Set cursor to move unless the brush cannot be translated
        const vgCursor = cursor ?? (selCmpt.translate ? 'move' : null);
        return [
            {
                name: `${name + BRUSH}_bg`,
                type: 'rect',
                clip: true,
                encode: {
                    enter: {
                        fill: { value: fill },
                        fillOpacity: { value: fillOpacity }
                    },
                    update
                }
            },
            ...marks,
            {
                name: name + BRUSH,
                type: 'rect',
                clip: true,
                encode: {
                    enter: {
                        ...(vgCursor ? { cursor: { value: vgCursor } } : {}),
                        fill: { value: 'transparent' }
                    },
                    update: { ...update, ...vgStroke }
                }
            }
        ];
    }
};
/* harmony default export */ const selection_interval = (interval_interval);
/**
 * Returns the visual and data signals for an interval selection.
 */
function channelSignals(model, selCmpt, proj, init) {
    const scaledInterval = !model.hasProjection;
    const channel = proj.channel;
    const vname = proj.signals.visual;
    const scaleName = $(scaledInterval ? model.scaleName(channel) : model.projectionName());
    const scaled = (str) => `scale(${scaleName}, ${str})`;
    const size = model.getSizeSignalRef(channel === channel_X ? 'width' : 'height').signal;
    const coord = `${channel}(unit)`;
    const von = selCmpt.events.reduce((def, evt) => {
        return [
            ...def,
            { events: evt.between[0], update: `[${coord}, ${coord}]` }, // Brush Start
            { events: evt, update: `[${vname}[0], clamp(${coord}, 0, ${size})]` } // Brush End
        ];
    }, []);
    if (scaledInterval) {
        const dname = proj.signals.data;
        const hasScales = selection_scales.defined(selCmpt);
        const scale = model.getScaleComponent(channel);
        const scaleType = scale ? scale.get('type') : undefined;
        const vinit = init ? { init: assembleInit(init, true, scaled) } : { value: [] };
        // React to pan/zooms of continuous scales. Non-continuous scales
        // (band, point) cannot be pan/zoomed and any other changes
        // to their domains (e.g., filtering) should clear the brushes.
        von.push({
            events: { signal: selCmpt.name + SCALE_TRIGGER },
            update: hasContinuousDomain(scaleType) ? `[${scaled(`${dname}[0]`)}, ${scaled(`${dname}[1]`)}]` : `[0, 0]`
        });
        return hasScales
            ? [{ name: dname, on: [] }]
            : [
                { name: vname, ...vinit, on: von },
                {
                    name: dname,
                    ...(init ? { init: assembleInit(init) } : {}), // Cannot be `value` as `init` may require datetime exprs.
                    on: [
                        {
                            events: { signal: vname },
                            update: `${vname}[0] === ${vname}[1] ? null : invert(${scaleName}, ${vname})`
                        }
                    ]
                }
            ];
    }
    else {
        const initIdx = channel === channel_X ? 0 : 1;
        const initSg = selCmpt.name + INIT;
        const vinit = init ? { init: `[${initSg}[0][${initIdx}], ${initSg}[1][${initIdx}]]` } : { value: [] };
        return [{ name: vname, ...vinit, on: von }];
    }
}
//# sourceMappingURL=interval.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/conditional.js




/**
 * Return a VgEncodeEntry that includes a Vega production rule for a scale channel's encoding or guide encoding, which includes:
 * (1) the conditional rules (if provided as part of channelDef)
 * (2) invalidValueRef for handling invalid values (if provided as a parameter of this method)
 * (3) main reference for the encoded data.
 */
function wrapCondition({ model, channelDef, vgChannel, invalidValueRef, mainRefFn }) {
    const condition = isConditionalDef(channelDef) && channelDef.condition;
    let valueRefs = [];
    if (condition) {
        const conditions = vega_util_module_array(condition);
        valueRefs = conditions.map(c => {
            const conditionValueRef = mainRefFn(c);
            if (isConditionalParameter(c)) {
                const { param, empty } = c;
                const test = parseSelectionPredicate(model, { param, empty });
                return { test, ...conditionValueRef };
            }
            else {
                const test = predicate_expression(model, c.test); // FIXME: remove casting once TS is no longer dumb about it
                return { test, ...conditionValueRef };
            }
        });
    }
    if (invalidValueRef !== undefined) {
        valueRefs.push(invalidValueRef);
    }
    const mainValueRef = mainRefFn(channelDef);
    if (mainValueRef !== undefined) {
        valueRefs.push(mainValueRef);
    }
    if (valueRefs.length > 1 ||
        (valueRefs.length === 1 && Boolean(valueRefs[0].test)) // We must use array form valueRefs if test exists, otherwise Vega won't execute the test.
    ) {
        return { [vgChannel]: valueRefs };
    }
    else if (valueRefs.length === 1) {
        return { [vgChannel]: valueRefs[0] };
    }
    return {};
}
//# sourceMappingURL=conditional.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/text.js




function text_text(model, channel = 'text') {
    const channelDef = model.encoding[channel];
    return wrapCondition({
        model,
        channelDef,
        vgChannel: channel,
        mainRefFn: cDef => textRef(cDef, model.config),
        invalidValueRef: undefined // text encoding doesn't have continuous scales and thus can't have invalid values
    });
}
function textRef(channelDef, config, expr = 'datum') {
    // text
    if (channelDef) {
        if (isValueDef(channelDef)) {
            return signalOrValueRef(channelDef.value);
        }
        if (isFieldOrDatumDef(channelDef)) {
            const { format, formatType } = getFormatMixins(channelDef);
            return formatSignalRef({ fieldOrDatumDef: channelDef, format, formatType, expr, config });
        }
    }
    return undefined;
}
//# sourceMappingURL=text.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/tooltip.js











function tooltip_tooltip(model, opt = {}) {
    const { encoding, markDef, config, stack } = model;
    const channelDef = encoding.tooltip;
    if (vega_util_module_isArray(channelDef)) {
        return { tooltip: tooltipRefForEncoding({ tooltip: channelDef }, stack, config, opt) };
    }
    else {
        const datum = opt.reactiveGeom ? 'datum.datum' : 'datum';
        const mainRefFn = (cDef) => {
            // use valueRef based on channelDef first
            const tooltipRefFromChannelDef = textRef(cDef, config, datum);
            if (tooltipRefFromChannelDef) {
                return tooltipRefFromChannelDef;
            }
            if (cDef === null) {
                // Allow using encoding.tooltip = null to disable tooltip
                return undefined;
            }
            let markTooltip = getMarkPropOrConfig('tooltip', markDef, config);
            if (markTooltip === true) {
                markTooltip = { content: 'encoding' };
            }
            if (vega_util_module_isString(markTooltip)) {
                return { value: markTooltip };
            }
            else if (vega_util_module_isObject(markTooltip)) {
                // `tooltip` is `{fields: 'encodings' | 'fields'}`
                if (isSignalRef(markTooltip)) {
                    return markTooltip;
                }
                else if (markTooltip.content === 'encoding') {
                    return tooltipRefForEncoding(encoding, stack, config, opt);
                }
                else {
                    return { signal: datum };
                }
            }
            return undefined;
        };
        return wrapCondition({
            model,
            channelDef,
            vgChannel: 'tooltip',
            mainRefFn,
            invalidValueRef: undefined // tooltip encoding doesn't have continuous scales and thus can't have invalid values
        });
    }
}
function tooltipData(encoding, stack, config, { reactiveGeom } = {}) {
    const formatConfig = { ...config, ...config.tooltipFormat };
    const toSkip = new Set();
    const expr = reactiveGeom ? 'datum.datum' : 'datum';
    const tuples = [];
    function add(fDef, channel) {
        const mainChannel = getMainRangeChannel(channel);
        const fieldDef = isTypedFieldDef(fDef)
            ? fDef
            : {
                ...fDef,
                type: encoding[mainChannel].type // for secondary field def, copy type from main channel
            };
        const title = fieldDef.title || defaultTitle(fieldDef, formatConfig);
        const key = vega_util_module_array(title).join(', ').replaceAll(/"/g, '\\"');
        let value;
        if (isXorY(channel)) {
            const channel2 = channel === 'x' ? 'x2' : 'y2';
            const fieldDef2 = getFieldDef(encoding[channel2]);
            if (isBinned(fieldDef.bin) && fieldDef2) {
                const startField = vgField(fieldDef, { expr });
                const endField = vgField(fieldDef2, { expr });
                const { format, formatType } = getFormatMixins(fieldDef);
                value = binFormatExpression(startField, endField, format, formatType, formatConfig);
                toSkip.add(channel2);
            }
        }
        if ((isXorY(channel) || channel === THETA || channel === RADIUS) &&
            stack &&
            stack.fieldChannel === channel &&
            stack.offset === 'normalize') {
            const { format, formatType } = getFormatMixins(fieldDef);
            value = formatSignalRef({
                fieldOrDatumDef: fieldDef,
                format,
                formatType,
                expr,
                config: formatConfig,
                normalizeStack: true
            }).signal;
        }
        value ?? (value = textRef(fieldDef, formatConfig, expr).signal);
        tuples.push({ channel, key, value });
    }
    forEach(encoding, (channelDef, channel) => {
        if (isFieldDef(channelDef)) {
            add(channelDef, channel);
        }
        else if (hasConditionalFieldDef(channelDef)) {
            add(channelDef.condition, channel);
        }
    });
    const out = {};
    for (const { channel, key, value } of tuples) {
        if (!toSkip.has(channel) && !out[key]) {
            out[key] = value;
        }
    }
    return out;
}
function tooltipRefForEncoding(encoding, stack, config, { reactiveGeom } = {}) {
    const data = tooltipData(encoding, stack, config, { reactiveGeom });
    const keyValues = util_entries(data).map(([key, value]) => `"${key}": ${value}`);
    return keyValues.length > 0 ? { signal: `{${keyValues.join(', ')}}` } : undefined;
}
//# sourceMappingURL=tooltip.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/aria.js







function aria(model) {
    const { markDef, config } = model;
    const enableAria = getMarkPropOrConfig('aria', markDef, config);
    // We can ignore other aria properties if ariaHidden is true.
    if (enableAria === false) {
        // getMarkGroups sets aria to false already so we don't have to set it in the encode block
        return {};
    }
    return {
        ...(enableAria ? { aria: enableAria } : {}),
        ...ariaRoleDescription(model),
        ...description(model)
    };
}
function ariaRoleDescription(model) {
    const { mark, markDef, config } = model;
    if (config.aria === false) {
        return {};
    }
    const ariaRoleDesc = getMarkPropOrConfig('ariaRoleDescription', markDef, config);
    if (ariaRoleDesc != null) {
        return { ariaRoleDescription: { value: ariaRoleDesc } };
    }
    return vega_util_module_has(VG_MARK_INDEX, mark) ? {} : { ariaRoleDescription: { value: mark } };
}
function description(model) {
    const { encoding, markDef, config, stack } = model;
    const channelDef = encoding.description;
    if (channelDef) {
        return wrapCondition({
            model,
            channelDef,
            vgChannel: 'description',
            mainRefFn: cDef => textRef(cDef, model.config),
            invalidValueRef: undefined // aria encoding doesn't have continuous scales and thus can't have invalid values
        });
    }
    // Use default from mark def or config if defined.
    // Functions in encode usually just return undefined but since we are defining a default below, we need to check the default here.
    const descriptionValue = getMarkPropOrConfig('description', markDef, config);
    if (descriptionValue != null) {
        return {
            description: signalOrValueRef(descriptionValue)
        };
    }
    if (config.aria === false) {
        return {};
    }
    const data = tooltipData(encoding, stack, config);
    if (isEmpty(data)) {
        return undefined;
    }
    return {
        description: {
            signal: util_entries(data)
                .map(([key, value], index) => `"${index > 0 ? '; ' : ''}${key}: " + (${value})`)
                .join(' + ')
        }
    };
}
//# sourceMappingURL=aria.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/nonposition.js





/**
 * Return encode for non-positional channels with scales. (Text doesn't have scale.)
 */
function nonPosition(channel, model, opt = {}) {
    const { markDef, encoding, config } = model;
    const { vgChannel } = opt;
    let { defaultRef, defaultValue } = opt;
    const channelDef = encoding[channel];
    if (defaultRef === undefined) {
        // prettier-ignore
        defaultValue ?? (defaultValue = getMarkPropOrConfig(channel, markDef, config, {
            vgChannel,
            // If there is no conditonal def, we ignore vgConfig so the output spec is concise.
            // However, if there is a conditional def, we must include vgConfig so the default is respected.
            ignoreVgConfig: !isConditionalDef(channelDef)
        }));
        if (defaultValue !== undefined) {
            defaultRef = signalOrValueRef(defaultValue);
        }
    }
    const commonProps = {
        markDef,
        config,
        scaleName: model.scaleName(channel),
        scale: model.getScaleComponent(channel)
    };
    const invalidValueRef = getConditionalValueRefForIncludingInvalidValue({
        ...commonProps,
        scaleChannel: channel,
        channelDef
    });
    const mainRefFn = (cDef) => {
        return midPoint({
            ...commonProps,
            channel,
            channelDef: cDef,
            stack: null, // No need to provide stack for non-position as it does not affect mid point
            defaultRef
        });
    };
    return wrapCondition({
        model,
        channelDef,
        vgChannel: vgChannel ?? channel,
        invalidValueRef,
        mainRefFn
    });
}
//# sourceMappingURL=nonposition.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/color.js




function color_color(model, opt = { filled: undefined }) {
    const { markDef, encoding, config } = model;
    const { type: markType } = markDef;
    // Allow filled to be overridden (for trail's "filled")
    const filled = opt.filled ?? getMarkPropOrConfig('filled', markDef, config);
    const transparentIfNeeded = util_contains(['bar', 'point', 'circle', 'square', 'geoshape'], markType)
        ? 'transparent'
        : undefined;
    const defaultFill = getMarkPropOrConfig(filled === true ? 'color' : undefined, markDef, config, { vgChannel: 'fill' }) ??
        // need to add this manually as getMarkConfig normally drops config.mark[channel] if vgChannel is specified
        config.mark[filled === true && 'color'] ??
        // If there is no fill, always fill symbols, bar, geoshape
        // with transparent fills https://github.com/vega/vega-lite/issues/1316
        transparentIfNeeded;
    const defaultStroke = getMarkPropOrConfig(filled === false ? 'color' : undefined, markDef, config, { vgChannel: 'stroke' }) ??
        // need to add this manually as getMarkConfig normally drops config.mark[channel] if vgChannel is specified
        config.mark[filled === false && 'color'];
    const colorVgChannel = filled ? 'fill' : 'stroke';
    const fillStrokeMarkDefAndConfig = {
        ...(defaultFill ? { fill: signalOrValueRef(defaultFill) } : {}),
        ...(defaultStroke ? { stroke: signalOrValueRef(defaultStroke) } : {})
    };
    if (markDef.color && (filled ? markDef.fill : markDef.stroke)) {
        log_warn(droppingColor('property', { fill: 'fill' in markDef, stroke: 'stroke' in markDef }));
    }
    return {
        ...fillStrokeMarkDefAndConfig,
        ...nonPosition('color', model, {
            vgChannel: colorVgChannel,
            defaultValue: filled ? defaultFill : defaultStroke
        }),
        ...nonPosition('fill', model, {
            // if there is encoding.fill, include default fill just in case we have conditional-only fill encoding
            defaultValue: encoding.fill ? defaultFill : undefined
        }),
        ...nonPosition('stroke', model, {
            // if there is encoding.stroke, include default fill just in case we have conditional-only stroke encoding
            defaultValue: encoding.stroke ? defaultStroke : undefined
        })
    };
}
//# sourceMappingURL=color.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/zindex.js




function zindex(model) {
    const { encoding, mark } = model;
    const order = encoding.order;
    if (!isPathMark(mark) && isValueDef(order)) {
        return wrapCondition({
            model,
            channelDef: order,
            vgChannel: 'zindex',
            mainRefFn: cd => signalOrValueRef(cd.value),
            invalidValueRef: undefined // zindex encoding doesn't have continuous scales and thus can't have invalid values
        });
    }
    return {};
}
//# sourceMappingURL=zindex.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/offset.js


function positionOffset({ channel: baseChannel, markDef, encoding = {}, model, bandPosition }) {
    const channel = `${baseChannel}Offset`; // Need to cast as the type can't be inferred automatically
    const defaultValue = markDef[channel];
    // FIXME: remove as any
    const channelDef = encoding[channel];
    if ((channel === 'xOffset' || channel === 'yOffset') && channelDef) {
        const ref = midPoint({
            channel: channel,
            channelDef,
            markDef,
            config: model?.config,
            scaleName: model.scaleName(channel),
            scale: model.getScaleComponent(channel),
            stack: null,
            defaultRef: signalOrValueRef(defaultValue),
            bandPosition
        });
        return { offsetType: 'encoding', offset: ref };
    }
    const markDefOffsetValue = markDef[channel];
    if (markDefOffsetValue) {
        return { offsetType: 'visual', offset: markDefOffsetValue };
    }
    return {};
}
//# sourceMappingURL=offset.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/position-point.js






/**
 * Return encode for point (non-band) position channels.
 */
function pointPosition(channel, model, { defaultPos, vgChannel }) {
    const { encoding, markDef, config, stack } = model;
    const channelDef = encoding[channel];
    const channel2Def = encoding[getSecondaryRangeChannel(channel)];
    const scaleName = model.scaleName(channel);
    const scale = model.getScaleComponent(channel);
    const { offset, offsetType } = positionOffset({
        channel,
        markDef,
        encoding,
        model,
        bandPosition: 0.5
    });
    // Get default position or position from mark def
    const defaultRef = pointPositionDefaultRef({
        model,
        defaultPos,
        channel,
        scaleName,
        scale
    });
    const valueRef = !channelDef && isXorY(channel) && (encoding.latitude || encoding.longitude)
        ? // use geopoint output if there are lat/long and there is no point position overriding lat/long.
            { field: model.getName(channel) }
        : positionRef({
            channel,
            channelDef,
            channel2Def,
            markDef,
            config,
            scaleName,
            scale,
            stack,
            offset,
            defaultRef,
            bandPosition: offsetType === 'encoding' ? 0 : undefined
        });
    return valueRef ? { [vgChannel || channel]: valueRef } : undefined;
}
// TODO: we need to find a way to refactor these so that scaleName is a part of scale
// but that's complicated. For now, this is a huge step moving forward.
/**
 * @return Vega ValueRef for normal x- or y-position without projection
 */
function positionRef(params) {
    const { channel, channelDef, scaleName, stack, offset, markDef } = params;
    // This isn't a part of midPoint because we use midPoint for non-position too
    if (isFieldOrDatumDef(channelDef) && stack && channel === stack.fieldChannel) {
        if (isFieldDef(channelDef)) {
            let bandPosition = channelDef.bandPosition;
            if (bandPosition === undefined && markDef.type === 'text' && (channel === 'radius' || channel === 'theta')) {
                // theta and radius of text mark should use bandPosition = 0.5 by default
                // so that labels for arc marks are centered automatically
                bandPosition = 0.5;
            }
            if (bandPosition !== undefined) {
                return interpolatedSignalRef({
                    scaleName,
                    fieldOrDatumDef: channelDef, // positionRef always have type
                    startSuffix: 'start',
                    bandPosition,
                    offset
                });
            }
        }
        // x or y use stack_end so that stacked line's point mark use stack_end too.
        return valueRefForFieldOrDatumDef(channelDef, scaleName, { suffix: 'end' }, { offset });
    }
    return midPointRefWithPositionInvalidTest(params);
}
function pointPositionDefaultRef({ model, defaultPos, channel, scaleName, scale }) {
    const { markDef, config } = model;
    return () => {
        const mainChannel = getMainRangeChannel(channel);
        const vgChannel = getVgPositionChannel(channel);
        const definedValueOrConfig = getMarkPropOrConfig(channel, markDef, config, { vgChannel });
        if (definedValueOrConfig !== undefined) {
            return widthHeightValueOrSignalRef(channel, definedValueOrConfig);
        }
        switch (defaultPos) {
            case 'zeroOrMin':
                return zeroOrMinOrMaxPosition({ scaleName, scale, mode: 'zeroOrMin', mainChannel, config });
            case 'zeroOrMax':
                return zeroOrMinOrMaxPosition({
                    scaleName,
                    scale,
                    mode: { zeroOrMax: { widthSignal: model.width.signal, heightSignal: model.height.signal } },
                    mainChannel,
                    config
                });
            case 'mid': {
                const sizeRef = model[getSizeChannel(channel)];
                return { ...sizeRef, mult: 0.5 };
            }
        }
        // defaultPos === null
        return undefined;
    };
}
function zeroOrMinOrMaxPosition({ mainChannel, config, ...otherProps }) {
    const scaledValueRef = scaledZeroOrMinOrMax(otherProps);
    const { mode } = otherProps;
    if (scaledValueRef) {
        return scaledValueRef;
    }
    switch (mainChannel) {
        case 'radius': {
            if (mode === 'zeroOrMin') {
                return { value: 0 }; // min value
            }
            const { widthSignal, heightSignal } = mode.zeroOrMax;
            // max of radius is min(width, height) / 2
            return {
                signal: `min(${widthSignal},${heightSignal})/2`
            };
        }
        case 'theta':
            return mode === 'zeroOrMin' ? { value: 0 } : { signal: '2*PI' };
        case 'x':
            return mode === 'zeroOrMin' ? { value: 0 } : { field: { group: 'width' } };
        case 'y':
            return mode === 'zeroOrMin' ? { field: { group: 'height' } } : { value: 0 };
    }
}
//# sourceMappingURL=position-point.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/position-align.js




const ALIGNED_X_CHANNEL = {
    left: 'x',
    center: 'xc',
    right: 'x2'
};
const BASELINED_Y_CHANNEL = {
    top: 'y',
    middle: 'yc',
    bottom: 'y2'
};
function vgAlignedPositionChannel(channel, markDef, config, defaultAlign = 'middle') {
    if (channel === 'radius' || channel === 'theta') {
        return getVgPositionChannel(channel);
    }
    const alignChannel = channel === 'x' ? 'align' : 'baseline';
    const align = getMarkPropOrConfig(alignChannel, markDef, config);
    let alignExcludingSignal;
    if (isSignalRef(align)) {
        log_warn(rangeMarkAlignmentCannotBeExpression(alignChannel));
        alignExcludingSignal = undefined;
    }
    else {
        alignExcludingSignal = align;
    }
    // FIXME: remove as any
    if (channel === 'x') {
        return ALIGNED_X_CHANNEL[alignExcludingSignal || (defaultAlign === 'top' ? 'left' : 'center')];
    }
    else {
        return BASELINED_Y_CHANNEL[alignExcludingSignal || defaultAlign];
    }
}
//# sourceMappingURL=position-align.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/position-range.js









/**
 * Utility for area/rule position, which can be either point or range.
 * (One of the axes should be point and the other should be range.)
 */
function pointOrRangePosition(channel, model, { defaultPos, defaultPos2, range }) {
    if (range) {
        return rangePosition(channel, model, { defaultPos, defaultPos2 });
    }
    return pointPosition(channel, model, { defaultPos });
}
function rangePosition(channel, model, { defaultPos, defaultPos2 }) {
    const { markDef, config } = model;
    const channel2 = getSecondaryRangeChannel(channel);
    const sizeChannel = getSizeChannel(channel);
    const pos2Mixins = pointPosition2OrSize(model, defaultPos2, channel2);
    const vgChannel = pos2Mixins[sizeChannel]
        ? // If there is width/height, we need to position the marks based on the alignment.
            vgAlignedPositionChannel(channel, markDef, config)
        : // Otherwise, make sure to apply to the right Vg Channel (for arc mark)
            getVgPositionChannel(channel);
    return {
        ...pointPosition(channel, model, { defaultPos, vgChannel }),
        ...pos2Mixins
    };
}
/**
 * Return encode for x2, y2.
 * If channel is not specified, return one channel based on orientation.
 */
function pointPosition2OrSize(model, defaultPos, channel) {
    const { encoding, mark, markDef, stack, config } = model;
    const baseChannel = getMainRangeChannel(channel);
    const sizeChannel = getSizeChannel(channel);
    const vgChannel = getVgPositionChannel(channel);
    const channelDef = encoding[baseChannel];
    const scaleName = model.scaleName(baseChannel);
    const scale = model.getScaleComponent(baseChannel);
    const { offset } = channel in encoding || channel in markDef
        ? positionOffset({ channel, markDef, encoding, model })
        : positionOffset({ channel: baseChannel, markDef, encoding, model });
    if (!channelDef && (channel === 'x2' || channel === 'y2') && (encoding.latitude || encoding.longitude)) {
        const vgSizeChannel = getSizeChannel(channel);
        const size = model.markDef[vgSizeChannel];
        if (size != null) {
            return {
                [vgSizeChannel]: { value: size }
            };
        }
        else {
            return {
                [vgChannel]: { field: model.getName(channel) }
            };
        }
    }
    const valueRef = position2Ref({
        channel,
        channelDef,
        channel2Def: encoding[channel],
        markDef,
        config,
        scaleName,
        scale,
        stack,
        offset,
        defaultRef: undefined
    });
    if (valueRef !== undefined) {
        return { [vgChannel]: valueRef };
    }
    // TODO: check width/height encoding here once we add them
    // no x2/y2 encoding, then try to read x2/y2 or width/height based on precedence:
    // markDef > config.style > mark-specific config (config[mark]) > general mark config (config.mark)
    return (position2orSize(channel, markDef) ||
        position2orSize(channel, {
            [channel]: getMarkStyleConfig(channel, markDef, config.style),
            [sizeChannel]: getMarkStyleConfig(sizeChannel, markDef, config.style)
        }) ||
        position2orSize(channel, config[mark]) ||
        position2orSize(channel, config.mark) || {
        [vgChannel]: pointPositionDefaultRef({
            model,
            defaultPos,
            channel,
            scaleName,
            scale
        })()
    });
}
function position2Ref({ channel, channelDef, channel2Def, markDef, config, scaleName, scale, stack, offset, defaultRef }) {
    if (isFieldOrDatumDef(channelDef) &&
        stack &&
        // If fieldChannel is X and channel is X2 (or Y and Y2)
        channel.charAt(0) === stack.fieldChannel.charAt(0)) {
        return valueRefForFieldOrDatumDef(channelDef, scaleName, { suffix: 'start' }, { offset });
    }
    return midPointRefWithPositionInvalidTest({
        channel,
        channelDef: channel2Def,
        scaleName,
        scale,
        stack,
        markDef,
        config,
        offset,
        defaultRef
    });
}
function position2orSize(channel, markDef) {
    const sizeChannel = getSizeChannel(channel);
    const vgChannel = getVgPositionChannel(channel);
    if (markDef[vgChannel] !== undefined) {
        return { [vgChannel]: widthHeightValueOrSignalRef(channel, markDef[vgChannel]) };
    }
    else if (markDef[channel] !== undefined) {
        return { [vgChannel]: widthHeightValueOrSignalRef(channel, markDef[channel]) };
    }
    else if (markDef[sizeChannel]) {
        const dimensionSize = markDef[sizeChannel];
        if (isRelativeBandSize(dimensionSize)) {
            log_warn(relativeBandSizeNotSupported(sizeChannel));
        }
        else {
            return { [sizeChannel]: widthHeightValueOrSignalRef(channel, dimensionSize) };
        }
    }
    return undefined;
}
//# sourceMappingURL=position-range.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/position-rect.js



















function rectPosition(model, channel) {
    const { config, encoding, markDef } = model;
    const mark = markDef.type;
    const channel2 = getSecondaryRangeChannel(channel);
    const sizeChannel = getSizeChannel(channel);
    const channelDef = encoding[channel];
    const channelDef2 = encoding[channel2];
    const scale = model.getScaleComponent(channel);
    const scaleType = scale ? scale.get('type') : undefined;
    const orient = markDef.orient;
    const hasSizeDef = encoding[sizeChannel] ??
        encoding.size ??
        getMarkPropOrConfig('size', markDef, config, { vgChannel: sizeChannel });
    const offsetScaleChannel = getOffsetChannel(channel);
    const isBarOrTickBand = (mark === 'bar' && (channel === 'x' ? orient === 'vertical' : orient === 'horizontal')) ||
        (mark === 'tick' && (channel === 'y' ? orient === 'vertical' : orient === 'horizontal'));
    // x, x2, and width -- we must specify two of these in all conditions
    if (isFieldDef(channelDef) &&
        (isBinning(channelDef.bin) || isBinned(channelDef.bin) || (channelDef.timeUnit && !channelDef2)) &&
        !(hasSizeDef && !isRelativeBandSize(hasSizeDef)) &&
        !encoding[offsetScaleChannel] &&
        !hasDiscreteDomain(scaleType)) {
        return rectBinPosition({
            fieldDef: channelDef,
            fieldDef2: channelDef2,
            channel,
            model
        });
    }
    else if (((isFieldOrDatumDef(channelDef) && hasDiscreteDomain(scaleType)) || isBarOrTickBand) && !channelDef2) {
        return positionAndSize(channelDef, channel, model);
    }
    else {
        return rangePosition(channel, model, { defaultPos: 'zeroOrMax', defaultPos2: 'zeroOrMin' });
    }
}
function defaultSizeRef(sizeChannel, scaleName, scale, config, bandSize, hasFieldDef, mark) {
    if (isRelativeBandSize(bandSize)) {
        if (scale) {
            const scaleType = scale.get('type');
            if (scaleType === 'band') {
                let bandWidth = `bandwidth('${scaleName}')`;
                if (bandSize.band !== 1) {
                    bandWidth = `${bandSize.band} * ${bandWidth}`;
                }
                const minBandSize = getMarkConfig('minBandSize', { type: mark }, config);
                return { signal: minBandSize ? `max(${signalOrStringValue(minBandSize)}, ${bandWidth})` : bandWidth };
            }
            else if (bandSize.band !== 1) {
                log_warn(cannotUseRelativeBandSizeWithNonBandScale(scaleType));
                bandSize = undefined;
            }
        }
        else {
            return {
                mult: bandSize.band,
                field: { group: sizeChannel }
            };
        }
    }
    else if (isSignalRef(bandSize)) {
        return bandSize;
    }
    else if (bandSize) {
        return { value: bandSize };
    }
    // no valid band size
    if (scale) {
        const scaleRange = scale.get('range');
        if (isVgRangeStep(scaleRange) && vega_util_module_isNumber(scaleRange.step)) {
            return { value: scaleRange.step - 2 };
        }
    }
    if (!hasFieldDef) {
        const { bandPaddingInner, barBandPaddingInner, rectBandPaddingInner, tickBandPaddingInner } = config.scale;
        const padding = getFirstDefined(bandPaddingInner, mark === 'tick' ? tickBandPaddingInner : mark === 'bar' ? barBandPaddingInner : rectBandPaddingInner); // this part is like paddingInner in scale.ts
        if (isSignalRef(padding)) {
            return { signal: `(1 - (${padding.signal})) * ${sizeChannel}` };
        }
        else if (vega_util_module_isNumber(padding)) {
            return { signal: `${1 - padding} * ${sizeChannel}` };
        }
    }
    const defaultStep = getViewConfigDiscreteStep(config.view, sizeChannel);
    return { value: defaultStep - 2 };
}
/**
 * Output position encoding and its size encoding for continuous, point, and band scales.
 */
function positionAndSize(fieldDef, channel, model) {
    const { markDef, encoding, config, stack } = model;
    const orient = markDef.orient;
    const scaleName = model.scaleName(channel);
    const scale = model.getScaleComponent(channel);
    const vgSizeChannel = getSizeChannel(channel);
    const channel2 = getSecondaryRangeChannel(channel);
    const offsetScaleChannel = getOffsetChannel(channel);
    const offsetScaleName = model.scaleName(offsetScaleChannel);
    const offsetScale = model.getScaleComponent(getOffsetScaleChannel(channel));
    const useVlSizeChannel = 
    // Always uses size channel for ticks, because tick only calls rectPosition() for the size channel
    markDef.type === 'tick' ||
        // use "size" channel for bars, if there is orient and the channel matches the right orientation
        (orient === 'horizontal' && channel === 'y') ||
        (orient === 'vertical' && channel === 'x');
    // Use size encoding / mark property / config if it exists
    let sizeMixins;
    if (encoding.size || markDef.size) {
        if (useVlSizeChannel) {
            sizeMixins = nonPosition('size', model, {
                vgChannel: vgSizeChannel,
                defaultRef: signalOrValueRef(markDef.size)
            });
        }
        else {
            log_warn(cannotApplySizeToNonOrientedMark(markDef.type));
        }
    }
    const hasSizeFromMarkOrEncoding = !!sizeMixins;
    // Otherwise, apply default value
    const bandSize = getBandSize({
        channel,
        fieldDef,
        markDef,
        config,
        scaleType: (scale || offsetScale)?.get('type'),
        useVlSizeChannel
    });
    sizeMixins = sizeMixins || {
        [vgSizeChannel]: defaultSizeRef(vgSizeChannel, offsetScaleName || scaleName, offsetScale || scale, config, bandSize, !!fieldDef, markDef.type)
    };
    /*
      Band scales with size value and all point scales, use xc/yc + band=0.5
  
      Otherwise (band scales that has size based on a band ref), use x/y with position band = (1 - size_band) / 2.
      In this case, size_band is the band specified in the x/y-encoding.
      By default band is 1, so `(1 - band) / 2` = 0.
      If band is 0.6, the the x/y position in such case should be `(1 - band) / 2` = 0.2
     */
    const defaultBandAlign = (scale || offsetScale)?.get('type') === 'band' && isRelativeBandSize(bandSize) && !hasSizeFromMarkOrEncoding
        ? 'top'
        : 'middle';
    const vgChannel = vgAlignedPositionChannel(channel, markDef, config, defaultBandAlign);
    const center = vgChannel === 'xc' || vgChannel === 'yc';
    const { offset, offsetType } = positionOffset({ channel, markDef, encoding, model, bandPosition: center ? 0.5 : 0 });
    const posRef = midPointRefWithPositionInvalidTest({
        channel,
        channelDef: fieldDef,
        markDef,
        config,
        scaleName,
        scale,
        stack,
        offset,
        defaultRef: pointPositionDefaultRef({ model, defaultPos: 'mid', channel, scaleName, scale }),
        bandPosition: center
            ? offsetType === 'encoding'
                ? 0
                : 0.5
            : isSignalRef(bandSize)
                ? { signal: `(1-${bandSize})/2` }
                : isRelativeBandSize(bandSize)
                    ? (1 - bandSize.band) / 2
                    : 0
    });
    if (vgSizeChannel) {
        return { [vgChannel]: posRef, ...sizeMixins };
    }
    else {
        // otherwise, we must simulate size by setting position2 = position + size
        // (for theta/radius since Vega doesn't have thetaWidth/radiusWidth)
        const vgChannel2 = getVgPositionChannel(channel2);
        const sizeRef = sizeMixins[vgSizeChannel];
        const sizeOffset = offset ? { ...sizeRef, offset } : sizeRef;
        return {
            [vgChannel]: posRef,
            // posRef might be an array that wraps position invalid test
            [vgChannel2]: vega_util_module_isArray(posRef)
                ? [posRef[0], { ...posRef[1], offset: sizeOffset }]
                : {
                    ...posRef,
                    offset: sizeOffset
                }
        };
    }
}
function getBinSpacing(channel, spacing, reverse, axisTranslate, offset, minBandSize, bandSizeExpr) {
    if (isPolarPositionChannel(channel)) {
        return 0;
    }
    const isEnd = channel === 'x' || channel === 'y2';
    const spacingOffset = isEnd ? -spacing / 2 : spacing / 2;
    if (isSignalRef(reverse) || isSignalRef(offset) || isSignalRef(axisTranslate) || minBandSize) {
        const reverseExpr = signalOrStringValue(reverse);
        const offsetExpr = signalOrStringValue(offset);
        const axisTranslateExpr = signalOrStringValue(axisTranslate);
        const minBandSizeExpr = signalOrStringValue(minBandSize);
        const sign = isEnd ? '' : '-';
        const spacingAndSizeOffset = minBandSize
            ? `(${bandSizeExpr} < ${minBandSizeExpr} ? ${sign}0.5 * (${minBandSizeExpr} - (${bandSizeExpr})) : ${spacingOffset})`
            : spacingOffset;
        const t = axisTranslateExpr ? `${axisTranslateExpr} + ` : '';
        const r = reverseExpr ? `(${reverseExpr} ? -1 : 1) * ` : '';
        const o = offsetExpr ? `(${offsetExpr} + ${spacingAndSizeOffset})` : spacingAndSizeOffset;
        return {
            signal: t + r + o
        };
    }
    else {
        offset = offset || 0;
        return axisTranslate + (reverse ? -offset - spacingOffset : +offset + spacingOffset);
    }
}
function rectBinPosition({ fieldDef, fieldDef2, channel, model }) {
    const { config, markDef, encoding } = model;
    const scale = model.getScaleComponent(channel);
    const scaleName = model.scaleName(channel);
    const scaleType = scale ? scale.get('type') : undefined;
    const reverse = scale.get('reverse');
    const bandSize = getBandSize({ channel, fieldDef, markDef, config, scaleType });
    const axis = model.component.axes[channel]?.[0];
    const axisTranslate = axis?.get('translate') ?? 0.5; // vega default is 0.5
    const spacing = isXorY(channel) ? (getMarkPropOrConfig('binSpacing', markDef, config) ?? 0) : 0;
    const channel2 = getSecondaryRangeChannel(channel);
    const vgChannel = getVgPositionChannel(channel);
    const vgChannel2 = getVgPositionChannel(channel2);
    const minBandSize = getMarkConfig('minBandSize', markDef, config);
    const { offset } = positionOffset({ channel, markDef, encoding, model, bandPosition: 0 });
    const { offset: offset2 } = positionOffset({ channel: channel2, markDef, encoding, model, bandPosition: 0 });
    const bandSizeExpr = binSizeExpr({ fieldDef, scaleName });
    const binSpacingOffset = getBinSpacing(channel, spacing, reverse, axisTranslate, offset, minBandSize, bandSizeExpr);
    const binSpacingOffset2 = getBinSpacing(channel2, spacing, reverse, axisTranslate, offset2 ?? offset, minBandSize, bandSizeExpr);
    const bandPositionForBandSize = isSignalRef(bandSize)
        ? { signal: `(1-${bandSize.signal})/2` }
        : isRelativeBandSize(bandSize)
            ? (1 - bandSize.band) / 2
            : 0.5;
    const bandPosition = getBandPosition({ fieldDef, fieldDef2, markDef, config });
    if (isBinning(fieldDef.bin) || fieldDef.timeUnit) {
        const useRectOffsetField = fieldDef.timeUnit && bandPosition !== 0.5;
        return {
            [vgChannel2]: rectBinRef({
                fieldDef,
                scaleName,
                bandPosition: bandPositionForBandSize,
                offset: binSpacingOffset2,
                useRectOffsetField
            }),
            [vgChannel]: rectBinRef({
                fieldDef,
                scaleName,
                bandPosition: isSignalRef(bandPositionForBandSize)
                    ? { signal: `1-${bandPositionForBandSize.signal}` }
                    : 1 - bandPositionForBandSize,
                offset: binSpacingOffset,
                useRectOffsetField
            })
        };
    }
    else if (isBinned(fieldDef.bin)) {
        const startRef = valueRefForFieldOrDatumDef(fieldDef, scaleName, {}, { offset: binSpacingOffset2 });
        if (isFieldDef(fieldDef2)) {
            return {
                [vgChannel2]: startRef,
                [vgChannel]: valueRefForFieldOrDatumDef(fieldDef2, scaleName, {}, { offset: binSpacingOffset })
            };
        }
        else if (isBinParams(fieldDef.bin) && fieldDef.bin.step) {
            return {
                [vgChannel2]: startRef,
                [vgChannel]: {
                    signal: `scale("${scaleName}", ${vgField(fieldDef, { expr: 'datum' })} + ${fieldDef.bin.step})`,
                    offset: binSpacingOffset
                }
            };
        }
    }
    log_warn(channelRequiredForBinned(channel2));
    return undefined;
}
/**
 * Value Ref for binned fields
 */
function rectBinRef({ fieldDef, scaleName, bandPosition, offset, useRectOffsetField }) {
    return interpolatedSignalRef({
        scaleName,
        fieldOrDatumDef: fieldDef,
        bandPosition,
        offset,
        ...(useRectOffsetField
            ? {
                startSuffix: OFFSETTED_RECT_START_SUFFIX,
                endSuffix: OFFSETTED_RECT_END_SUFFIX
            }
            : {})
    });
}
//# sourceMappingURL=position-rect.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/base.js
















const ALWAYS_IGNORE = new Set(['aria', 'width', 'height']);
function baseEncodeEntry(model, ignore) {
    const { fill = undefined, stroke = undefined } = ignore.color === 'include' ? color_color(model) : {};
    return {
        ...markDefProperties(model.markDef, ignore),
        ...colorRef('fill', fill),
        ...colorRef('stroke', stroke),
        ...nonPosition('opacity', model),
        ...nonPosition('fillOpacity', model),
        ...nonPosition('strokeOpacity', model),
        ...nonPosition('strokeWidth', model),
        ...nonPosition('strokeDash', model),
        ...zindex(model),
        ...tooltip_tooltip(model),
        ...text_text(model, 'href'),
        ...aria(model)
    };
}
function colorRef(channel, valueRef) {
    return valueRef ? { [channel]: valueRef } : {};
}
function markDefProperties(mark, ignore) {
    return VG_MARK_CONFIGS.reduce((m, prop) => {
        if (!ALWAYS_IGNORE.has(prop) && util_hasProperty(mark, prop) && ignore[prop] !== 'ignore') {
            m[prop] = signalOrValueRef(mark[prop]);
        }
        return m;
    }, {});
}
//# sourceMappingURL=base.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/defined.js





/**
 * Create Vega's "defined" encoding to break paths in a path mark for invalid values.
 */
function defined(model) {
    const { config, markDef } = model;
    // For each channel (x/y), add fields to break path to a set first.
    const fieldsToBreakPath = new Set();
    model.forEachFieldDef((fieldDef, channel) => {
        let scaleType;
        if (!isScaleChannel(channel) || !(scaleType = model.getScaleType(channel))) {
            // Skip if the channel is not a scale channel or does not have a scale
            return;
        }
        const isCountAggregate = isCountingAggregateOp(fieldDef.aggregate);
        const invalidDataMode = getScaleInvalidDataMode({
            scaleChannel: channel,
            markDef,
            config,
            scaleType,
            isCountAggregate
        });
        if (shouldBreakPath(invalidDataMode)) {
            const field = model.vgField(channel, { expr: 'datum', binSuffix: model.stack?.impute ? 'mid' : undefined });
            if (field) {
                fieldsToBreakPath.add(field);
            }
        }
    });
    // If the set is not empty, return a defined signal.
    if (fieldsToBreakPath.size > 0) {
        const signal = [...fieldsToBreakPath].map(field => fieldValidPredicate(field, true)).join(' && ');
        return { defined: { signal } };
    }
    return undefined;
}
function valueIfDefined(prop, value) {
    if (value !== undefined) {
        return { [prop]: signalOrValueRef(value) };
    }
    return undefined;
}
//# sourceMappingURL=defined.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/encode/index.js










//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/nearest.js



const VORONOI = 'voronoi';
const nearest = {
    defined: selCmpt => {
        return selCmpt.type === 'point' && selCmpt.nearest;
    },
    parse: (model, selCmpt) => {
        // Scope selection events to the voronoi mark to prevent capturing
        // events that occur on the group mark (https://github.com/vega/vega/issues/2112).
        if (selCmpt.events) {
            for (const s of selCmpt.events) {
                s.markname = model.getName(VORONOI);
            }
        }
    },
    marks: (model, selCmpt, marks) => {
        const { x, y } = selCmpt.project.hasChannel;
        const markType = model.mark;
        if (isPathMark(markType)) {
            log_warn(nearestNotSupportForContinuous(markType));
            return marks;
        }
        const cellDef = {
            name: model.getName(VORONOI),
            type: 'path',
            interactive: true,
            from: { data: model.getName('marks') },
            encode: {
                update: {
                    fill: { value: 'transparent' },
                    strokeWidth: { value: 0.35 },
                    stroke: { value: 'transparent' },
                    isVoronoi: { value: true },
                    ...tooltip_tooltip(model, { reactiveGeom: true })
                }
            },
            transform: [
                {
                    type: 'voronoi',
                    x: { expr: x || !y ? 'datum.datum.x || 0' : '0' },
                    y: { expr: y || !x ? 'datum.datum.y || 0' : '0' },
                    size: [model.getSizeSignalRef('width'), model.getSizeSignalRef('height')]
                }
            ]
        };
        let index = 0;
        let exists = false;
        marks.forEach((mark, i) => {
            const name = mark.name ?? '';
            if (name === model.component.mark[0].name) {
                index = i;
            }
            else if (name.includes(VORONOI)) {
                exists = true;
            }
        });
        if (!exists) {
            marks.splice(index + 1, 0, cellDef);
        }
        return marks;
    }
};
/* harmony default export */ const selection_nearest = (nearest);
//# sourceMappingURL=nearest.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/inputs.js







const inputBindings = {
    defined: selCmpt => {
        return (selCmpt.type === 'point' &&
            selCmpt.resolve === 'global' &&
            selCmpt.bind &&
            selCmpt.bind !== 'scales' &&
            !isLegendBinding(selCmpt.bind));
    },
    parse: (model, selCmpt, selDef) => disableDirectManipulation(selCmpt, selDef),
    topLevelSignals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const proj = selCmpt.project;
        const bind = selCmpt.bind;
        const init = selCmpt.init && selCmpt.init[0]; // Can only exist on single selections (one initial value).
        const datum = selection_nearest.defined(selCmpt) ? '(item().isVoronoi ? datum.datum : datum)' : 'datum';
        proj.items.forEach((p, i) => {
            const sgname = varName(`${name}_${p.field}`);
            const hasSignal = signals.filter(s => s.name === sgname);
            if (!hasSignal.length) {
                signals.unshift({
                    name: sgname,
                    ...(init ? { init: assembleInit(init[i]) } : { value: null }),
                    on: selCmpt.events
                        ? [
                            {
                                events: selCmpt.events,
                                update: `datum && item().mark.marktype !== 'group' ? ${datum}[${$(p.field)}] : null`
                            }
                        ]
                        : [],
                    bind: bind[p.field] ?? bind[p.channel] ?? bind
                });
            }
        });
        return signals;
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const proj = selCmpt.project;
        const signal = signals.find(s => s.name === name + TUPLE);
        const fields = name + TUPLE_FIELDS;
        const values = proj.items.map(p => varName(`${name}_${p.field}`));
        const valid = values.map(v => `${v} !== null`).join(' && ');
        if (values.length) {
            signal.update = `${valid} ? {fields: ${fields}, values: [${values.join(', ')}]} : null`;
        }
        delete signal.value;
        delete signal.on;
        return signals;
    }
};
/* harmony default export */ const inputs = (inputBindings);
//# sourceMappingURL=inputs.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/toggle.js

const TOGGLE = '_toggle';
const toggle = {
    defined: selCmpt => {
        return selCmpt.type === 'point' && !isTimerSelection(selCmpt) && !!selCmpt.toggle;
    },
    signals: (model, selCmpt, signals) => {
        return signals.concat({
            name: selCmpt.name + TOGGLE,
            value: false,
            on: [{ events: selCmpt.events, update: selCmpt.toggle }]
        });
    },
    modifyExpr: (model, selCmpt) => {
        const tpl = selCmpt.name + TUPLE;
        const signal = selCmpt.name + TOGGLE;
        return (`${signal} ? null : ${tpl}, ` +
            (selCmpt.resolve === 'global' ? `${signal} ? null : true, ` : `${signal} ? null : {unit: ${unitName(model)}}, `) +
            `${signal} ? ${tpl} : null`);
    }
};
/* harmony default export */ const selection_toggle = (toggle);
//# sourceMappingURL=toggle.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/clear.js






const clear = {
    defined: selCmpt => {
        return selCmpt.clear !== undefined && selCmpt.clear !== false && !isTimerSelection(selCmpt);
    },
    parse: (model, selCmpt) => {
        if (selCmpt.clear) {
            selCmpt.clear = vega_util_module_isString(selCmpt.clear) ? eventSelector(selCmpt.clear, 'view') : selCmpt.clear;
        }
    },
    topLevelSignals: (model, selCmpt, signals) => {
        if (inputs.defined(selCmpt)) {
            for (const proj of selCmpt.project.items) {
                const idx = signals.findIndex(n => n.name === varName(`${selCmpt.name}_${proj.field}`));
                if (idx !== -1) {
                    signals[idx].on.push({ events: selCmpt.clear, update: 'null' });
                }
            }
        }
        return signals;
    },
    signals: (model, selCmpt, signals) => {
        function addClear(idx, update) {
            if (idx !== -1 && signals[idx].on) {
                signals[idx].on.push({ events: selCmpt.clear, update });
            }
        }
        // Be as minimalist as possible when adding clear triggers to minimize dataflow execution.
        if (selCmpt.type === 'interval') {
            for (const proj of selCmpt.project.items) {
                const vIdx = signals.findIndex(n => n.name === proj.signals.visual);
                addClear(vIdx, '[0, 0]');
                if (vIdx === -1) {
                    const dIdx = signals.findIndex(n => n.name === proj.signals.data);
                    addClear(dIdx, 'null');
                }
            }
        }
        else {
            let tIdx = signals.findIndex(n => n.name === selCmpt.name + TUPLE);
            addClear(tIdx, 'null');
            if (selection_toggle.defined(selCmpt)) {
                tIdx = signals.findIndex(n => n.name === selCmpt.name + TOGGLE);
                addClear(tIdx, 'false');
            }
        }
        return signals;
    }
};
/* harmony default export */ const selection_clear = (clear);
//# sourceMappingURL=clear.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/legends.js









const legendBindings = {
    defined: selCmpt => {
        const spec = selCmpt.resolve === 'global' && selCmpt.bind && isLegendBinding(selCmpt.bind);
        const projLen = selCmpt.project.items.length === 1 && selCmpt.project.items[0].field !== SELECTION_ID;
        if (spec && !projLen) {
            log_warn(LEGEND_BINDINGS_MUST_HAVE_PROJECTION);
        }
        return spec && projLen;
    },
    parse: (model, selCmpt, selDef) => {
        // Allow legend items to be toggleable by default even though direct manipulation is disabled.
        const selDef_ = duplicate(selDef);
        selDef_.select = vega_util_module_isString(selDef_.select)
            ? { type: selDef_.select, toggle: selCmpt.toggle }
            : { ...selDef_.select, toggle: selCmpt.toggle };
        disableDirectManipulation(selCmpt, selDef_);
        if (vega_util_module_isObject(selDef.select) && (selDef.select.on || selDef.select.clear)) {
            const legendFilter = 'event.item && indexof(event.item.mark.role, "legend") < 0';
            for (const evt of selCmpt.events) {
                evt.filter = vega_util_module_array(evt.filter ?? []);
                if (!evt.filter.includes(legendFilter)) {
                    evt.filter.push(legendFilter);
                }
            }
        }
        const evt = isLegendStreamBinding(selCmpt.bind) ? selCmpt.bind.legend : 'click';
        const stream = vega_util_module_isString(evt) ? eventSelector(evt, 'view') : vega_util_module_array(evt);
        selCmpt.bind = { legend: { merge: stream } };
    },
    topLevelSignals: (model, selCmpt, signals) => {
        const selName = selCmpt.name;
        const stream = isLegendStreamBinding(selCmpt.bind) && selCmpt.bind.legend;
        const markName = (name) => (s) => {
            const ds = duplicate(s);
            ds.markname = name;
            return ds;
        };
        for (const proj of selCmpt.project.items) {
            if (!proj.hasLegend)
                continue;
            const prefix = `${varName(proj.field)}_legend`;
            const sgName = `${selName}_${prefix}`;
            const hasSignal = signals.filter(s => s.name === sgName);
            if (hasSignal.length === 0) {
                const events = stream.merge
                    .map(markName(`${prefix}_symbols`))
                    .concat(stream.merge.map(markName(`${prefix}_labels`)))
                    .concat(stream.merge.map(markName(`${prefix}_entries`)));
                signals.unshift({
                    name: sgName,
                    ...(!selCmpt.init ? { value: null } : {}),
                    on: [
                        // Legend entries do not store values, so we need to walk the scenegraph to the symbol datum.
                        {
                            events,
                            update: 'isDefined(datum.value) ? datum.value : item().items[0].items[0].datum.value',
                            force: true
                        },
                        { events: stream.merge, update: `!event.item || !datum ? null : ${sgName}`, force: true }
                    ]
                });
            }
        }
        return signals;
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const proj = selCmpt.project;
        const tuple = signals.find(s => s.name === name + TUPLE);
        const fields = name + TUPLE_FIELDS;
        const values = proj.items.filter(p => p.hasLegend).map(p => varName(`${name}_${varName(p.field)}_legend`));
        const valid = values.map(v => `${v} !== null`).join(' && ');
        const update = `${valid} ? {fields: ${fields}, values: [${values.join(', ')}]} : null`;
        if (selCmpt.events && values.length > 0) {
            tuple.on.push({
                events: values.map(signal => ({ signal })),
                update
            });
        }
        else if (values.length > 0) {
            tuple.update = update;
            delete tuple.value;
            delete tuple.on;
        }
        const toggle = signals.find(s => s.name === name + TOGGLE);
        const events = isLegendStreamBinding(selCmpt.bind) && selCmpt.bind.legend;
        if (toggle) {
            if (!selCmpt.events)
                toggle.on[0].events = events;
            else
                toggle.on.push({ ...toggle.on[0], events });
        }
        return signals;
    }
};
/* harmony default export */ const legends = (legendBindings);
function parseInteractiveLegend(model, channel, legendCmpt) {
    const field = model.fieldDef(channel)?.field;
    for (const selCmpt of vals(model.component.selection ?? {})) {
        const proj = selCmpt.project.hasField[field] ?? selCmpt.project.hasChannel[channel];
        if (proj && legendBindings.defined(selCmpt)) {
            const legendSelections = legendCmpt.get('selections') ?? [];
            legendSelections.push(selCmpt.name);
            legendCmpt.set('selections', legendSelections, false);
            proj.hasLegend = true;
        }
    }
}
//# sourceMappingURL=legends.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/translate.js




const ANCHOR = '_translate_anchor';
const DELTA = '_translate_delta';
const translate_translate = {
    defined: selCmpt => {
        return selCmpt.type === 'interval' && selCmpt.translate;
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const boundScales = selection_scales.defined(selCmpt);
        const anchor = name + ANCHOR;
        const { x, y } = selCmpt.project.hasChannel;
        let events = eventSelector(selCmpt.translate, 'scope');
        if (!boundScales) {
            events = events.map(e => ((e.between[0].markname = name + BRUSH), e));
        }
        signals.push({
            name: anchor,
            value: {},
            on: [
                {
                    events: events.map(e => e.between[0]),
                    update: '{x: x(unit), y: y(unit)' +
                        (x !== undefined ? `, extent_x: ${boundScales ? scales_domain(model, channel_X) : `slice(${x.signals.visual})`}` : '') +
                        (y !== undefined ? `, extent_y: ${boundScales ? scales_domain(model, channel_Y) : `slice(${y.signals.visual})`}` : '') +
                        '}'
                }
            ]
        }, {
            name: name + DELTA,
            value: {},
            on: [
                {
                    events,
                    update: `{x: ${anchor}.x - x(unit), y: ${anchor}.y - y(unit)}`
                }
            ]
        });
        if (x !== undefined) {
            onDelta(model, selCmpt, x, 'width', signals);
        }
        if (y !== undefined) {
            onDelta(model, selCmpt, y, 'height', signals);
        }
        return signals;
    }
};
/* harmony default export */ const selection_translate = (translate_translate);
function onDelta(model, selCmpt, proj, size, signals) {
    const name = selCmpt.name;
    const anchor = name + ANCHOR;
    const delta = name + DELTA;
    const channel = proj.channel;
    const boundScales = selection_scales.defined(selCmpt);
    const signal = signals.find(s => s.name === proj.signals[boundScales ? 'data' : 'visual']);
    const sizeSg = model.getSizeSignalRef(size).signal;
    const scaleCmpt = model.getScaleComponent(channel);
    const scaleType = scaleCmpt && scaleCmpt.get('type');
    const reversed = scaleCmpt && scaleCmpt.get('reverse'); // scale parsing sets this flag for fieldDef.sort
    const sign = !boundScales ? '' : channel === channel_X ? (reversed ? '' : '-') : reversed ? '-' : '';
    const extent = `${anchor}.extent_${channel}`;
    const offset = `${sign}${delta}.${channel} / ${boundScales ? `${sizeSg}` : `span(${extent})`}`;
    const panFn = !boundScales || !scaleCmpt
        ? 'panLinear'
        : scaleType === 'log'
            ? 'panLog'
            : scaleType === 'symlog'
                ? 'panSymlog'
                : scaleType === 'pow'
                    ? 'panPow'
                    : 'panLinear';
    const arg = !boundScales
        ? ''
        : scaleType === 'pow'
            ? `, ${scaleCmpt.get('exponent') ?? 1}`
            : scaleType === 'symlog'
                ? `, ${scaleCmpt.get('constant') ?? 1}`
                : '';
    const update = `${panFn}(${extent}, ${offset}${arg})`;
    signal.on.push({
        events: { signal: delta },
        update: boundScales ? update : `clampRange(${update}, 0, ${sizeSg})`
    });
}
//# sourceMappingURL=translate.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/zoom.js





const zoom_ANCHOR = '_zoom_anchor';
const zoom_DELTA = '_zoom_delta';
const zoom_zoom = {
    defined: selCmpt => {
        return selCmpt.type === 'interval' && selCmpt.zoom;
    },
    signals: (model, selCmpt, signals) => {
        const name = selCmpt.name;
        const boundScales = selection_scales.defined(selCmpt);
        const delta = name + zoom_DELTA;
        const { x, y } = selCmpt.project.hasChannel;
        const sx = $(model.scaleName(channel_X));
        const sy = $(model.scaleName(channel_Y));
        let events = eventSelector(selCmpt.zoom, 'scope');
        if (!boundScales) {
            events = events.map(e => ((e.markname = name + BRUSH), e));
        }
        signals.push({
            name: name + zoom_ANCHOR,
            on: [
                {
                    events,
                    update: !boundScales
                        ? `{x: x(unit), y: y(unit)}`
                        : '{' +
                            [sx ? `x: invert(${sx}, x(unit))` : '', sy ? `y: invert(${sy}, y(unit))` : '']
                                .filter(expr => expr)
                                .join(', ') +
                            '}'
                }
            ]
        }, {
            name: delta,
            on: [
                {
                    events,
                    force: true,
                    update: 'pow(1.001, event.deltaY * pow(16, event.deltaMode))'
                }
            ]
        });
        if (x !== undefined) {
            zoom_onDelta(model, selCmpt, x, 'width', signals);
        }
        if (y !== undefined) {
            zoom_onDelta(model, selCmpt, y, 'height', signals);
        }
        return signals;
    }
};
/* harmony default export */ const selection_zoom = (zoom_zoom);
function zoom_onDelta(model, selCmpt, proj, size, signals) {
    const name = selCmpt.name;
    const channel = proj.channel;
    const boundScales = selection_scales.defined(selCmpt);
    const signal = signals.find(s => s.name === proj.signals[boundScales ? 'data' : 'visual']);
    const sizeSg = model.getSizeSignalRef(size).signal;
    const scaleCmpt = model.getScaleComponent(channel);
    const scaleType = scaleCmpt && scaleCmpt.get('type');
    const base = boundScales ? scales_domain(model, channel) : signal.name;
    const delta = name + zoom_DELTA;
    const anchor = `${name}${zoom_ANCHOR}.${channel}`;
    const zoomFn = !boundScales || !scaleCmpt
        ? 'zoomLinear'
        : scaleType === 'log'
            ? 'zoomLog'
            : scaleType === 'symlog'
                ? 'zoomSymlog'
                : scaleType === 'pow'
                    ? 'zoomPow'
                    : 'zoomLinear';
    const arg = !boundScales
        ? ''
        : scaleType === 'pow'
            ? `, ${scaleCmpt.get('exponent') ?? 1}`
            : scaleType === 'symlog'
                ? `, ${scaleCmpt.get('constant') ?? 1}`
                : '';
    const update = `${zoomFn}(${base}, ${anchor}, ${delta}${arg})`;
    signal.on.push({
        events: { signal: delta },
        update: boundScales ? update : `clampRange(${update}, 0, ${sizeSg})`
    });
}
//# sourceMappingURL=zoom.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/index.js
















const STORE = '_store';
const TUPLE = '_tuple';
const MODIFY = '_modify';
const SELECTION_DOMAIN = '_selection_domain_';
const VL_SELECTION_RESOLVE = 'vlSelectionResolve';
// Order matters for parsing and assembly.
const selectionCompilers = [
    selection_point,
    selection_interval,
    selection_project,
    selection_toggle,
    // Bindings may disable direct manipulation.
    inputs,
    selection_scales,
    legends,
    selection_clear,
    selection_translate,
    selection_zoom,
    selection_nearest
];
function getFacetModel(model) {
    let parent = model.parent;
    while (parent) {
        if (isFacetModel(parent))
            break;
        parent = parent.parent;
    }
    return parent;
}
function unitName(model, { escape } = { escape: true }) {
    let name = escape ? $(model.name) : model.name;
    const facetModel = getFacetModel(model);
    if (facetModel) {
        const { facet } = facetModel;
        for (const channel of FACET_CHANNELS) {
            if (facet[channel]) {
                name += ` + '__facet_${channel}_' + (facet[${$(facetModel.vgField(channel))}])`;
            }
        }
    }
    return name;
}
function requiresSelectionId(model) {
    return vals(model.component.selection ?? {}).reduce((identifier, selCmpt) => {
        return identifier || selCmpt.project.hasSelectionId;
    }, false);
}
// Binding a point selection to query widgets or legends disables default direct manipulation interaction.
// A user can choose to re-enable it by explicitly specifying triggering input events.
function disableDirectManipulation(selCmpt, selDef) {
    if (vega_util_module_isString(selDef.select) || !selDef.select.on)
        delete selCmpt.events;
    if (vega_util_module_isString(selDef.select) || !selDef.select.clear)
        delete selCmpt.clear;
    if (vega_util_module_isString(selDef.select) || !selDef.select.toggle)
        delete selCmpt.toggle;
}
function isTimerSelection(selCmpt) {
    return selCmpt.events?.find(e => 'type' in e && e.type === 'timer');
}
//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-lite/node_modules/vega-expression/build/vega-expression.module.js


const vega_expression_module_RawCode = 'RawCode';
const build_vega_expression_module_Literal = 'Literal';
const build_vega_expression_module_Property = 'Property';
const build_vega_expression_module_Identifier = 'Identifier';
const vega_expression_module_ArrayExpression = 'ArrayExpression';
const vega_expression_module_BinaryExpression = 'BinaryExpression';
const vega_expression_module_CallExpression = 'CallExpression';
const vega_expression_module_ConditionalExpression = 'ConditionalExpression';
const vega_expression_module_LogicalExpression = 'LogicalExpression';
const build_vega_expression_module_MemberExpression = 'MemberExpression';
const build_vega_expression_module_ObjectExpression = 'ObjectExpression';
const vega_expression_module_UnaryExpression = 'UnaryExpression';
function vega_expression_module_ASTNode(type) {
  this.type = type;
}
vega_expression_module_ASTNode.prototype.visit = function (visitor) {
  let c, i, n;
  if (visitor(this)) return 1;
  for (c = build_vega_expression_module_children(this), i = 0, n = c.length; i < n; ++i) {
    if (c[i].visit(visitor)) return 1;
  }
};
function build_vega_expression_module_children(node) {
  switch (node.type) {
    case vega_expression_module_ArrayExpression:
      return node.elements;
    case vega_expression_module_BinaryExpression:
    case vega_expression_module_LogicalExpression:
      return [node.left, node.right];
    case vega_expression_module_CallExpression:
      return [node.callee].concat(node.arguments);
    case vega_expression_module_ConditionalExpression:
      return [node.test, node.consequent, node.alternate];
    case build_vega_expression_module_MemberExpression:
      return [node.object, node.property];
    case build_vega_expression_module_ObjectExpression:
      return node.properties;
    case build_vega_expression_module_Property:
      return [node.key, node.value];
    case vega_expression_module_UnaryExpression:
      return [node.argument];
    case build_vega_expression_module_Identifier:
    case build_vega_expression_module_Literal:
    case vega_expression_module_RawCode:
    default:
      return [];
  }
}

/*
  The following expression parser is based on Esprima (http://esprima.org/).
  Original header comment and license for Esprima is included here:

  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
  Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be>
  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var vega_expression_module_TokenName, build_vega_expression_module_source, build_vega_expression_module_index, build_vega_expression_module_length, vega_expression_module_lookahead;
var vega_expression_module_TokenBooleanLiteral = 1,
  vega_expression_module_TokenEOF = 2,
  vega_expression_module_TokenIdentifier = 3,
  vega_expression_module_TokenKeyword = 4,
  vega_expression_module_TokenNullLiteral = 5,
  vega_expression_module_TokenNumericLiteral = 6,
  vega_expression_module_TokenPunctuator = 7,
  vega_expression_module_TokenStringLiteral = 8,
  vega_expression_module_TokenRegularExpression = 9;
vega_expression_module_TokenName = {};
vega_expression_module_TokenName[vega_expression_module_TokenBooleanLiteral] = 'Boolean';
vega_expression_module_TokenName[vega_expression_module_TokenEOF] = '<end>';
vega_expression_module_TokenName[vega_expression_module_TokenIdentifier] = 'Identifier';
vega_expression_module_TokenName[vega_expression_module_TokenKeyword] = 'Keyword';
vega_expression_module_TokenName[vega_expression_module_TokenNullLiteral] = 'Null';
vega_expression_module_TokenName[vega_expression_module_TokenNumericLiteral] = 'Numeric';
vega_expression_module_TokenName[vega_expression_module_TokenPunctuator] = 'Punctuator';
vega_expression_module_TokenName[vega_expression_module_TokenStringLiteral] = 'String';
vega_expression_module_TokenName[vega_expression_module_TokenRegularExpression] = 'RegularExpression';
var vega_expression_module_SyntaxArrayExpression = 'ArrayExpression',
  vega_expression_module_SyntaxBinaryExpression = 'BinaryExpression',
  vega_expression_module_SyntaxCallExpression = 'CallExpression',
  vega_expression_module_SyntaxConditionalExpression = 'ConditionalExpression',
  vega_expression_module_SyntaxIdentifier = 'Identifier',
  vega_expression_module_SyntaxLiteral = 'Literal',
  vega_expression_module_SyntaxLogicalExpression = 'LogicalExpression',
  vega_expression_module_SyntaxMemberExpression = 'MemberExpression',
  vega_expression_module_SyntaxObjectExpression = 'ObjectExpression',
  vega_expression_module_SyntaxProperty = 'Property',
  vega_expression_module_SyntaxUnaryExpression = 'UnaryExpression';

// Error messages should be identical to V8.
var vega_expression_module_MessageUnexpectedToken = 'Unexpected token %0',
  vega_expression_module_MessageUnexpectedNumber = 'Unexpected number',
  vega_expression_module_MessageUnexpectedString = 'Unexpected string',
  vega_expression_module_MessageUnexpectedIdentifier = 'Unexpected identifier',
  vega_expression_module_MessageUnexpectedReserved = 'Unexpected reserved word',
  vega_expression_module_MessageUnexpectedEOS = 'Unexpected end of input',
  vega_expression_module_MessageInvalidRegExp = 'Invalid regular expression',
  vega_expression_module_MessageUnterminatedRegExp = 'Invalid regular expression: missing /',
  vega_expression_module_MessageStrictOctalLiteral = 'Octal literals are not allowed in strict mode.',
  vega_expression_module_MessageStrictDuplicateProperty = 'Duplicate data property in object literal not allowed in strict mode';
var vega_expression_module_ILLEGAL = 'ILLEGAL',
  vega_expression_module_DISABLED = 'Disabled.';

// See also tools/generate-unicode-regex.py.
var vega_expression_module_RegexNonAsciiIdentifierStart = new RegExp('[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]'),
  // eslint-disable-next-line no-misleading-character-class
  vega_expression_module_RegexNonAsciiIdentifierPart = new RegExp('[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]');

// Ensure the condition is true, otherwise throw an error.
// This is only to have a better contract semantic, i.e. another safety net
// to catch a logic error. The condition shall be fulfilled in normal case.
// Do NOT use this to enforce a certain condition on any user input.

function vega_expression_module_assert(condition, message) {
  /* istanbul ignore next */
  if (!condition) {
    throw new Error('ASSERT: ' + message);
  }
}
function build_vega_expression_module_isDecimalDigit(ch) {
  return ch >= 0x30 && ch <= 0x39; // 0..9
}
function build_vega_expression_module_isHexDigit(ch) {
  return '0123456789abcdefABCDEF'.includes(ch);
}
function build_vega_expression_module_isOctalDigit(ch) {
  return '01234567'.includes(ch);
}

// 7.2 White Space

function vega_expression_module_isWhiteSpace(ch) {
  return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 || ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].includes(ch);
}

// 7.3 Line Terminators

function vega_expression_module_isLineTerminator(ch) {
  return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029;
}

// 7.6 Identifier Names and Identifiers

function build_vega_expression_module_isIdentifierStart(ch) {
  return ch === 0x24 || ch === 0x5F ||
  // $ (dollar) and _ (underscore)
  ch >= 0x41 && ch <= 0x5A ||
  // A..Z
  ch >= 0x61 && ch <= 0x7A ||
  // a..z
  ch === 0x5C ||
  // \ (backslash)
  ch >= 0x80 && vega_expression_module_RegexNonAsciiIdentifierStart.test(String.fromCharCode(ch));
}
function vega_expression_module_isIdentifierPart(ch) {
  return ch === 0x24 || ch === 0x5F ||
  // $ (dollar) and _ (underscore)
  ch >= 0x41 && ch <= 0x5A ||
  // A..Z
  ch >= 0x61 && ch <= 0x7A ||
  // a..z
  ch >= 0x30 && ch <= 0x39 ||
  // 0..9
  ch === 0x5C ||
  // \ (backslash)
  ch >= 0x80 && vega_expression_module_RegexNonAsciiIdentifierPart.test(String.fromCharCode(ch));
}

// 7.6.1.1 Keywords

const build_vega_expression_module_keywords = {
  'if': 1,
  'in': 1,
  'do': 1,
  'var': 1,
  'for': 1,
  'new': 1,
  'try': 1,
  'let': 1,
  'this': 1,
  'else': 1,
  'case': 1,
  'void': 1,
  'with': 1,
  'enum': 1,
  'while': 1,
  'break': 1,
  'catch': 1,
  'throw': 1,
  'const': 1,
  'yield': 1,
  'class': 1,
  'super': 1,
  'return': 1,
  'typeof': 1,
  'delete': 1,
  'switch': 1,
  'export': 1,
  'import': 1,
  'public': 1,
  'static': 1,
  'default': 1,
  'finally': 1,
  'extends': 1,
  'package': 1,
  'private': 1,
  'function': 1,
  'continue': 1,
  'debugger': 1,
  'interface': 1,
  'protected': 1,
  'instanceof': 1,
  'implements': 1
};
function vega_expression_module_skipComment() {
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    const ch = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index);
    if (vega_expression_module_isWhiteSpace(ch) || vega_expression_module_isLineTerminator(ch)) {
      ++build_vega_expression_module_index;
    } else {
      break;
    }
  }
}
function vega_expression_module_scanHexEscape(prefix) {
  var i,
    len,
    ch,
    code = 0;
  len = prefix === 'u' ? 4 : 2;
  for (i = 0; i < len; ++i) {
    if (build_vega_expression_module_index < build_vega_expression_module_length && build_vega_expression_module_isHexDigit(build_vega_expression_module_source[build_vega_expression_module_index])) {
      ch = build_vega_expression_module_source[build_vega_expression_module_index++];
      code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
    } else {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
    }
  }
  return String.fromCharCode(code);
}
function vega_expression_module_scanUnicodeCodePointEscape() {
  var ch, code, cu1, cu2;
  ch = build_vega_expression_module_source[build_vega_expression_module_index];
  code = 0;

  // At least, one hex digit is required.
  if (ch === '}') {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source[build_vega_expression_module_index++];
    if (!build_vega_expression_module_isHexDigit(ch)) {
      break;
    }
    code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
  }
  if (code > 0x10FFFF || ch !== '}') {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }

  // UTF-16 Encoding
  if (code <= 0xFFFF) {
    return String.fromCharCode(code);
  }
  cu1 = (code - 0x10000 >> 10) + 0xD800;
  cu2 = (code - 0x10000 & 1023) + 0xDC00;
  return String.fromCharCode(cu1, cu2);
}
function vega_expression_module_getEscapedIdentifier() {
  var ch, id;
  ch = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index++);
  id = String.fromCharCode(ch);

  // '\u' (U+005C, U+0075) denotes an escaped character.
  if (ch === 0x5C) {
    if (build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index) !== 0x75) {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
    }
    ++build_vega_expression_module_index;
    ch = vega_expression_module_scanHexEscape('u');
    if (!ch || ch === '\\' || !build_vega_expression_module_isIdentifierStart(ch.charCodeAt(0))) {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
    }
    id = ch;
  }
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index);
    if (!vega_expression_module_isIdentifierPart(ch)) {
      break;
    }
    ++build_vega_expression_module_index;
    id += String.fromCharCode(ch);

    // '\u' (U+005C, U+0075) denotes an escaped character.
    if (ch === 0x5C) {
      id = id.substr(0, id.length - 1);
      if (build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index) !== 0x75) {
        vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
      }
      ++build_vega_expression_module_index;
      ch = vega_expression_module_scanHexEscape('u');
      if (!ch || ch === '\\' || !vega_expression_module_isIdentifierPart(ch.charCodeAt(0))) {
        vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
      }
      id += ch;
    }
  }
  return id;
}
function vega_expression_module_getIdentifier() {
  var start, ch;
  start = build_vega_expression_module_index++;
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index);
    if (ch === 0x5C) {
      // Blackslash (U+005C) marks Unicode escape sequence.
      build_vega_expression_module_index = start;
      return vega_expression_module_getEscapedIdentifier();
    }
    if (vega_expression_module_isIdentifierPart(ch)) {
      ++build_vega_expression_module_index;
    } else {
      break;
    }
  }
  return build_vega_expression_module_source.slice(start, build_vega_expression_module_index);
}
function vega_expression_module_scanIdentifier() {
  var start, id, type;
  start = build_vega_expression_module_index;

  // Backslash (U+005C) starts an escaped character.
  id = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index) === 0x5C ? vega_expression_module_getEscapedIdentifier() : vega_expression_module_getIdentifier();

  // There is no keyword or literal with only one character.
  // Thus, it must be an identifier.
  if (id.length === 1) {
    type = vega_expression_module_TokenIdentifier;
  } else if (build_vega_expression_module_keywords.hasOwnProperty(id)) {
    // eslint-disable-line no-prototype-builtins
    type = vega_expression_module_TokenKeyword;
  } else if (id === 'null') {
    type = vega_expression_module_TokenNullLiteral;
  } else if (id === 'true' || id === 'false') {
    type = vega_expression_module_TokenBooleanLiteral;
  } else {
    type = vega_expression_module_TokenIdentifier;
  }
  return {
    type: type,
    value: id,
    start: start,
    end: build_vega_expression_module_index
  };
}

// 7.7 Punctuators

function vega_expression_module_scanPunctuator() {
  var start = build_vega_expression_module_index,
    code = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index),
    code2,
    ch1 = build_vega_expression_module_source[build_vega_expression_module_index],
    ch2,
    ch3,
    ch4;
  switch (code) {
    // Check for most common single-character punctuators.
    case 0x2E: // . dot
    case 0x28: // ( open bracket
    case 0x29: // ) close bracket
    case 0x3B: // ; semicolon
    case 0x2C: // , comma
    case 0x7B: // { open curly brace
    case 0x7D: // } close curly brace
    case 0x5B: // [
    case 0x5D: // ]
    case 0x3A: // :
    case 0x3F: // ?
    case 0x7E:
      // ~
      ++build_vega_expression_module_index;
      return {
        type: vega_expression_module_TokenPunctuator,
        value: String.fromCharCode(code),
        start: start,
        end: build_vega_expression_module_index
      };
    default:
      code2 = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index + 1);

      // '=' (U+003D) marks an assignment or comparison operator.
      if (code2 === 0x3D) {
        switch (code) {
          case 0x2B: // +
          case 0x2D: // -
          case 0x2F: // /
          case 0x3C: // <
          case 0x3E: // >
          case 0x5E: // ^
          case 0x7C: // |
          case 0x25: // %
          case 0x26: // &
          case 0x2A:
            // *
            build_vega_expression_module_index += 2;
            return {
              type: vega_expression_module_TokenPunctuator,
              value: String.fromCharCode(code) + String.fromCharCode(code2),
              start: start,
              end: build_vega_expression_module_index
            };
          case 0x21: // !
          case 0x3D:
            // =
            build_vega_expression_module_index += 2;

            // !== and ===
            if (build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index) === 0x3D) {
              ++build_vega_expression_module_index;
            }
            return {
              type: vega_expression_module_TokenPunctuator,
              value: build_vega_expression_module_source.slice(start, build_vega_expression_module_index),
              start: start,
              end: build_vega_expression_module_index
            };
        }
      }
  }

  // 4-character punctuator: >>>=

  ch4 = build_vega_expression_module_source.substr(build_vega_expression_module_index, 4);
  if (ch4 === '>>>=') {
    build_vega_expression_module_index += 4;
    return {
      type: vega_expression_module_TokenPunctuator,
      value: ch4,
      start: start,
      end: build_vega_expression_module_index
    };
  }

  // 3-character punctuators: === !== >>> <<= >>=

  ch3 = ch4.substr(0, 3);
  if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
    build_vega_expression_module_index += 3;
    return {
      type: vega_expression_module_TokenPunctuator,
      value: ch3,
      start: start,
      end: build_vega_expression_module_index
    };
  }

  // Other 2-character punctuators: ++ -- << >> && ||
  ch2 = ch3.substr(0, 2);
  if (ch1 === ch2[1] && '+-<>&|'.includes(ch1) || ch2 === '=>') {
    build_vega_expression_module_index += 2;
    return {
      type: vega_expression_module_TokenPunctuator,
      value: ch2,
      start: start,
      end: build_vega_expression_module_index
    };
  }
  if (ch2 === '//') {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }

  // 1-character punctuators: < > = ! + - * % & | ^ /

  if ('<>=!+-*%&|^/'.includes(ch1)) {
    ++build_vega_expression_module_index;
    return {
      type: vega_expression_module_TokenPunctuator,
      value: ch1,
      start: start,
      end: build_vega_expression_module_index
    };
  }
  vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
}

// 7.8.3 Numeric Literals

function vega_expression_module_scanHexLiteral(start) {
  let number = '';
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    if (!build_vega_expression_module_isHexDigit(build_vega_expression_module_source[build_vega_expression_module_index])) {
      break;
    }
    number += build_vega_expression_module_source[build_vega_expression_module_index++];
  }
  if (number.length === 0) {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  if (build_vega_expression_module_isIdentifierStart(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  return {
    type: vega_expression_module_TokenNumericLiteral,
    value: parseInt('0x' + number, 16),
    start: start,
    end: build_vega_expression_module_index
  };
}
function vega_expression_module_scanOctalLiteral(start) {
  let number = '0' + build_vega_expression_module_source[build_vega_expression_module_index++];
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    if (!build_vega_expression_module_isOctalDigit(build_vega_expression_module_source[build_vega_expression_module_index])) {
      break;
    }
    number += build_vega_expression_module_source[build_vega_expression_module_index++];
  }
  if (build_vega_expression_module_isIdentifierStart(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index)) || build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  return {
    type: vega_expression_module_TokenNumericLiteral,
    value: parseInt(number, 8),
    octal: true,
    start: start,
    end: build_vega_expression_module_index
  };
}
function vega_expression_module_scanNumericLiteral() {
  var number, start, ch;
  ch = build_vega_expression_module_source[build_vega_expression_module_index];
  vega_expression_module_assert(build_vega_expression_module_isDecimalDigit(ch.charCodeAt(0)) || ch === '.', 'Numeric literal must start with a decimal digit or a decimal point');
  start = build_vega_expression_module_index;
  number = '';
  if (ch !== '.') {
    number = build_vega_expression_module_source[build_vega_expression_module_index++];
    ch = build_vega_expression_module_source[build_vega_expression_module_index];

    // Hex number starts with '0x'.
    // Octal number starts with '0'.
    if (number === '0') {
      if (ch === 'x' || ch === 'X') {
        ++build_vega_expression_module_index;
        return vega_expression_module_scanHexLiteral(start);
      }
      if (build_vega_expression_module_isOctalDigit(ch)) {
        return vega_expression_module_scanOctalLiteral(start);
      }

      // decimal number starts with '0' such as '09' is illegal.
      if (ch && build_vega_expression_module_isDecimalDigit(ch.charCodeAt(0))) {
        vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
      }
    }
    while (build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
      number += build_vega_expression_module_source[build_vega_expression_module_index++];
    }
    ch = build_vega_expression_module_source[build_vega_expression_module_index];
  }
  if (ch === '.') {
    number += build_vega_expression_module_source[build_vega_expression_module_index++];
    while (build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
      number += build_vega_expression_module_source[build_vega_expression_module_index++];
    }
    ch = build_vega_expression_module_source[build_vega_expression_module_index];
  }
  if (ch === 'e' || ch === 'E') {
    number += build_vega_expression_module_source[build_vega_expression_module_index++];
    ch = build_vega_expression_module_source[build_vega_expression_module_index];
    if (ch === '+' || ch === '-') {
      number += build_vega_expression_module_source[build_vega_expression_module_index++];
    }
    if (build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
      while (build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
        number += build_vega_expression_module_source[build_vega_expression_module_index++];
      }
    } else {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
    }
  }
  if (build_vega_expression_module_isIdentifierStart(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index))) {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  return {
    type: vega_expression_module_TokenNumericLiteral,
    value: parseFloat(number),
    start: start,
    end: build_vega_expression_module_index
  };
}

// 7.8.4 String Literals

function vega_expression_module_scanStringLiteral() {
  var str = '',
    quote,
    start,
    ch,
    code,
    octal = false;
  quote = build_vega_expression_module_source[build_vega_expression_module_index];
  vega_expression_module_assert(quote === '\'' || quote === '"', 'String literal must starts with a quote');
  start = build_vega_expression_module_index;
  ++build_vega_expression_module_index;
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source[build_vega_expression_module_index++];
    if (ch === quote) {
      quote = '';
      break;
    } else if (ch === '\\') {
      ch = build_vega_expression_module_source[build_vega_expression_module_index++];
      if (!ch || !vega_expression_module_isLineTerminator(ch.charCodeAt(0))) {
        switch (ch) {
          case 'u':
          case 'x':
            if (build_vega_expression_module_source[build_vega_expression_module_index] === '{') {
              ++build_vega_expression_module_index;
              str += vega_expression_module_scanUnicodeCodePointEscape();
            } else {
              str += vega_expression_module_scanHexEscape(ch);
            }
            break;
          case 'n':
            str += '\n';
            break;
          case 'r':
            str += '\r';
            break;
          case 't':
            str += '\t';
            break;
          case 'b':
            str += '\b';
            break;
          case 'f':
            str += '\f';
            break;
          case 'v':
            str += '\x0B';
            break;
          default:
            if (build_vega_expression_module_isOctalDigit(ch)) {
              code = '01234567'.indexOf(ch);

              // \0 is not octal escape sequence
              if (code !== 0) {
                octal = true;
              }
              if (build_vega_expression_module_index < build_vega_expression_module_length && build_vega_expression_module_isOctalDigit(build_vega_expression_module_source[build_vega_expression_module_index])) {
                octal = true;
                code = code * 8 + '01234567'.indexOf(build_vega_expression_module_source[build_vega_expression_module_index++]);

                // 3 digits are only allowed when string starts
                // with 0, 1, 2, 3
                if ('0123'.includes(ch) && build_vega_expression_module_index < build_vega_expression_module_length && build_vega_expression_module_isOctalDigit(build_vega_expression_module_source[build_vega_expression_module_index])) {
                  code = code * 8 + '01234567'.indexOf(build_vega_expression_module_source[build_vega_expression_module_index++]);
                }
              }
              str += String.fromCharCode(code);
            } else {
              str += ch;
            }
            break;
        }
      } else {
        if (ch === '\r' && build_vega_expression_module_source[build_vega_expression_module_index] === '\n') {
          ++build_vega_expression_module_index;
        }
      }
    } else if (vega_expression_module_isLineTerminator(ch.charCodeAt(0))) {
      break;
    } else {
      str += ch;
    }
  }
  if (quote !== '') {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
  }
  return {
    type: vega_expression_module_TokenStringLiteral,
    value: str,
    octal: octal,
    start: start,
    end: build_vega_expression_module_index
  };
}
function vega_expression_module_testRegExp(pattern, flags) {
  let tmp = pattern;
  if (flags.includes('u')) {
    // Replace each astral symbol and every Unicode code point
    // escape sequence with a single ASCII symbol to avoid throwing on
    // regular expressions that are only valid in combination with the
    // `/u` flag.
    // Note: replacing with the ASCII symbol `x` might cause false
    // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
    // perfectly valid pattern that is equivalent to `[a-b]`, but it
    // would be replaced by `[x-b]` which throws an error.
    tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, ($0, $1) => {
      if (parseInt($1, 16) <= 0x10FFFF) {
        return 'x';
      }
      vega_expression_module_throwError({}, vega_expression_module_MessageInvalidRegExp);
    }).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
  }

  // First, detect invalid regular expressions.
  try {
    new RegExp(tmp);
  } catch (e) {
    vega_expression_module_throwError({}, vega_expression_module_MessageInvalidRegExp);
  }

  // Return a regular expression object for this pattern-flag pair, or
  // `null` in case the current environment doesn't support the flags it
  // uses.
  try {
    return new RegExp(pattern, flags);
  } catch (exception) {
    return null;
  }
}
function vega_expression_module_scanRegExpBody() {
  var ch, str, classMarker, terminated, body;
  ch = build_vega_expression_module_source[build_vega_expression_module_index];
  vega_expression_module_assert(ch === '/', 'Regular expression literal must start with a slash');
  str = build_vega_expression_module_source[build_vega_expression_module_index++];
  classMarker = false;
  terminated = false;
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source[build_vega_expression_module_index++];
    str += ch;
    if (ch === '\\') {
      ch = build_vega_expression_module_source[build_vega_expression_module_index++];
      // ECMA-262 7.8.5
      if (vega_expression_module_isLineTerminator(ch.charCodeAt(0))) {
        vega_expression_module_throwError({}, vega_expression_module_MessageUnterminatedRegExp);
      }
      str += ch;
    } else if (vega_expression_module_isLineTerminator(ch.charCodeAt(0))) {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnterminatedRegExp);
    } else if (classMarker) {
      if (ch === ']') {
        classMarker = false;
      }
    } else {
      if (ch === '/') {
        terminated = true;
        break;
      } else if (ch === '[') {
        classMarker = true;
      }
    }
  }
  if (!terminated) {
    vega_expression_module_throwError({}, vega_expression_module_MessageUnterminatedRegExp);
  }

  // Exclude leading and trailing slash.
  body = str.substr(1, str.length - 2);
  return {
    value: body,
    literal: str
  };
}
function vega_expression_module_scanRegExpFlags() {
  var ch, str, flags;
  str = '';
  flags = '';
  while (build_vega_expression_module_index < build_vega_expression_module_length) {
    ch = build_vega_expression_module_source[build_vega_expression_module_index];
    if (!vega_expression_module_isIdentifierPart(ch.charCodeAt(0))) {
      break;
    }
    ++build_vega_expression_module_index;
    if (ch === '\\' && build_vega_expression_module_index < build_vega_expression_module_length) {
      vega_expression_module_throwError({}, vega_expression_module_MessageUnexpectedToken, vega_expression_module_ILLEGAL);
    } else {
      flags += ch;
      str += ch;
    }
  }
  if (flags.search(/[^gimuy]/g) >= 0) {
    vega_expression_module_throwError({}, vega_expression_module_MessageInvalidRegExp, flags);
  }
  return {
    value: flags,
    literal: str
  };
}
function vega_expression_module_scanRegExp() {
  var start, body, flags, value;
  vega_expression_module_lookahead = null;
  vega_expression_module_skipComment();
  start = build_vega_expression_module_index;
  body = vega_expression_module_scanRegExpBody();
  flags = vega_expression_module_scanRegExpFlags();
  value = vega_expression_module_testRegExp(body.value, flags.value);
  return {
    literal: body.literal + flags.literal,
    value: value,
    regex: {
      pattern: body.value,
      flags: flags.value
    },
    start: start,
    end: build_vega_expression_module_index
  };
}
function vega_expression_module_isIdentifierName(token) {
  return token.type === vega_expression_module_TokenIdentifier || token.type === vega_expression_module_TokenKeyword || token.type === vega_expression_module_TokenBooleanLiteral || token.type === vega_expression_module_TokenNullLiteral;
}
function vega_expression_module_advance() {
  vega_expression_module_skipComment();
  if (build_vega_expression_module_index >= build_vega_expression_module_length) {
    return {
      type: vega_expression_module_TokenEOF,
      start: build_vega_expression_module_index,
      end: build_vega_expression_module_index
    };
  }
  const ch = build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index);
  if (build_vega_expression_module_isIdentifierStart(ch)) {
    return vega_expression_module_scanIdentifier();
  }

  // Very common: ( and ) and ;
  if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
    return vega_expression_module_scanPunctuator();
  }

  // String literal starts with single quote (U+0027) or double quote (U+0022).
  if (ch === 0x27 || ch === 0x22) {
    return vega_expression_module_scanStringLiteral();
  }

  // Dot (.) U+002E can also start a floating-point number, hence the need
  // to check the next character.
  if (ch === 0x2E) {
    if (build_vega_expression_module_isDecimalDigit(build_vega_expression_module_source.charCodeAt(build_vega_expression_module_index + 1))) {
      return vega_expression_module_scanNumericLiteral();
    }
    return vega_expression_module_scanPunctuator();
  }
  if (build_vega_expression_module_isDecimalDigit(ch)) {
    return vega_expression_module_scanNumericLiteral();
  }
  return vega_expression_module_scanPunctuator();
}
function vega_expression_module_lex() {
  const token = vega_expression_module_lookahead;
  build_vega_expression_module_index = token.end;
  vega_expression_module_lookahead = vega_expression_module_advance();
  build_vega_expression_module_index = token.end;
  return token;
}
function build_vega_expression_module_peek() {
  const pos = build_vega_expression_module_index;
  vega_expression_module_lookahead = vega_expression_module_advance();
  build_vega_expression_module_index = pos;
}
function vega_expression_module_finishArrayExpression(elements) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxArrayExpression);
  node.elements = elements;
  return node;
}
function vega_expression_module_finishBinaryExpression(operator, left, right) {
  const node = new vega_expression_module_ASTNode(operator === '||' || operator === '&&' ? vega_expression_module_SyntaxLogicalExpression : vega_expression_module_SyntaxBinaryExpression);
  node.operator = operator;
  node.left = left;
  node.right = right;
  return node;
}
function vega_expression_module_finishCallExpression(callee, args) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxCallExpression);
  node.callee = callee;
  node.arguments = args;
  return node;
}
function vega_expression_module_finishConditionalExpression(test, consequent, alternate) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxConditionalExpression);
  node.test = test;
  node.consequent = consequent;
  node.alternate = alternate;
  return node;
}
function vega_expression_module_finishIdentifier(name) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxIdentifier);
  node.name = name;
  return node;
}
function vega_expression_module_finishLiteral(token) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxLiteral);
  node.value = token.value;
  node.raw = build_vega_expression_module_source.slice(token.start, token.end);
  if (token.regex) {
    if (node.raw === '//') {
      node.raw = '/(?:)/';
    }
    node.regex = token.regex;
  }
  return node;
}
function vega_expression_module_finishMemberExpression(accessor, object, property) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxMemberExpression);
  node.computed = accessor === '[';
  node.object = object;
  node.property = property;
  if (!node.computed) property.member = true;
  return node;
}
function vega_expression_module_finishObjectExpression(properties) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxObjectExpression);
  node.properties = properties;
  return node;
}
function vega_expression_module_finishProperty(kind, key, value) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxProperty);
  node.key = key;
  node.value = value;
  node.kind = kind;
  return node;
}
function vega_expression_module_finishUnaryExpression(operator, argument) {
  const node = new vega_expression_module_ASTNode(vega_expression_module_SyntaxUnaryExpression);
  node.operator = operator;
  node.argument = argument;
  node.prefix = true;
  return node;
}

// Throw an exception

function vega_expression_module_throwError(token, messageFormat) {
  var error,
    args = Array.prototype.slice.call(arguments, 2),
    msg = messageFormat.replace(/%(\d)/g, (whole, index) => {
      vega_expression_module_assert(index < args.length, 'Message reference must be in range');
      return args[index];
    });
  error = new Error(msg);
  error.index = build_vega_expression_module_index;
  error.description = msg;
  throw error;
}

// Throw an exception because of the token.

function vega_expression_module_throwUnexpected(token) {
  if (token.type === vega_expression_module_TokenEOF) {
    vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedEOS);
  }
  if (token.type === vega_expression_module_TokenNumericLiteral) {
    vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedNumber);
  }
  if (token.type === vega_expression_module_TokenStringLiteral) {
    vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedString);
  }
  if (token.type === vega_expression_module_TokenIdentifier) {
    vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedIdentifier);
  }
  if (token.type === vega_expression_module_TokenKeyword) {
    vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedReserved);
  }

  // BooleanLiteral, NullLiteral, or Punctuator.
  vega_expression_module_throwError(token, vega_expression_module_MessageUnexpectedToken, token.value);
}

// Expect the next token to match the specified punctuator.
// If not, an exception will be thrown.

function vega_expression_module_expect(value) {
  const token = vega_expression_module_lex();
  if (token.type !== vega_expression_module_TokenPunctuator || token.value !== value) {
    vega_expression_module_throwUnexpected(token);
  }
}

// Return true if the next token matches the specified punctuator.

function build_vega_expression_module_match(value) {
  return vega_expression_module_lookahead.type === vega_expression_module_TokenPunctuator && vega_expression_module_lookahead.value === value;
}

// Return true if the next token matches the specified keyword

function vega_expression_module_matchKeyword(keyword) {
  return vega_expression_module_lookahead.type === vega_expression_module_TokenKeyword && vega_expression_module_lookahead.value === keyword;
}

// 11.1.4 Array Initialiser

function vega_expression_module_parseArrayInitialiser() {
  const elements = [];
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  vega_expression_module_expect('[');
  while (!build_vega_expression_module_match(']')) {
    if (build_vega_expression_module_match(',')) {
      vega_expression_module_lex();
      elements.push(null);
    } else {
      elements.push(vega_expression_module_parseConditionalExpression());
      if (!build_vega_expression_module_match(']')) {
        vega_expression_module_expect(',');
      }
    }
  }
  vega_expression_module_lex();
  return vega_expression_module_finishArrayExpression(elements);
}

// 11.1.5 Object Initialiser

function vega_expression_module_parseObjectPropertyKey() {
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  const token = vega_expression_module_lex();

  // Note: This function is called only from parseObjectProperty(), where
  // EOF and Punctuator tokens are already filtered out.

  if (token.type === vega_expression_module_TokenStringLiteral || token.type === vega_expression_module_TokenNumericLiteral) {
    if (token.octal) {
      vega_expression_module_throwError(token, vega_expression_module_MessageStrictOctalLiteral);
    }
    return vega_expression_module_finishLiteral(token);
  }
  return vega_expression_module_finishIdentifier(token.value);
}
function vega_expression_module_parseObjectProperty() {
  var token, key, id, value;
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  token = vega_expression_module_lookahead;
  if (token.type === vega_expression_module_TokenIdentifier) {
    id = vega_expression_module_parseObjectPropertyKey();
    vega_expression_module_expect(':');
    value = vega_expression_module_parseConditionalExpression();
    return vega_expression_module_finishProperty('init', id, value);
  }
  if (token.type === vega_expression_module_TokenEOF || token.type === vega_expression_module_TokenPunctuator) {
    vega_expression_module_throwUnexpected(token);
  } else {
    key = vega_expression_module_parseObjectPropertyKey();
    vega_expression_module_expect(':');
    value = vega_expression_module_parseConditionalExpression();
    return vega_expression_module_finishProperty('init', key, value);
  }
}
function vega_expression_module_parseObjectInitialiser() {
  var properties = [],
    property,
    name,
    key,
    map = {},
    toString = String;
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  vega_expression_module_expect('{');
  while (!build_vega_expression_module_match('}')) {
    property = vega_expression_module_parseObjectProperty();
    if (property.key.type === vega_expression_module_SyntaxIdentifier) {
      name = property.key.name;
    } else {
      name = toString(property.key.value);
    }
    key = '$' + name;
    if (Object.prototype.hasOwnProperty.call(map, key)) {
      vega_expression_module_throwError({}, vega_expression_module_MessageStrictDuplicateProperty);
    } else {
      map[key] = true;
    }
    properties.push(property);
    if (!build_vega_expression_module_match('}')) {
      vega_expression_module_expect(',');
    }
  }
  vega_expression_module_expect('}');
  return vega_expression_module_finishObjectExpression(properties);
}

// 11.1.6 The Grouping Operator

function vega_expression_module_parseGroupExpression() {
  vega_expression_module_expect('(');
  const expr = build_vega_expression_module_parseExpression();
  vega_expression_module_expect(')');
  return expr;
}

// 11.1 Primary Expressions

const vega_expression_module_legalKeywords = {
  'if': 1
};
function vega_expression_module_parsePrimaryExpression() {
  var type, token, expr;
  if (build_vega_expression_module_match('(')) {
    return vega_expression_module_parseGroupExpression();
  }
  if (build_vega_expression_module_match('[')) {
    return vega_expression_module_parseArrayInitialiser();
  }
  if (build_vega_expression_module_match('{')) {
    return vega_expression_module_parseObjectInitialiser();
  }
  type = vega_expression_module_lookahead.type;
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  if (type === vega_expression_module_TokenIdentifier || vega_expression_module_legalKeywords[vega_expression_module_lookahead.value]) {
    expr = vega_expression_module_finishIdentifier(vega_expression_module_lex().value);
  } else if (type === vega_expression_module_TokenStringLiteral || type === vega_expression_module_TokenNumericLiteral) {
    if (vega_expression_module_lookahead.octal) {
      vega_expression_module_throwError(vega_expression_module_lookahead, vega_expression_module_MessageStrictOctalLiteral);
    }
    expr = vega_expression_module_finishLiteral(vega_expression_module_lex());
  } else if (type === vega_expression_module_TokenKeyword) {
    throw new Error(vega_expression_module_DISABLED);
  } else if (type === vega_expression_module_TokenBooleanLiteral) {
    token = vega_expression_module_lex();
    token.value = token.value === 'true';
    expr = vega_expression_module_finishLiteral(token);
  } else if (type === vega_expression_module_TokenNullLiteral) {
    token = vega_expression_module_lex();
    token.value = null;
    expr = vega_expression_module_finishLiteral(token);
  } else if (build_vega_expression_module_match('/') || build_vega_expression_module_match('/=')) {
    expr = vega_expression_module_finishLiteral(vega_expression_module_scanRegExp());
    build_vega_expression_module_peek();
  } else {
    vega_expression_module_throwUnexpected(vega_expression_module_lex());
  }
  return expr;
}

// 11.2 Left-Hand-Side Expressions

function vega_expression_module_parseArguments() {
  const args = [];
  vega_expression_module_expect('(');
  if (!build_vega_expression_module_match(')')) {
    while (build_vega_expression_module_index < build_vega_expression_module_length) {
      args.push(vega_expression_module_parseConditionalExpression());
      if (build_vega_expression_module_match(')')) {
        break;
      }
      vega_expression_module_expect(',');
    }
  }
  vega_expression_module_expect(')');
  return args;
}
function vega_expression_module_parseNonComputedProperty() {
  build_vega_expression_module_index = vega_expression_module_lookahead.start;
  const token = vega_expression_module_lex();
  if (!vega_expression_module_isIdentifierName(token)) {
    vega_expression_module_throwUnexpected(token);
  }
  return vega_expression_module_finishIdentifier(token.value);
}
function vega_expression_module_parseNonComputedMember() {
  vega_expression_module_expect('.');
  return vega_expression_module_parseNonComputedProperty();
}
function vega_expression_module_parseComputedMember() {
  vega_expression_module_expect('[');
  const expr = build_vega_expression_module_parseExpression();
  vega_expression_module_expect(']');
  return expr;
}
function vega_expression_module_parseLeftHandSideExpressionAllowCall() {
  var expr, args, property;
  expr = vega_expression_module_parsePrimaryExpression();
  for (;;) {
    if (build_vega_expression_module_match('.')) {
      property = vega_expression_module_parseNonComputedMember();
      expr = vega_expression_module_finishMemberExpression('.', expr, property);
    } else if (build_vega_expression_module_match('(')) {
      args = vega_expression_module_parseArguments();
      expr = vega_expression_module_finishCallExpression(expr, args);
    } else if (build_vega_expression_module_match('[')) {
      property = vega_expression_module_parseComputedMember();
      expr = vega_expression_module_finishMemberExpression('[', expr, property);
    } else {
      break;
    }
  }
  return expr;
}

// 11.3 Postfix Expressions

function vega_expression_module_parsePostfixExpression() {
  const expr = vega_expression_module_parseLeftHandSideExpressionAllowCall();
  if (vega_expression_module_lookahead.type === vega_expression_module_TokenPunctuator) {
    if (build_vega_expression_module_match('++') || build_vega_expression_module_match('--')) {
      throw new Error(vega_expression_module_DISABLED);
    }
  }
  return expr;
}

// 11.4 Unary Operators

function vega_expression_module_parseUnaryExpression() {
  var token, expr;
  if (vega_expression_module_lookahead.type !== vega_expression_module_TokenPunctuator && vega_expression_module_lookahead.type !== vega_expression_module_TokenKeyword) {
    expr = vega_expression_module_parsePostfixExpression();
  } else if (build_vega_expression_module_match('++') || build_vega_expression_module_match('--')) {
    throw new Error(vega_expression_module_DISABLED);
  } else if (build_vega_expression_module_match('+') || build_vega_expression_module_match('-') || build_vega_expression_module_match('~') || build_vega_expression_module_match('!')) {
    token = vega_expression_module_lex();
    expr = vega_expression_module_parseUnaryExpression();
    expr = vega_expression_module_finishUnaryExpression(token.value, expr);
  } else if (vega_expression_module_matchKeyword('delete') || vega_expression_module_matchKeyword('void') || vega_expression_module_matchKeyword('typeof')) {
    throw new Error(vega_expression_module_DISABLED);
  } else {
    expr = vega_expression_module_parsePostfixExpression();
  }
  return expr;
}
function vega_expression_module_binaryPrecedence(token) {
  let prec = 0;
  if (token.type !== vega_expression_module_TokenPunctuator && token.type !== vega_expression_module_TokenKeyword) {
    return 0;
  }
  switch (token.value) {
    case '||':
      prec = 1;
      break;
    case '&&':
      prec = 2;
      break;
    case '|':
      prec = 3;
      break;
    case '^':
      prec = 4;
      break;
    case '&':
      prec = 5;
      break;
    case '==':
    case '!=':
    case '===':
    case '!==':
      prec = 6;
      break;
    case '<':
    case '>':
    case '<=':
    case '>=':
    case 'instanceof':
    case 'in':
      prec = 7;
      break;
    case '<<':
    case '>>':
    case '>>>':
      prec = 8;
      break;
    case '+':
    case '-':
      prec = 9;
      break;
    case '*':
    case '/':
    case '%':
      prec = 11;
      break;
  }
  return prec;
}

// 11.5 Multiplicative Operators
// 11.6 Additive Operators
// 11.7 Bitwise Shift Operators
// 11.8 Relational Operators
// 11.9 Equality Operators
// 11.10 Binary Bitwise Operators
// 11.11 Binary Logical Operators

function vega_expression_module_parseBinaryExpression() {
  var marker, markers, expr, token, prec, stack, right, operator, left, i;
  marker = vega_expression_module_lookahead;
  left = vega_expression_module_parseUnaryExpression();
  token = vega_expression_module_lookahead;
  prec = vega_expression_module_binaryPrecedence(token);
  if (prec === 0) {
    return left;
  }
  token.prec = prec;
  vega_expression_module_lex();
  markers = [marker, vega_expression_module_lookahead];
  right = vega_expression_module_parseUnaryExpression();
  stack = [left, token, right];
  while ((prec = vega_expression_module_binaryPrecedence(vega_expression_module_lookahead)) > 0) {
    // Reduce: make a binary expression from the three topmost entries.
    while (stack.length > 2 && prec <= stack[stack.length - 2].prec) {
      right = stack.pop();
      operator = stack.pop().value;
      left = stack.pop();
      markers.pop();
      expr = vega_expression_module_finishBinaryExpression(operator, left, right);
      stack.push(expr);
    }

    // Shift.
    token = vega_expression_module_lex();
    token.prec = prec;
    stack.push(token);
    markers.push(vega_expression_module_lookahead);
    expr = vega_expression_module_parseUnaryExpression();
    stack.push(expr);
  }

  // Final reduce to clean-up the stack.
  i = stack.length - 1;
  expr = stack[i];
  markers.pop();
  while (i > 1) {
    markers.pop();
    expr = vega_expression_module_finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
    i -= 2;
  }
  return expr;
}

// 11.12 Conditional Operator

function vega_expression_module_parseConditionalExpression() {
  var expr, consequent, alternate;
  expr = vega_expression_module_parseBinaryExpression();
  if (build_vega_expression_module_match('?')) {
    vega_expression_module_lex();
    consequent = vega_expression_module_parseConditionalExpression();
    vega_expression_module_expect(':');
    alternate = vega_expression_module_parseConditionalExpression();
    expr = vega_expression_module_finishConditionalExpression(expr, consequent, alternate);
  }
  return expr;
}

// 11.14 Comma Operator

function build_vega_expression_module_parseExpression() {
  const expr = vega_expression_module_parseConditionalExpression();
  if (build_vega_expression_module_match(',')) {
    throw new Error(vega_expression_module_DISABLED); // no sequence expressions
  }
  return expr;
}
function vega_expression_module_parser (code) {
  build_vega_expression_module_source = code;
  build_vega_expression_module_index = 0;
  build_vega_expression_module_length = build_vega_expression_module_source.length;
  vega_expression_module_lookahead = null;
  build_vega_expression_module_peek();
  const expr = build_vega_expression_module_parseExpression();
  if (vega_expression_module_lookahead.type !== vega_expression_module_TokenEOF) {
    throw new Error('Unexpect token after expression.');
  }
  return expr;
}

var vega_expression_module_Constants = {
  NaN: 'NaN',
  E: 'Math.E',
  LN2: 'Math.LN2',
  LN10: 'Math.LN10',
  LOG2E: 'Math.LOG2E',
  LOG10E: 'Math.LOG10E',
  PI: 'Math.PI',
  SQRT1_2: 'Math.SQRT1_2',
  SQRT2: 'Math.SQRT2',
  MIN_VALUE: 'Number.MIN_VALUE',
  MAX_VALUE: 'Number.MAX_VALUE'
};

function vega_expression_module_Functions (codegen) {
  function fncall(name, args, cast, type) {
    let obj = codegen(args[0]);
    if (cast) {
      obj = cast + '(' + obj + ')';
      if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
    }
    return obj + '.' + name + (type < 0 ? '' : type === 0 ? '()' : '(' + args.slice(1).map(codegen).join(',') + ')');
  }
  function fn(name, cast, type) {
    return args => fncall(name, args, cast, type);
  }
  const DATE = 'new Date',
    STRING = 'String',
    REGEXP = 'RegExp';
  return {
    // MATH functions
    isNaN: 'Number.isNaN',
    isFinite: 'Number.isFinite',
    abs: 'Math.abs',
    acos: 'Math.acos',
    asin: 'Math.asin',
    atan: 'Math.atan',
    atan2: 'Math.atan2',
    ceil: 'Math.ceil',
    cos: 'Math.cos',
    exp: 'Math.exp',
    floor: 'Math.floor',
    hypot: 'Math.hypot',
    log: 'Math.log',
    max: 'Math.max',
    min: 'Math.min',
    pow: 'Math.pow',
    random: 'Math.random',
    round: 'Math.round',
    sin: 'Math.sin',
    sqrt: 'Math.sqrt',
    tan: 'Math.tan',
    clamp: function (args) {
      if (args.length < 3) error('Missing arguments to clamp function.');
      if (args.length > 3) error('Too many arguments to clamp function.');
      const a = args.map(codegen);
      return 'Math.max(' + a[1] + ', Math.min(' + a[2] + ',' + a[0] + '))';
    },
    // DATE functions
    now: 'Date.now',
    utc: 'Date.UTC',
    datetime: DATE,
    date: fn('getDate', DATE, 0),
    day: fn('getDay', DATE, 0),
    year: fn('getFullYear', DATE, 0),
    month: fn('getMonth', DATE, 0),
    hours: fn('getHours', DATE, 0),
    minutes: fn('getMinutes', DATE, 0),
    seconds: fn('getSeconds', DATE, 0),
    milliseconds: fn('getMilliseconds', DATE, 0),
    time: fn('getTime', DATE, 0),
    timezoneoffset: fn('getTimezoneOffset', DATE, 0),
    utcdate: fn('getUTCDate', DATE, 0),
    utcday: fn('getUTCDay', DATE, 0),
    utcyear: fn('getUTCFullYear', DATE, 0),
    utcmonth: fn('getUTCMonth', DATE, 0),
    utchours: fn('getUTCHours', DATE, 0),
    utcminutes: fn('getUTCMinutes', DATE, 0),
    utcseconds: fn('getUTCSeconds', DATE, 0),
    utcmilliseconds: fn('getUTCMilliseconds', DATE, 0),
    // sequence functions
    length: fn('length', null, -1),
    // STRING functions
    parseFloat: 'parseFloat',
    parseInt: 'parseInt',
    upper: fn('toUpperCase', STRING, 0),
    lower: fn('toLowerCase', STRING, 0),
    substring: fn('substring', STRING),
    split: fn('split', STRING),
    trim: fn('trim', STRING, 0),
    // REGEXP functions
    regexp: REGEXP,
    test: fn('test', REGEXP),
    // Control Flow functions
    if: function (args) {
      if (args.length < 3) error('Missing arguments to if function.');
      if (args.length > 3) error('Too many arguments to if function.');
      const a = args.map(codegen);
      return '(' + a[0] + '?' + a[1] + ':' + a[2] + ')';
    }
  };
}

function vega_expression_module_stripQuotes(s) {
  const n = s && s.length - 1;
  return n && (s[0] === '"' && s[n] === '"' || s[0] === '\'' && s[n] === '\'') ? s.slice(1, -1) : s;
}
function build_vega_expression_module_codegen (opt) {
  opt = opt || {};
  const allowed = opt.allowed ? toSet(opt.allowed) : {},
    forbidden = opt.forbidden ? toSet(opt.forbidden) : {},
    constants = opt.constants || vega_expression_module_Constants,
    functions = (opt.functions || vega_expression_module_Functions)(visit),
    globalvar = opt.globalvar,
    fieldvar = opt.fieldvar,
    outputGlobal = isFunction(globalvar) ? globalvar : id => `${globalvar}["${id}"]`;
  let globals = {},
    fields = {},
    memberDepth = 0;
  function visit(ast) {
    if (isString(ast)) return ast;
    const generator = Generators[ast.type];
    if (generator == null) error('Unsupported type: ' + ast.type);
    return generator(ast);
  }
  const Generators = {
    Literal: n => n.raw,
    Identifier: n => {
      const id = n.name;
      if (memberDepth > 0) {
        return id;
      } else if (hasOwnProperty(forbidden, id)) {
        return error('Illegal identifier: ' + id);
      } else if (hasOwnProperty(constants, id)) {
        return constants[id];
      } else if (hasOwnProperty(allowed, id)) {
        return id;
      } else {
        globals[id] = 1;
        return outputGlobal(id);
      }
    },
    MemberExpression: n => {
      const d = !n.computed,
        o = visit(n.object);
      if (d) memberDepth += 1;
      const p = visit(n.property);
      if (o === fieldvar) {
        // strip quotes to sanitize field name (#1653)
        fields[vega_expression_module_stripQuotes(p)] = 1;
      }
      if (d) memberDepth -= 1;
      return o + (d ? '.' + p : '[' + p + ']');
    },
    CallExpression: n => {
      if (n.callee.type !== 'Identifier') {
        error('Illegal callee type: ' + n.callee.type);
      }
      const callee = n.callee.name,
        args = n.arguments,
        fn = hasOwnProperty(functions, callee) && functions[callee];
      if (!fn) error('Unrecognized function: ' + callee);
      return isFunction(fn) ? fn(args) : fn + '(' + args.map(visit).join(',') + ')';
    },
    ArrayExpression: n => '[' + n.elements.map(visit).join(',') + ']',
    BinaryExpression: n => '(' + visit(n.left) + ' ' + n.operator + ' ' + visit(n.right) + ')',
    UnaryExpression: n => '(' + n.operator + visit(n.argument) + ')',
    ConditionalExpression: n => '(' + visit(n.test) + '?' + visit(n.consequent) + ':' + visit(n.alternate) + ')',
    LogicalExpression: n => '(' + visit(n.left) + n.operator + visit(n.right) + ')',
    ObjectExpression: n => '{' + n.properties.map(visit).join(',') + '}',
    Property: n => {
      memberDepth += 1;
      const k = visit(n.key);
      memberDepth -= 1;
      return k + ':' + visit(n.value);
    }
  };
  function codegen(ast) {
    const result = {
      code: visit(ast),
      globals: Object.keys(globals),
      fields: Object.keys(fields)
    };
    globals = {};
    fields = {};
    return result;
  }
  codegen.functions = functions;
  codegen.constants = constants;
  return codegen;
}



;// ../../node_modules/vega-lite/build/src/compile/data/expressions.js

function getName(node) {
    const name = [];
    if (node.type === 'Identifier') {
        return [node.name];
    }
    if (node.type === 'Literal') {
        return [node.value];
    }
    if (node.type === 'MemberExpression') {
        name.push(...getName(node.object));
        name.push(...getName(node.property));
    }
    return name;
}
function startsWithDatum(node) {
    if (node.object.type === 'MemberExpression') {
        return startsWithDatum(node.object);
    }
    return node.object.name === 'datum';
}
function getDependentFields(expression) {
    const ast = vega_expression_module_parser(expression);
    const dependents = new Set();
    // visit is missing in types https://github.com/vega/vega/issues/3298
    ast.visit((node) => {
        if (node.type === 'MemberExpression' && startsWithDatum(node)) {
            dependents.add(getName(node).slice(1).join('.'));
        }
    });
    return dependents;
}
//# sourceMappingURL=expressions.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/filter.js




class FilterNode extends DataFlowNode {
    clone() {
        return new FilterNode(null, this.model, duplicate(this.filter));
    }
    constructor(parent, model, filter) {
        super(parent);
        this.model = model;
        this.filter = filter;
        // TODO: refactor this to not take a node and
        // then add a static function makeFromOperand and make the constructor take only an expression
        this.expr = predicate_expression(this.model, this.filter, this);
        this._dependentFields = getDependentFields(this.expr);
    }
    dependentFields() {
        return this._dependentFields;
    }
    producedFields() {
        return new Set(); // filter does not produce any new fields
    }
    assemble() {
        return {
            type: 'filter',
            expr: this.expr
        };
    }
    hash() {
        return `Filter ${this.expr}`;
    }
}
//# sourceMappingURL=filter.js.map
;// ../../node_modules/vega-lite/build/src/compile/selection/parse.js









function parseUnitSelection(model, selDefs) {
    const selCmpts = {};
    const selectionConfig = model.config.selection;
    if (!selDefs || !selDefs.length)
        return selCmpts;
    let nTimerSelections = 0;
    for (const def of selDefs) {
        const name = varName(def.name);
        const selDef = def.select;
        const type = vega_util_module_isString(selDef) ? selDef : selDef.type;
        const defaults = vega_util_module_isObject(selDef) ? duplicate(selDef) : { type };
        // Set default values from config if a property hasn't been specified,
        // or if it is true. E.g., "translate": true should use the default
        // event handlers for translate. However, true may be a valid value for
        // a property (e.g., "nearest": true).
        const cfg = selectionConfig[type];
        for (const key in cfg) {
            // Project transform applies its defaults.
            if (key === 'fields' || key === 'encodings') {
                continue;
            }
            if (key === 'mark') {
                defaults.mark = { ...cfg.mark, ...defaults.mark };
            }
            if (defaults[key] === undefined || defaults[key] === true) {
                defaults[key] = duplicate(cfg[key] ?? defaults[key]);
            }
        }
        const selCmpt = (selCmpts[name] = {
            ...defaults,
            name,
            type,
            init: def.value,
            bind: def.bind,
            events: vega_util_module_isString(defaults.on) ? eventSelector(defaults.on, 'scope') : vega_util_module_array(duplicate(defaults.on))
        });
        if (isTimerSelection(selCmpt)) {
            nTimerSelections++;
            // check for multiple timer selections and ignore all but the first one
            if (nTimerSelections > 1) {
                delete selCmpts[name];
                continue;
            }
        }
        const def_ = duplicate(def); // defensive copy to prevent compilers from causing side effects
        for (const c of selectionCompilers) {
            if (c.defined(selCmpt) && c.parse) {
                c.parse(model, selCmpt, def_);
            }
        }
    }
    if (nTimerSelections > 1) {
        // if multiple timer selections were found, issue a warning
        log_warn(MULTIPLE_TIMER_ANIMATION_SELECTION);
    }
    return selCmpts;
}
function parseSelectionPredicate(model, pred, dfnode, datum = 'datum') {
    const name = vega_util_module_isString(pred) ? pred : pred.param;
    const vname = varName(name);
    const store = $(vname + STORE);
    let selCmpt;
    try {
        selCmpt = model.getSelectionComponent(vname, name);
    }
    catch (e) {
        // If a selection isn't found, treat as a variable parameter and coerce to boolean.
        return `!!${vname}`;
    }
    if (selCmpt.project.timeUnit) {
        const child = dfnode ?? model.component.data.raw;
        const tunode = selCmpt.project.timeUnit.clone();
        if (child.parent) {
            tunode.insertAsParentOf(child);
        }
        else {
            child.parent = tunode;
        }
    }
    const fn = selCmpt.project.hasSelectionId ? 'vlSelectionIdTest(' : 'vlSelectionTest(';
    const resolve = selCmpt.resolve === 'global' ? ')' : `, ${$(selCmpt.resolve)})`;
    const test = `${fn}${store}, ${datum}${resolve}`;
    const length = `length(data(${store}))`;
    return pred.empty === false ? `${length} && ${test}` : `!${length} || ${test}`;
}
function parseSelectionExtent(model, name, extent) {
    const vname = varName(name);
    const encoding = extent.encoding;
    let field = extent.field;
    let selCmpt;
    try {
        selCmpt = model.getSelectionComponent(vname, name);
    }
    catch (e) {
        // If a selection isn't found, treat it as a variable parameter.
        return vname;
    }
    if (!encoding && !field) {
        field = selCmpt.project.items[0].field;
        if (selCmpt.project.items.length > 1) {
            log_warn(selectionAsScaleDomainWithoutField(field));
        }
    }
    else if (encoding && !field) {
        const encodings = selCmpt.project.items.filter(p => p.channel === encoding);
        if (!encodings.length || encodings.length > 1) {
            field = selCmpt.project.items[0].field;
            log_warn(selectionAsScaleDomainWrongEncodings(encodings, encoding, extent, field));
        }
        else {
            field = encodings[0].field;
        }
    }
    return `${selCmpt.name}[${$(replacePathInField(field))}]`;
}
function materializeSelections(model, main) {
    for (const [selection, selCmpt] of util_entries(model.component.selection ?? {})) {
        const lookupName = model.getName(`lookup_${selection}`);
        model.component.data.outputNodes[lookupName] = selCmpt.materialized = new OutputNode(new FilterNode(main, model, { param: selection }), lookupName, DataSourceType.Lookup, model.component.data.outputNodeRefCounts);
    }
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/predicate.js




/**
 * Converts a predicate into an expression.
 */
// model is only used for selection filters.
function predicate_expression(model, filterOp, node) {
    return logicalExpr(filterOp, (predicate) => {
        if (vega_util_module_isString(predicate)) {
            return predicate;
        }
        else if (isSelectionPredicate(predicate)) {
            return parseSelectionPredicate(model, predicate, node);
        }
        else {
            // Filter Object
            return fieldFilterExpression(predicate);
        }
    });
}
//# sourceMappingURL=predicate.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/assemble.js









function assembleTitle(title, config) {
    if (!title) {
        return undefined;
    }
    if (vega_util_module_isArray(title) && !isText(title)) {
        return title.map(fieldDef => defaultTitle(fieldDef, config)).join(', ');
    }
    return title;
}
function setAxisEncode(axis, part, vgProp, vgRef) {
    var _a, _b;
    axis.encode ?? (axis.encode = {});
    (_a = axis.encode)[part] ?? (_a[part] = {});
    (_b = axis.encode[part]).update ?? (_b.update = {});
    // TODO: remove as any after https://github.com/prisma/nexus-prisma/issues/291
    axis.encode[part].update[vgProp] = vgRef;
}
function assembleAxis(axisCmpt, kind, config, opt = { header: false }) {
    const { disable, orient, scale, labelExpr, title, zindex, ...axis } = axisCmpt.combine();
    if (disable) {
        return undefined;
    }
    for (const p in axis) {
        const prop = p;
        const propType = AXIS_PROPERTY_TYPE[prop];
        const propValue = axis[prop];
        if (propType && propType !== kind && propType !== 'both') {
            // Remove properties that are not valid for this kind of axis
            delete axis[prop];
        }
        else if (isConditionalAxisValue(propValue)) {
            // deal with conditional axis value
            const { condition, ...valueOrSignalRef } = propValue;
            const conditions = vega_util_module_array(condition);
            const propIndex = CONDITIONAL_AXIS_PROP_INDEX[prop];
            if (propIndex) {
                const { vgProp, part } = propIndex;
                // If there is a corresponding Vega property for the channel,
                // use Vega's custom axis encoding and delete the original axis property to avoid conflicts
                const vgRef = [
                    ...conditions.map(c => {
                        const { test, ...valueOrSignalCRef } = c;
                        return {
                            test: predicate_expression(null, test),
                            ...valueOrSignalCRef
                        };
                    }),
                    valueOrSignalRef
                ];
                setAxisEncode(axis, part, vgProp, vgRef);
                delete axis[prop];
            }
            else if (propIndex === null) {
                // If propIndex is null, this means we support conditional axis property by converting the condition to signal instead.
                const signalRef = {
                    signal: conditions
                        .map(c => {
                        const { test, ...valueOrSignalCRef } = c;
                        return `${predicate_expression(null, test)} ? ${exprFromValueRefOrSignalRef(valueOrSignalCRef)} : `;
                    })
                        .join('') + exprFromValueRefOrSignalRef(valueOrSignalRef)
                };
                axis[prop] = signalRef;
            }
        }
        else if (isSignalRef(propValue)) {
            const propIndex = CONDITIONAL_AXIS_PROP_INDEX[prop];
            if (propIndex) {
                const { vgProp, part } = propIndex;
                // FIXME: remove as any
                setAxisEncode(axis, part, vgProp, propValue);
                delete axis[prop];
            } // else do nothing since the property already supports signal
        }
        // Do not pass labelAlign/Baseline = null to Vega since it won't pass the schema
        // Note that we need to use null so the default labelAlign is preserved.
        if (util_contains(['labelAlign', 'labelBaseline'], prop) && axis[prop] === null) {
            delete axis[prop];
        }
    }
    if (kind === 'grid') {
        if (!axis.grid) {
            return undefined;
        }
        // Remove unnecessary encode block
        if (axis.encode) {
            // Only need to keep encode block for grid
            const { grid } = axis.encode;
            axis.encode = {
                ...(grid ? { grid } : {})
            };
            if (isEmpty(axis.encode)) {
                delete axis.encode;
            }
        }
        return {
            scale,
            orient,
            ...axis,
            domain: false,
            labels: false,
            aria: false, // always hide grid axis
            // Always set min/maxExtent to 0 to ensure that `config.axis*.minExtent` and `config.axis*.maxExtent`
            // would not affect gridAxis
            maxExtent: 0,
            minExtent: 0,
            ticks: false,
            zindex: getFirstDefined(zindex, 0) // put grid behind marks by default
        };
    }
    else {
        // kind === 'main'
        if (!opt.header && axisCmpt.mainExtracted) {
            // if mainExtracted has been extracted to a separate facet
            return undefined;
        }
        if (labelExpr !== undefined) {
            let expr = labelExpr;
            if (axis.encode?.labels?.update && isSignalRef(axis.encode.labels.update.text)) {
                expr = replaceAll(labelExpr, 'datum.label', axis.encode.labels.update.text.signal);
            }
            setAxisEncode(axis, 'labels', 'text', { signal: expr });
        }
        if (axis.labelAlign === null) {
            delete axis.labelAlign;
        }
        // Remove unnecessary encode block
        if (axis.encode) {
            for (const part of AXIS_PARTS) {
                if (!axisCmpt.hasAxisPart(part)) {
                    delete axis.encode[part];
                }
            }
            if (isEmpty(axis.encode)) {
                delete axis.encode;
            }
        }
        const titleString = assembleTitle(title, config);
        return {
            scale,
            orient,
            grid: false,
            ...(titleString ? { title: titleString } : {}),
            ...axis,
            ...(config.aria === false ? { aria: false } : {}),
            zindex: getFirstDefined(zindex, 0) // put axis line above marks by default
        };
    }
}
/**
 * Add axis signals so grid line works correctly
 * (Fix https://github.com/vega/vega-lite/issues/4226)
 */
function assembleAxisSignals(model) {
    const { axes } = model.component;
    const signals = [];
    for (const channel of POSITION_SCALE_CHANNELS) {
        if (axes[channel]) {
            for (const axis of axes[channel]) {
                if (!axis.get('disable') && !axis.get('gridScale')) {
                    // If there is x-axis but no y-scale for gridScale, need to set height/width so x-axis can draw the grid with the right height. Same for y-axis and width.
                    const sizeType = channel === 'x' ? 'height' : 'width';
                    const update = model.getSizeSignalRef(sizeType).signal;
                    if (sizeType !== update) {
                        signals.push({
                            name: sizeType,
                            update
                        });
                    }
                }
            }
        }
    }
    return signals;
}
function assembleAxes(axisComponents, config) {
    const { x = [], y = [] } = axisComponents;
    return [
        ...x.map(a => assembleAxis(a, 'grid', config)),
        ...y.map(a => assembleAxis(a, 'grid', config)),
        ...x.map(a => assembleAxis(a, 'main', config)),
        ...y.map(a => assembleAxis(a, 'main', config))
    ].filter(a => a); // filter undefined
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/config.js





function getAxisConfigFromConfigTypes(configTypes, config, channel, orient) {
    // TODO: add special casing to add conditional value based on orient signal
    return Object.assign.apply(null, [
        {},
        ...configTypes.map(configType => {
            if (configType === 'axisOrient') {
                const orient1 = channel === 'x' ? 'bottom' : 'left';
                const orientConfig1 = config[channel === 'x' ? 'axisBottom' : 'axisLeft'] || {};
                const orientConfig2 = config[channel === 'x' ? 'axisTop' : 'axisRight'] || {};
                const props = new Set([...util_keys(orientConfig1), ...util_keys(orientConfig2)]);
                const conditionalOrientAxisConfig = {};
                for (const prop of props.values()) {
                    conditionalOrientAxisConfig[prop] = {
                        // orient is surely signal in this case
                        signal: `${orient['signal']} === "${orient1}" ? ${signalOrStringValue(orientConfig1[prop])} : ${signalOrStringValue(orientConfig2[prop])}`
                    };
                }
                return conditionalOrientAxisConfig;
            }
            return config[configType];
        })
    ]);
}
function getAxisConfigs(channel, scaleType, orient, config) {
    const typeBasedConfigTypes = scaleType === 'band'
        ? ['axisDiscrete', 'axisBand']
        : scaleType === 'point'
            ? ['axisDiscrete', 'axisPoint']
            : isQuantitative(scaleType)
                ? ['axisQuantitative']
                : scaleType === 'time' || scaleType === 'utc'
                    ? ['axisTemporal']
                    : [];
    const axisChannel = channel === 'x' ? 'axisX' : 'axisY';
    const axisOrient = isSignalRef(orient) ? 'axisOrient' : `axis${titleCase(orient)}`; // axisTop, axisBottom, ...
    const vlOnlyConfigTypes = [
        // technically Vega does have axisBand, but if we make another separation here,
        // it will further introduce complexity in the code
        ...typeBasedConfigTypes,
        ...typeBasedConfigTypes.map(c => axisChannel + c.substr(4))
    ];
    const vgConfigTypes = ['axis', axisOrient, axisChannel];
    return {
        vlOnlyAxisConfig: getAxisConfigFromConfigTypes(vlOnlyConfigTypes, config, channel, orient),
        vgAxisConfig: getAxisConfigFromConfigTypes(vgConfigTypes, config, channel, orient),
        axisConfigStyle: getAxisConfigStyle([...vgConfigTypes, ...vlOnlyConfigTypes], config)
    };
}
function getAxisConfigStyle(axisConfigTypes, config) {
    const toMerge = [{}];
    for (const configType of axisConfigTypes) {
        // TODO: add special casing to add conditional value based on orient signal
        let style = config[configType]?.style;
        if (style) {
            style = vega_util_module_array(style);
            for (const s of style) {
                toMerge.push(config.style[s]);
            }
        }
    }
    return Object.assign.apply(null, toMerge);
}
function getAxisConfig(property, styleConfigIndex, style, axisConfigs = {}) {
    const styleConfig = getStyleConfig(property, style, styleConfigIndex);
    if (styleConfig !== undefined) {
        return {
            configFrom: 'style',
            configValue: styleConfig
        };
    }
    for (const configFrom of ['vlOnlyAxisConfig', 'vgAxisConfig', 'axisConfigStyle']) {
        if (axisConfigs[configFrom]?.[property] !== undefined) {
            return { configFrom, configValue: axisConfigs[configFrom][property] };
        }
    }
    return {};
}
//# sourceMappingURL=config.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/properties.js











const axisRules = {
    scale: ({ model, channel }) => model.scaleName(channel),
    format: ({ format }) => format, // we already calculate this in parse
    formatType: ({ formatType }) => formatType, // we already calculate this in parse
    grid: ({ fieldOrDatumDef, axis, scaleType }) => axis.grid ?? defaultGrid(scaleType, fieldOrDatumDef),
    gridScale: ({ model, channel }) => gridScale(model, channel),
    labelAlign: ({ axis, labelAngle, orient, channel }) => axis.labelAlign || defaultLabelAlign(labelAngle, orient, channel),
    labelAngle: ({ labelAngle }) => labelAngle, // we already calculate this in parse
    labelBaseline: ({ axis, labelAngle, orient, channel }) => axis.labelBaseline || defaultLabelBaseline(labelAngle, orient, channel),
    labelFlush: ({ axis, fieldOrDatumDef, channel }) => axis.labelFlush ?? defaultLabelFlush(fieldOrDatumDef.type, channel),
    labelOverlap: ({ axis, fieldOrDatumDef, scaleType }) => axis.labelOverlap ??
        defaultLabelOverlap(fieldOrDatumDef.type, scaleType, isFieldDef(fieldOrDatumDef) && !!fieldOrDatumDef.timeUnit, isFieldDef(fieldOrDatumDef) ? fieldOrDatumDef.sort : undefined),
    // we already calculate orient in parse
    orient: ({ orient }) => orient, // Need to cast until Vega supports signal
    tickCount: ({ channel, model, axis, fieldOrDatumDef, scaleType }) => {
        const sizeType = channel === 'x' ? 'width' : channel === 'y' ? 'height' : undefined;
        const size = sizeType ? model.getSizeSignalRef(sizeType) : undefined;
        return axis.tickCount ?? defaultTickCount({ fieldOrDatumDef, scaleType, size, values: axis.values });
    },
    tickMinStep: defaultTickMinStep,
    title: ({ axis, model, channel }) => {
        if (axis.title !== undefined) {
            return axis.title;
        }
        const fieldDefTitle = getFieldDefTitle(model, channel);
        if (fieldDefTitle !== undefined) {
            return fieldDefTitle;
        }
        const fieldDef = model.typedFieldDef(channel);
        const channel2 = channel === 'x' ? 'x2' : 'y2';
        const fieldDef2 = model.fieldDef(channel2);
        // If title not specified, store base parts of fieldDef (and fieldDef2 if exists)
        return mergeTitleFieldDefs(fieldDef ? [toFieldDefBase(fieldDef)] : [], isFieldDef(fieldDef2) ? [toFieldDefBase(fieldDef2)] : []);
    },
    values: ({ axis, fieldOrDatumDef }) => properties_values(axis, fieldOrDatumDef),
    zindex: ({ axis, fieldOrDatumDef, mark }) => axis.zindex ?? defaultZindex(mark, fieldOrDatumDef)
};
// TODO: we need to refactor this method after we take care of config refactoring
/**
 * Default rules for whether to show a grid should be shown for a channel.
 * If `grid` is unspecified, the default value is `true` for ordinal scales that are not binned
 */
function defaultGrid(scaleType, fieldDef) {
    return !hasDiscreteDomain(scaleType) && isFieldDef(fieldDef) && !isBinning(fieldDef?.bin) && !isBinned(fieldDef?.bin);
}
function gridScale(model, channel) {
    const gridChannel = channel === 'x' ? 'y' : 'x';
    if (model.getScaleComponent(gridChannel)) {
        return model.scaleName(gridChannel);
    }
    return undefined;
}
function getLabelAngle(fieldOrDatumDef, axis, channel, styleConfig, axisConfigs) {
    const labelAngle = axis?.labelAngle;
    // try axis value
    if (labelAngle !== undefined) {
        return isSignalRef(labelAngle) ? labelAngle : normalizeAngle(labelAngle);
    }
    else {
        // try axis config value
        const { configValue: angle } = getAxisConfig('labelAngle', styleConfig, axis?.style, axisConfigs);
        if (angle !== undefined) {
            return normalizeAngle(angle);
        }
        else {
            // get default value
            if (channel === channel_X &&
                util_contains([NOMINAL, ORDINAL], fieldOrDatumDef.type) &&
                !(isFieldDef(fieldOrDatumDef) && fieldOrDatumDef.timeUnit)) {
                return 270;
            }
            // no default
            return undefined;
        }
    }
}
function normalizeAngleExpr(angle) {
    return `(((${angle.signal} % 360) + 360) % 360)`;
}
function defaultLabelBaseline(angle, orient, channel, alwaysIncludeMiddle) {
    if (angle !== undefined) {
        if (channel === 'x') {
            if (isSignalRef(angle)) {
                const a = normalizeAngleExpr(angle);
                const orientIsTop = isSignalRef(orient) ? `(${orient.signal} === "top")` : orient === 'top';
                return {
                    signal: `(45 < ${a} && ${a} < 135) || (225 < ${a} && ${a} < 315) ? "middle" :` +
                        `(${a} <= 45 || 315 <= ${a}) === ${orientIsTop} ? "bottom" : "top"`
                };
            }
            if ((45 < angle && angle < 135) || (225 < angle && angle < 315)) {
                return 'middle';
            }
            if (isSignalRef(orient)) {
                const op = angle <= 45 || 315 <= angle ? '===' : '!==';
                return { signal: `${orient.signal} ${op} "top" ? "bottom" : "top"` };
            }
            return (angle <= 45 || 315 <= angle) === (orient === 'top') ? 'bottom' : 'top';
        }
        else {
            if (isSignalRef(angle)) {
                const a = normalizeAngleExpr(angle);
                const orientIsLeft = isSignalRef(orient) ? `(${orient.signal} === "left")` : orient === 'left';
                const middle = alwaysIncludeMiddle ? '"middle"' : 'null';
                return {
                    signal: `${a} <= 45 || 315 <= ${a} || (135 <= ${a} && ${a} <= 225) ? ${middle} : (45 <= ${a} && ${a} <= 135) === ${orientIsLeft} ? "top" : "bottom"`
                };
            }
            if (angle <= 45 || 315 <= angle || (135 <= angle && angle <= 225)) {
                return alwaysIncludeMiddle ? 'middle' : null;
            }
            if (isSignalRef(orient)) {
                const op = 45 <= angle && angle <= 135 ? '===' : '!==';
                return { signal: `${orient.signal} ${op} "left" ? "top" : "bottom"` };
            }
            return (45 <= angle && angle <= 135) === (orient === 'left') ? 'top' : 'bottom';
        }
    }
    return undefined;
}
function defaultLabelAlign(angle, orient, channel) {
    if (angle === undefined) {
        return undefined;
    }
    const isX = channel === 'x';
    const startAngle = isX ? 0 : 90;
    const mainOrient = isX ? 'bottom' : 'left';
    if (isSignalRef(angle)) {
        const a = normalizeAngleExpr(angle);
        const orientIsMain = isSignalRef(orient) ? `(${orient.signal} === "${mainOrient}")` : orient === mainOrient;
        return {
            signal: `(${startAngle ? `(${a} + 90)` : a} % 180 === 0) ? ${isX ? null : '"center"'} :` +
                `(${startAngle} < ${a} && ${a} < ${180 + startAngle}) === ${orientIsMain} ? "left" : "right"`
        };
    }
    if ((angle + startAngle) % 180 === 0) {
        // For bottom, use default label align so label flush still works
        return isX ? null : 'center';
    }
    if (isSignalRef(orient)) {
        const op = startAngle < angle && angle < 180 + startAngle ? '===' : '!==';
        const orientIsMain = `${orient.signal} ${op} "${mainOrient}"`;
        return {
            signal: `${orientIsMain} ? "left" : "right"`
        };
    }
    if ((startAngle < angle && angle < 180 + startAngle) === (orient === mainOrient)) {
        return 'left';
    }
    return 'right';
}
function defaultLabelFlush(type, channel) {
    if (channel === 'x' && util_contains(['quantitative', 'temporal'], type)) {
        return true;
    }
    return undefined;
}
function defaultLabelOverlap(type, scaleType, hasTimeUnit, sort) {
    // do not prevent overlap for nominal data because there is no way to infer what the missing labels are
    if ((hasTimeUnit && !vega_util_module_isObject(sort)) || (type !== 'nominal' && type !== 'ordinal')) {
        if (scaleType === 'log' || scaleType === 'symlog') {
            return 'greedy';
        }
        return true;
    }
    return undefined;
}
function defaultOrient(channel) {
    return channel === 'x' ? 'bottom' : 'left';
}
function defaultTickCount({ fieldOrDatumDef, scaleType, size, values: vals }) {
    if (!vals && !hasDiscreteDomain(scaleType) && scaleType !== 'log') {
        if (isFieldDef(fieldOrDatumDef)) {
            if (isBinning(fieldOrDatumDef.bin)) {
                // for binned data, we don't want more ticks than maxbins
                return { signal: `ceil(${size.signal}/10)` };
            }
            if (fieldOrDatumDef.timeUnit &&
                util_contains(['month', 'hours', 'day', 'quarter'], normalizeTimeUnit(fieldOrDatumDef.timeUnit)?.unit)) {
                return undefined;
            }
        }
        return { signal: `ceil(${size.signal}/40)` };
    }
    return undefined;
}
function defaultTickMinStep({ format, fieldOrDatumDef }) {
    if (format === 'd') {
        return 1;
    }
    if (isFieldDef(fieldOrDatumDef)) {
        const { timeUnit } = fieldOrDatumDef;
        if (timeUnit) {
            const signal = durationExpr(timeUnit);
            if (signal) {
                return { signal };
            }
        }
    }
    return undefined;
}
function getFieldDefTitle(model, channel) {
    const channel2 = channel === 'x' ? 'x2' : 'y2';
    const fieldDef = model.fieldDef(channel);
    const fieldDef2 = model.fieldDef(channel2);
    const title1 = fieldDef ? fieldDef.title : undefined;
    const title2 = fieldDef2 ? fieldDef2.title : undefined;
    if (title1 && title2) {
        return mergeTitle(title1, title2);
    }
    else if (title1) {
        return title1;
    }
    else if (title2) {
        return title2;
    }
    else if (title1 !== undefined) {
        // falsy value to disable config
        return title1;
    }
    else if (title2 !== undefined) {
        // falsy value to disable config
        return title2;
    }
    return undefined;
}
function properties_values(axis, fieldOrDatumDef) {
    const vals = axis.values;
    if (vega_util_module_isArray(vals)) {
        return valueArray(fieldOrDatumDef, vals);
    }
    else if (isSignalRef(vals)) {
        return vals;
    }
    return undefined;
}
function defaultZindex(mark, fieldDef) {
    if (mark === 'rect' && channeldef_isDiscrete(fieldDef)) {
        return 1;
    }
    return 0;
}
//# sourceMappingURL=properties.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/calculate.js






class CalculateNode extends DataFlowNode {
    clone() {
        return new CalculateNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this._dependentFields = getDependentFields(this.transform.calculate);
    }
    static parseAllForSortIndex(parent, model) {
        // get all the encoding with sort fields from model
        model.forEachFieldDef((fieldDef, channel) => {
            if (!isScaleFieldDef(fieldDef)) {
                return;
            }
            if (isSortArray(fieldDef.sort)) {
                const { field, timeUnit } = fieldDef;
                const sort = fieldDef.sort;
                // generate `datum["a"] === val0 ? 0 : datum["a"] === val1 ? 1 : ... : n` via FieldEqualPredicate
                const calculate = sort
                    .map((sortValue, i) => {
                    return `${fieldFilterExpression({ field, timeUnit, equal: sortValue })} ? ${i} : `;
                })
                    .join('') + sort.length;
                parent = new CalculateNode(parent, {
                    calculate,
                    as: sortArrayIndexField(fieldDef, channel, { forAs: true })
                });
            }
        });
        return parent;
    }
    producedFields() {
        return new Set([this.transform.as]);
    }
    dependentFields() {
        return this._dependentFields;
    }
    assemble() {
        return {
            type: 'formula',
            expr: this.transform.calculate,
            as: this.transform.as
        };
    }
    hash() {
        return `Calculate ${util_hash(this.transform)}`;
    }
}
function sortArrayIndexField(fieldDef, channel, opt) {
    return vgField(fieldDef, { prefix: channel, suffix: 'sort_index', ...opt });
}
//# sourceMappingURL=calculate.js.map
;// ../../node_modules/vega-lite/build/src/compile/header/common.js

/**
 * Get header channel, which can be different from facet channel when orient is specified or when the facet channel is facet.
 */
function getHeaderChannel(channel, orient) {
    if (util_contains(['top', 'bottom'], orient)) {
        return 'column';
    }
    else if (util_contains(['left', 'right'], orient)) {
        return 'row';
    }
    return channel === 'row' ? 'row' : 'column';
}
function getHeaderProperty(prop, header, config, channel) {
    const headerSpecificConfig = channel === 'row' ? config.headerRow : channel === 'column' ? config.headerColumn : config.headerFacet;
    return getFirstDefined((header || {})[prop], headerSpecificConfig[prop], config.header[prop]);
}
function getHeaderProperties(properties, header, config, channel) {
    const props = {};
    for (const prop of properties) {
        const value = getHeaderProperty(prop, header || {}, config, channel);
        if (value !== undefined) {
            props[prop] = value;
        }
    }
    return props;
}
//# sourceMappingURL=common.js.map
;// ../../node_modules/vega-lite/build/src/compile/header/component.js
const HEADER_CHANNELS = ['row', 'column'];
const HEADER_TYPES = ['header', 'footer'];
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/header/assemble.js
/**
 * Utility for generating row / column headers
 */













// TODO: rename to assembleHeaderTitleGroup
function assembleTitleGroup(model, channel) {
    const title = model.component.layoutHeaders[channel].title;
    const config = model.config ? model.config : undefined;
    const facetFieldDef = model.component.layoutHeaders[channel].facetFieldDef
        ? model.component.layoutHeaders[channel].facetFieldDef
        : undefined;
    const { titleAnchor, titleAngle: ta, titleOrient } = getHeaderProperties(['titleAnchor', 'titleAngle', 'titleOrient'], facetFieldDef.header, config, channel);
    const headerChannel = getHeaderChannel(channel, titleOrient);
    const titleAngle = normalizeAngle(ta);
    return {
        name: `${channel}-title`,
        type: 'group',
        role: `${headerChannel}-title`,
        title: {
            text: title,
            ...(channel === 'row' ? { orient: 'left' } : {}),
            style: 'guide-title',
            ...defaultHeaderGuideBaseline(titleAngle, headerChannel),
            ...defaultHeaderGuideAlign(headerChannel, titleAngle, titleAnchor),
            ...assembleHeaderProperties(config, facetFieldDef, channel, HEADER_TITLE_PROPERTIES, HEADER_TITLE_PROPERTIES_MAP)
        }
    };
}
function defaultHeaderGuideAlign(headerChannel, angle, anchor = 'middle') {
    switch (anchor) {
        case 'start':
            return { align: 'left' };
        case 'end':
            return { align: 'right' };
    }
    const align = defaultLabelAlign(angle, headerChannel === 'row' ? 'left' : 'top', headerChannel === 'row' ? 'y' : 'x');
    return align ? { align } : {};
}
function defaultHeaderGuideBaseline(angle, channel) {
    const baseline = defaultLabelBaseline(angle, channel === 'row' ? 'left' : 'top', channel === 'row' ? 'y' : 'x', true);
    return baseline ? { baseline } : {};
}
function assembleHeaderGroups(model, channel) {
    const layoutHeader = model.component.layoutHeaders[channel];
    const groups = [];
    for (const headerType of HEADER_TYPES) {
        if (layoutHeader[headerType]) {
            for (const headerComponent of layoutHeader[headerType]) {
                const group = assembleHeaderGroup(model, channel, headerType, layoutHeader, headerComponent);
                if (group != null) {
                    groups.push(group);
                }
            }
        }
    }
    return groups;
}
function getSort(facetFieldDef, channel) {
    const { sort } = facetFieldDef;
    if (isSortField(sort)) {
        return {
            field: vgField(sort, { expr: 'datum' }),
            order: sort.order ?? 'ascending'
        };
    }
    else if (vega_util_module_isArray(sort)) {
        return {
            field: sortArrayIndexField(facetFieldDef, channel, { expr: 'datum' }),
            order: 'ascending'
        };
    }
    else {
        return {
            field: vgField(facetFieldDef, { expr: 'datum' }),
            order: sort ?? 'ascending'
        };
    }
}
function assembleLabelTitle(facetFieldDef, channel, config) {
    const { format, formatType, labelAngle, labelAnchor, labelOrient, labelExpr } = getHeaderProperties(['format', 'formatType', 'labelAngle', 'labelAnchor', 'labelOrient', 'labelExpr'], facetFieldDef.header, config, channel);
    const titleTextExpr = formatSignalRef({
        fieldOrDatumDef: facetFieldDef,
        format,
        formatType,
        expr: 'parent',
        config
    }).signal;
    const headerChannel = getHeaderChannel(channel, labelOrient);
    return {
        text: {
            signal: labelExpr
                ? replaceAll(replaceAll(labelExpr, 'datum.label', titleTextExpr), 'datum.value', vgField(facetFieldDef, { expr: 'parent' }))
                : titleTextExpr
        },
        ...(channel === 'row' ? { orient: 'left' } : {}),
        style: 'guide-label',
        frame: 'group',
        ...defaultHeaderGuideBaseline(labelAngle, headerChannel),
        ...defaultHeaderGuideAlign(headerChannel, labelAngle, labelAnchor),
        ...assembleHeaderProperties(config, facetFieldDef, channel, HEADER_LABEL_PROPERTIES, HEADER_LABEL_PROPERTIES_MAP)
    };
}
function assembleHeaderGroup(model, channel, headerType, layoutHeader, headerComponent) {
    if (headerComponent) {
        let title = null;
        const { facetFieldDef } = layoutHeader;
        const config = model.config ? model.config : undefined;
        if (facetFieldDef && headerComponent.labels) {
            const { labelOrient } = getHeaderProperties(['labelOrient'], facetFieldDef.header, config, channel);
            // Include label title in the header if orient aligns with the channel
            if ((channel === 'row' && !util_contains(['top', 'bottom'], labelOrient)) ||
                (channel === 'column' && !util_contains(['left', 'right'], labelOrient))) {
                title = assembleLabelTitle(facetFieldDef, channel, config);
            }
        }
        const isFacetWithoutRowCol = isFacetModel(model) && !isFacetMapping(model.facet);
        const axes = headerComponent.axes;
        const hasAxes = axes?.length > 0;
        if (title || hasAxes) {
            const sizeChannel = channel === 'row' ? 'height' : 'width';
            return {
                name: model.getName(`${channel}_${headerType}`),
                type: 'group',
                role: `${channel}-${headerType}`,
                ...(layoutHeader.facetFieldDef
                    ? {
                        from: { data: model.getName(`${channel}_domain`) },
                        sort: getSort(facetFieldDef, channel)
                    }
                    : {}),
                ...(hasAxes && isFacetWithoutRowCol
                    ? {
                        from: { data: model.getName(`facet_domain_${channel}`) }
                    }
                    : {}),
                ...(title ? { title } : {}),
                ...(headerComponent.sizeSignal
                    ? {
                        encode: {
                            update: {
                                [sizeChannel]: headerComponent.sizeSignal
                            }
                        }
                    }
                    : {}),
                ...(hasAxes ? { axes } : {})
            };
        }
    }
    return null;
}
const LAYOUT_TITLE_BAND = {
    column: {
        start: 0,
        end: 1
    },
    row: {
        start: 1,
        end: 0
    }
};
function getLayoutTitleBand(titleAnchor, headerChannel) {
    return LAYOUT_TITLE_BAND[headerChannel][titleAnchor];
}
function assembleLayoutTitleBand(headerComponentIndex, config) {
    const titleBand = {};
    for (const channel of FACET_CHANNELS) {
        const headerComponent = headerComponentIndex[channel];
        if (headerComponent?.facetFieldDef) {
            const { titleAnchor, titleOrient } = getHeaderProperties(['titleAnchor', 'titleOrient'], headerComponent.facetFieldDef.header, config, channel);
            const headerChannel = getHeaderChannel(channel, titleOrient);
            const band = getLayoutTitleBand(titleAnchor, headerChannel);
            if (band !== undefined) {
                titleBand[headerChannel] = band;
            }
        }
    }
    return isEmpty(titleBand) ? undefined : titleBand;
}
function assembleHeaderProperties(config, facetFieldDef, channel, properties, propertiesMap) {
    const props = {};
    for (const prop of properties) {
        if (!propertiesMap[prop]) {
            continue;
        }
        const value = getHeaderProperty(prop, facetFieldDef?.header, config, channel);
        if (value !== undefined) {
            props[propertiesMap[prop]] = value;
        }
    }
    return props;
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/layoutsize/assemble.js






function assembleLayoutSignals(model) {
    return [
        ...sizeSignals(model, 'width'),
        ...sizeSignals(model, 'height'),
        ...sizeSignals(model, 'childWidth'),
        ...sizeSignals(model, 'childHeight')
    ];
}
function sizeSignals(model, sizeType) {
    const channel = sizeType === 'width' ? 'x' : 'y';
    const size = model.component.layoutSize.get(sizeType);
    if (!size || size === 'merged') {
        return [];
    }
    // Read size signal name from name map, just in case it is the top-level size signal that got renamed.
    const name = model.getSizeSignalRef(sizeType).signal;
    if (size === 'step') {
        const scaleComponent = model.getScaleComponent(channel);
        if (scaleComponent) {
            const type = scaleComponent.get('type');
            const range = scaleComponent.get('range');
            if (hasDiscreteDomain(type) && isVgRangeStep(range)) {
                const scaleName = model.scaleName(channel);
                if (isFacetModel(model.parent)) {
                    // If parent is facet and this is an independent scale, return only signal signal
                    // as the width/height will be calculated using the cardinality from
                    // facet's aggregate rather than reading from scale domain
                    const parentResolve = model.parent.component.resolve;
                    if (parentResolve.scale[channel] === 'independent') {
                        return [stepSignal(scaleName, range)];
                    }
                }
                return [
                    stepSignal(scaleName, range),
                    {
                        name,
                        update: sizeExpr(scaleName, scaleComponent, `domain('${scaleName}').length`)
                    }
                ];
            }
        }
        /* istanbul ignore next: Condition should not happen -- only for warning in development. */
        throw new Error('layout size is step although width/height is not step.');
    }
    else if (size == 'container') {
        const isWidth = name.endsWith('width');
        const expr = isWidth ? 'containerSize()[0]' : 'containerSize()[1]';
        const defaultValue = getViewConfigContinuousSize(model.config.view, isWidth ? 'width' : 'height');
        const safeExpr = `isFinite(${expr}) ? ${expr} : ${defaultValue}`;
        return [{ name, init: safeExpr, on: [{ update: safeExpr, events: 'window:resize' }] }];
    }
    else {
        return [
            {
                name,
                value: size
            }
        ];
    }
}
function stepSignal(scaleName, range) {
    const name = `${scaleName}_step`;
    if (isSignalRef(range.step)) {
        return { name, update: range.step.signal };
    }
    else {
        return { name, value: range.step };
    }
}
function sizeExpr(scaleName, scaleComponent, cardinality) {
    const type = scaleComponent.get('type');
    const padding = scaleComponent.get('padding');
    const paddingOuter = getFirstDefined(scaleComponent.get('paddingOuter'), padding);
    let paddingInner = scaleComponent.get('paddingInner');
    paddingInner =
        type === 'band'
            ? // only band has real paddingInner
                paddingInner !== undefined
                    ? paddingInner
                    : padding
            : // For point, as calculated in https://github.com/vega/vega-scale/blob/master/src/band.js#L128,
                // it's equivalent to have paddingInner = 1 since there is only n-1 steps between n points.
                1;
    return `bandspace(${cardinality}, ${signalOrStringValue(paddingInner)}, ${signalOrStringValue(paddingOuter)}) * ${scaleName}_step`;
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/layoutsize/component.js
function getSizeTypeFromLayoutSizeType(layoutSizeType) {
    return layoutSizeType === 'childWidth' ? 'width' : layoutSizeType === 'childHeight' ? 'height' : layoutSizeType;
}
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/guide.js



function guideEncodeEntry(encoding, model) {
    return util_keys(encoding).reduce((encode, channel) => {
        return {
            ...encode,
            ...wrapCondition({
                model,
                channelDef: encoding[channel],
                vgChannel: channel,
                mainRefFn: def => signalOrValueRef(def.value),
                invalidValueRef: undefined // guide encoding won't show invalid values for the scale
            })
        };
    }, {});
}
//# sourceMappingURL=guide.js.map
;// ../../node_modules/vega-lite/build/src/compile/resolve.js



function defaultScaleResolve(channel, model) {
    if (isFacetModel(model)) {
        return channel === 'theta' ? 'independent' : 'shared';
    }
    else if (isLayerModel(model)) {
        return 'shared';
    }
    else if (isConcatModel(model)) {
        return isXorY(channel) || channel === 'theta' || channel === 'radius' ? 'independent' : 'shared';
    }
    /* istanbul ignore next: should never reach here. */
    throw new Error('invalid model type for resolve');
}
function parseGuideResolve(resolve, channel) {
    const channelScaleResolve = resolve.scale[channel];
    const guide = isXorY(channel) ? 'axis' : 'legend';
    if (channelScaleResolve === 'independent') {
        if (resolve[guide][channel] === 'shared') {
            log_warn(independentScaleMeansIndependentGuide(channel));
        }
        return 'independent';
    }
    return resolve[guide][channel] || 'shared';
}
//# sourceMappingURL=resolve.js.map
;// ../../node_modules/vega-lite/build/src/compile/legend/component.js



const LEGEND_COMPONENT_PROPERTY_INDEX = {
    ...COMMON_LEGEND_PROPERTY_INDEX,
    disable: 1,
    labelExpr: 1,
    selections: 1,
    // channel scales
    opacity: 1,
    shape: 1,
    stroke: 1,
    fill: 1,
    size: 1,
    strokeWidth: 1,
    strokeDash: 1,
    // encode
    encode: 1
};
const LEGEND_COMPONENT_PROPERTIES = util_keys(LEGEND_COMPONENT_PROPERTY_INDEX);
class LegendComponent extends Split {
}
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/legend/encode.js









const legendEncodeRules = {
    symbols: encode_symbols,
    gradient: encode_gradient,
    labels,
    entries: encode_entries
};
function encode_symbols(symbolsSpec, { fieldOrDatumDef, model, channel, legendCmpt, legendType }) {
    if (legendType !== 'symbol') {
        return undefined;
    }
    const { markDef, encoding, config, mark } = model;
    const filled = markDef.filled && mark !== 'trail';
    let out = {
        ...applyMarkConfig({}, model, FILL_STROKE_CONFIG),
        ...color_color(model, { filled })
    }; // FIXME: remove this when VgEncodeEntry is compatible with SymbolEncodeEntry
    const symbolOpacity = legendCmpt.get('symbolOpacity') ?? config.legend.symbolOpacity;
    const symbolFillColor = legendCmpt.get('symbolFillColor') ?? config.legend.symbolFillColor;
    const symbolStrokeColor = legendCmpt.get('symbolStrokeColor') ?? config.legend.symbolStrokeColor;
    const opacity = symbolOpacity === undefined ? (getMaxValue(encoding.opacity) ?? markDef.opacity) : undefined;
    if (out.fill) {
        // for fill legend, we don't want any fill in symbol
        if (channel === 'fill' || (filled && channel === COLOR)) {
            delete out.fill;
        }
        else if (util_hasProperty(out.fill, 'field')) {
            // For others, set fill to some opaque value (or nothing if a color is already set)
            if (symbolFillColor) {
                delete out.fill;
            }
            else {
                out.fill = signalOrValueRef(config.legend.symbolBaseFillColor ?? 'black');
                out.fillOpacity = signalOrValueRef(opacity ?? 1);
            }
        }
        else if (vega_util_module_isArray(out.fill)) {
            const fill = getFirstConditionValue(encoding.fill ?? encoding.color) ?? markDef.fill ?? (filled && markDef.color);
            if (fill) {
                out.fill = signalOrValueRef(fill);
            }
        }
    }
    if (out.stroke) {
        if (channel === 'stroke' || (!filled && channel === COLOR)) {
            delete out.stroke;
        }
        else if (util_hasProperty(out.stroke, 'field') || symbolStrokeColor) {
            // For others, remove stroke field
            delete out.stroke;
        }
        else if (vega_util_module_isArray(out.stroke)) {
            const stroke = getFirstDefined(getFirstConditionValue(encoding.stroke || encoding.color), markDef.stroke, filled ? markDef.color : undefined);
            if (stroke) {
                out.stroke = { value: stroke };
            }
        }
    }
    if (channel !== OPACITY) {
        const condition = isFieldDef(fieldOrDatumDef) && selectedCondition(model, legendCmpt, fieldOrDatumDef);
        if (condition) {
            out.opacity = [
                { test: condition, ...signalOrValueRef(opacity ?? 1) },
                signalOrValueRef(config.legend.unselectedOpacity)
            ];
        }
        else if (opacity) {
            out.opacity = signalOrValueRef(opacity);
        }
    }
    out = { ...out, ...symbolsSpec };
    return isEmpty(out) ? undefined : out;
}
function encode_gradient(gradientSpec, { model, legendType, legendCmpt }) {
    if (legendType !== 'gradient') {
        return undefined;
    }
    const { config, markDef, encoding } = model;
    let out = {};
    const gradientOpacity = legendCmpt.get('gradientOpacity') ?? config.legend.gradientOpacity;
    const opacity = gradientOpacity === undefined ? getMaxValue(encoding.opacity) || markDef.opacity : undefined;
    if (opacity) {
        // only apply opacity if it is neither zero or undefined
        out.opacity = signalOrValueRef(opacity);
    }
    out = { ...out, ...gradientSpec };
    return isEmpty(out) ? undefined : out;
}
function labels(specifiedlabelsSpec, { fieldOrDatumDef, model, channel, legendCmpt }) {
    const legend = model.legend(channel) || {};
    const config = model.config;
    const condition = isFieldDef(fieldOrDatumDef) ? selectedCondition(model, legendCmpt, fieldOrDatumDef) : undefined;
    const opacity = condition ? [{ test: condition, value: 1 }, { value: config.legend.unselectedOpacity }] : undefined;
    const { format, formatType } = legend;
    let text = undefined;
    if (isCustomFormatType(formatType)) {
        text = formatCustomType({
            fieldOrDatumDef,
            field: 'datum.value',
            format,
            formatType,
            config
        });
    }
    else if (format === undefined && formatType === undefined && config.customFormatTypes) {
        if (fieldOrDatumDef.type === 'quantitative' && config.numberFormatType) {
            text = formatCustomType({
                fieldOrDatumDef,
                field: 'datum.value',
                format: config.numberFormat,
                formatType: config.numberFormatType,
                config
            });
        }
        else if (fieldOrDatumDef.type === 'temporal' &&
            config.timeFormatType &&
            isFieldDef(fieldOrDatumDef) &&
            fieldOrDatumDef.timeUnit === undefined) {
            text = formatCustomType({
                fieldOrDatumDef,
                field: 'datum.value',
                format: config.timeFormat,
                formatType: config.timeFormatType,
                config
            });
        }
    }
    const labelsSpec = {
        ...(opacity ? { opacity } : {}),
        ...(text ? { text } : {}),
        ...specifiedlabelsSpec
    };
    return isEmpty(labelsSpec) ? undefined : labelsSpec;
}
function encode_entries(entriesSpec, { legendCmpt }) {
    const selections = legendCmpt.get('selections');
    return selections?.length ? { ...entriesSpec, fill: { value: 'transparent' } } : entriesSpec;
}
function getMaxValue(channelDef) {
    return getConditionValue(channelDef, (v, conditionalDef) => Math.max(v, conditionalDef.value));
}
function getFirstConditionValue(channelDef) {
    return getConditionValue(channelDef, (v, conditionalDef) => {
        return getFirstDefined(v, conditionalDef.value);
    });
}
function getConditionValue(channelDef, reducer) {
    if (hasConditionalValueDef(channelDef)) {
        return vega_util_module_array(channelDef.condition).reduce(reducer, channelDef.value);
    }
    else if (isValueDef(channelDef)) {
        return channelDef.value;
    }
    return undefined;
}
function selectedCondition(model, legendCmpt, fieldDef) {
    const selections = legendCmpt.get('selections');
    if (!selections?.length)
        return undefined;
    const field = $(fieldDef.field);
    return selections
        .map(name => {
        const store = $(varName(name) + STORE);
        return `(!length(data(${store})) || (${name}[${field}] && indexof(${name}[${field}], datum.value) >= 0))`;
    })
        .join(' || ');
}
//# sourceMappingURL=encode.js.map
;// ../../node_modules/vega-lite/build/src/compile/legend/properties.js








const legendRules = {
    direction: ({ direction }) => direction,
    format: ({ fieldOrDatumDef, legend, config }) => {
        const { format, formatType } = legend;
        return guideFormat(fieldOrDatumDef, fieldOrDatumDef.type, format, formatType, config, false);
    },
    formatType: ({ legend, fieldOrDatumDef, scaleType }) => {
        const { formatType } = legend;
        return guideFormatType(formatType, fieldOrDatumDef, scaleType);
    },
    gradientLength: params => {
        const { legend, legendConfig } = params;
        return legend.gradientLength ?? legendConfig.gradientLength ?? defaultGradientLength(params);
    },
    labelOverlap: ({ legend, legendConfig, scaleType }) => legend.labelOverlap ?? legendConfig.labelOverlap ?? properties_defaultLabelOverlap(scaleType),
    symbolType: ({ legend, markDef, channel, encoding }) => legend.symbolType ?? defaultSymbolType(markDef.type, channel, encoding.shape, markDef.shape),
    title: ({ fieldOrDatumDef, config }) => channeldef_title(fieldOrDatumDef, config, { allowDisabling: true }),
    type: ({ legendType, scaleType, channel }) => {
        if (isColorChannel(channel) && isContinuousToContinuous(scaleType)) {
            if (legendType === 'gradient') {
                return undefined;
            }
        }
        else if (legendType === 'symbol') {
            return undefined;
        }
        return legendType;
    }, // depended by other property, let's define upfront
    values: ({ fieldOrDatumDef, legend }) => legend_properties_values(legend, fieldOrDatumDef)
};
function legend_properties_values(legend, fieldOrDatumDef) {
    const vals = legend.values;
    if (vega_util_module_isArray(vals)) {
        return valueArray(fieldOrDatumDef, vals);
    }
    else if (isSignalRef(vals)) {
        return vals;
    }
    return undefined;
}
function defaultSymbolType(mark, channel, shapeChannelDef, markShape) {
    if (channel !== 'shape') {
        // use the value from the shape encoding or the mark config if they exist
        const shape = getFirstConditionValue(shapeChannelDef) ?? markShape;
        if (shape) {
            return shape;
        }
    }
    switch (mark) {
        case 'bar':
        case 'rect':
        case 'image':
        case 'square':
            return 'square';
        case 'line':
        case 'trail':
        case 'rule':
            return 'stroke';
        case 'arc':
        case 'point':
        case 'circle':
        case 'tick':
        case 'geoshape':
        case 'area':
        case 'text':
            return 'circle';
    }
}
function clipHeight(legendType) {
    if (legendType === 'gradient') {
        return 20;
    }
    return undefined;
}
function getLegendType(params) {
    const { legend } = params;
    return getFirstDefined(legend.type, properties_defaultType(params));
}
function properties_defaultType({ channel, timeUnit, scaleType }) {
    // Following the logic in https://github.com/vega/vega-parser/blob/master/src/parsers/legend.js
    if (isColorChannel(channel)) {
        if (util_contains(['quarter', 'month', 'day'], timeUnit)) {
            return 'symbol';
        }
        if (isContinuousToContinuous(scaleType)) {
            return 'gradient';
        }
    }
    return 'symbol';
}
function getDirection({ legendConfig, legendType, orient, legend }) {
    return (legend.direction ??
        legendConfig[legendType ? 'gradientDirection' : 'symbolDirection'] ??
        defaultDirection(orient, legendType));
}
function defaultDirection(orient, legendType) {
    switch (orient) {
        case 'top':
        case 'bottom':
            return 'horizontal';
        case 'left':
        case 'right':
        case 'none':
        case undefined: // undefined = "right" in Vega
            return undefined; // vertical is Vega's default
        default:
            // top-left / ...
            // For inner legend, uses compact layout like Tableau
            return legendType === 'gradient' ? 'horizontal' : undefined;
    }
}
function defaultGradientLength({ legendConfig, model, direction, orient, scaleType }) {
    const { gradientHorizontalMaxLength, gradientHorizontalMinLength, gradientVerticalMaxLength, gradientVerticalMinLength } = legendConfig;
    if (isContinuousToContinuous(scaleType)) {
        if (direction === 'horizontal') {
            if (orient === 'top' || orient === 'bottom') {
                return gradientLengthSignal(model, 'width', gradientHorizontalMinLength, gradientHorizontalMaxLength);
            }
            else {
                return gradientHorizontalMinLength;
            }
        }
        else {
            // vertical / undefined (Vega uses vertical by default)
            return gradientLengthSignal(model, 'height', gradientVerticalMinLength, gradientVerticalMaxLength);
        }
    }
    return undefined;
}
function gradientLengthSignal(model, sizeType, min, max) {
    const sizeSignal = model.getSizeSignalRef(sizeType).signal;
    return { signal: `clamp(${sizeSignal}, ${min}, ${max})` };
}
function properties_defaultLabelOverlap(scaleType) {
    if (util_contains(['quantile', 'threshold', 'log', 'symlog'], scaleType)) {
        return 'greedy';
    }
    return undefined;
}
//# sourceMappingURL=properties.js.map
;// ../../node_modules/vega-lite/build/src/compile/legend/parse.js















function parse_parseLegend(model) {
    const legendComponent = isUnitModel(model) ? parseUnitLegend(model) : parseNonUnitLegend(model);
    model.component.legends = legendComponent;
    return legendComponent;
}
function parseUnitLegend(model) {
    const { encoding } = model;
    const legendComponent = {};
    for (const channel of [COLOR, ...LEGEND_SCALE_CHANNELS]) {
        const def = getFieldOrDatumDef(encoding[channel]);
        if (!def || !model.getScaleComponent(channel)) {
            continue;
        }
        if (channel === SHAPE && isFieldDef(def) && def.type === GEOJSON) {
            continue;
        }
        legendComponent[channel] = parseLegendForChannel(model, channel);
    }
    return legendComponent;
}
function getLegendDefWithScale(model, channel) {
    const scale = model.scaleName(channel);
    if (model.mark === 'trail') {
        if (channel === 'color') {
            // trail is a filled mark, but its default symbolType ("stroke") should use "stroke"
            return { stroke: scale };
        }
        else if (channel === 'size') {
            return { strokeWidth: scale };
        }
    }
    if (channel === 'color') {
        return model.markDef.filled ? { fill: scale } : { stroke: scale };
    }
    return { [channel]: scale };
}
// eslint-disable-next-line @typescript-eslint/ban-types
function isExplicit(value, property, legend, fieldDef) {
    switch (property) {
        case 'disable':
            return legend !== undefined; // if axis is specified or null/false, then its enable/disable state is explicit
        case 'values':
            // specified legend.values is already respected, but may get transformed.
            return !!legend?.values;
        case 'title':
            // title can be explicit if fieldDef.title is set
            if (property === 'title' && value === fieldDef?.title) {
                return true;
            }
    }
    // Otherwise, things are explicit if the returned value matches the specified property
    return value === (legend || {})[property];
}
function parseLegendForChannel(model, channel) {
    let legend = model.legend(channel);
    const { markDef, encoding, config } = model;
    const legendConfig = config.legend;
    const legendCmpt = new LegendComponent({}, getLegendDefWithScale(model, channel));
    parseInteractiveLegend(model, channel, legendCmpt);
    const disable = legend !== undefined ? !legend : legendConfig.disable;
    legendCmpt.set('disable', disable, legend !== undefined);
    if (disable) {
        return legendCmpt;
    }
    legend = legend || {};
    const scaleType = model.getScaleComponent(channel).get('type');
    const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]);
    const timeUnit = isFieldDef(fieldOrDatumDef) ? normalizeTimeUnit(fieldOrDatumDef.timeUnit)?.unit : undefined;
    const orient = legend.orient || config.legend.orient || 'right';
    const legendType = getLegendType({ legend, channel, timeUnit, scaleType });
    const direction = getDirection({ legend, legendType, orient, legendConfig });
    const ruleParams = {
        legend,
        channel,
        model,
        markDef,
        encoding,
        fieldOrDatumDef,
        legendConfig,
        config,
        scaleType,
        orient,
        legendType,
        direction
    };
    for (const property of LEGEND_COMPONENT_PROPERTIES) {
        if ((legendType === 'gradient' && property.startsWith('symbol')) ||
            (legendType === 'symbol' && property.startsWith('gradient'))) {
            continue;
        }
        const value = property in legendRules ? legendRules[property](ruleParams) : legend[property];
        if (value !== undefined) {
            const explicit = isExplicit(value, property, legend, model.fieldDef(channel));
            if (explicit || config.legend[property] === undefined) {
                legendCmpt.set(property, value, explicit);
            }
        }
    }
    const legendEncoding = legend?.encoding ?? {};
    const selections = legendCmpt.get('selections');
    const legendEncode = {};
    const legendEncodeParams = { fieldOrDatumDef, model, channel, legendCmpt, legendType };
    for (const part of ['labels', 'legend', 'title', 'symbols', 'gradient', 'entries']) {
        // FIXME: remove as any (figure out what legendEncoding.entries is)
        const legendEncodingPart = guideEncodeEntry(legendEncoding[part] ?? {}, model);
        const value = part in legendEncodeRules
            ? legendEncodeRules[part](legendEncodingPart, legendEncodeParams) // apply rule
            : legendEncodingPart; // no rule -- just default values
        if (value !== undefined && !isEmpty(value)) {
            legendEncode[part] = {
                ...(selections?.length && isFieldDef(fieldOrDatumDef)
                    ? { name: `${varName(fieldOrDatumDef.field)}_legend_${part}` }
                    : {}),
                ...(selections?.length ? { interactive: !!selections } : {}),
                update: value
            };
        }
    }
    if (!isEmpty(legendEncode)) {
        legendCmpt.set('encode', legendEncode, !!legend?.encoding);
    }
    return legendCmpt;
}
function parseNonUnitLegend(model) {
    const { legends, resolve } = model.component;
    for (const child of model.children) {
        parse_parseLegend(child);
        for (const channel of util_keys(child.component.legends)) {
            resolve.legend[channel] = parseGuideResolve(model.component.resolve, channel);
            if (resolve.legend[channel] === 'shared') {
                // If the resolve says shared (and has not been overridden)
                // We will try to merge and see if there is a conflict
                legends[channel] = mergeLegendComponent(legends[channel], child.component.legends[channel]);
                if (!legends[channel]) {
                    // If merge returns nothing, there is a conflict so we cannot make the legend shared.
                    // Thus, mark legend as independent and remove the legend component.
                    resolve.legend[channel] = 'independent';
                    delete legends[channel];
                }
            }
        }
    }
    for (const channel of util_keys(legends)) {
        for (const child of model.children) {
            if (!child.component.legends[channel]) {
                // skip if the child does not have a particular legend
                continue;
            }
            if (resolve.legend[channel] === 'shared') {
                // After merging shared legend, make sure to remove legend from child
                delete child.component.legends[channel];
            }
        }
    }
    return legends;
}
function mergeLegendComponent(mergedLegend, childLegend) {
    if (!mergedLegend) {
        return childLegend.clone();
    }
    const mergedOrient = mergedLegend.getWithExplicit('orient');
    const childOrient = childLegend.getWithExplicit('orient');
    if (mergedOrient.explicit && childOrient.explicit && mergedOrient.value !== childOrient.value) {
        // TODO: throw warning if resolve is explicit (We don't have info about explicit/implicit resolve yet.)
        // Cannot merge due to inconsistent orient
        return undefined;
    }
    let typeMerged = false;
    // Otherwise, let's merge
    for (const prop of LEGEND_COMPONENT_PROPERTIES) {
        const mergedValueWithExplicit = mergeValuesWithExplicit(mergedLegend.getWithExplicit(prop), childLegend.getWithExplicit(prop), prop, 'legend', 
        // Tie breaker function
        (v1, v2) => {
            switch (prop) {
                case 'symbolType':
                    return mergeSymbolType(v1, v2);
                case 'title':
                    return mergeTitleComponent(v1, v2);
                case 'type':
                    // There are only two types. If we have different types, then prefer symbol over gradient.
                    typeMerged = true;
                    return makeImplicit('symbol');
            }
            return defaultTieBreaker(v1, v2, prop, 'legend');
        });
        mergedLegend.setWithExplicit(prop, mergedValueWithExplicit);
    }
    if (typeMerged) {
        if (mergedLegend.implicit?.encode?.gradient) {
            deleteNestedProperty(mergedLegend.implicit, ['encode', 'gradient']);
        }
        if (mergedLegend.explicit?.encode?.gradient) {
            deleteNestedProperty(mergedLegend.explicit, ['encode', 'gradient']);
        }
    }
    return mergedLegend;
}
function mergeSymbolType(st1, st2) {
    if (st2.value === 'circle') {
        // prefer "circle" over "stroke"
        return st2;
    }
    return st1;
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/legend/assemble.js




function setLegendEncode(legend, part, vgProp, vgRef) {
    var _a, _b;
    legend.encode ?? (legend.encode = {});
    (_a = legend.encode)[part] ?? (_a[part] = {});
    (_b = legend.encode[part]).update ?? (_b.update = {});
    // TODO: remove as any after https://github.com/prisma/nexus-prisma/issues/291
    legend.encode[part].update[vgProp] = vgRef;
}
function assembleLegends(model) {
    const legendComponentIndex = model.component.legends;
    const legendByDomain = {};
    for (const channel of util_keys(legendComponentIndex)) {
        const scaleComponent = model.getScaleComponent(channel);
        const domainHash = util_stringify(scaleComponent.get('domains'));
        if (legendByDomain[domainHash]) {
            for (const mergedLegendComponent of legendByDomain[domainHash]) {
                const merged = mergeLegendComponent(mergedLegendComponent, legendComponentIndex[channel]);
                if (!merged) {
                    // If cannot merge, need to add this legend separately
                    legendByDomain[domainHash].push(legendComponentIndex[channel]);
                }
            }
        }
        else {
            legendByDomain[domainHash] = [legendComponentIndex[channel].clone()];
        }
    }
    const legends = vals(legendByDomain)
        .flat()
        .map(l => assembleLegend(l, model.config))
        .filter(l => l !== undefined);
    return legends;
}
function assembleLegend(legendCmpt, config) {
    const { disable, labelExpr, selections, ...legend } = legendCmpt.combine();
    if (disable) {
        return undefined;
    }
    if (config.aria === false && legend.aria == undefined) {
        legend.aria = false;
    }
    if (legend.encode?.symbols) {
        const out = legend.encode.symbols.update;
        if (out.fill && out.fill['value'] !== 'transparent' && !out.stroke && !legend.stroke) {
            // For non color channel's legend, we need to override symbol stroke config from Vega config if stroke channel is not used.
            out.stroke = { value: 'transparent' };
        }
        // Remove properties that the legend is encoding.
        for (const property of LEGEND_SCALE_CHANNELS) {
            if (legend[property]) {
                delete out[property];
            }
        }
    }
    if (!legend.title) {
        // title schema doesn't include null, ''
        delete legend.title;
    }
    if (labelExpr !== undefined) {
        let expr = labelExpr;
        if (legend.encode?.labels?.update && isSignalRef(legend.encode.labels.update.text)) {
            expr = replaceAll(labelExpr, 'datum.label', legend.encode.labels.update.text.signal);
        }
        setLegendEncode(legend, 'labels', 'text', { signal: expr });
    }
    return legend;
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/projection/assemble.js



function assembleProjections(model) {
    if (isLayerModel(model) || isConcatModel(model)) {
        return assembleProjectionsForModelAndChildren(model);
    }
    else {
        return assembleProjectionForModel(model);
    }
}
function assembleProjectionsForModelAndChildren(model) {
    return model.children.reduce((projections, child) => {
        return projections.concat(child.assembleProjections());
    }, assembleProjectionForModel(model));
}
function assembleProjectionForModel(model) {
    const component = model.component.projection;
    if (!component || component.merged) {
        return [];
    }
    const projection = component.combine();
    const { name } = projection; // we need to extract name so that it is always present in the output and pass TS type validation
    if (!component.data) {
        // generate custom projection, no automatic fitting
        return [
            {
                name,
                // translate to center by default
                translate: { signal: '[width / 2, height / 2]' },
                // parameters, overwrite default translate if specified
                ...projection
            }
        ];
    }
    else {
        // generate projection that uses extent fitting
        const size = {
            signal: `[${component.size.map(ref => ref.signal).join(', ')}]`
        };
        const fits = component.data.reduce((sources, data) => {
            const source = isSignalRef(data) ? data.signal : `data('${model.lookupDataSource(data)}')`;
            if (!util_contains(sources, source)) {
                // build a unique list of sources
                sources.push(source);
            }
            return sources;
        }, []);
        if (fits.length <= 0) {
            throw new Error("Projection's fit didn't find any data sources");
        }
        return [
            {
                name,
                size,
                fit: {
                    signal: fits.length > 1 ? `[${fits.join(', ')}]` : fits[0]
                },
                ...projection
            }
        ];
    }
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/projection.js
const PROJECTION_PROPERTIES = [
    'type',
    'clipAngle',
    'clipExtent',
    'center',
    'rotate',
    'precision',
    'reflectX',
    'reflectY',
    'coefficient',
    'distance',
    'fraction',
    'lobes',
    'parallel',
    'radius',
    'ratio',
    'spacing',
    'tilt'
];
//# sourceMappingURL=projection.js.map
;// ../../node_modules/vega-lite/build/src/compile/projection/component.js

class ProjectionComponent extends Split {
    constructor(name, specifiedProjection, size, data) {
        super({ ...specifiedProjection }, // all explicit properties of projection
        { name } // name as initial implicit property
        );
        this.specifiedProjection = specifiedProjection;
        this.size = size;
        this.data = data;
        this.merged = false;
    }
    /**
     * Whether the projection parameters should fit provided data.
     */
    get isFit() {
        return !!this.data;
    }
}
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/projection/parse.js










function parse_parseProjection(model) {
    model.component.projection = isUnitModel(model) ? parseUnitProjection(model) : parseNonUnitProjections(model);
}
function parseUnitProjection(model) {
    if (model.hasProjection) {
        const proj = replaceExprRef(model.specifiedProjection);
        const fit = !(proj && (proj.scale != null || proj.translate != null));
        const size = fit ? [model.getSizeSignalRef('width'), model.getSizeSignalRef('height')] : undefined;
        const data = fit ? gatherFitData(model) : undefined;
        const projComp = new ProjectionComponent(model.projectionName(true), {
            ...replaceExprRef(model.config.projection),
            ...proj
        }, size, data);
        if (!projComp.get('type')) {
            projComp.set('type', 'equalEarth', false);
        }
        return projComp;
    }
    return undefined;
}
function gatherFitData(model) {
    const data = [];
    const { encoding } = model;
    for (const posssiblePair of [
        [LONGITUDE, LATITUDE],
        [LONGITUDE2, LATITUDE2]
    ]) {
        if (getFieldOrDatumDef(encoding[posssiblePair[0]]) || getFieldOrDatumDef(encoding[posssiblePair[1]])) {
            data.push({
                signal: model.getName(`geojson_${data.length}`)
            });
        }
    }
    if (model.channelHasField(SHAPE) && model.typedFieldDef(SHAPE).type === GEOJSON) {
        data.push({
            signal: model.getName(`geojson_${data.length}`)
        });
    }
    if (data.length === 0) {
        // main source is geojson, so we can just use that
        data.push(model.requestDataName(DataSourceType.Main));
    }
    return data;
}
function mergeIfNoConflict(first, second) {
    const allPropertiesShared = every(PROJECTION_PROPERTIES, prop => {
        // neither has the property
        if (!vega_util_module_has(first.explicit, prop) && !vega_util_module_has(second.explicit, prop)) {
            return true;
        }
        // both have property and an equal value for property
        if (vega_util_module_has(first.explicit, prop) &&
            vega_util_module_has(second.explicit, prop) &&
            // some properties might be signals or objects and require hashing for comparison
            util_deepEqual(first.get(prop), second.get(prop))) {
            return true;
        }
        return false;
    });
    const size = util_deepEqual(first.size, second.size);
    if (size) {
        if (allPropertiesShared) {
            return first;
        }
        else if (util_deepEqual(first.explicit, {})) {
            return second;
        }
        else if (util_deepEqual(second.explicit, {})) {
            return first;
        }
    }
    // if all properties don't match, let each unit spec have its own projection
    return null;
}
function parseNonUnitProjections(model) {
    if (model.children.length === 0) {
        return undefined;
    }
    let nonUnitProjection;
    // parse all children first
    for (const child of model.children) {
        parse_parseProjection(child);
    }
    // analyze parsed projections, attempt to merge
    const mergable = every(model.children, child => {
        const projection = child.component.projection;
        if (!projection) {
            // child layer does not use a projection
            return true;
        }
        else if (!nonUnitProjection) {
            // cached 'projection' is null, cache this one
            nonUnitProjection = projection;
            return true;
        }
        else {
            const merge = mergeIfNoConflict(nonUnitProjection, projection);
            if (merge) {
                nonUnitProjection = merge;
            }
            return !!merge;
        }
    });
    // if cached one and all other children share the same projection,
    if (nonUnitProjection && mergable) {
        // so we can elevate it to the layer level
        const name = model.projectionName(true);
        const modelProjection = new ProjectionComponent(name, nonUnitProjection.specifiedProjection, nonUnitProjection.size, duplicate(nonUnitProjection.data));
        // rename and assign all others as merged
        for (const child of model.children) {
            const projection = child.component.projection;
            if (projection) {
                if (projection.isFit) {
                    modelProjection.data.push(...child.component.projection.data);
                }
                child.renameProjection(projection.get('name'), name);
                projection.merged = true;
            }
        }
        return modelProjection;
    }
    return undefined;
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/bin.js








function rangeFormula(model, fieldDef, channel, config) {
    if (binRequiresRange(fieldDef, channel)) {
        // read format from axis or legend, if there is no format then use config.numberFormat
        const guide = isUnitModel(model)
            ? (model.axis(channel) ?? model.legend(channel) ?? {})
            : {};
        const startField = vgField(fieldDef, { expr: 'datum' });
        const endField = vgField(fieldDef, { expr: 'datum', binSuffix: 'end' });
        return {
            formulaAs: vgField(fieldDef, { binSuffix: 'range', forAs: true }),
            formula: binFormatExpression(startField, endField, guide.format, guide.formatType, config)
        };
    }
    return {};
}
function binKey(bin, field) {
    return `${binToString(bin)}_${field}`;
}
function getSignalsFromModel(model, key) {
    return {
        signal: model.getName(`${key}_bins`),
        extentSignal: model.getName(`${key}_extent`)
    };
}
function getBinSignalName(model, field, bin) {
    const normalizedBin = normalizeBin(bin, undefined) ?? {};
    const key = binKey(normalizedBin, field);
    return model.getName(`${key}_bins`);
}
function isBinTransform(t) {
    return 'as' in t;
}
function createBinComponent(t, bin, model) {
    let as;
    let span;
    if (isBinTransform(t)) {
        as = vega_util_module_isString(t.as) ? [t.as, `${t.as}_end`] : [t.as[0], t.as[1]];
    }
    else {
        as = [vgField(t, { forAs: true }), vgField(t, { binSuffix: 'end', forAs: true })];
    }
    const normalizedBin = { ...normalizeBin(bin, undefined) };
    const key = binKey(normalizedBin, t.field);
    const { signal, extentSignal } = getSignalsFromModel(model, key);
    if (isParameterExtent(normalizedBin.extent)) {
        const ext = normalizedBin.extent;
        span = parseSelectionExtent(model, ext.param, ext);
        delete normalizedBin.extent; // Vega-Lite selection extent map to Vega's span property.
    }
    const binComponent = {
        bin: normalizedBin,
        field: t.field,
        as: [as],
        ...(signal ? { signal } : {}),
        ...(extentSignal ? { extentSignal } : {}),
        ...(span ? { span } : {})
    };
    return { key, binComponent };
}
class BinNode extends DataFlowNode {
    clone() {
        return new BinNode(null, duplicate(this.bins));
    }
    constructor(parent, bins) {
        super(parent);
        this.bins = bins;
    }
    static makeFromEncoding(parent, model) {
        const bins = model.reduceFieldDef((binComponentIndex, fieldDef, channel) => {
            if (isTypedFieldDef(fieldDef) && isBinning(fieldDef.bin)) {
                const { key, binComponent } = createBinComponent(fieldDef, fieldDef.bin, model);
                binComponentIndex[key] = {
                    ...binComponent,
                    ...binComponentIndex[key],
                    ...rangeFormula(model, fieldDef, channel, model.config)
                };
            }
            return binComponentIndex;
        }, {});
        if (isEmpty(bins)) {
            return null;
        }
        return new BinNode(parent, bins);
    }
    /**
     * Creates a bin node from BinTransform.
     * The optional parameter should provide
     */
    static makeFromTransform(parent, t, model) {
        const { key, binComponent } = createBinComponent(t, t.bin, model);
        return new BinNode(parent, {
            [key]: binComponent
        });
    }
    /**
     * Merge bin nodes. This method either integrates the bin config from the other node
     * or if this node already has a bin config, renames the corresponding signal in the model.
     */
    merge(other, renameSignal) {
        for (const key of util_keys(other.bins)) {
            if (key in this.bins) {
                renameSignal(other.bins[key].signal, this.bins[key].signal);
                // Ensure that we don't have duplicate names for signal pairs
                this.bins[key].as = unique([...this.bins[key].as, ...other.bins[key].as], util_hash);
            }
            else {
                this.bins[key] = other.bins[key];
            }
        }
        for (const child of other.children) {
            other.removeChild(child);
            child.parent = this;
        }
        other.remove();
    }
    producedFields() {
        return new Set(vals(this.bins)
            .map(c => c.as)
            .flat(2));
    }
    dependentFields() {
        return new Set(vals(this.bins).map(c => c.field));
    }
    hash() {
        return `Bin ${util_hash(this.bins)}`;
    }
    assemble() {
        return vals(this.bins).flatMap(bin => {
            const transform = [];
            const [binAs, ...remainingAs] = bin.as;
            const { extent, ...params } = bin.bin;
            const binTrans = {
                type: 'bin',
                field: replacePathInField(bin.field),
                as: binAs,
                signal: bin.signal,
                ...(!isParameterExtent(extent) ? { extent } : { extent: null }),
                ...(bin.span ? { span: { signal: `span(${bin.span})` } } : {}),
                ...params
            };
            if (!extent && bin.extentSignal) {
                transform.push({
                    type: 'extent',
                    field: replacePathInField(bin.field),
                    signal: bin.extentSignal
                });
                binTrans.extent = { signal: bin.extentSignal };
            }
            transform.push(binTrans);
            for (const as of remainingAs) {
                for (let i = 0; i < 2; i++) {
                    transform.push({
                        type: 'formula',
                        expr: vgField({ field: binAs[i] }, { expr: 'datum' }),
                        as: as[i]
                    });
                }
            }
            if (bin.formula) {
                transform.push({
                    type: 'formula',
                    expr: bin.formula,
                    as: bin.formulaAs
                });
            }
            return transform;
        });
    }
}
//# sourceMappingURL=bin.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/aggregate.js










function addDimension(dims, channel, fieldDef, model) {
    const channelDef2 = isUnitModel(model) ? model.encoding[getSecondaryRangeChannel(channel)] : undefined;
    if (isTypedFieldDef(fieldDef) &&
        isUnitModel(model) &&
        hasBandEnd(fieldDef, channelDef2, model.markDef, model.config)) {
        dims.add(vgField(fieldDef, {}));
        dims.add(vgField(fieldDef, { suffix: 'end' }));
        const { mark, markDef, config } = model;
        const bandPosition = getBandPosition({ fieldDef, markDef, config });
        if (isRectBasedMark(mark) && bandPosition !== 0.5 && isXorY(channel)) {
            dims.add(vgField(fieldDef, { suffix: OFFSETTED_RECT_START_SUFFIX }));
            dims.add(vgField(fieldDef, { suffix: OFFSETTED_RECT_END_SUFFIX }));
        }
        if (fieldDef.bin && binRequiresRange(fieldDef, channel)) {
            dims.add(vgField(fieldDef, { binSuffix: 'range' }));
        }
    }
    else if (isGeoPositionChannel(channel)) {
        const posChannel = getPositionChannelFromLatLong(channel);
        dims.add(model.getName(posChannel));
    }
    else {
        dims.add(vgField(fieldDef));
    }
    if (isScaleFieldDef(fieldDef) && isFieldRange(fieldDef.scale?.range)) {
        dims.add(fieldDef.scale.range.field);
    }
    return dims;
}
function mergeMeasures(parentMeasures, childMeasures) {
    for (const field of util_keys(childMeasures)) {
        // when we merge a measure, we either have to add an aggregation operator or even a new field
        const ops = childMeasures[field];
        for (const op of util_keys(ops)) {
            if (field in parentMeasures) {
                // add operator to existing measure field
                parentMeasures[field][op] = new Set([...(parentMeasures[field][op] ?? []), ...ops[op]]);
            }
            else {
                parentMeasures[field] = { [op]: ops[op] };
            }
        }
    }
}
class AggregateNode extends DataFlowNode {
    clone() {
        return new AggregateNode(null, new Set(this.dimensions), duplicate(this.measures));
    }
    /**
     * @param dimensions string set for dimensions
     * @param measures dictionary mapping field name => dict of aggregation functions and names to use
     */
    constructor(parent, dimensions, measures) {
        super(parent);
        this.dimensions = dimensions;
        this.measures = measures;
    }
    get groupBy() {
        return this.dimensions;
    }
    static makeFromEncoding(parent, model) {
        let isAggregate = false;
        model.forEachFieldDef(fd => {
            if (fd.aggregate) {
                isAggregate = true;
            }
        });
        const meas = {};
        const dims = new Set();
        if (!isAggregate) {
            // no need to create this node if the model has no aggregation
            return null;
        }
        model.forEachFieldDef((fieldDef, channel) => {
            const { aggregate, field } = fieldDef;
            if (aggregate) {
                if (aggregate === 'count') {
                    meas['*'] ?? (meas['*'] = {});
                    meas['*']['count'] = new Set([vgField(fieldDef, { forAs: true })]);
                }
                else {
                    if (isArgminDef(aggregate) || isArgmaxDef(aggregate)) {
                        const op = isArgminDef(aggregate) ? 'argmin' : 'argmax';
                        const argField = aggregate[op];
                        meas[argField] ?? (meas[argField] = {});
                        meas[argField][op] = new Set([vgField({ op, field: argField }, { forAs: true })]);
                    }
                    else {
                        meas[field] ?? (meas[field] = {});
                        meas[field][aggregate] = new Set([vgField(fieldDef, { forAs: true })]);
                    }
                    // For scale channel with domain === 'unaggregated', add min/max so we can use their union as unaggregated domain
                    if (isScaleChannel(channel) && model.scaleDomain(channel) === 'unaggregated') {
                        meas[field] ?? (meas[field] = {});
                        meas[field]['min'] = new Set([vgField({ field, aggregate: 'min' }, { forAs: true })]);
                        meas[field]['max'] = new Set([vgField({ field, aggregate: 'max' }, { forAs: true })]);
                    }
                }
            }
            else {
                addDimension(dims, channel, fieldDef, model);
            }
        });
        if (dims.size + util_keys(meas).length === 0) {
            return null;
        }
        return new AggregateNode(parent, dims, meas);
    }
    static makeFromTransform(parent, t) {
        var _a;
        const dims = new Set();
        const meas = {};
        for (const s of t.aggregate) {
            const { op, field, as } = s;
            if (op) {
                if (op === 'count') {
                    meas['*'] ?? (meas['*'] = {});
                    meas['*']['count'] = new Set([as ? as : vgField(s, { forAs: true })]);
                }
                else {
                    meas[field] ?? (meas[field] = {});
                    (_a = meas[field])[op] ?? (_a[op] = new Set());
                    meas[field][op].add(as ? as : vgField(s, { forAs: true }));
                }
            }
        }
        for (const s of t.groupby ?? []) {
            dims.add(s);
        }
        if (dims.size + util_keys(meas).length === 0) {
            return null;
        }
        return new AggregateNode(parent, dims, meas);
    }
    merge(other) {
        if (setEqual(this.dimensions, other.dimensions)) {
            mergeMeasures(this.measures, other.measures);
            return true;
        }
        log_debug('different dimensions, cannot merge');
        return false;
    }
    addDimensions(fields) {
        fields.forEach(this.dimensions.add, this.dimensions);
    }
    dependentFields() {
        return new Set([...this.dimensions, ...util_keys(this.measures)]);
    }
    producedFields() {
        const out = new Set();
        for (const field of util_keys(this.measures)) {
            for (const op of util_keys(this.measures[field])) {
                const m = this.measures[field][op];
                if (m.size === 0) {
                    out.add(`${op}_${field}`);
                }
                else {
                    m.forEach(out.add, out);
                }
            }
        }
        return out;
    }
    hash() {
        return `Aggregate ${util_hash({ dimensions: this.dimensions, measures: this.measures })}`;
    }
    assemble() {
        const ops = [];
        const fields = [];
        const as = [];
        for (const field of util_keys(this.measures)) {
            for (const op of util_keys(this.measures[field])) {
                for (const alias of this.measures[field][op]) {
                    as.push(alias);
                    ops.push(op);
                    fields.push(field === '*' ? null : replacePathInField(field));
                }
            }
        }
        const result = {
            type: 'aggregate',
            groupby: [...this.dimensions].map(replacePathInField),
            ops,
            fields,
            as
        };
        return result;
    }
}
//# sourceMappingURL=aggregate.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/facet.js













/**
 * A node that helps us track what fields we are faceting by.
 */
class FacetNode extends DataFlowNode {
    /**
     * @param model The facet model.
     * @param name The name that this facet source will have.
     * @param data The source data for this facet data.
     */
    constructor(parent, model, name, data) {
        super(parent);
        this.model = model;
        this.name = name;
        this.data = data;
        for (const channel of FACET_CHANNELS) {
            const fieldDef = model.facet[channel];
            if (fieldDef) {
                const { bin, sort } = fieldDef;
                this[channel] = {
                    name: model.getName(`${channel}_domain`),
                    fields: [vgField(fieldDef), ...(isBinning(bin) ? [vgField(fieldDef, { binSuffix: 'end' })] : [])],
                    ...(isSortField(sort)
                        ? { sortField: sort }
                        : vega_util_module_isArray(sort)
                            ? { sortIndexField: sortArrayIndexField(fieldDef, channel) }
                            : {})
                };
            }
        }
        this.childModel = model.child;
    }
    hash() {
        let out = `Facet`;
        for (const channel of FACET_CHANNELS) {
            if (this[channel]) {
                out += ` ${channel.charAt(0)}:${util_hash(this[channel])}`;
            }
        }
        return out;
    }
    get fields() {
        const f = [];
        for (const channel of FACET_CHANNELS) {
            if (this[channel]?.fields) {
                f.push(...this[channel].fields);
            }
        }
        return f;
    }
    dependentFields() {
        const depFields = new Set(this.fields);
        for (const channel of FACET_CHANNELS) {
            if (this[channel]) {
                if (this[channel].sortField) {
                    depFields.add(this[channel].sortField.field);
                }
                if (this[channel].sortIndexField) {
                    depFields.add(this[channel].sortIndexField);
                }
            }
        }
        return depFields;
    }
    producedFields() {
        return new Set(); // facet does not produce any new fields
    }
    /**
     * The name to reference this source is its name.
     */
    getSource() {
        return this.name;
    }
    getChildIndependentFieldsWithStep() {
        const childIndependentFieldsWithStep = {};
        for (const channel of POSITION_SCALE_CHANNELS) {
            const childScaleComponent = this.childModel.component.scales[channel];
            if (childScaleComponent && !childScaleComponent.merged) {
                // independent scale
                const type = childScaleComponent.get('type');
                const range = childScaleComponent.get('range');
                if (hasDiscreteDomain(type) && isVgRangeStep(range)) {
                    const domain = assembleDomain(this.childModel, channel);
                    const field = getFieldFromDomain(domain);
                    if (field) {
                        childIndependentFieldsWithStep[channel] = field;
                    }
                    else {
                        log_warn(unknownField(channel));
                    }
                }
            }
        }
        return childIndependentFieldsWithStep;
    }
    assembleRowColumnHeaderData(channel, crossedDataName, childIndependentFieldsWithStep) {
        const childChannel = { row: 'y', column: 'x', facet: undefined }[channel];
        const fields = [];
        const ops = [];
        const as = [];
        if (childChannel && childIndependentFieldsWithStep && childIndependentFieldsWithStep[childChannel]) {
            if (crossedDataName) {
                // If there is a crossed data, calculate max
                fields.push(`distinct_${childIndependentFieldsWithStep[childChannel]}`);
                ops.push('max');
            }
            else {
                // If there is no crossed data, just calculate distinct
                fields.push(childIndependentFieldsWithStep[childChannel]);
                ops.push('distinct');
            }
            // Although it is technically a max, just name it distinct so it's easier to refer to it
            as.push(`distinct_${childIndependentFieldsWithStep[childChannel]}`);
        }
        const { sortField, sortIndexField } = this[channel];
        if (sortField) {
            const { op = DEFAULT_SORT_OP, field } = sortField;
            fields.push(field);
            ops.push(op);
            as.push(vgField(sortField, { forAs: true }));
        }
        else if (sortIndexField) {
            fields.push(sortIndexField);
            ops.push('max');
            as.push(sortIndexField);
        }
        return {
            name: this[channel].name,
            // Use data from the crossed one if it exist
            source: crossedDataName ?? this.data,
            transform: [
                {
                    type: 'aggregate',
                    groupby: this[channel].fields,
                    ...(fields.length
                        ? {
                            fields,
                            ops,
                            as
                        }
                        : {})
                }
            ]
        };
    }
    assembleFacetHeaderData(childIndependentFieldsWithStep) {
        const { columns } = this.model.layout;
        const { layoutHeaders } = this.model.component;
        const data = [];
        const hasSharedAxis = {};
        for (const headerChannel of HEADER_CHANNELS) {
            for (const headerType of HEADER_TYPES) {
                const headers = (layoutHeaders[headerChannel] && layoutHeaders[headerChannel][headerType]) ?? [];
                for (const header of headers) {
                    if (header.axes?.length > 0) {
                        hasSharedAxis[headerChannel] = true;
                        break;
                    }
                }
            }
            if (hasSharedAxis[headerChannel]) {
                const cardinality = `length(data("${this.facet.name}"))`;
                const stop = headerChannel === 'row'
                    ? columns
                        ? { signal: `ceil(${cardinality} / ${columns})` }
                        : 1
                    : columns
                        ? { signal: `min(${cardinality}, ${columns})` }
                        : { signal: cardinality };
                data.push({
                    name: `${this.facet.name}_${headerChannel}`,
                    transform: [
                        {
                            type: 'sequence',
                            start: 0,
                            stop
                        }
                    ]
                });
            }
        }
        const { row, column } = hasSharedAxis;
        if (row || column) {
            data.unshift(this.assembleRowColumnHeaderData('facet', null, childIndependentFieldsWithStep));
        }
        return data;
    }
    assemble() {
        const data = [];
        let crossedDataName = null;
        const childIndependentFieldsWithStep = this.getChildIndependentFieldsWithStep();
        const { column, row, facet } = this;
        if (column && row && (childIndependentFieldsWithStep.x || childIndependentFieldsWithStep.y)) {
            // Need to create a cross dataset to correctly calculate cardinality
            crossedDataName = `cross_${this.column.name}_${this.row.name}`;
            const fields = [].concat(childIndependentFieldsWithStep.x ?? [], childIndependentFieldsWithStep.y ?? []);
            const ops = fields.map(() => 'distinct');
            data.push({
                name: crossedDataName,
                source: this.data,
                transform: [
                    {
                        type: 'aggregate',
                        groupby: this.fields,
                        fields,
                        ops
                    }
                ]
            });
        }
        for (const channel of [COLUMN, ROW]) {
            if (this[channel]) {
                data.push(this.assembleRowColumnHeaderData(channel, crossedDataName, childIndependentFieldsWithStep));
            }
        }
        if (facet) {
            const facetData = this.assembleFacetHeaderData(childIndependentFieldsWithStep);
            if (facetData) {
                data.push(...facetData);
            }
        }
        return data;
    }
}
//# sourceMappingURL=facet.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/formatparse.js
















/**
 * Remove quotes from a string.
 */
function formatparse_unquote(pattern) {
    if ((pattern.startsWith("'") && pattern.endsWith("'")) || (pattern.startsWith('"') && pattern.endsWith('"'))) {
        return pattern.slice(1, -1);
    }
    return pattern;
}
/**
 * @param field The field.
 * @param parse What to parse the field as.
 */
function formatparse_parseExpression(field, parse) {
    const f = accessPathWithDatum(field);
    if (parse === 'number') {
        return `toNumber(${f})`;
    }
    else if (parse === 'boolean') {
        return `toBoolean(${f})`;
    }
    else if (parse === 'string') {
        return `toString(${f})`;
    }
    else if (parse === 'date') {
        return `toDate(${f})`;
    }
    else if (parse === 'flatten') {
        return f;
    }
    else if (parse.startsWith('date:')) {
        const specifier = formatparse_unquote(parse.slice(5, parse.length));
        return `timeParse(${f},'${specifier}')`;
    }
    else if (parse.startsWith('utc:')) {
        const specifier = formatparse_unquote(parse.slice(4, parse.length));
        return `utcParse(${f},'${specifier}')`;
    }
    else {
        log_warn(unrecognizedParse(parse));
        return null;
    }
}
function getImplicitFromFilterTransform(transform) {
    const implicit = {};
    forEachLeaf(transform.filter, filter => {
        if (isFieldPredicate(filter)) {
            // Automatically add a parse node for filters with filter objects
            let val = null;
            // For EqualFilter, just use the equal property.
            // For RangeFilter and OneOfFilter, all array members should have
            // the same type, so we only use the first one.
            if (isFieldEqualPredicate(filter)) {
                val = signalRefOrValue(filter.equal);
            }
            else if (isFieldLTEPredicate(filter)) {
                val = signalRefOrValue(filter.lte);
            }
            else if (isFieldLTPredicate(filter)) {
                val = signalRefOrValue(filter.lt);
            }
            else if (isFieldGTPredicate(filter)) {
                val = signalRefOrValue(filter.gt);
            }
            else if (isFieldGTEPredicate(filter)) {
                val = signalRefOrValue(filter.gte);
            }
            else if (isFieldRangePredicate(filter)) {
                // FIXME: remove as any
                val = filter.range[0];
            }
            else if (isFieldOneOfPredicate(filter)) {
                val = (filter.oneOf ?? filter.in)[0];
            } // else -- for filter expression, we can't infer anything
            if (val) {
                if (isDateTime(val)) {
                    implicit[filter.field] = 'date';
                }
                else if (vega_util_module_isNumber(val)) {
                    implicit[filter.field] = 'number';
                }
                else if (vega_util_module_isString(val)) {
                    implicit[filter.field] = 'string';
                }
            }
            if (filter.timeUnit) {
                implicit[filter.field] = 'date';
            }
        }
    });
    return implicit;
}
/**
 * Creates a parse node for implicit parsing from a model and updates ancestorParse.
 */
function getImplicitFromEncoding(model) {
    const implicit = {};
    function add(fieldDef) {
        if (isFieldOrDatumDefForTimeFormat(fieldDef)) {
            implicit[fieldDef.field] = 'date';
        }
        else if (fieldDef.type === 'quantitative' &&
            isMinMaxOp(fieldDef.aggregate) // we need to parse numbers to support correct min and max
        ) {
            implicit[fieldDef.field] = 'number';
        }
        else if (accessPathDepth(fieldDef.field) > 1) {
            // For non-date/non-number (strings and booleans), derive a flattened field for a referenced nested field.
            // (Parsing numbers / dates already flattens numeric and temporal fields.)
            if (!(fieldDef.field in implicit)) {
                implicit[fieldDef.field] = 'flatten';
            }
        }
        else if (isScaleFieldDef(fieldDef) && isSortField(fieldDef.sort) && accessPathDepth(fieldDef.sort.field) > 1) {
            // Flatten fields that we sort by but that are not otherwise flattened.
            if (!(fieldDef.sort.field in implicit)) {
                implicit[fieldDef.sort.field] = 'flatten';
            }
        }
    }
    if (isUnitModel(model) || isFacetModel(model)) {
        // Parse encoded fields
        model.forEachFieldDef((fieldDef, channel) => {
            if (isTypedFieldDef(fieldDef)) {
                add(fieldDef);
            }
            else {
                const mainChannel = getMainRangeChannel(channel);
                const mainFieldDef = model.fieldDef(mainChannel);
                add({
                    ...fieldDef,
                    type: mainFieldDef.type
                });
            }
        });
    }
    // Parse quantitative dimension fields of path marks as numbers so that we sort them correctly.
    if (isUnitModel(model)) {
        const { mark, markDef, encoding } = model;
        if (isPathMark(mark) &&
            // No need to sort by dimension if we have a connected scatterplot (order channel is present)
            !model.encoding.order) {
            const dimensionChannel = markDef.orient === 'horizontal' ? 'y' : 'x';
            const dimensionChannelDef = encoding[dimensionChannel];
            if (isFieldDef(dimensionChannelDef) &&
                dimensionChannelDef.type === 'quantitative' &&
                !(dimensionChannelDef.field in implicit)) {
                implicit[dimensionChannelDef.field] = 'number';
            }
        }
    }
    return implicit;
}
/**
 * Creates a parse node for implicit parsing from a model and updates ancestorParse.
 */
function getImplicitFromSelection(model) {
    const implicit = {};
    if (isUnitModel(model) && model.component.selection) {
        for (const name of util_keys(model.component.selection)) {
            const selCmpt = model.component.selection[name];
            for (const proj of selCmpt.project.items) {
                if (!proj.channel && accessPathDepth(proj.field) > 1) {
                    implicit[proj.field] = 'flatten';
                }
            }
        }
    }
    return implicit;
}
class ParseNode extends DataFlowNode {
    clone() {
        return new ParseNode(null, duplicate(this._parse));
    }
    constructor(parent, parse) {
        super(parent);
        this._parse = parse;
    }
    hash() {
        return `Parse ${util_hash(this._parse)}`;
    }
    /**
     * Creates a parse node from a data.format.parse and updates ancestorParse.
     */
    static makeExplicit(parent, model, ancestorParse) {
        // Custom parse
        let explicit = {};
        const data = model.data;
        if (!isGenerator(data) && data?.format?.parse) {
            explicit = data.format.parse;
        }
        return this.makeWithAncestors(parent, explicit, {}, ancestorParse);
    }
    /**
     * Creates a parse node from "explicit" parse and "implicit" parse and updates ancestorParse.
     */
    static makeWithAncestors(parent, explicit, implicit, ancestorParse) {
        // We should not parse what has already been parsed in a parent (explicitly or implicitly) or what has been derived (maked as "derived"). We also don't need to flatten a field that has already been parsed.
        for (const field of util_keys(implicit)) {
            const parsedAs = ancestorParse.getWithExplicit(field);
            if (parsedAs.value !== undefined) {
                // We always ignore derived fields even if they are implicitly defined because we expect users to create the right types.
                if (parsedAs.explicit ||
                    parsedAs.value === implicit[field] ||
                    parsedAs.value === 'derived' ||
                    implicit[field] === 'flatten') {
                    delete implicit[field];
                }
                else {
                    log_warn(differentParse(field, implicit[field], parsedAs.value));
                }
            }
        }
        for (const field of util_keys(explicit)) {
            const parsedAs = ancestorParse.get(field);
            if (parsedAs !== undefined) {
                // Don't parse a field again if it has been parsed with the same type already.
                if (parsedAs === explicit[field]) {
                    delete explicit[field];
                }
                else {
                    log_warn(differentParse(field, explicit[field], parsedAs));
                }
            }
        }
        const parse = new Split(explicit, implicit);
        // add the format parse from this model so that children don't parse the same field again
        ancestorParse.copyAll(parse);
        // copy only non-null parses
        const p = {};
        for (const key of util_keys(parse.combine())) {
            const val = parse.get(key);
            if (val !== null) {
                p[key] = val;
            }
        }
        if (util_keys(p).length === 0 || ancestorParse.parseNothing) {
            return null;
        }
        return new ParseNode(parent, p);
    }
    get parse() {
        return this._parse;
    }
    merge(other) {
        this._parse = { ...this._parse, ...other.parse };
        other.remove();
    }
    /**
     * Assemble an object for Vega's format.parse property.
     */
    assembleFormatParse() {
        const formatParse = {};
        for (const field of util_keys(this._parse)) {
            const p = this._parse[field];
            if (accessPathDepth(field) === 1) {
                formatParse[field] = p;
            }
        }
        return formatParse;
    }
    // format parse depends and produces all fields in its parse
    producedFields() {
        return new Set(util_keys(this._parse));
    }
    dependentFields() {
        return new Set(util_keys(this._parse));
    }
    assembleTransforms(onlyNested = false) {
        return util_keys(this._parse)
            .filter(field => (onlyNested ? accessPathDepth(field) > 1 : true))
            .map(field => {
            const expr = formatparse_parseExpression(field, this._parse[field]);
            if (!expr) {
                return null;
            }
            const formula = {
                type: 'formula',
                expr,
                as: removePathFromField(field) // Vega output is always flattened
            };
            return formula;
        })
            .filter(t => t !== null);
    }
}
//# sourceMappingURL=formatparse.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/identifier.js


class IdentifierNode extends DataFlowNode {
    clone() {
        return new IdentifierNode(null);
    }
    constructor(parent) {
        super(parent);
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return new Set([SELECTION_ID]);
    }
    hash() {
        return 'Identifier';
    }
    assemble() {
        return { type: 'identifier', as: SELECTION_ID };
    }
}
//# sourceMappingURL=identifier.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/graticule.js


class GraticuleNode extends DataFlowNode {
    clone() {
        return new GraticuleNode(null, this.params);
    }
    constructor(parent, params) {
        super(parent);
        this.params = params;
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return undefined; // there should never be a node before graticule
    }
    hash() {
        return `Graticule ${util_hash(this.params)}`;
    }
    assemble() {
        return {
            type: 'graticule',
            ...(this.params === true ? {} : this.params)
        };
    }
}
//# sourceMappingURL=graticule.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/sequence.js


class SequenceNode extends DataFlowNode {
    clone() {
        return new SequenceNode(null, this.params);
    }
    constructor(parent, params) {
        super(parent);
        this.params = params;
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return new Set([this.params.as ?? 'data']);
    }
    hash() {
        return `Hash ${util_hash(this.params)}`;
    }
    assemble() {
        return {
            type: 'sequence',
            ...this.params
        };
    }
}
//# sourceMappingURL=sequence.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/source.js



class SourceNode extends DataFlowNode {
    constructor(data) {
        super(null); // source cannot have parent
        data ?? (data = { name: 'source' });
        let format;
        if (!isGenerator(data)) {
            format = data.format ? { ...omit(data.format, ['parse']) } : {};
        }
        if (isInlineData(data)) {
            this._data = { values: data.values };
        }
        else if (isUrlData(data)) {
            this._data = { url: data.url };
            if (!format.type) {
                // Extract extension from URL using snippet from
                // http://stackoverflow.com/questions/680929/how-to-extract-extension-from-filename-string-in-javascript
                let defaultExtension = /(?:\.([^.]+))?$/.exec(data.url)[1];
                if (!util_contains(['json', 'csv', 'tsv', 'dsv', 'topojson'], defaultExtension)) {
                    defaultExtension = 'json';
                }
                // defaultExtension has type string but we ensure that it is DataFormatType above
                format.type = defaultExtension;
            }
        }
        else if (isSphereGenerator(data)) {
            // hardwire GeoJSON sphere data into output specification
            this._data = { values: [{ type: 'Sphere' }] };
        }
        else if (isNamedData(data) || isGenerator(data)) {
            this._data = {};
        }
        // set flag to check if generator
        this._generator = isGenerator(data);
        // any dataset can be named
        if (data.name) {
            this._name = data.name;
        }
        if (format && !isEmpty(format)) {
            this._data.format = format;
        }
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return undefined; // we don't know what this source produces
    }
    get data() {
        return this._data;
    }
    hasName() {
        return !!this._name;
    }
    get isGenerator() {
        return this._generator;
    }
    get dataName() {
        return this._name;
    }
    set dataName(name) {
        this._name = name;
    }
    set parent(parent) {
        throw new Error('Source nodes have to be roots.');
    }
    remove() {
        throw new Error('Source nodes are roots and cannot be removed.');
    }
    hash() {
        throw new Error('Cannot hash sources');
    }
    assemble() {
        return {
            name: this._name,
            ...this._data,
            transform: []
        };
    }
}
//# sourceMappingURL=source.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/optimizer.js
var optimizer_classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var optimizer_classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Optimizer_modified;



/**
 * Whether this dataflow node is the source of the dataflow that produces data i.e. a source or a generator.
 */
function isDataSourceNode(node) {
    return node instanceof SourceNode || node instanceof GraticuleNode || node instanceof SequenceNode;
}
/**
 * Abstract base class for Dataflow optimizers.
 * Contains only mutation handling logic. Subclasses need to implement iteration logic.
 */
class Optimizer {
    constructor() {
        _Optimizer_modified.set(this, void 0);
        optimizer_classPrivateFieldSet(this, _Optimizer_modified, false, "f");
    }
    // Once true, #modified is never set to false
    setModified() {
        optimizer_classPrivateFieldSet(this, _Optimizer_modified, true, "f");
    }
    get modifiedFlag() {
        return optimizer_classPrivateFieldGet(this, _Optimizer_modified, "f");
    }
}
_Optimizer_modified = new WeakMap();
/**
 * Starts from a node and runs the optimization function (the "run" method) upwards to the root,
 * depending on the continue and modified flag values returned by the optimization function.
 */
class BottomUpOptimizer extends Optimizer {
    /**
     * Compute a map of node depths that we can use to determine a topological sort order.
     */
    getNodeDepths(node, depth, depths) {
        depths.set(node, depth);
        for (const child of node.children) {
            this.getNodeDepths(child, depth + 1, depths);
        }
        return depths;
    }
    /**
     * Run the optimizer on all nodes starting from the leaves.
     */
    optimize(node) {
        const depths = this.getNodeDepths(node, 0, new Map());
        const topologicalSort = [...depths.entries()].sort((a, b) => b[1] - a[1]);
        for (const tuple of topologicalSort) {
            this.run(tuple[0]);
        }
        return this.modifiedFlag;
    }
}
/**
 * The optimizer function (the "run" method), is invoked on the given node and then continues recursively.
 */
class TopDownOptimizer extends Optimizer {
    /**
     * Run the optimizer depth first on all nodes starting from the roots.
     */
    optimize(node) {
        this.run(node);
        for (const child of node.children) {
            this.optimize(child);
        }
        return this.modifiedFlag;
    }
}
//# sourceMappingURL=optimizer.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/optimizers.js












/**
 * Merge identical nodes at forks by comparing hashes.
 *
 * Does not need to iterate from leaves so we implement this with recursion as it's a bit simpler.
 */
class MergeIdenticalNodes extends TopDownOptimizer {
    mergeNodes(parent, nodes) {
        const mergedNode = nodes.shift();
        for (const node of nodes) {
            parent.removeChild(node);
            node.parent = mergedNode;
            node.remove();
        }
    }
    run(node) {
        const hashes = node.children.map(x => x.hash());
        const buckets = {};
        for (let i = 0; i < hashes.length; i++) {
            if (buckets[hashes[i]] === undefined) {
                buckets[hashes[i]] = [node.children[i]];
            }
            else {
                buckets[hashes[i]].push(node.children[i]);
            }
        }
        for (const k of util_keys(buckets)) {
            if (buckets[k].length > 1) {
                this.setModified();
                this.mergeNodes(node, buckets[k]);
            }
        }
    }
}
/**
 * Optimizer that removes identifier nodes that are not needed for selections.
 */
class RemoveUnnecessaryIdentifierNodes extends TopDownOptimizer {
    constructor(model) {
        super();
        this.requiresSelectionId = model && requiresSelectionId(model);
    }
    run(node) {
        if (node instanceof IdentifierNode) {
            // Only preserve IdentifierNodes if we have default discrete selections
            // in our model tree, and if the nodes come after tuple producing nodes.
            if (!(this.requiresSelectionId &&
                (isDataSourceNode(node.parent) || node.parent instanceof AggregateNode || node.parent instanceof ParseNode))) {
                this.setModified();
                node.remove();
            }
        }
    }
}
/**
 * Removes duplicate time unit nodes (as determined by the name of the output field) that may be generated due to
 * selections projected over time units. Only keeps the first time unit in any branch.
 *
 * This optimizer is a custom top down optimizer that keep track of produced fields in a branch.
 */
class RemoveDuplicateTimeUnits extends Optimizer {
    optimize(node) {
        this.run(node, new Set());
        return this.modifiedFlag;
    }
    run(node, timeUnitFields) {
        let producedFields = new Set();
        if (node instanceof TimeUnitNode) {
            producedFields = node.producedFields();
            if (hasIntersection(producedFields, timeUnitFields)) {
                this.setModified();
                node.removeFormulas(timeUnitFields);
                if (node.producedFields.length === 0) {
                    node.remove();
                }
            }
        }
        for (const child of node.children) {
            this.run(child, new Set([...timeUnitFields, ...producedFields]));
        }
    }
}
/**
 * Remove output nodes that are not required.
 */
class RemoveUnnecessaryOutputNodes extends TopDownOptimizer {
    constructor() {
        super();
    }
    run(node) {
        if (node instanceof OutputNode && !node.isRequired()) {
            this.setModified();
            node.remove();
        }
    }
}
/**
 * Move parse nodes up to forks and merges them if possible.
 */
class MoveParseUp extends BottomUpOptimizer {
    run(node) {
        if (isDataSourceNode(node)) {
            return;
        }
        if (node.numChildren() > 1) {
            // Don't move parse further up but continue with parent.
            return;
        }
        for (const child of node.children) {
            if (child instanceof ParseNode) {
                if (node instanceof ParseNode) {
                    this.setModified();
                    node.merge(child);
                }
                else {
                    // Don't swap with nodes that produce something that the parse node depends on (e.g. lookup).
                    if (fieldIntersection(node.producedFields(), child.dependentFields())) {
                        continue;
                    }
                    this.setModified();
                    child.swapWithParent();
                }
            }
        }
        return;
    }
}
/**
 * Inserts an intermediate ParseNode containing all non-conflicting parse fields and removes the empty ParseNodes.
 *
 * We assume that dependent paths that do not have a parse node can be just merged.
 */
class MergeParse extends BottomUpOptimizer {
    run(node) {
        const originalChildren = [...node.children];
        const parseChildren = node.children.filter((child) => child instanceof ParseNode);
        if (node.numChildren() > 1 && parseChildren.length >= 1) {
            const commonParse = {};
            const conflictingParse = new Set();
            for (const parseNode of parseChildren) {
                const parse = parseNode.parse;
                for (const k of util_keys(parse)) {
                    if (!(k in commonParse)) {
                        commonParse[k] = parse[k];
                    }
                    else if (commonParse[k] !== parse[k]) {
                        conflictingParse.add(k);
                    }
                }
            }
            for (const field of conflictingParse) {
                delete commonParse[field];
            }
            if (!isEmpty(commonParse)) {
                this.setModified();
                const mergedParseNode = new ParseNode(node, commonParse);
                for (const childNode of originalChildren) {
                    if (childNode instanceof ParseNode) {
                        for (const key of util_keys(commonParse)) {
                            delete childNode.parse[key];
                        }
                    }
                    node.removeChild(childNode);
                    childNode.parent = mergedParseNode;
                    // remove empty parse nodes
                    if (childNode instanceof ParseNode && util_keys(childNode.parse).length === 0) {
                        childNode.remove();
                    }
                }
            }
        }
    }
}
/**
 * Repeatedly remove leaf nodes that are not output or facet nodes.
 * The reason is that we don't need subtrees that don't have any output nodes.
 * Facet nodes are needed for the row or column domains.
 */
class RemoveUnusedSubtrees extends BottomUpOptimizer {
    run(node) {
        if (node instanceof OutputNode || node.numChildren() > 0 || node instanceof FacetNode) {
            // no need to continue with parent because it is output node or will have children (there was a fork)
        }
        else if (node instanceof SourceNode) {
            // ignore empty unused sources as they will be removed in optimizationDataflowHelper
        }
        else {
            this.setModified();
            node.remove();
        }
    }
}
/**
 * Merge adjacent time unit nodes.
 */
class MergeTimeUnits extends BottomUpOptimizer {
    run(node) {
        const timeUnitChildren = node.children.filter((x) => x instanceof TimeUnitNode);
        const combination = timeUnitChildren.pop();
        for (const timeUnit of timeUnitChildren) {
            this.setModified();
            combination.merge(timeUnit);
        }
    }
}
class MergeAggregates extends BottomUpOptimizer {
    run(node) {
        const aggChildren = node.children.filter((child) => child instanceof AggregateNode);
        // Object which we'll use to map the fields which an aggregate is grouped by to
        // the set of aggregates with that grouping. This is useful as only aggregates
        // with the same group by can be merged
        const groupedAggregates = {};
        // Build groupedAggregates
        for (const agg of aggChildren) {
            const groupBys = util_hash(agg.groupBy);
            if (!(groupBys in groupedAggregates)) {
                groupedAggregates[groupBys] = [];
            }
            groupedAggregates[groupBys].push(agg);
        }
        // Merge aggregateNodes with same key in groupedAggregates
        for (const group of util_keys(groupedAggregates)) {
            const mergeableAggs = groupedAggregates[group];
            if (mergeableAggs.length > 1) {
                const mergedAggs = mergeableAggs.pop();
                for (const agg of mergeableAggs) {
                    if (mergedAggs.merge(agg)) {
                        node.removeChild(agg);
                        agg.parent = mergedAggs;
                        agg.remove();
                        this.setModified();
                    }
                }
            }
        }
    }
}
/**
 * Merge bin nodes and move them up through forks. Stop at filters, parse, identifier as we want them to stay before the bin node.
 */
class MergeBins extends BottomUpOptimizer {
    constructor(model) {
        super();
        this.model = model;
    }
    run(node) {
        const moveBinsUp = !(isDataSourceNode(node) ||
            node instanceof FilterNode ||
            node instanceof ParseNode ||
            node instanceof IdentifierNode);
        const promotableBins = [];
        const remainingBins = [];
        for (const child of node.children) {
            if (child instanceof BinNode) {
                if (moveBinsUp && !fieldIntersection(node.producedFields(), child.dependentFields())) {
                    promotableBins.push(child);
                }
                else {
                    remainingBins.push(child);
                }
            }
        }
        if (promotableBins.length > 0) {
            const promotedBin = promotableBins.pop();
            for (const bin of promotableBins) {
                promotedBin.merge(bin, this.model.renameSignal.bind(this.model));
            }
            this.setModified();
            if (node instanceof BinNode) {
                node.merge(promotedBin, this.model.renameSignal.bind(this.model));
            }
            else {
                promotedBin.swapWithParent();
            }
        }
        if (remainingBins.length > 1) {
            const remainingBin = remainingBins.pop();
            for (const bin of remainingBins) {
                remainingBin.merge(bin, this.model.renameSignal.bind(this.model));
            }
            this.setModified();
        }
    }
}
/**
 * This optimizer takes output nodes that are at a fork and moves them before the fork.
 *
 * The algorithm iterates over the children and tries to find the last output node in a chain of output nodes.
 * It then moves all output nodes before that main output node. All other children (and the children of the output nodes)
 * are inserted after the main output node.
 */
class MergeOutputs extends BottomUpOptimizer {
    run(node) {
        const children = [...node.children];
        const hasOutputChild = some(children, child => child instanceof OutputNode);
        if (!hasOutputChild || node.numChildren() <= 1) {
            return;
        }
        const otherChildren = [];
        // The output node we will connect all other nodes to.
        // Output nodes will be added before the new node, other nodes after.
        let mainOutput;
        for (const child of children) {
            if (child instanceof OutputNode) {
                let lastOutput = child;
                while (lastOutput.numChildren() === 1) {
                    const [theChild] = lastOutput.children;
                    if (theChild instanceof OutputNode) {
                        lastOutput = theChild;
                    }
                    else {
                        break;
                    }
                }
                otherChildren.push(...lastOutput.children);
                if (mainOutput) {
                    // Move the output nodes before the mainOutput. We do this by setting
                    // the parent of the first not to the parent of the main output and
                    // the main output's parent to the last output.
                    // note: the child is the first output
                    node.removeChild(child);
                    child.parent = mainOutput.parent;
                    mainOutput.parent.removeChild(mainOutput);
                    mainOutput.parent = lastOutput;
                    this.setModified();
                }
                else {
                    mainOutput = lastOutput;
                }
            }
            else {
                otherChildren.push(child);
            }
        }
        if (otherChildren.length) {
            this.setModified();
            for (const child of otherChildren) {
                child.parent.removeChild(child);
                child.parent = mainOutput;
            }
        }
    }
}
//# sourceMappingURL=optimizers.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/joinaggregate.js




/**
 * A class for the join aggregate transform nodes.
 */
class JoinAggregateTransformNode extends DataFlowNode {
    clone() {
        return new JoinAggregateTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
    }
    addDimensions(fields) {
        this.transform.groupby = unique(this.transform.groupby.concat(fields), d => d);
    }
    dependentFields() {
        const out = new Set();
        if (this.transform.groupby) {
            this.transform.groupby.forEach(out.add, out);
        }
        this.transform.joinaggregate
            .map(w => w.field)
            .filter(f => f !== undefined)
            .forEach(out.add, out);
        return out;
    }
    producedFields() {
        return new Set(this.transform.joinaggregate.map(this.getDefaultName));
    }
    getDefaultName(joinAggregateFieldDef) {
        return joinAggregateFieldDef.as ?? vgField(joinAggregateFieldDef);
    }
    hash() {
        return `JoinAggregateTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const fields = [];
        const ops = [];
        const as = [];
        for (const joinaggregate of this.transform.joinaggregate) {
            ops.push(joinaggregate.op);
            as.push(this.getDefaultName(joinaggregate));
            fields.push(joinaggregate.field === undefined ? null : joinaggregate.field);
        }
        const groupby = this.transform.groupby;
        return {
            type: 'joinaggregate',
            as,
            ops,
            fields,
            ...(groupby !== undefined ? { groupby } : {})
        };
    }
}
//# sourceMappingURL=joinaggregate.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/filterinvalid.js






class FilterInvalidNode extends DataFlowNode {
    clone() {
        return new FilterInvalidNode(null, { ...this.filter });
    }
    constructor(parent, filter) {
        super(parent);
        this.filter = filter;
    }
    static make(parent, model, dataSourcesForHandlingInvalidValues) {
        const { config, markDef } = model;
        const { marks, scales } = dataSourcesForHandlingInvalidValues;
        if (marks === 'include-invalid-values' && scales === 'include-invalid-values') {
            // If neither marks nor scale domains need data source to filter null values, then don't add the filter.
            return null;
        }
        const filter = model.reduceFieldDef((aggregator, fieldDef, channel) => {
            const scaleComponent = isScaleChannel(channel) && model.getScaleComponent(channel);
            if (scaleComponent) {
                const scaleType = scaleComponent.get('type');
                const { aggregate } = fieldDef;
                const invalidDataMode = getScaleInvalidDataMode({
                    scaleChannel: channel,
                    markDef,
                    config,
                    scaleType,
                    isCountAggregate: isCountingAggregateOp(aggregate)
                });
                // If the invalid data mode is include or always-valid, we don't need to filter invalid values as the scale can handle invalid values.
                if (invalidDataMode !== 'show' && invalidDataMode !== 'always-valid') {
                    aggregator[fieldDef.field] = fieldDef; // we know that the fieldDef is a typed field def
                }
            }
            return aggregator;
        }, {});
        if (!util_keys(filter).length) {
            return null;
        }
        return new FilterInvalidNode(parent, filter);
    }
    dependentFields() {
        return new Set(util_keys(this.filter));
    }
    producedFields() {
        return new Set(); // filter does not produce any new fields
    }
    hash() {
        return `FilterInvalid ${util_hash(this.filter)}`;
    }
    /**
     * Create the VgTransforms for each of the filtered fields.
     */
    assemble() {
        const filters = util_keys(this.filter).reduce((vegaFilters, field) => {
            const fieldDef = this.filter[field];
            const ref = vgField(fieldDef, { expr: 'datum' });
            if (fieldDef !== null) {
                if (fieldDef.type === 'temporal') {
                    vegaFilters.push(`(isDate(${ref}) || (${isValidFiniteNumberExpr(ref)}))`);
                }
                else if (fieldDef.type === 'quantitative') {
                    vegaFilters.push(isValidFiniteNumberExpr(ref));
                }
                else {
                    // should never get here
                }
            }
            return vegaFilters;
        }, []);
        return filters.length > 0
            ? {
                type: 'filter',
                expr: filters.join(' && ')
            }
            : null;
    }
}
function isValidFiniteNumberExpr(ref) {
    return `isValid(${ref}) && isFinite(+${ref})`;
}
//# sourceMappingURL=filterinvalid.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/stack.js






function getStackByFields(model) {
    return model.stack.stackBy.reduce((fields, by) => {
        const fieldDef = by.fieldDef;
        const _field = vgField(fieldDef);
        if (_field) {
            fields.push(_field);
        }
        return fields;
    }, []);
}
function isValidAsArray(as) {
    return vega_util_module_isArray(as) && as.every(s => vega_util_module_isString(s)) && as.length > 1;
}
class StackNode extends DataFlowNode {
    clone() {
        return new StackNode(null, duplicate(this._stack));
    }
    constructor(parent, stack) {
        super(parent);
        this._stack = stack;
    }
    static makeFromTransform(parent, stackTransform) {
        const { stack, groupby, as, offset = 'zero' } = stackTransform;
        const sortFields = [];
        const sortOrder = [];
        if (stackTransform.sort !== undefined) {
            for (const sortField of stackTransform.sort) {
                sortFields.push(sortField.field);
                sortOrder.push(getFirstDefined(sortField.order, 'ascending'));
            }
        }
        const sort = {
            field: sortFields,
            order: sortOrder
        };
        let normalizedAs;
        if (isValidAsArray(as)) {
            normalizedAs = as;
        }
        else if (vega_util_module_isString(as)) {
            normalizedAs = [as, `${as}_end`];
        }
        else {
            normalizedAs = [`${stackTransform.stack}_start`, `${stackTransform.stack}_end`];
        }
        return new StackNode(parent, {
            dimensionFieldDefs: [],
            stackField: stack,
            groupby,
            offset,
            sort,
            facetby: [],
            as: normalizedAs
        });
    }
    static makeFromEncoding(parent, model) {
        const stackProperties = model.stack;
        const { encoding } = model;
        if (!stackProperties) {
            return null;
        }
        const { groupbyChannels, fieldChannel, offset, impute } = stackProperties;
        const dimensionFieldDefs = groupbyChannels
            .map(groupbyChannel => {
            const cDef = encoding[groupbyChannel];
            return getFieldDef(cDef);
        })
            .filter(def => !!def);
        const stackby = getStackByFields(model);
        const orderDef = model.encoding.order;
        let sort;
        if (vega_util_module_isArray(orderDef) || isFieldDef(orderDef)) {
            sort = sortParams(orderDef);
        }
        else {
            const sortOrder = isOrderOnlyDef(orderDef) ? orderDef.sort : fieldChannel === 'y' ? 'descending' : 'ascending';
            // default = descending by stackFields
            // FIXME is the default here correct for binned fields?
            sort = stackby.reduce((s, field) => {
                if (!s.field.includes(field)) {
                    s.field.push(field);
                    s.order.push(sortOrder);
                }
                return s;
            }, { field: [], order: [] });
        }
        return new StackNode(parent, {
            dimensionFieldDefs,
            stackField: model.vgField(fieldChannel),
            facetby: [],
            stackby,
            sort,
            offset,
            impute,
            as: [
                model.vgField(fieldChannel, { suffix: 'start', forAs: true }),
                model.vgField(fieldChannel, { suffix: 'end', forAs: true })
            ]
        });
    }
    get stack() {
        return this._stack;
    }
    addDimensions(fields) {
        this._stack.facetby.push(...fields);
    }
    dependentFields() {
        const out = new Set();
        out.add(this._stack.stackField);
        this.getGroupbyFields().forEach(out.add, out);
        this._stack.facetby.forEach(out.add, out);
        this._stack.sort.field.forEach(out.add, out);
        return out;
    }
    producedFields() {
        return new Set(this._stack.as);
    }
    hash() {
        return `Stack ${util_hash(this._stack)}`;
    }
    getGroupbyFields() {
        const { dimensionFieldDefs, impute, groupby } = this._stack;
        if (dimensionFieldDefs.length > 0) {
            return dimensionFieldDefs
                .map(dimensionFieldDef => {
                if (dimensionFieldDef.bin) {
                    if (impute) {
                        // For binned group by field with impute, we calculate bin_mid
                        // as we cannot impute two fields simultaneously
                        return [vgField(dimensionFieldDef, { binSuffix: 'mid' })];
                    }
                    return [
                        // For binned group by field without impute, we need both bin (start) and bin_end
                        vgField(dimensionFieldDef, {}),
                        vgField(dimensionFieldDef, { binSuffix: 'end' })
                    ];
                }
                return [vgField(dimensionFieldDef)];
            })
                .flat();
        }
        return groupby ?? [];
    }
    assemble() {
        const transform = [];
        const { facetby, dimensionFieldDefs, stackField: field, stackby, sort, offset, impute, as } = this._stack;
        // Impute
        if (impute) {
            for (const dimensionFieldDef of dimensionFieldDefs) {
                const { bandPosition = 0.5, bin } = dimensionFieldDef;
                if (bin) {
                    // As we can only impute one field at a time, we need to calculate
                    // mid point for a binned field
                    const binStart = vgField(dimensionFieldDef, { expr: 'datum' });
                    const binEnd = vgField(dimensionFieldDef, { expr: 'datum', binSuffix: 'end' });
                    transform.push({
                        type: 'formula',
                        expr: `${isValidFiniteNumberExpr(binStart)} ? ${bandPosition}*${binStart}+${1 - bandPosition}*${binEnd} : ${binStart}`,
                        as: vgField(dimensionFieldDef, { binSuffix: 'mid', forAs: true })
                    });
                }
                transform.push({
                    type: 'impute',
                    field,
                    groupby: [...stackby, ...facetby],
                    key: vgField(dimensionFieldDef, { binSuffix: 'mid' }),
                    method: 'value',
                    value: 0
                });
            }
        }
        // Stack
        transform.push({
            type: 'stack',
            groupby: [...this.getGroupbyFields(), ...facetby],
            field,
            sort,
            as,
            offset
        });
        return transform;
    }
}
//# sourceMappingURL=stack.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/window.js





/**
 * A class for the window transform nodes
 */
class WindowTransformNode extends DataFlowNode {
    clone() {
        return new WindowTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
    }
    addDimensions(fields) {
        this.transform.groupby = unique(this.transform.groupby.concat(fields), d => d);
    }
    dependentFields() {
        const out = new Set();
        (this.transform.groupby ?? []).forEach(out.add, out);
        (this.transform.sort ?? []).forEach(m => out.add(m.field));
        this.transform.window
            .map(w => w.field)
            .filter(f => f !== undefined)
            .forEach(out.add, out);
        return out;
    }
    producedFields() {
        return new Set(this.transform.window.map(this.getDefaultName));
    }
    getDefaultName(windowFieldDef) {
        return windowFieldDef.as ?? vgField(windowFieldDef);
    }
    hash() {
        return `WindowTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const fields = [];
        const ops = [];
        const as = [];
        const params = [];
        for (const window of this.transform.window) {
            ops.push(window.op);
            as.push(this.getDefaultName(window));
            params.push(window.param === undefined ? null : window.param);
            fields.push(window.field === undefined ? null : window.field);
        }
        const frame = this.transform.frame;
        const groupby = this.transform.groupby;
        if (frame && frame[0] === null && frame[1] === null && ops.every(o => isAggregateOp(o))) {
            // when the window does not rely on any particular window ops or frame, switch to a simpler and more efficient joinaggregate
            return {
                type: 'joinaggregate',
                as,
                ops: ops,
                fields,
                ...(groupby !== undefined ? { groupby } : {})
            };
        }
        const sortFields = [];
        const sortOrder = [];
        if (this.transform.sort !== undefined) {
            for (const sortField of this.transform.sort) {
                sortFields.push(sortField.field);
                sortOrder.push(sortField.order ?? 'ascending');
            }
        }
        const sort = {
            field: sortFields,
            order: sortOrder
        };
        const ignorePeers = this.transform.ignorePeers;
        return {
            type: 'window',
            params,
            as,
            ops,
            fields,
            sort,
            ...(ignorePeers !== undefined ? { ignorePeers } : {}),
            ...(groupby !== undefined ? { groupby } : {}),
            ...(frame !== undefined ? { frame } : {})
        };
    }
}
//# sourceMappingURL=window.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/subtree.js








/**
 * Clones the subtree and ignores output nodes except for the leaves, which are renamed.
 */
function cloneSubtree(facet) {
    function clone(node) {
        if (!(node instanceof FacetNode)) {
            const copy = node.clone();
            if (copy instanceof OutputNode) {
                const newName = FACET_SCALE_PREFIX + copy.getSource();
                copy.setSource(newName);
                facet.model.component.data.outputNodes[newName] = copy;
            }
            else if (copy instanceof AggregateNode ||
                copy instanceof StackNode ||
                copy instanceof WindowTransformNode ||
                copy instanceof JoinAggregateTransformNode) {
                copy.addDimensions(facet.fields);
            }
            for (const n of node.children.flatMap(clone)) {
                n.parent = copy;
            }
            return [copy];
        }
        return node.children.flatMap(clone);
    }
    return clone;
}
/**
 * Move facet nodes down to the next fork or output node. Also pull the main output with the facet node.
 * After moving down the facet node, make a copy of the subtree and make it a child of the main output.
 */
function moveFacetDown(node) {
    if (node instanceof FacetNode) {
        if (node.numChildren() === 1 && !(node.children[0] instanceof OutputNode)) {
            // move down until we hit a fork or output node
            const child = node.children[0];
            if (child instanceof AggregateNode ||
                child instanceof StackNode ||
                child instanceof WindowTransformNode ||
                child instanceof JoinAggregateTransformNode) {
                child.addDimensions(node.fields);
            }
            child.swapWithParent();
            moveFacetDown(node);
        }
        else {
            // move main to facet
            const facetMain = node.model.component.data.main;
            moveMainDownToFacet(facetMain);
            // replicate the subtree and place it before the facet's main node
            const cloner = cloneSubtree(node);
            const copy = node.children.map(cloner).flat();
            for (const c of copy) {
                c.parent = facetMain;
            }
        }
    }
    else {
        node.children.map(moveFacetDown);
    }
}
function moveMainDownToFacet(node) {
    if (node instanceof OutputNode && node.type === DataSourceType.Main) {
        if (node.numChildren() === 1) {
            const child = node.children[0];
            if (!(child instanceof FacetNode)) {
                child.swapWithParent();
                moveMainDownToFacet(node);
            }
        }
    }
}
//# sourceMappingURL=subtree.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/optimize.js



const FACET_SCALE_PREFIX = 'scale_';
const MAX_OPTIMIZATION_RUNS = 5;
/**
 * Iterates over a dataflow graph and checks whether all links are consistent.
 */
function checkLinks(nodes) {
    for (const node of nodes) {
        for (const child of node.children) {
            if (child.parent !== node) {
                // log.error('Dataflow graph is inconsistent.', node, child);
                return false;
            }
        }
        if (!checkLinks(node.children)) {
            return false;
        }
    }
    return true;
}
/**
 * Run the specified optimizer on the provided nodes.
 *
 * @param optimizer The optimizer instance to run.
 * @param nodes A set of nodes to optimize.
 */
function runOptimizer(optimizer, nodes) {
    let modified = false;
    for (const node of nodes) {
        modified = optimizer.optimize(node) || modified;
    }
    return modified;
}
function optimizationDataflowHelper(dataComponent, model, firstPass) {
    let roots = dataComponent.sources;
    let modified = false;
    modified = runOptimizer(new RemoveUnnecessaryOutputNodes(), roots) || modified;
    modified = runOptimizer(new RemoveUnnecessaryIdentifierNodes(model), roots) || modified;
    // remove source nodes that don't have any children because they also don't have output nodes
    roots = roots.filter(r => r.numChildren() > 0);
    modified = runOptimizer(new RemoveUnusedSubtrees(), roots) || modified;
    roots = roots.filter(r => r.numChildren() > 0);
    if (!firstPass) {
        // Only run these optimizations after the optimizer has moved down the facet node.
        // With this change, we can be more aggressive in the optimizations.
        modified = runOptimizer(new MoveParseUp(), roots) || modified;
        modified = runOptimizer(new MergeBins(model), roots) || modified;
        modified = runOptimizer(new RemoveDuplicateTimeUnits(), roots) || modified;
        modified = runOptimizer(new MergeParse(), roots) || modified;
        modified = runOptimizer(new MergeAggregates(), roots) || modified;
        modified = runOptimizer(new MergeTimeUnits(), roots) || modified;
        modified = runOptimizer(new MergeIdenticalNodes(), roots) || modified;
        modified = runOptimizer(new MergeOutputs(), roots) || modified;
    }
    dataComponent.sources = roots;
    return modified;
}
/**
 * Optimizes the dataflow of the passed in data component.
 */
function optimizeDataflow(data, model) {
    // check before optimizations
    checkLinks(data.sources);
    let firstPassCounter = 0;
    let secondPassCounter = 0;
    for (let i = 0; i < MAX_OPTIMIZATION_RUNS; i++) {
        if (!optimizationDataflowHelper(data, model, true)) {
            break;
        }
        firstPassCounter++;
    }
    // move facets down and make a copy of the subtree so that we can have scales at the top level
    data.sources.map(moveFacetDown);
    for (let i = 0; i < MAX_OPTIMIZATION_RUNS; i++) {
        if (!optimizationDataflowHelper(data, model, false)) {
            break;
        }
        secondPassCounter++;
    }
    // check after optimizations
    checkLinks(data.sources);
    if (Math.max(firstPassCounter, secondPassCounter) === MAX_OPTIMIZATION_RUNS) {
        log_warn(`Maximum optimization runs(${MAX_OPTIMIZATION_RUNS}) reached.`);
    }
}
//# sourceMappingURL=optimize.js.map
;// ../../node_modules/vega-lite/build/src/compile/signal.js
/**
 * A class that behaves like a SignalRef but lazily generates the signal.
 * The provided generator function should use `Model.getSignalName` to use the correct signal name.
 */
class SignalRefWrapper {
    constructor(exprGenerator) {
        Object.defineProperty(this, 'signal', {
            enumerable: true,
            get: exprGenerator
        });
    }
    static fromName(rename, signalName) {
        return new SignalRefWrapper(() => rename(signalName));
    }
}
//# sourceMappingURL=signal.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/domain.js






















function domain_parseScaleDomain(model) {
    if (isUnitModel(model)) {
        parseUnitScaleDomain(model);
    }
    else {
        parseNonUnitScaleDomain(model);
    }
}
function parseUnitScaleDomain(model) {
    const localScaleComponents = model.component.scales;
    for (const channel of util_keys(localScaleComponents)) {
        const domains = parseDomainForChannel(model, channel);
        const localScaleCmpt = localScaleComponents[channel];
        localScaleCmpt.setWithExplicit('domains', domains);
        parseSelectionDomain(model, channel);
        if (model.component.data.isFaceted) {
            // get resolve from closest facet parent as this decides whether we need to refer to cloned subtree or not
            let facetParent = model;
            while (!isFacetModel(facetParent) && facetParent.parent) {
                facetParent = facetParent.parent;
            }
            const resolve = facetParent.component.resolve.scale[channel];
            if (resolve === 'shared') {
                for (const domain of domains.value) {
                    // Replace the scale domain with data output from a cloned subtree after the facet.
                    if (isDataRefDomain(domain)) {
                        // use data from cloned subtree (which is the same as data but with a prefix added once)
                        domain.data = FACET_SCALE_PREFIX + domain.data.replace(FACET_SCALE_PREFIX, '');
                    }
                }
            }
        }
    }
}
function parseNonUnitScaleDomain(model) {
    for (const child of model.children) {
        domain_parseScaleDomain(child);
    }
    const localScaleComponents = model.component.scales;
    for (const channel of util_keys(localScaleComponents)) {
        let domains;
        let selectionExtent = null;
        for (const child of model.children) {
            const childComponent = child.component.scales[channel];
            if (childComponent) {
                if (domains === undefined) {
                    domains = childComponent.getWithExplicit('domains');
                }
                else {
                    domains = mergeValuesWithExplicit(domains, childComponent.getWithExplicit('domains'), 'domains', 'scale', domainsTieBreaker);
                }
                const se = childComponent.get('selectionExtent');
                if (selectionExtent && se && selectionExtent.param !== se.param) {
                    log_warn(NEEDS_SAME_SELECTION);
                }
                selectionExtent = se;
            }
        }
        localScaleComponents[channel].setWithExplicit('domains', domains);
        if (selectionExtent) {
            localScaleComponents[channel].set('selectionExtent', selectionExtent, true);
        }
    }
}
/**
 * Remove unaggregated domain if it is not applicable
 * Add unaggregated domain if domain is not specified and config.scale.useUnaggregatedDomain is true.
 */
function normalizeUnaggregatedDomain(domain, fieldDef, scaleType, scaleConfig) {
    if (domain === 'unaggregated') {
        const { valid, reason } = canUseUnaggregatedDomain(fieldDef, scaleType);
        if (!valid) {
            log_warn(reason);
            return undefined;
        }
    }
    else if (domain === undefined && scaleConfig.useUnaggregatedDomain) {
        // Apply config if domain is not specified.
        const { valid } = canUseUnaggregatedDomain(fieldDef, scaleType);
        if (valid) {
            return 'unaggregated';
        }
    }
    return domain;
}
function parseDomainForChannel(model, channel) {
    const scaleType = model.getScaleComponent(channel).get('type');
    const { encoding } = model;
    const domain = normalizeUnaggregatedDomain(model.scaleDomain(channel), model.typedFieldDef(channel), scaleType, model.config.scale);
    if (domain !== model.scaleDomain(channel)) {
        model.specifiedScales[channel] = {
            ...model.specifiedScales[channel],
            domain
        };
    }
    // If channel is either X or Y then union them with X2 & Y2 if they exist
    if (channel === 'x' && getFieldOrDatumDef(encoding.x2)) {
        if (getFieldOrDatumDef(encoding.x)) {
            return mergeValuesWithExplicit(parseSingleChannelDomain(scaleType, domain, model, 'x'), parseSingleChannelDomain(scaleType, domain, model, 'x2'), 'domain', 'scale', domainsTieBreaker);
        }
        else {
            return parseSingleChannelDomain(scaleType, domain, model, 'x2');
        }
    }
    else if (channel === 'y' && getFieldOrDatumDef(encoding.y2)) {
        if (getFieldOrDatumDef(encoding.y)) {
            return mergeValuesWithExplicit(parseSingleChannelDomain(scaleType, domain, model, 'y'), parseSingleChannelDomain(scaleType, domain, model, 'y2'), 'domain', 'scale', domainsTieBreaker);
        }
        else {
            return parseSingleChannelDomain(scaleType, domain, model, 'y2');
        }
    }
    return parseSingleChannelDomain(scaleType, domain, model, channel);
}
function mapDomainToDataSignal(domain, type, timeUnit) {
    return domain.map(v => {
        const data = valueExpr(v, { timeUnit, type });
        return { signal: `{data: ${data}}` };
    });
}
function convertDomainIfItIsDateTime(domain, type, timeUnit) {
    // explicit value
    const normalizedTimeUnit = normalizeTimeUnit(timeUnit)?.unit;
    if (type === 'temporal' || normalizedTimeUnit) {
        return mapDomainToDataSignal(domain, type, normalizedTimeUnit);
    }
    return [domain]; // Date time won't make sense
}
function parseSingleChannelDomain(scaleType, domain, model, channel) {
    const { encoding, markDef, mark, config, stack } = model;
    const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]);
    const { type } = fieldOrDatumDef;
    const timeUnit = fieldOrDatumDef['timeUnit'];
    const dataSourceTypeForScaleDomain = getScaleDataSourceForHandlingInvalidValues({
        invalid: getMarkConfig('invalid', markDef, config),
        isPath: isPathMark(mark)
    });
    if (isDomainUnionWith(domain)) {
        const defaultDomain = parseSingleChannelDomain(scaleType, undefined, model, channel);
        const unionWith = convertDomainIfItIsDateTime(domain.unionWith, type, timeUnit);
        return makeExplicit([...unionWith, ...defaultDomain.value]);
    }
    else if (isSignalRef(domain)) {
        return makeExplicit([domain]);
    }
    else if (domain && domain !== 'unaggregated' && !isParameterDomain(domain)) {
        return makeExplicit(convertDomainIfItIsDateTime(domain, type, timeUnit));
    }
    if (stack && channel === stack.fieldChannel) {
        if (stack.offset === 'normalize') {
            return makeImplicit([[0, 1]]);
        }
        const data = model.requestDataName(dataSourceTypeForScaleDomain);
        return makeImplicit([
            {
                data,
                field: model.vgField(channel, { suffix: 'start' })
            },
            {
                data,
                field: model.vgField(channel, { suffix: 'end' })
            }
        ]);
    }
    const sort = isScaleChannel(channel) && isFieldDef(fieldOrDatumDef) ? domainSort(model, channel, scaleType) : undefined;
    if (isDatumDef(fieldOrDatumDef)) {
        const d = convertDomainIfItIsDateTime([fieldOrDatumDef.datum], type, timeUnit);
        return makeImplicit(d);
    }
    const fieldDef = fieldOrDatumDef; // now we can be sure it's a fieldDef
    if (domain === 'unaggregated') {
        const { field } = fieldOrDatumDef;
        return makeImplicit([
            {
                data: model.requestDataName(dataSourceTypeForScaleDomain),
                field: vgField({ field, aggregate: 'min' })
            },
            {
                data: model.requestDataName(dataSourceTypeForScaleDomain),
                field: vgField({ field, aggregate: 'max' })
            }
        ]);
    }
    else if (isBinning(fieldDef.bin)) {
        if (hasDiscreteDomain(scaleType)) {
            if (scaleType === 'bin-ordinal') {
                // we can omit the domain as it is inferred from the `bins` property
                return makeImplicit([]);
            }
            // ordinal bin scale takes domain from bin_range, ordered by bin start
            // This is useful for both axis-based scale (x/y) and legend-based scale (other channels).
            return makeImplicit([
                {
                    // If sort by aggregation of a specified sort field, we need to use RAW table,
                    // so we can aggregate values for the scale independently from the main aggregation.
                    data: util_isBoolean(sort)
                        ? model.requestDataName(dataSourceTypeForScaleDomain)
                        : model.requestDataName(DataSourceType.Raw),
                    // Use range if we added it and the scale does not support computing a range as a signal.
                    field: model.vgField(channel, binRequiresRange(fieldDef, channel) ? { binSuffix: 'range' } : {}),
                    // we have to use a sort object if sort = true to make the sort correct by bin start
                    sort: sort === true || !vega_util_module_isObject(sort)
                        ? {
                            field: model.vgField(channel, {}),
                            op: 'min' // min or max doesn't matter since we sort by the start of the bin range
                        }
                        : sort
                }
            ]);
        }
        else {
            // continuous scales
            const { bin } = fieldDef;
            if (isBinning(bin)) {
                const binSignal = getBinSignalName(model, fieldDef.field, bin);
                return makeImplicit([
                    new SignalRefWrapper(() => {
                        const signal = model.getSignalName(binSignal);
                        return `[${signal}.start, ${signal}.stop]`;
                    })
                ]);
            }
            else {
                return makeImplicit([
                    {
                        data: model.requestDataName(dataSourceTypeForScaleDomain),
                        field: model.vgField(channel, {})
                    }
                ]);
            }
        }
    }
    else if (fieldDef.timeUnit && util_contains(['time', 'utc'], scaleType)) {
        const fieldDef2 = encoding[getSecondaryRangeChannel(channel)];
        if (hasBandEnd(fieldDef, fieldDef2, markDef, config)) {
            const data = model.requestDataName(dataSourceTypeForScaleDomain);
            const bandPosition = getBandPosition({ fieldDef, fieldDef2, markDef, config });
            const isRectWithOffset = isRectBasedMark(mark) && bandPosition !== 0.5 && isXorY(channel);
            return makeImplicit([
                {
                    data,
                    field: model.vgField(channel, isRectWithOffset ? { suffix: OFFSETTED_RECT_START_SUFFIX } : {})
                },
                {
                    data,
                    field: model.vgField(channel, { suffix: isRectWithOffset ? OFFSETTED_RECT_END_SUFFIX : 'end' })
                }
            ]);
        }
    }
    if (sort) {
        return makeImplicit([
            {
                // If sort by aggregation of a specified sort field, we need to use RAW table,
                // so we can aggregate values for the scale independently from the main aggregation.
                data: util_isBoolean(sort)
                    ? model.requestDataName(dataSourceTypeForScaleDomain)
                    : model.requestDataName(DataSourceType.Raw),
                field: model.vgField(channel),
                sort
            }
        ]);
    }
    else {
        return makeImplicit([
            {
                data: model.requestDataName(dataSourceTypeForScaleDomain),
                field: model.vgField(channel)
            }
        ]);
    }
}
function normalizeSortField(sort, isStackedMeasure) {
    const { op, field, order } = sort;
    return {
        // Apply default op
        op: op ?? (isStackedMeasure ? 'sum' : DEFAULT_SORT_OP),
        // flatten nested fields
        ...(field ? { field: replacePathInField(field) } : {}),
        ...(order ? { order } : {})
    };
}
function parseSelectionDomain(model, channel) {
    const scale = model.component.scales[channel];
    const spec = model.specifiedScales[channel].domain;
    const bin = model.fieldDef(channel)?.bin;
    const domain = isParameterDomain(spec) ? spec : undefined;
    const extent = isBinParams(bin) && isParameterExtent(bin.extent) ? bin.extent : undefined;
    if (domain || extent) {
        // As scale parsing occurs before selection parsing, we cannot set
        // domainRaw directly. So instead, we store the selectionExtent on
        // the scale component, and then add domainRaw during scale assembly.
        scale.set('selectionExtent', domain ?? extent, true);
    }
}
function domainSort(model, channel, scaleType) {
    if (!hasDiscreteDomain(scaleType)) {
        return undefined;
    }
    // save to cast as the only exception is the geojson type for shape, which would not generate a scale
    const fieldDef = model.fieldDef(channel);
    const sort = fieldDef.sort;
    // if the sort is specified with array, use the derived sort index field
    if (isSortArray(sort)) {
        return {
            op: 'min',
            field: sortArrayIndexField(fieldDef, channel),
            order: 'ascending'
        };
    }
    const { stack } = model;
    const stackDimensions = stack
        ? new Set([...stack.groupbyFields, ...stack.stackBy.map(s => s.fieldDef.field)])
        : undefined;
    // Sorted based on an aggregate calculation over a specified sort field (only for ordinal scale)
    if (isSortField(sort)) {
        const isStackedMeasure = stack && !stackDimensions.has(sort.field);
        return normalizeSortField(sort, isStackedMeasure);
    }
    else if (isSortByEncoding(sort)) {
        const { encoding, order } = sort;
        const fieldDefToSortBy = model.fieldDef(encoding);
        const { aggregate, field } = fieldDefToSortBy;
        const isStackedMeasure = stack && !stackDimensions.has(field);
        if (isArgminDef(aggregate) || isArgmaxDef(aggregate)) {
            return normalizeSortField({
                field: vgField(fieldDefToSortBy),
                order
            }, isStackedMeasure);
        }
        else if (isAggregateOp(aggregate) || !aggregate) {
            return normalizeSortField({
                op: aggregate, // can't be argmin/argmax since we don't support them in encoding field def
                field,
                order
            }, isStackedMeasure);
        }
    }
    else if (sort === 'descending') {
        return {
            op: 'min',
            field: model.vgField(channel),
            order: 'descending'
        };
    }
    else if (util_contains(['ascending', undefined /* default =ascending*/], sort)) {
        return true;
    }
    // sort == null
    return undefined;
}
/**
 * Determine if a scale can use unaggregated domain.
 * @return {Boolean} Returns true if all of the following conditions apply:
 * 1. `scale.domain` is `unaggregated`
 * 2. Aggregation function is not `count` or `sum`
 * 3. The scale is quantitative or time scale.
 */
function canUseUnaggregatedDomain(fieldDef, scaleType) {
    const { aggregate, type } = fieldDef;
    if (!aggregate) {
        return {
            valid: false,
            reason: unaggregateDomainHasNoEffectForRawField(fieldDef)
        };
    }
    if (vega_util_module_isString(aggregate) && !SHARED_DOMAIN_OPS.has(aggregate)) {
        return {
            valid: false,
            reason: unaggregateDomainWithNonSharedDomainOp(aggregate)
        };
    }
    if (type === 'quantitative') {
        if (scaleType === 'log') {
            return {
                valid: false,
                reason: unaggregatedDomainWithLogScale(fieldDef)
            };
        }
    }
    return { valid: true };
}
/**
 * Tie breaker for mergeValuesWithExplicit for domains. We concat the specified values.
 */
function domainsTieBreaker(v1, v2, property, propertyOf) {
    if (v1.explicit && v2.explicit) {
        log_warn(mergeConflictingDomainProperty(property, propertyOf, v1.value, v2.value));
    }
    // If equal score, concat the domains so that we union them later.
    return { explicit: v1.explicit, value: [...v1.value, ...v2.value] };
}
/**
 * Converts an array of domains to a single Vega scale domain.
 */
function mergeDomains(domains) {
    const uniqueDomains = unique(domains.map(domain => {
        // ignore sort property when computing the unique domains
        if (isDataRefDomain(domain)) {
            const { sort: _s, ...domainWithoutSort } = domain;
            return domainWithoutSort;
        }
        return domain;
    }), util_hash);
    const sorts = unique(domains
        .map(d => {
        if (isDataRefDomain(d)) {
            const s = d.sort;
            if (s !== undefined && !util_isBoolean(s)) {
                if ('op' in s && s.op === 'count') {
                    // let's make sure that if op is count, we don't use a field
                    delete s.field;
                }
                if (s.order === 'ascending') {
                    // drop order: ascending as it is the default
                    delete s.order;
                }
            }
            return s;
        }
        return undefined;
    })
        .filter(s => s !== undefined), util_hash);
    if (uniqueDomains.length === 0) {
        return undefined;
    }
    else if (uniqueDomains.length === 1) {
        const domain = domains[0];
        if (isDataRefDomain(domain) && sorts.length > 0) {
            let sort = sorts[0];
            if (sorts.length > 1) {
                log_warn(MORE_THAN_ONE_SORT);
                // Get sorts with non-default ops
                const filteredSorts = sorts.filter(s => vega_util_module_isObject(s) && 'op' in s && s.op !== 'min');
                if (sorts.every(s => vega_util_module_isObject(s) && 'op' in s) && filteredSorts.length === 1) {
                    sort = filteredSorts[0];
                }
                else {
                    sort = true;
                }
            }
            else {
                // Simplify domain sort by removing field and op when the field is the same as the domain field.
                if (vega_util_module_isObject(sort) && 'field' in sort) {
                    const sortField = sort.field;
                    if (domain.field === sortField) {
                        sort = sort.order ? { order: sort.order } : true;
                    }
                }
            }
            return {
                ...domain,
                sort
            };
        }
        return domain;
    }
    // only keep sort properties that work with unioned domains
    const unionDomainSorts = unique(sorts.map(s => {
        if (util_isBoolean(s) || !('op' in s) || (vega_util_module_isString(s.op) && vega_util_module_has(MULTIDOMAIN_SORT_OP_INDEX, s.op))) {
            return s;
        }
        log_warn(domainSortDropped(s));
        return true;
    }), util_hash);
    let sort;
    if (unionDomainSorts.length === 1) {
        sort = unionDomainSorts[0];
    }
    else if (unionDomainSorts.length > 1) {
        log_warn(MORE_THAN_ONE_SORT);
        sort = true;
    }
    const allData = unique(domains.map(d => {
        if (isDataRefDomain(d)) {
            return d.data;
        }
        return null;
    }), x => x);
    if (allData.length === 1 && allData[0] !== null) {
        // create a union domain of different fields with a single data source
        const domain = {
            data: allData[0],
            fields: uniqueDomains.map(d => d.field),
            ...(sort ? { sort } : {})
        };
        return domain;
    }
    return { fields: uniqueDomains, ...(sort ? { sort } : {}) };
}
/**
 * Return a field if a scale uses a single field.
 * Return `undefined` otherwise.
 */
function getFieldFromDomain(domain) {
    if (isDataRefDomain(domain) && vega_util_module_isString(domain.field)) {
        return domain.field;
    }
    else if (isDataRefUnionedDomain(domain)) {
        let field;
        for (const nonUnionDomain of domain.fields) {
            if (isDataRefDomain(nonUnionDomain) && vega_util_module_isString(nonUnionDomain.field)) {
                if (!field) {
                    field = nonUnionDomain.field;
                }
                else if (field !== nonUnionDomain.field) {
                    log_warn(FACETED_INDEPENDENT_DIFFERENT_SOURCES);
                    return field;
                }
            }
        }
        log_warn(FACETED_INDEPENDENT_SAME_FIELDS_DIFFERENT_SOURCES);
        return field;
    }
    else if (isFieldRefUnionDomain(domain)) {
        log_warn(FACETED_INDEPENDENT_SAME_SOURCE);
        const field = domain.fields[0];
        return vega_util_module_isString(field) ? field : undefined;
    }
    return undefined;
}
function assembleDomain(model, channel) {
    const scaleComponent = model.component.scales[channel];
    const domains = scaleComponent.get('domains').map((domain) => {
        // Correct references to data as the original domain's data was determined
        // in parseScale, which happens before parseData. Thus the original data
        // reference can be incorrect.
        if (isDataRefDomain(domain)) {
            domain.data = model.lookupDataSource(domain.data);
        }
        return domain;
    });
    // domains is an array that has to be merged into a single vega domain
    return mergeDomains(domains);
}
//# sourceMappingURL=domain.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/assemble.js







function assembleScales(model) {
    if (isLayerModel(model) || isConcatModel(model)) {
        // For concat and layer, include scales of children too
        return model.children.reduce((scales, child) => {
            return scales.concat(assembleScales(child));
        }, assembleScalesForModel(model));
    }
    else {
        // For facet, child scales would not be included in the parent's scope.
        // For unit, there is no child.
        return assembleScalesForModel(model);
    }
}
function assembleScalesForModel(model) {
    return util_keys(model.component.scales).reduce((scales, channel) => {
        const scaleComponent = model.component.scales[channel];
        if (scaleComponent.merged) {
            // Skipped merged scales
            return scales;
        }
        const scale = scaleComponent.combine();
        const { name, type, selectionExtent, domains: _d, range: _r, reverse, ...otherScaleProps } = scale;
        const range = assembleScaleRange(scale.range, name, channel, model);
        const domain = assembleDomain(model, channel);
        const domainRaw = selectionExtent
            ? assembleSelectionScaleDomain(model, selectionExtent, scaleComponent, domain)
            : null;
        scales.push({
            name,
            type,
            ...(domain ? { domain } : {}),
            ...(domainRaw ? { domainRaw } : {}),
            range,
            ...(reverse !== undefined ? { reverse: reverse } : {}),
            ...otherScaleProps
        });
        return scales;
    }, []);
}
function assembleScaleRange(scaleRange, scaleName, channel, model) {
    // add signals to x/y range
    if (isXorY(channel)) {
        if (isVgRangeStep(scaleRange)) {
            // For width/height step, use a signal created in layout assemble instead of a constant step.
            return {
                step: { signal: `${scaleName}_step` }
            };
        }
    }
    else if (vega_util_module_isObject(scaleRange) && isDataRefDomain(scaleRange)) {
        return {
            ...scaleRange,
            data: model.lookupDataSource(scaleRange.data)
        };
    }
    return scaleRange;
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/component.js




class ScaleComponent extends Split {
    constructor(name, typeWithExplicit) {
        super({}, // no initial explicit property
        { name } // name as initial implicit property
        );
        this.merged = false;
        this.setWithExplicit('type', typeWithExplicit);
    }
    /**
     * Whether the scale definitely includes or not include zero in the domain
     */
    domainHasZero() {
        const scaleType = this.get('type');
        if (util_contains([ScaleType.LOG, ScaleType.TIME, ScaleType.UTC], scaleType)) {
            // Log scales cannot have zero.
            // Zero in time scale is arbitrary, and does not affect ratio.
            // (Time is an interval level of measurement, not ratio).
            // See https://en.wikipedia.org/wiki/Level_of_measurement for more info.
            return 'definitely-not';
        }
        const scaleZero = this.get('zero');
        if (scaleZero === true ||
            // If zero is undefined, linear/sqrt/pow scales have zero by default.
            (scaleZero === undefined && util_contains([ScaleType.LINEAR, ScaleType.SQRT, ScaleType.POW], scaleType))) {
            return 'definitely';
        }
        const domains = this.get('domains');
        if (domains.length > 0) {
            let hasExplicitDomainWithZero = false;
            let hasExplicitDomainWithoutZero = false;
            let hasDomainBasedOnField = false;
            for (const d of domains) {
                if (vega_util_module_isArray(d)) {
                    const first = d[0];
                    const last = d[d.length - 1];
                    if (vega_util_module_isNumber(first) && vega_util_module_isNumber(last)) {
                        if (first <= 0 && last >= 0) {
                            hasExplicitDomainWithZero = true;
                            continue;
                        }
                        else {
                            hasExplicitDomainWithoutZero = true;
                            continue;
                        }
                    }
                }
                hasDomainBasedOnField = true;
            }
            if (hasExplicitDomainWithZero) {
                return 'definitely';
            }
            else if (hasExplicitDomainWithoutZero && !hasDomainBasedOnField) {
                return 'definitely-not';
            }
        }
        return 'maybe';
    }
}
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/range.js



















const RANGE_PROPERTIES = ['range', 'scheme'];
function parseUnitScaleRange(model) {
    const localScaleComponents = model.component.scales;
    // use SCALE_CHANNELS instead of scales[channel] to ensure that x, y come first!
    for (const channel of SCALE_CHANNELS) {
        const localScaleCmpt = localScaleComponents[channel];
        if (!localScaleCmpt) {
            continue;
        }
        const rangeWithExplicit = parseRangeForChannel(channel, model);
        localScaleCmpt.setWithExplicit('range', rangeWithExplicit);
    }
}
function getBinStepSignal(model, channel) {
    const fieldDef = model.fieldDef(channel);
    if (fieldDef?.bin) {
        const { bin, field } = fieldDef;
        const sizeType = getSizeChannel(channel);
        const sizeSignal = model.getName(sizeType);
        if (vega_util_module_isObject(bin) && bin.binned && bin.step !== undefined) {
            return new SignalRefWrapper(() => {
                const scaleName = model.scaleName(channel);
                const binCount = `(domain("${scaleName}")[1] - domain("${scaleName}")[0]) / ${bin.step}`;
                return `${model.getSignalName(sizeSignal)} / (${binCount})`;
            });
        }
        else if (isBinning(bin)) {
            const binSignal = getBinSignalName(model, field, bin);
            // TODO: extract this to be range step signal
            return new SignalRefWrapper(() => {
                const updatedName = model.getSignalName(binSignal);
                const binCount = `(${updatedName}.stop - ${updatedName}.start) / ${updatedName}.step`;
                return `${model.getSignalName(sizeSignal)} / (${binCount})`;
            });
        }
    }
    return undefined;
}
/**
 * Return mixins that includes one of the Vega range types (explicit range, range.step, range.scheme).
 */
function parseRangeForChannel(channel, model) {
    const specifiedScale = model.specifiedScales[channel];
    const { size } = model;
    const mergedScaleCmpt = model.getScaleComponent(channel);
    const scaleType = mergedScaleCmpt.get('type');
    // Check if any of the range properties is specified.
    // If so, check if it is compatible and make sure that we only output one of the properties
    for (const property of RANGE_PROPERTIES) {
        if (specifiedScale[property] !== undefined) {
            const supportedByScaleType = scaleTypeSupportProperty(scaleType, property);
            const channelIncompatability = channelScalePropertyIncompatability(channel, property);
            if (!supportedByScaleType) {
                log_warn(scalePropertyNotWorkWithScaleType(scaleType, property, channel));
            }
            else if (channelIncompatability) {
                // channel
                log_warn(channelIncompatability);
            }
            else {
                switch (property) {
                    case 'range': {
                        const range = specifiedScale.range;
                        if (vega_util_module_isArray(range)) {
                            if (isXorY(channel)) {
                                return makeExplicit(range.map(v => {
                                    if (v === 'width' || v === 'height') {
                                        // get signal for width/height
                                        // Just like default range logic below, we use SignalRefWrapper to account for potential merges and renames.
                                        const sizeSignal = model.getName(v);
                                        const getSignalName = model.getSignalName.bind(model);
                                        return SignalRefWrapper.fromName(getSignalName, sizeSignal);
                                    }
                                    return v;
                                }));
                            }
                        }
                        else if (vega_util_module_isObject(range)) {
                            return makeExplicit({
                                data: model.requestDataName(DataSourceType.Main),
                                field: range.field,
                                sort: { op: 'min', field: model.vgField(channel) }
                            });
                        }
                        return makeExplicit(range);
                    }
                    case 'scheme':
                        return makeExplicit(parseScheme(specifiedScale[property]));
                }
            }
        }
    }
    const sizeChannel = channel === channel_X || channel === 'xOffset' ? 'width' : 'height';
    const sizeValue = size[sizeChannel];
    if (isStep(sizeValue)) {
        if (isXorY(channel)) {
            if (hasDiscreteDomain(scaleType)) {
                const step = getPositionStep(sizeValue, model, channel);
                // Need to be explicit so layer with step wins over layer without step
                if (step) {
                    return makeExplicit({ step });
                }
            }
            else {
                log_warn(stepDropped(sizeChannel));
            }
        }
        else if (isXorYOffset(channel)) {
            const positionChannel = channel === XOFFSET ? 'x' : 'y';
            const positionScaleCmpt = model.getScaleComponent(positionChannel);
            const positionScaleType = positionScaleCmpt.get('type');
            if (positionScaleType === 'band') {
                const step = getOffsetStep(sizeValue, scaleType);
                if (step) {
                    return makeExplicit(step);
                }
            }
        }
    }
    const { rangeMin, rangeMax } = specifiedScale;
    const d = defaultRange(channel, model);
    if ((rangeMin !== undefined || rangeMax !== undefined) &&
        // it's ok to check just rangeMin's compatibility since rangeMin/rangeMax are the same
        scaleTypeSupportProperty(scaleType, 'rangeMin') &&
        vega_util_module_isArray(d) &&
        d.length === 2) {
        return makeExplicit([rangeMin ?? d[0], rangeMax ?? d[1]]);
    }
    return makeImplicit(d);
}
function parseScheme(scheme) {
    if (isExtendedScheme(scheme)) {
        return {
            scheme: scheme.name,
            ...omit(scheme, ['name'])
        };
    }
    return { scheme };
}
function fullWidthOrHeightRange(channel, model, scaleType, { center } = {}) {
    // If step is null, use zero to width or height.
    // Note that we use SignalRefWrapper to account for potential merges and renames.
    const sizeType = getSizeChannel(channel);
    const sizeSignal = model.getName(sizeType);
    const getSignalName = model.getSignalName.bind(model);
    if (channel === channel_Y && hasContinuousDomain(scaleType)) {
        // For y continuous scale, we have to start from the height as the bottom part has the max value.
        return center
            ? [
                SignalRefWrapper.fromName(name => `${getSignalName(name)}/2`, sizeSignal),
                SignalRefWrapper.fromName(name => `-${getSignalName(name)}/2`, sizeSignal)
            ]
            : [SignalRefWrapper.fromName(getSignalName, sizeSignal), 0];
    }
    else {
        return center
            ? [
                SignalRefWrapper.fromName(name => `-${getSignalName(name)}/2`, sizeSignal),
                SignalRefWrapper.fromName(name => `${getSignalName(name)}/2`, sizeSignal)
            ]
            : [0, SignalRefWrapper.fromName(getSignalName, sizeSignal)];
    }
}
function defaultRange(channel, model) {
    const { size, config, mark, encoding } = model;
    const { type } = getFieldOrDatumDef(encoding[channel]);
    const mergedScaleCmpt = model.getScaleComponent(channel);
    const scaleType = mergedScaleCmpt.get('type');
    const { domain, domainMid } = model.specifiedScales[channel];
    switch (channel) {
        case channel_X:
        case channel_Y: {
            // If there is no explicit width/height for discrete x/y scales
            if (util_contains(['point', 'band'], scaleType)) {
                const positionSize = getDiscretePositionSize(channel, size, config.view);
                if (isStep(positionSize)) {
                    const step = getPositionStep(positionSize, model, channel);
                    return { step };
                }
            }
            return fullWidthOrHeightRange(channel, model, scaleType);
        }
        case XOFFSET:
        case YOFFSET:
            return getOffsetRange(channel, model, scaleType);
        case channel_SIZE: {
            // TODO: support custom rangeMin, rangeMax
            const rangeMin = sizeRangeMin(mark, config);
            const rangeMax = sizeRangeMax(mark, size, model, config);
            if (isContinuousToDiscrete(scaleType)) {
                return range_interpolateRange(rangeMin, rangeMax, defaultContinuousToDiscreteCount(scaleType, config, domain, channel));
            }
            else {
                return [rangeMin, rangeMax];
            }
        }
        case THETA:
            return [0, Math.PI * 2];
        case ANGLE:
            // TODO: add config.scale.min/maxAngleDegree (for point and text) and config.scale.min/maxAngleRadian (for arc) once we add arc marks.
            // (It's weird to add just config.scale.min/maxAngleDegree for now)
            return [0, 360];
        case RADIUS: {
            // max radius = half od min(width,height)
            return [
                0,
                new SignalRefWrapper(() => {
                    const w = model.getSignalName(isFacetModel(model.parent) ? 'child_width' : 'width');
                    const h = model.getSignalName(isFacetModel(model.parent) ? 'child_height' : 'height');
                    return `min(${w},${h})/2`;
                })
            ];
        }
        case TIME: {
            // if (scaleType === 'band') {
            return { step: 1000 / config.scale.framesPerSecond };
            // }
            // return [0, config.scale.animationDuration * 1000]; // TODO(jzong): uncomment for linear scales when interpolation is implemented
        }
        case STROKEWIDTH:
            // TODO: support custom rangeMin, rangeMax
            return [config.scale.minStrokeWidth, config.scale.maxStrokeWidth];
        case STROKEDASH:
            return [
                // TODO: add this to Vega's config.range?
                [1, 0],
                [4, 2],
                [2, 1],
                [1, 1],
                [1, 2, 4, 2]
            ];
        case SHAPE:
            return 'symbol';
        case COLOR:
        case FILL:
        case STROKE:
            if (scaleType === 'ordinal') {
                // Only nominal data uses ordinal scale by default
                return type === 'nominal' ? 'category' : 'ordinal';
            }
            else {
                if (domainMid !== undefined) {
                    return 'diverging';
                }
                else {
                    return mark === 'rect' || mark === 'geoshape' ? 'heatmap' : 'ramp';
                }
            }
        case OPACITY:
        case FILLOPACITY:
        case STROKEOPACITY:
            // TODO: support custom rangeMin, rangeMax
            return [config.scale.minOpacity, config.scale.maxOpacity];
    }
}
function getPositionStep(step, model, channel) {
    const { encoding } = model;
    const mergedScaleCmpt = model.getScaleComponent(channel);
    const offsetChannel = getOffsetScaleChannel(channel);
    const offsetDef = encoding[offsetChannel];
    const stepFor = getStepFor({ step, offsetIsDiscrete: isFieldOrDatumDef(offsetDef) && type_isDiscrete(offsetDef.type) });
    if (stepFor === 'offset' && channelHasFieldOrDatum(encoding, offsetChannel)) {
        const offsetScaleCmpt = model.getScaleComponent(offsetChannel);
        const offsetScaleName = model.scaleName(offsetChannel);
        let stepCount = `domain('${offsetScaleName}').length`;
        if (offsetScaleCmpt.get('type') === 'band') {
            const offsetPaddingInner = offsetScaleCmpt.get('paddingInner') ?? offsetScaleCmpt.get('padding') ?? 0;
            const offsetPaddingOuter = offsetScaleCmpt.get('paddingOuter') ?? offsetScaleCmpt.get('padding') ?? 0;
            stepCount = `bandspace(${stepCount}, ${offsetPaddingInner}, ${offsetPaddingOuter})`;
        }
        const paddingInner = mergedScaleCmpt.get('paddingInner') ?? mergedScaleCmpt.get('padding');
        return {
            signal: `${step.step} * ${stepCount} / (1-${exprFromSignalRefOrValue(paddingInner)})`
        };
    }
    else {
        return step.step;
    }
}
function getOffsetStep(step, offsetScaleType) {
    const stepFor = getStepFor({ step, offsetIsDiscrete: hasDiscreteDomain(offsetScaleType) });
    if (stepFor === 'offset') {
        return { step: step.step };
    }
    return undefined;
}
function getOffsetRange(channel, model, offsetScaleType) {
    const positionChannel = channel === XOFFSET ? 'x' : 'y';
    const positionScaleCmpt = model.getScaleComponent(positionChannel);
    if (!positionScaleCmpt) {
        return fullWidthOrHeightRange(positionChannel, model, offsetScaleType, { center: true });
    }
    const positionScaleType = positionScaleCmpt.get('type');
    const positionScaleName = model.scaleName(positionChannel);
    const { markDef, config } = model;
    if (positionScaleType === 'band') {
        const size = getDiscretePositionSize(positionChannel, model.size, model.config.view);
        if (isStep(size)) {
            // step is for offset
            const step = getOffsetStep(size, offsetScaleType);
            if (step) {
                return step;
            }
        }
        // otherwise use the position
        return [0, { signal: `bandwidth('${positionScaleName}')` }];
    }
    else {
        // continuous scale
        const positionDef = model.encoding[positionChannel];
        if (isFieldDef(positionDef) && positionDef.timeUnit) {
            const duration = durationExpr(positionDef.timeUnit, expr => `scale('${positionScaleName}', ${expr})`);
            const padding = model.config.scale.bandWithNestedOffsetPaddingInner;
            const bandPositionOffset = getBandPosition({
                fieldDef: positionDef,
                markDef,
                config
            }) - 0.5;
            const bandPositionOffsetExpr = bandPositionOffset !== 0 ? ` + ${bandPositionOffset}` : '';
            if (padding) {
                const startRatio = isSignalRef(padding)
                    ? `${padding.signal}/2` + bandPositionOffsetExpr
                    : `${padding / 2 + bandPositionOffset}`;
                const endRatio = isSignalRef(padding)
                    ? `(1 - ${padding.signal}/2)` + bandPositionOffsetExpr
                    : `${1 - padding / 2 + bandPositionOffset}`;
                return [{ signal: `${startRatio} * (${duration})` }, { signal: `${endRatio} * (${duration})` }];
            }
            return [0, { signal: duration }];
        }
        return never(`Cannot use ${channel} scale if ${positionChannel} scale is not discrete.`);
    }
}
function getDiscretePositionSize(channel, size, viewConfig) {
    const sizeChannel = channel === channel_X ? 'width' : 'height';
    const sizeValue = size[sizeChannel];
    if (sizeValue) {
        return sizeValue;
    }
    return getViewConfigDiscreteSize(viewConfig, sizeChannel);
}
function defaultContinuousToDiscreteCount(scaleType, config, domain, channel) {
    switch (scaleType) {
        case 'quantile':
            return config.scale.quantileCount;
        case 'quantize':
            return config.scale.quantizeCount;
        case 'threshold':
            if (domain !== undefined && vega_util_module_isArray(domain)) {
                return domain.length + 1;
            }
            else {
                log_warn(domainRequiredForThresholdScale(channel));
                // default threshold boundaries for threshold scale since domain has cardinality of 2
                return 3;
            }
    }
}
/**
 * Returns the linear interpolation of the range according to the cardinality
 *
 * @param rangeMin start of the range
 * @param rangeMax end of the range
 * @param cardinality number of values in the output range
 */
function range_interpolateRange(rangeMin, rangeMax, cardinality) {
    // always return a signal since it's better to compute the sequence in Vega later
    const f = () => {
        const rMax = signalOrStringValue(rangeMax);
        const rMin = signalOrStringValue(rangeMin);
        const step = `(${rMax} - ${rMin}) / (${cardinality} - 1)`;
        return `sequence(${rMin}, ${rMax} + ${step}, ${step})`;
    };
    if (isSignalRef(rangeMax)) {
        return new SignalRefWrapper(f);
    }
    else {
        return { signal: f() };
    }
}
function sizeRangeMin(mark, config) {
    switch (mark) {
        case 'bar':
        case 'tick':
            return config.scale.minBandSize;
        case 'line':
        case 'trail':
        case 'rule':
            return config.scale.minStrokeWidth;
        case 'text':
            return config.scale.minFontSize;
        case 'point':
        case 'square':
        case 'circle':
            return config.scale.minSize;
    }
    /* istanbul ignore next: should never reach here */
    // sizeRangeMin not implemented for the mark
    throw new Error(incompatibleChannel('size', mark));
}
const MAX_SIZE_RANGE_STEP_RATIO = 0.95;
function sizeRangeMax(mark, size, model, config) {
    const xyStepSignals = {
        x: getBinStepSignal(model, 'x'),
        y: getBinStepSignal(model, 'y')
    };
    switch (mark) {
        case 'bar':
        case 'tick': {
            if (config.scale.maxBandSize !== undefined) {
                return config.scale.maxBandSize;
            }
            const min = minXYStep(size, xyStepSignals, config.view);
            if (vega_util_module_isNumber(min)) {
                return min - 1;
            }
            else {
                return new SignalRefWrapper(() => `${min.signal} - 1`);
            }
        }
        case 'line':
        case 'trail':
        case 'rule':
            return config.scale.maxStrokeWidth;
        case 'text':
            return config.scale.maxFontSize;
        case 'point':
        case 'square':
        case 'circle': {
            if (config.scale.maxSize) {
                return config.scale.maxSize;
            }
            const pointStep = minXYStep(size, xyStepSignals, config.view);
            if (vega_util_module_isNumber(pointStep)) {
                return Math.pow(MAX_SIZE_RANGE_STEP_RATIO * pointStep, 2);
            }
            else {
                return new SignalRefWrapper(() => `pow(${MAX_SIZE_RANGE_STEP_RATIO} * ${pointStep.signal}, 2)`);
            }
        }
    }
    /* istanbul ignore next: should never reach here */
    // sizeRangeMax not implemented for the mark
    throw new Error(incompatibleChannel('size', mark));
}
/**
 * @returns {number} Range step of x or y or minimum between the two if both are ordinal scale.
 */
function minXYStep(size, xyStepSignals, viewConfig) {
    const widthStep = isStep(size.width) ? size.width.step : getViewConfigDiscreteStep(viewConfig, 'width');
    const heightStep = isStep(size.height) ? size.height.step : getViewConfigDiscreteStep(viewConfig, 'height');
    if (xyStepSignals.x || xyStepSignals.y) {
        return new SignalRefWrapper(() => {
            const exprs = [
                xyStepSignals.x ? xyStepSignals.x.signal : widthStep,
                xyStepSignals.y ? xyStepSignals.y.signal : heightStep
            ];
            return `min(${exprs.join(', ')})`;
        });
    }
    return Math.min(widthStep, heightStep);
}
//# sourceMappingURL=range.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/properties.js
















function parseScaleProperty(model, property) {
    if (isUnitModel(model)) {
        parseUnitScaleProperty(model, property);
    }
    else {
        parseNonUnitScaleProperty(model, property);
    }
}
function parseUnitScaleProperty(model, property) {
    const localScaleComponents = model.component.scales;
    const { config, encoding, markDef, specifiedScales } = model;
    for (const channel of util_keys(localScaleComponents)) {
        const specifiedScale = specifiedScales[channel];
        const localScaleCmpt = localScaleComponents[channel];
        const mergedScaleCmpt = model.getScaleComponent(channel);
        const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]);
        const specifiedValue = specifiedScale[property];
        const scaleType = mergedScaleCmpt.get('type');
        const scalePadding = mergedScaleCmpt.get('padding');
        const scalePaddingInner = mergedScaleCmpt.get('paddingInner');
        const supportedByScaleType = scaleTypeSupportProperty(scaleType, property);
        const channelIncompatability = channelScalePropertyIncompatability(channel, property);
        if (specifiedValue !== undefined) {
            // If there is a specified value, check if it is compatible with scale type and channel
            if (!supportedByScaleType) {
                log_warn(scalePropertyNotWorkWithScaleType(scaleType, property, channel));
            }
            else if (channelIncompatability) {
                // channel
                log_warn(channelIncompatability);
            }
        }
        if (supportedByScaleType && channelIncompatability === undefined) {
            if (specifiedValue !== undefined) {
                const timeUnit = fieldOrDatumDef.timeUnit;
                const type = fieldOrDatumDef.type;
                switch (property) {
                    // domainMax/Min to signal if the value is a datetime object
                    case 'domainMax':
                    case 'domainMin':
                        if (isDateTime(specifiedScale[property]) || type === 'temporal' || timeUnit) {
                            localScaleCmpt.set(property, { signal: valueExpr(specifiedScale[property], { type, timeUnit }) }, true);
                        }
                        else {
                            localScaleCmpt.set(property, specifiedScale[property], true);
                        }
                        break;
                    default:
                        localScaleCmpt.copyKeyFromObject(property, specifiedScale);
                }
            }
            else {
                const value = util_hasProperty(scaleRules, property)
                    ? scaleRules[property]({
                        model,
                        channel,
                        fieldOrDatumDef,
                        scaleType,
                        scalePadding,
                        scalePaddingInner,
                        domain: specifiedScale.domain,
                        domainMin: specifiedScale.domainMin,
                        domainMax: specifiedScale.domainMax,
                        markDef,
                        config,
                        hasNestedOffsetScale: channelHasNestedOffsetScale(encoding, channel),
                        hasSecondaryRangeChannel: !!encoding[getSecondaryRangeChannel(channel)]
                    })
                    : config.scale[property];
                if (value !== undefined) {
                    localScaleCmpt.set(property, value, false);
                }
            }
        }
    }
}
const scaleRules = {
    bins: ({ model, fieldOrDatumDef }) => (isFieldDef(fieldOrDatumDef) ? properties_bins(model, fieldOrDatumDef) : undefined),
    interpolate: ({ channel, fieldOrDatumDef }) => properties_interpolate(channel, fieldOrDatumDef.type),
    nice: ({ scaleType, channel, domain, domainMin, domainMax, fieldOrDatumDef }) => properties_nice(scaleType, channel, domain, domainMin, domainMax, fieldOrDatumDef),
    padding: ({ channel, scaleType, fieldOrDatumDef, markDef, config }) => properties_padding(channel, scaleType, config.scale, fieldOrDatumDef, markDef, config.bar),
    paddingInner: ({ scalePadding, channel, markDef, scaleType, config, hasNestedOffsetScale }) => paddingInner(scalePadding, channel, markDef.type, scaleType, config.scale, hasNestedOffsetScale),
    paddingOuter: ({ scalePadding, channel, scaleType, scalePaddingInner, config, hasNestedOffsetScale }) => paddingOuter(scalePadding, channel, scaleType, scalePaddingInner, config.scale, hasNestedOffsetScale),
    reverse: ({ fieldOrDatumDef, scaleType, channel, config }) => {
        const sort = isFieldDef(fieldOrDatumDef) ? fieldOrDatumDef.sort : undefined;
        return properties_reverse(scaleType, sort, channel, config.scale);
    },
    zero: ({ channel, fieldOrDatumDef, domain, markDef, scaleType, config, hasSecondaryRangeChannel }) => properties_zero(channel, fieldOrDatumDef, domain, markDef, scaleType, config.scale, hasSecondaryRangeChannel)
};
// This method is here rather than in range.ts to avoid circular dependency.
function properties_parseScaleRange(model) {
    if (isUnitModel(model)) {
        parseUnitScaleRange(model);
    }
    else {
        parseNonUnitScaleProperty(model, 'range');
    }
}
function parseNonUnitScaleProperty(model, property) {
    const localScaleComponents = model.component.scales;
    for (const child of model.children) {
        if (property === 'range') {
            properties_parseScaleRange(child);
        }
        else {
            parseScaleProperty(child, property);
        }
    }
    for (const channel of util_keys(localScaleComponents)) {
        let valueWithExplicit;
        for (const child of model.children) {
            const childComponent = child.component.scales[channel];
            if (childComponent) {
                const childValueWithExplicit = childComponent.getWithExplicit(property);
                valueWithExplicit = mergeValuesWithExplicit(valueWithExplicit, childValueWithExplicit, property, 'scale', tieBreakByComparing((v1, v2) => {
                    switch (property) {
                        case 'range':
                            // For step, prefer larger step
                            if (v1.step && v2.step) {
                                return v1.step - v2.step;
                            }
                            return 0;
                        // TODO: precedence rule for other properties
                    }
                    return 0;
                }));
            }
        }
        localScaleComponents[channel].setWithExplicit(property, valueWithExplicit);
    }
}
function properties_bins(model, fieldDef) {
    const bin = fieldDef.bin;
    if (isBinning(bin)) {
        const binSignal = getBinSignalName(model, fieldDef.field, bin);
        return new SignalRefWrapper(() => {
            return model.getSignalName(binSignal);
        });
    }
    else if (isBinned(bin) && isBinParams(bin) && bin.step !== undefined) {
        // start and stop will be determined from the scale domain
        return {
            step: bin.step
        };
    }
    return undefined;
}
function properties_interpolate(channel, type) {
    if (util_contains([COLOR, FILL, STROKE], channel) && type !== 'nominal') {
        return 'hcl';
    }
    return undefined;
}
function properties_nice(scaleType, channel, specifiedDomain, domainMin, domainMax, fieldOrDatumDef) {
    if (getFieldDef(fieldOrDatumDef)?.bin ||
        vega_util_module_isArray(specifiedDomain) ||
        domainMax != null ||
        domainMin != null ||
        util_contains([ScaleType.TIME, ScaleType.UTC], scaleType)) {
        return undefined;
    }
    return isXorY(channel) ? true : undefined;
}
function properties_padding(channel, scaleType, scaleConfig, fieldOrDatumDef, markDef, barConfig) {
    if (isXorY(channel)) {
        if (isContinuousToContinuous(scaleType)) {
            if (scaleConfig.continuousPadding !== undefined) {
                return scaleConfig.continuousPadding;
            }
            const { type, orient } = markDef;
            if (type === 'bar' && !(isFieldDef(fieldOrDatumDef) && (fieldOrDatumDef.bin || fieldOrDatumDef.timeUnit))) {
                if ((orient === 'vertical' && channel === 'x') || (orient === 'horizontal' && channel === 'y')) {
                    return barConfig.continuousBandSize;
                }
            }
        }
        if (scaleType === ScaleType.POINT) {
            return scaleConfig.pointPadding;
        }
    }
    return undefined;
}
function paddingInner(paddingValue, channel, mark, scaleType, scaleConfig, hasNestedOffsetScale = false) {
    if (paddingValue !== undefined) {
        // If user has already manually specified "padding", no need to add default paddingInner.
        return undefined;
    }
    if (isXorY(channel)) {
        // Padding is only set for X and Y by default.
        // Basically it doesn't make sense to add padding for color and size.
        // paddingOuter would only be called if it's a band scale, just return the default for bandScale.
        const { bandPaddingInner, barBandPaddingInner, rectBandPaddingInner, tickBandPaddingInner, bandWithNestedOffsetPaddingInner } = scaleConfig;
        if (hasNestedOffsetScale) {
            return bandWithNestedOffsetPaddingInner;
        }
        return getFirstDefined(bandPaddingInner, mark === 'bar' ? barBandPaddingInner : mark === 'tick' ? tickBandPaddingInner : rectBandPaddingInner);
    }
    else if (isXorYOffset(channel)) {
        if (scaleType === ScaleType.BAND) {
            return scaleConfig.offsetBandPaddingInner;
        }
    }
    return undefined;
}
function paddingOuter(paddingValue, channel, scaleType, paddingInnerValue, scaleConfig, hasNestedOffsetScale = false) {
    if (paddingValue !== undefined) {
        // If user has already manually specified "padding", no need to add default paddingOuter.
        return undefined;
    }
    if (isXorY(channel)) {
        const { bandPaddingOuter, bandWithNestedOffsetPaddingOuter } = scaleConfig;
        if (hasNestedOffsetScale) {
            return bandWithNestedOffsetPaddingOuter;
        }
        // Padding is only set for X and Y by default.
        // Basically it doesn't make sense to add padding for color and size.
        if (scaleType === ScaleType.BAND) {
            return getFirstDefined(bandPaddingOuter, 
            /* By default, paddingOuter is paddingInner / 2. The reason is that
              size (width/height) = step * (cardinality - paddingInner + 2 * paddingOuter).
              and we want the width/height to be integer by default.
              Note that step (by default) and cardinality are integers.) */
            isSignalRef(paddingInnerValue) ? { signal: `${paddingInnerValue.signal}/2` } : paddingInnerValue / 2);
        }
    }
    else if (isXorYOffset(channel)) {
        if (scaleType === ScaleType.POINT) {
            return 0.5; // so the point positions align with centers of band scales.
        }
        else if (scaleType === ScaleType.BAND) {
            return scaleConfig.offsetBandPaddingOuter;
        }
    }
    return undefined;
}
function properties_reverse(scaleType, sort, channel, scaleConfig) {
    if (channel === 'x' && scaleConfig.xReverse !== undefined) {
        if (hasContinuousDomain(scaleType) && sort === 'descending') {
            if (isSignalRef(scaleConfig.xReverse)) {
                return { signal: `!${scaleConfig.xReverse.signal}` };
            }
            else {
                return !scaleConfig.xReverse;
            }
        }
        return scaleConfig.xReverse;
    }
    if (hasContinuousDomain(scaleType) && sort === 'descending') {
        // For continuous domain scales, Vega does not support domain sort.
        // Thus, we reverse range instead if sort is descending
        return true;
    }
    return undefined;
}
function properties_zero(channel, fieldDef, specifiedDomain, markDef, scaleType, scaleConfig, hasSecondaryRangeChannel) {
    // If users explicitly provide a domain, we should not augment zero as that will be unexpected.
    const hasCustomDomain = !!specifiedDomain && specifiedDomain !== 'unaggregated';
    if (hasCustomDomain) {
        if (hasContinuousDomain(scaleType)) {
            if (vega_util_module_isArray(specifiedDomain)) {
                const first = specifiedDomain[0];
                const last = specifiedDomain[specifiedDomain.length - 1];
                if (vega_util_module_isNumber(first) && first <= 0 && vega_util_module_isNumber(last) && last >= 0) {
                    // if the domain includes zero, make zero remain true
                    return true;
                }
            }
            return false;
        }
    }
    // If there is no custom domain, return configZero value (=`true` as default) only for the following cases:
    // 1) using quantitative field with size
    // While this can be either ratio or interval fields, our assumption is that
    // ratio are more common. However, if the scaleType is discretizing scale, we want to return
    // false so that range doesn't start at zero
    if (channel === 'size' && fieldDef.type === 'quantitative' && !isContinuousToDiscrete(scaleType)) {
        return true;
    }
    // 2) non-binned, quantitative x-scale or y-scale
    // (For binning, we should not include zero by default because binning are calculated without zero.)
    // (For area/bar charts with ratio scale chart, we should always include zero.)
    if (!(isFieldDef(fieldDef) && fieldDef.bin) &&
        util_contains([...POSITION_SCALE_CHANNELS, ...POLAR_POSITION_SCALE_CHANNELS], channel)) {
        const { orient, type } = markDef;
        if (util_contains(['bar', 'area', 'line', 'trail'], type)) {
            if ((orient === 'horizontal' && channel === 'y') || (orient === 'vertical' && channel === 'x')) {
                return false;
            }
        }
        if (util_contains(['bar', 'area'], type) && !hasSecondaryRangeChannel) {
            return true;
        }
        return scaleConfig?.zero;
    }
    return false;
}
//# sourceMappingURL=properties.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/type.js









/**
 * Determine if there is a specified scale type and if it is appropriate,
 * or determine default type if type is unspecified or inappropriate.
 */
// NOTE: CompassQL uses this method.
function scaleType(specifiedScale, channel, fieldDef, mark, hasNestedOffsetScale = false) {
    const defaultScaleType = type_defaultType(channel, fieldDef, mark, hasNestedOffsetScale);
    const { type } = specifiedScale;
    if (!isScaleChannel(channel)) {
        // There is no scale for these channels
        return null;
    }
    if (type !== undefined) {
        // Check if explicitly specified scale type is supported by the channel
        if (!channelSupportScaleType(channel, type)) {
            log_warn(scaleTypeNotWorkWithChannel(channel, type, defaultScaleType));
            return defaultScaleType;
        }
        // Check if explicitly specified scale type is supported by the data type
        if (isFieldDef(fieldDef) && !scaleTypeSupportDataType(type, fieldDef.type)) {
            log_warn(scaleTypeNotWorkWithFieldDef(type, defaultScaleType));
            return defaultScaleType;
        }
        return type;
    }
    return defaultScaleType;
}
/**
 * Determine appropriate default scale type.
 */
// NOTE: Voyager uses this method.
function type_defaultType(channel, fieldDef, mark, hasNestedOffsetScale) {
    switch (fieldDef.type) {
        case 'nominal':
        case 'ordinal': {
            if (isColorChannel(channel) || rangeType(channel) === 'discrete') {
                if (channel === 'shape' && fieldDef.type === 'ordinal') {
                    log_warn(discreteChannelCannotEncode(channel, 'ordinal'));
                }
                return 'ordinal';
            }
            if (isTime(channel)) {
                return 'band';
            }
            if (isXorY(channel) || isXorYOffset(channel)) {
                if (util_contains(['rect', 'bar', 'image', 'rule', 'tick'], mark.type)) {
                    // The rect/bar/tick mark should fit into a band.
                    // For rule, using band scale to make rule align with axis ticks better https://github.com/vega/vega-lite/issues/3429
                    return 'band';
                }
                if (hasNestedOffsetScale) {
                    // If there is a nested offset scale, then there is a "band" for the span of the nested scale.
                    return 'band';
                }
            }
            else if (mark.type === 'arc' && channel in POLAR_POSITION_SCALE_CHANNEL_INDEX) {
                return 'band';
            }
            const dimensionSize = mark[getSizeChannel(channel)];
            if (isRelativeBandSize(dimensionSize)) {
                return 'band';
            }
            if (isPositionFieldOrDatumDef(fieldDef) && fieldDef.axis?.tickBand) {
                return 'band';
            }
            // Otherwise, use ordinal point scale so we can easily get center positions of the marks.
            return 'point';
        }
        case 'temporal':
            if (isColorChannel(channel)) {
                return 'time';
            }
            else if (rangeType(channel) === 'discrete') {
                log_warn(discreteChannelCannotEncode(channel, 'temporal'));
                // TODO: consider using quantize (equivalent to binning) once we have it
                return 'ordinal';
            }
            else if (isFieldDef(fieldDef) && fieldDef.timeUnit && normalizeTimeUnit(fieldDef.timeUnit).utc) {
                return 'utc';
            }
            else if (isTime(channel)) {
                // return 'linear';
                return 'band'; // TODO(jzong): when interpolation is implemented, this should be 'linear'
            }
            return 'time';
        case 'quantitative':
            if (isColorChannel(channel)) {
                if (isFieldDef(fieldDef) && isBinning(fieldDef.bin)) {
                    return 'bin-ordinal';
                }
                return 'linear';
            }
            else if (rangeType(channel) === 'discrete') {
                log_warn(discreteChannelCannotEncode(channel, 'quantitative'));
                // TODO: consider using quantize (equivalent to binning) once we have it
                return 'ordinal';
            }
            else if (isTime(channel)) {
                // return 'linear';
                return 'band'; // TODO(jzong): when interpolation is implemented, this should be 'linear'
            }
            return 'linear';
        case 'geojson':
            return undefined;
    }
    /* istanbul ignore next: should never reach this */
    throw new Error(invalidFieldType(fieldDef.type));
}
//# sourceMappingURL=type.js.map
;// ../../node_modules/vega-lite/build/src/compile/scale/parse.js














function parseScales(model, { ignoreRange } = {}) {
    parseScaleCore(model);
    domain_parseScaleDomain(model);
    for (const prop of NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES) {
        parseScaleProperty(model, prop);
    }
    if (!ignoreRange) {
        // range depends on zero
        properties_parseScaleRange(model);
    }
}
function parseScaleCore(model) {
    if (isUnitModel(model)) {
        model.component.scales = parseUnitScaleCore(model);
    }
    else {
        model.component.scales = parseNonUnitScaleCore(model);
    }
}
/**
 * Parse scales for all channels of a model.
 */
function parseUnitScaleCore(model) {
    const { encoding, mark, markDef } = model;
    const scaleComponents = {};
    for (const channel of SCALE_CHANNELS) {
        const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]); // must be typed def to have scale
        // Don't generate scale for shape of geoshape
        if (fieldOrDatumDef && mark === GEOSHAPE && channel === SHAPE && fieldOrDatumDef.type === GEOJSON) {
            continue;
        }
        let specifiedScale = fieldOrDatumDef && fieldOrDatumDef.scale;
        if (fieldOrDatumDef && specifiedScale !== null && specifiedScale !== false) {
            specifiedScale ?? (specifiedScale = {});
            const hasNestedOffsetScale = channelHasNestedOffsetScale(encoding, channel);
            const sType = scaleType(specifiedScale, channel, fieldOrDatumDef, markDef, hasNestedOffsetScale);
            scaleComponents[channel] = new ScaleComponent(model.scaleName(`${channel}`, true), {
                value: sType,
                explicit: specifiedScale.type === sType
            });
        }
    }
    return scaleComponents;
}
const scaleTypeTieBreaker = tieBreakByComparing((st1, st2) => scaleTypePrecedence(st1) - scaleTypePrecedence(st2));
function parseNonUnitScaleCore(model) {
    var _a;
    const scaleComponents = (model.component.scales = {});
    const scaleTypeWithExplicitIndex = {};
    const resolve = model.component.resolve;
    // Parse each child scale and determine if a particular channel can be merged.
    for (const child of model.children) {
        parseScaleCore(child);
        // Instead of always merging right away -- check if it is compatible to merge first!
        for (const channel of util_keys(child.component.scales)) {
            // if resolve is undefined, set default first
            (_a = resolve.scale)[channel] ?? (_a[channel] = defaultScaleResolve(channel, model));
            if (resolve.scale[channel] === 'shared') {
                const explicitScaleType = scaleTypeWithExplicitIndex[channel];
                const childScaleType = child.component.scales[channel].getWithExplicit('type');
                if (explicitScaleType) {
                    if (scaleCompatible(explicitScaleType.value, childScaleType.value)) {
                        // merge scale component if type are compatible
                        scaleTypeWithExplicitIndex[channel] = mergeValuesWithExplicit(explicitScaleType, childScaleType, 'type', 'scale', scaleTypeTieBreaker);
                    }
                    else {
                        // Otherwise, update conflicting channel to be independent
                        resolve.scale[channel] = 'independent';
                        // Remove from the index so they don't get merged
                        delete scaleTypeWithExplicitIndex[channel];
                    }
                }
                else {
                    scaleTypeWithExplicitIndex[channel] = childScaleType;
                }
            }
        }
    }
    // Merge each channel listed in the index
    for (const channel of util_keys(scaleTypeWithExplicitIndex)) {
        // Create new merged scale component
        const name = model.scaleName(channel, true);
        const typeWithExplicit = scaleTypeWithExplicitIndex[channel];
        scaleComponents[channel] = new ScaleComponent(name, typeWithExplicit);
        // rename each child and mark them as merged
        for (const child of model.children) {
            const childScale = child.component.scales[channel];
            if (childScale) {
                child.renameScale(childScale.get('name'), name);
                childScale.merged = true;
            }
        }
    }
    return scaleComponents;
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/model.js



























class NameMap {
    constructor() {
        this.nameMap = {};
    }
    rename(oldName, newName) {
        this.nameMap[oldName] = newName;
    }
    has(name) {
        return this.nameMap[name] !== undefined;
    }
    get(name) {
        // If the name appears in the _nameMap, we need to read its new name.
        // We have to loop over the dict just in case the new name also gets renamed.
        while (this.nameMap[name] && name !== this.nameMap[name]) {
            name = this.nameMap[name];
        }
        return name;
    }
}
/*
  We use type guards instead of `instanceof` as `instanceof` makes
  different parts of the compiler depend on the actual implementation of
  the model classes, which in turn depend on different parts of the compiler.
  Thus, `instanceof` leads to circular dependency problems.

  On the other hand, type guards only make different parts of the compiler
  depend on the type of the model classes, but not the actual implementation.
*/
function isUnitModel(model) {
    return model?.type === 'unit';
}
function isFacetModel(model) {
    return model?.type === 'facet';
}
function isConcatModel(model) {
    return model?.type === 'concat';
}
function isLayerModel(model) {
    return model?.type === 'layer';
}
class Model {
    constructor(spec, type, parent, parentGivenName, config, resolve, view) {
        this.type = type;
        this.parent = parent;
        this.config = config;
        this.parent = parent;
        this.config = config;
        this.view = replaceExprRef(view);
        // If name is not provided, always use parent's givenName to avoid name conflicts.
        this.name = spec.name ?? parentGivenName;
        this.title = isText(spec.title) ? { text: spec.title } : spec.title ? replaceExprRef(spec.title) : undefined;
        // Shared name maps
        this.scaleNameMap = parent ? parent.scaleNameMap : new NameMap();
        this.projectionNameMap = parent ? parent.projectionNameMap : new NameMap();
        this.signalNameMap = parent ? parent.signalNameMap : new NameMap();
        this.data = spec.data;
        this.description = spec.description;
        this.transforms = normalizeTransform(spec.transform ?? []);
        this.layout = type === 'layer' || type === 'unit' ? {} : extractCompositionLayout(spec, type, config);
        this.component = {
            data: {
                sources: parent ? parent.component.data.sources : [],
                outputNodes: parent ? parent.component.data.outputNodes : {},
                outputNodeRefCounts: parent ? parent.component.data.outputNodeRefCounts : {},
                // data is faceted if the spec is a facet spec or the parent has faceted data and data is undefined
                isFaceted: isFacetSpec(spec) || (parent?.component.data.isFaceted && spec.data === undefined)
            },
            layoutSize: new Split(),
            layoutHeaders: { row: {}, column: {}, facet: {} },
            mark: null,
            resolve: {
                scale: {},
                axis: {},
                legend: {},
                ...(resolve ? duplicate(resolve) : {})
            },
            selection: null,
            scales: null,
            projection: null,
            axes: {},
            legends: {}
        };
    }
    get width() {
        return this.getSizeSignalRef('width');
    }
    get height() {
        return this.getSizeSignalRef('height');
    }
    parse() {
        this.parseScale();
        this.parseLayoutSize(); // depends on scale
        this.renameTopLevelLayoutSizeSignal();
        this.parseSelections();
        this.parseProjection();
        this.parseData(); // (pathorder) depends on markDef; selection filters depend on parsed selections; depends on projection because some transforms require the finalized projection name.
        this.parseAxesAndHeaders(); // depends on scale and layout size
        this.parseLegends(); // depends on scale, markDef
        this.parseMarkGroup(); // depends on data name, scale, layout size, axisGroup, and children's scale, axis, legend and mark.
    }
    parseScale() {
        parseScales(this);
    }
    parseProjection() {
        parse_parseProjection(this);
    }
    /**
     * Rename top-level spec's size to be just width / height, ignoring model name.
     * This essentially merges the top-level spec's width/height signals with the width/height signals
     * to help us reduce redundant signals declaration.
     */
    renameTopLevelLayoutSizeSignal() {
        if (this.getName('width') !== 'width') {
            this.renameSignal(this.getName('width'), 'width');
        }
        if (this.getName('height') !== 'height') {
            this.renameSignal(this.getName('height'), 'height');
        }
    }
    parseLegends() {
        parse_parseLegend(this);
    }
    assembleEncodeFromView(view) {
        // Exclude "style"
        const { style: _, ...baseView } = view;
        const e = {};
        for (const property of util_keys(baseView)) {
            const value = baseView[property];
            if (value !== undefined) {
                e[property] = signalOrValueRef(value);
            }
        }
        return e;
    }
    assembleGroupEncodeEntry(isTopLevel) {
        let encodeEntry = {};
        if (this.view) {
            encodeEntry = this.assembleEncodeFromView(this.view);
        }
        if (!isTopLevel) {
            // Descriptions are already added to the top-level description so we only need to add them to the inner views.
            if (this.description) {
                encodeEntry['description'] = signalOrValueRef(this.description);
            }
            // For top-level spec, we can set the global width and height signal to adjust the group size.
            // For other child specs, we have to manually set width and height in the encode entry.
            if (this.type === 'unit' || this.type === 'layer') {
                return {
                    width: this.getSizeSignalRef('width'),
                    height: this.getSizeSignalRef('height'),
                    ...encodeEntry
                };
            }
        }
        return isEmpty(encodeEntry) ? undefined : encodeEntry;
    }
    assembleLayout() {
        if (!this.layout) {
            return undefined;
        }
        const { spacing, ...layout } = this.layout;
        const { component, config } = this;
        const titleBand = assembleLayoutTitleBand(component.layoutHeaders, config);
        return {
            padding: spacing,
            ...this.assembleDefaultLayout(),
            ...layout,
            ...(titleBand ? { titleBand } : {})
        };
    }
    assembleDefaultLayout() {
        return {};
    }
    assembleHeaderMarks() {
        const { layoutHeaders } = this.component;
        let headerMarks = [];
        for (const channel of FACET_CHANNELS) {
            if (layoutHeaders[channel].title) {
                headerMarks.push(assembleTitleGroup(this, channel));
            }
        }
        for (const channel of HEADER_CHANNELS) {
            headerMarks = headerMarks.concat(assembleHeaderGroups(this, channel));
        }
        return headerMarks;
    }
    assembleAxes() {
        return assembleAxes(this.component.axes, this.config);
    }
    assembleLegends() {
        return assembleLegends(this);
    }
    assembleProjections() {
        return assembleProjections(this);
    }
    assembleTitle() {
        const { encoding, ...titleNoEncoding } = this.title ?? {};
        const title = {
            ...extractTitleConfig(this.config.title).nonMarkTitleProperties,
            ...titleNoEncoding,
            ...(encoding ? { encode: { update: encoding } } : {})
        };
        if (title.text) {
            if (util_contains(['unit', 'layer'], this.type)) {
                // Unit/Layer
                if (util_contains(['middle', undefined], title.anchor)) {
                    title.frame ?? (title.frame = 'group');
                }
            }
            else {
                // composition with Vega layout
                // Set title = "start" by default for composition as "middle" does not look nice
                // https://github.com/vega/vega/issues/960#issuecomment-471360328
                title.anchor ?? (title.anchor = 'start');
            }
            return isEmpty(title) ? undefined : title;
        }
        return undefined;
    }
    /**
     * Assemble the mark group for this model. We accept optional `signals` so that we can include concat top-level signals with the top-level model's local signals.
     */
    assembleGroup(signals = []) {
        const group = {};
        signals = signals.concat(this.assembleSignals());
        if (signals.length > 0) {
            group.signals = signals;
        }
        const layout = this.assembleLayout();
        if (layout) {
            group.layout = layout;
        }
        group.marks = [].concat(this.assembleHeaderMarks(), this.assembleMarks());
        // Only include scales if this spec is top-level or if parent is facet.
        // (Otherwise, it will be merged with upper-level's scope.)
        const scales = !this.parent || isFacetModel(this.parent) ? assembleScales(this) : [];
        if (scales.length > 0) {
            group.scales = scales;
        }
        const axes = this.assembleAxes();
        if (axes.length > 0) {
            group.axes = axes;
        }
        const legends = this.assembleLegends();
        if (legends.length > 0) {
            group.legends = legends;
        }
        return group;
    }
    getName(text) {
        return varName((this.name ? `${this.name}_` : '') + text);
    }
    getDataName(type) {
        return this.getName(DataSourceType[type].toLowerCase());
    }
    /**
     * Request a data source name for the given data source type and mark that data source as required.
     * This method should be called in parse, so that all used data source can be correctly instantiated in assembleData().
     * You can lookup the correct dataset name in assemble with `lookupDataSource`.
     */
    requestDataName(name) {
        const fullName = this.getDataName(name);
        // Increase ref count. This is critical because otherwise we won't create a data source.
        // We also increase the ref counts on OutputNode.getSource() calls.
        const refCounts = this.component.data.outputNodeRefCounts;
        refCounts[fullName] = (refCounts[fullName] || 0) + 1;
        return fullName;
    }
    getSizeSignalRef(layoutSizeType) {
        if (isFacetModel(this.parent)) {
            const sizeType = getSizeTypeFromLayoutSizeType(layoutSizeType);
            const channel = getPositionScaleChannel(sizeType);
            const scaleComponent = this.component.scales[channel];
            if (scaleComponent && !scaleComponent.merged) {
                // independent scale
                const type = scaleComponent.get('type');
                const range = scaleComponent.get('range');
                if (hasDiscreteDomain(type) && isVgRangeStep(range)) {
                    const scaleName = scaleComponent.get('name');
                    const domain = assembleDomain(this, channel);
                    const field = getFieldFromDomain(domain);
                    if (field) {
                        const fieldRef = vgField({ aggregate: 'distinct', field }, { expr: 'datum' });
                        return {
                            signal: sizeExpr(scaleName, scaleComponent, fieldRef)
                        };
                    }
                    else {
                        log_warn(unknownField(channel));
                        return null;
                    }
                }
            }
        }
        return {
            signal: this.signalNameMap.get(this.getName(layoutSizeType))
        };
    }
    /**
     * Lookup the name of the datasource for an output node. You probably want to call this in assemble.
     */
    lookupDataSource(name) {
        const node = this.component.data.outputNodes[name];
        if (!node) {
            // Name not found in map so let's just return what we got.
            // This can happen if we already have the correct name.
            return name;
        }
        return node.getSource();
    }
    getSignalName(oldSignalName) {
        return this.signalNameMap.get(oldSignalName);
    }
    renameSignal(oldName, newName) {
        this.signalNameMap.rename(oldName, newName);
    }
    renameScale(oldName, newName) {
        this.scaleNameMap.rename(oldName, newName);
    }
    renameProjection(oldName, newName) {
        this.projectionNameMap.rename(oldName, newName);
    }
    /**
     * @return scale name for a given channel after the scale has been parsed and named.
     */
    scaleName(originalScaleName, parse) {
        if (parse) {
            // During the parse phase always return a value
            // No need to refer to rename map because a scale can't be renamed
            // before it has the original name.
            return this.getName(originalScaleName);
        }
        // If there is a scale for the channel, it should either
        // be in the scale component or exist in the name map
        if (
        // If there is a scale for the channel, there should be a local scale component for it
        (isChannel(originalScaleName) && isScaleChannel(originalScaleName) && this.component.scales[originalScaleName]) ||
            // in the scale name map (the scale get merged by its parent)
            this.scaleNameMap.has(this.getName(originalScaleName))) {
            return this.scaleNameMap.get(this.getName(originalScaleName));
        }
        return undefined;
    }
    /**
     * @return projection name after the projection has been parsed and named.
     */
    projectionName(parse) {
        if (parse) {
            // During the parse phase always return a value
            // No need to refer to rename map because a projection can't be renamed
            // before it has the original name.
            return this.getName('projection');
        }
        if ((this.component.projection && !this.component.projection.merged) ||
            this.projectionNameMap.has(this.getName('projection'))) {
            return this.projectionNameMap.get(this.getName('projection'));
        }
        return undefined;
    }
    /**
     * Traverse a model's hierarchy to get the scale component for a particular channel.
     */
    getScaleComponent(channel) {
        /* istanbul ignore next: This is warning for debugging test */
        if (!this.component.scales) {
            throw new Error('getScaleComponent cannot be called before parseScale(). Make sure you have called parseScale or use parseUnitModelWithScale().');
        }
        const localScaleComponent = this.component.scales[channel];
        if (localScaleComponent && !localScaleComponent.merged) {
            return localScaleComponent;
        }
        return this.parent ? this.parent.getScaleComponent(channel) : undefined;
    }
    getScaleType(channel) {
        const scaleComponent = this.getScaleComponent(channel);
        return scaleComponent ? scaleComponent.get('type') : undefined;
    }
    /**
     * Traverse a model's hierarchy to get a particular selection component.
     */
    getSelectionComponent(variableName, origName) {
        let sel = this.component.selection[variableName];
        if (!sel && this.parent) {
            sel = this.parent.getSelectionComponent(variableName, origName);
        }
        if (!sel) {
            throw new Error(selectionNotFound(origName));
        }
        return sel;
    }
    /**
     * Returns true if the model has a signalRef for an axis orient.
     */
    hasAxisOrientSignalRef() {
        return (this.component.axes.x?.some(a => a.hasOrientSignalRef()) ||
            this.component.axes.y?.some(a => a.hasOrientSignalRef()));
    }
}
/** Abstract class for UnitModel and FacetModel. Both of which can contain fieldDefs as a part of its own specification. */
class ModelWithField extends Model {
    /** Get "field" reference for Vega */
    vgField(channel, opt = {}) {
        const fieldDef = this.fieldDef(channel);
        if (!fieldDef) {
            return undefined;
        }
        return vgField(fieldDef, opt);
    }
    reduceFieldDef(f, init) {
        return encoding_reduce(this.getMapping(), (acc, cd, c) => {
            const fieldDef = getFieldDef(cd);
            if (fieldDef) {
                return f(acc, fieldDef, c);
            }
            return acc;
        }, init);
    }
    forEachFieldDef(f, t) {
        forEach(this.getMapping(), (cd, c) => {
            const fieldDef = getFieldDef(cd);
            if (fieldDef) {
                f(fieldDef, c);
            }
        }, t);
    }
}
//# sourceMappingURL=model.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/density.js


/**
 * A class for density transform nodes
 */
class DensityTransformNode extends DataFlowNode {
    clone() {
        return new DensityTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const specifiedAs = this.transform.as ?? [undefined, undefined];
        this.transform.as = [specifiedAs[0] ?? 'value', specifiedAs[1] ?? 'density'];
        const resolve = this.transform.resolve ?? 'shared';
        this.transform.resolve = resolve;
    }
    dependentFields() {
        return new Set([this.transform.density, ...(this.transform.groupby ?? [])]);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `DensityTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { density, ...rest } = this.transform;
        const result = {
            type: 'kde',
            field: density,
            ...rest
        };
        result.resolve = this.transform.resolve;
        return result;
    }
}
//# sourceMappingURL=density.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/extent.js


/**
 * A class for flatten transform nodes
 */
class ExtentTransformNode extends DataFlowNode {
    clone() {
        return new ExtentTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform);
    }
    dependentFields() {
        return new Set([this.transform.extent]);
    }
    producedFields() {
        return new Set([]);
    }
    hash() {
        return `ExtentTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { extent, param } = this.transform;
        const result = {
            type: 'extent',
            field: extent,
            signal: param
        };
        return result;
    }
}
//# sourceMappingURL=extent.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/flatten.js


/**
 * A class for flatten transform nodes
 */
class FlattenTransformNode extends DataFlowNode {
    clone() {
        return new FlattenTransformNode(this.parent, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const { flatten, as = [] } = this.transform;
        this.transform.as = flatten.map((f, i) => as[i] ?? f);
    }
    dependentFields() {
        return new Set(this.transform.flatten);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `FlattenTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { flatten: fields, as } = this.transform;
        const result = {
            type: 'flatten',
            fields,
            as
        };
        return result;
    }
}
//# sourceMappingURL=flatten.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/fold.js


/**
 * A class for flatten transform nodes
 */
class FoldTransformNode extends DataFlowNode {
    clone() {
        return new FoldTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const specifiedAs = this.transform.as ?? [undefined, undefined];
        this.transform.as = [specifiedAs[0] ?? 'key', specifiedAs[1] ?? 'value'];
    }
    dependentFields() {
        return new Set(this.transform.fold);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `FoldTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { fold, as } = this.transform;
        const result = {
            type: 'fold',
            fields: fold,
            as
        };
        return result;
    }
}
//# sourceMappingURL=fold.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/geojson.js






class GeoJSONNode extends DataFlowNode {
    clone() {
        return new GeoJSONNode(null, duplicate(this.fields), this.geojson, this.signal);
    }
    static parseAll(parent, model) {
        if (model.component.projection && !model.component.projection.isFit) {
            return parent;
        }
        let geoJsonCounter = 0;
        for (const coordinates of [
            [LONGITUDE, LATITUDE],
            [LONGITUDE2, LATITUDE2]
        ]) {
            const pair = coordinates.map(channel => {
                const def = getFieldOrDatumDef(model.encoding[channel]);
                return isFieldDef(def)
                    ? def.field
                    : isDatumDef(def)
                        ? { expr: `${def.datum}` }
                        : isValueDef(def)
                            ? { expr: `${def['value']}` }
                            : undefined;
            });
            if (pair[0] || pair[1]) {
                parent = new GeoJSONNode(parent, pair, null, model.getName(`geojson_${geoJsonCounter++}`));
            }
        }
        if (model.channelHasField(SHAPE)) {
            const fieldDef = model.typedFieldDef(SHAPE);
            if (fieldDef.type === GEOJSON) {
                parent = new GeoJSONNode(parent, null, fieldDef.field, model.getName(`geojson_${geoJsonCounter++}`));
            }
        }
        return parent;
    }
    constructor(parent, fields, geojson, signal) {
        super(parent);
        this.fields = fields;
        this.geojson = geojson;
        this.signal = signal;
    }
    dependentFields() {
        const fields = (this.fields ?? []).filter(vega_util_module_isString);
        return new Set([...(this.geojson ? [this.geojson] : []), ...fields]);
    }
    producedFields() {
        return new Set();
    }
    hash() {
        return `GeoJSON ${this.geojson} ${this.signal} ${util_hash(this.fields)}`;
    }
    assemble() {
        return [
            ...(this.geojson
                ? [
                    {
                        type: 'filter',
                        expr: `isValid(datum["${this.geojson}"])`
                    }
                ]
                : []),
            {
                type: 'geojson',
                ...(this.fields ? { fields: this.fields } : {}),
                ...(this.geojson ? { geojson: this.geojson } : {}),
                signal: this.signal
            }
        ];
    }
}
//# sourceMappingURL=geojson.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/geopoint.js





class GeoPointNode extends DataFlowNode {
    clone() {
        return new GeoPointNode(null, this.projection, duplicate(this.fields), duplicate(this.as));
    }
    constructor(parent, projection, fields, as) {
        super(parent);
        this.projection = projection;
        this.fields = fields;
        this.as = as;
    }
    static parseAll(parent, model) {
        if (!model.projectionName()) {
            return parent;
        }
        for (const coordinates of [
            [LONGITUDE, LATITUDE],
            [LONGITUDE2, LATITUDE2]
        ]) {
            const pair = coordinates.map(channel => {
                const def = getFieldOrDatumDef(model.encoding[channel]);
                return isFieldDef(def)
                    ? def.field
                    : isDatumDef(def)
                        ? { expr: `${def.datum}` }
                        : isValueDef(def)
                            ? { expr: `${def['value']}` }
                            : undefined;
            });
            const suffix = coordinates[0] === LONGITUDE2 ? '2' : '';
            if (pair[0] || pair[1]) {
                parent = new GeoPointNode(parent, model.projectionName(), pair, [
                    model.getName(`x${suffix}`),
                    model.getName(`y${suffix}`)
                ]);
            }
        }
        return parent;
    }
    dependentFields() {
        return new Set(this.fields.filter(vega_util_module_isString));
    }
    producedFields() {
        return new Set(this.as);
    }
    hash() {
        return `Geopoint ${this.projection} ${util_hash(this.fields)} ${util_hash(this.as)}`;
    }
    assemble() {
        return {
            type: 'geopoint',
            projection: this.projection,
            fields: this.fields,
            as: this.as
        };
    }
}
//# sourceMappingURL=geopoint.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/impute.js





class ImputeNode extends DataFlowNode {
    clone() {
        return new ImputeNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
    }
    dependentFields() {
        return new Set([this.transform.impute, this.transform.key, ...(this.transform.groupby ?? [])]);
    }
    producedFields() {
        return new Set([this.transform.impute]);
    }
    processSequence(keyvals) {
        const { start = 0, stop, step } = keyvals;
        const result = [start, stop, ...(step ? [step] : [])].join(',');
        return { signal: `sequence(${result})` };
    }
    static makeFromTransform(parent, imputeTransform) {
        return new ImputeNode(parent, imputeTransform);
    }
    static makeFromEncoding(parent, model) {
        const encoding = model.encoding;
        const xDef = encoding.x;
        const yDef = encoding.y;
        if (isFieldDef(xDef) && isFieldDef(yDef)) {
            const imputedChannel = xDef.impute ? xDef : yDef.impute ? yDef : undefined;
            if (imputedChannel === undefined) {
                return undefined;
            }
            const keyChannel = xDef.impute ? yDef : yDef.impute ? xDef : undefined;
            const { method, value, frame, keyvals } = imputedChannel.impute;
            const groupbyFields = pathGroupingFields(model.mark, encoding);
            return new ImputeNode(parent, {
                impute: imputedChannel.field,
                key: keyChannel.field,
                ...(method ? { method } : {}),
                ...(value !== undefined ? { value } : {}),
                ...(frame ? { frame } : {}),
                ...(keyvals !== undefined ? { keyvals } : {}),
                ...(groupbyFields.length ? { groupby: groupbyFields } : {})
            });
        }
        return null;
    }
    hash() {
        return `Impute ${util_hash(this.transform)}`;
    }
    assemble() {
        const { impute, key, keyvals, method, groupby, value, frame = [null, null] } = this.transform;
        const imputeTransform = {
            type: 'impute',
            field: impute,
            key,
            ...(keyvals ? { keyvals: isImputeSequence(keyvals) ? this.processSequence(keyvals) : keyvals } : {}),
            method: 'value',
            ...(groupby ? { groupby } : {}),
            value: !method || method === 'value' ? value : null
        };
        if (method && method !== 'value') {
            const deriveNewField = {
                type: 'window',
                as: [`imputed_${impute}_value`],
                ops: [method],
                fields: [impute],
                frame,
                ignorePeers: false,
                ...(groupby ? { groupby } : {})
            };
            const replaceOriginal = {
                type: 'formula',
                expr: `datum.${impute} === null ? datum.imputed_${impute}_value : datum.${impute}`,
                as: impute
            };
            return [imputeTransform, deriveNewField, replaceOriginal];
        }
        else {
            return [imputeTransform];
        }
    }
}
//# sourceMappingURL=impute.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/loess.js


/**
 * A class for loess transform nodes
 */
class LoessTransformNode extends DataFlowNode {
    clone() {
        return new LoessTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const specifiedAs = this.transform.as ?? [undefined, undefined];
        this.transform.as = [specifiedAs[0] ?? transform.on, specifiedAs[1] ?? transform.loess];
    }
    dependentFields() {
        return new Set([this.transform.loess, this.transform.on, ...(this.transform.groupby ?? [])]);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `LoessTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { loess, on, ...rest } = this.transform;
        const result = {
            type: 'loess',
            x: on,
            y: loess,
            ...rest
        };
        return result;
    }
}
//# sourceMappingURL=loess.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/lookup.js








class LookupNode extends DataFlowNode {
    clone() {
        return new LookupNode(null, duplicate(this.transform), this.secondary);
    }
    constructor(parent, transform, secondary) {
        super(parent);
        this.transform = transform;
        this.secondary = secondary;
    }
    static make(parent, model, transform, counter) {
        const sources = model.component.data.sources;
        const { from } = transform;
        let fromOutputNode = null;
        if (isLookupData(from)) {
            let fromSource = findSource(from.data, sources);
            if (!fromSource) {
                fromSource = new SourceNode(from.data);
                sources.push(fromSource);
            }
            const fromOutputName = model.getName(`lookup_${counter}`);
            fromOutputNode = new OutputNode(fromSource, fromOutputName, DataSourceType.Lookup, model.component.data.outputNodeRefCounts);
            model.component.data.outputNodes[fromOutputName] = fromOutputNode;
        }
        else if (isLookupSelection(from)) {
            const selName = from.param;
            transform = { as: selName, ...transform };
            let selCmpt;
            try {
                selCmpt = model.getSelectionComponent(varName(selName), selName);
            }
            catch (e) {
                throw new Error(cannotLookupVariableParameter(selName));
            }
            fromOutputNode = selCmpt.materialized;
            if (!fromOutputNode) {
                throw new Error(noSameUnitLookup(selName));
            }
        }
        return new LookupNode(parent, transform, fromOutputNode.getSource());
    }
    dependentFields() {
        return new Set([this.transform.lookup]);
    }
    producedFields() {
        return new Set(this.transform.as ? vega_util_module_array(this.transform.as) : this.transform.from.fields);
    }
    hash() {
        return `Lookup ${util_hash({ transform: this.transform, secondary: this.secondary })}`;
    }
    assemble() {
        let foreign;
        if (this.transform.from.fields) {
            // lookup a few fields and add create a flat output
            foreign = {
                values: this.transform.from.fields,
                ...(this.transform.as ? { as: vega_util_module_array(this.transform.as) } : {})
            };
        }
        else {
            // lookup full record and nest it
            let asName = this.transform.as;
            if (!vega_util_module_isString(asName)) {
                log_warn(NO_FIELDS_NEEDS_AS);
                asName = '_lookup';
            }
            foreign = {
                as: [asName]
            };
        }
        return {
            type: 'lookup',
            from: this.secondary,
            key: this.transform.from.key,
            fields: [this.transform.lookup],
            ...foreign,
            ...(this.transform.default ? { default: this.transform.default } : {})
        };
    }
}
//# sourceMappingURL=lookup.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/quantile.js


/**
 * A class for quantile transform nodes
 */
class QuantileTransformNode extends DataFlowNode {
    clone() {
        return new QuantileTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const specifiedAs = this.transform.as ?? [undefined, undefined];
        this.transform.as = [specifiedAs[0] ?? 'prob', specifiedAs[1] ?? 'value'];
    }
    dependentFields() {
        return new Set([this.transform.quantile, ...(this.transform.groupby ?? [])]);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `QuantileTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { quantile, ...rest } = this.transform;
        const result = {
            type: 'quantile',
            field: quantile,
            ...rest
        };
        return result;
    }
}
//# sourceMappingURL=quantile.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/regression.js


/**
 * A class for regression transform nodes
 */
class RegressionTransformNode extends DataFlowNode {
    clone() {
        return new RegressionTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
        this.transform = duplicate(transform); // duplicate to prevent side effects
        const specifiedAs = this.transform.as ?? [undefined, undefined];
        this.transform.as = [specifiedAs[0] ?? transform.on, specifiedAs[1] ?? transform.regression];
    }
    dependentFields() {
        return new Set([this.transform.regression, this.transform.on, ...(this.transform.groupby ?? [])]);
    }
    producedFields() {
        return new Set(this.transform.as);
    }
    hash() {
        return `RegressionTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { regression, on, ...rest } = this.transform;
        const result = {
            type: 'regression',
            x: on,
            y: regression,
            ...rest
        };
        return result;
    }
}
//# sourceMappingURL=regression.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/pivot.js


/**
 * A class for pivot transform nodes.
 */
class PivotTransformNode extends DataFlowNode {
    clone() {
        return new PivotTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
    }
    addDimensions(fields) {
        this.transform.groupby = unique((this.transform.groupby ?? []).concat(fields), d => d);
    }
    producedFields() {
        return undefined; // return undefined so that potentially everything can depend on the pivot
    }
    dependentFields() {
        return new Set([this.transform.pivot, this.transform.value, ...(this.transform.groupby ?? [])]);
    }
    hash() {
        return `PivotTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        const { pivot, value, groupby, limit, op } = this.transform;
        return {
            type: 'pivot',
            field: pivot,
            value,
            ...(limit !== undefined ? { limit } : {}),
            ...(op !== undefined ? { op } : {}),
            ...(groupby !== undefined ? { groupby } : {})
        };
    }
}
//# sourceMappingURL=pivot.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/sample.js


/**
 * A class for the sample transform nodes
 */
class SampleTransformNode extends DataFlowNode {
    clone() {
        return new SampleTransformNode(null, duplicate(this.transform));
    }
    constructor(parent, transform) {
        super(parent);
        this.transform = transform;
    }
    dependentFields() {
        return new Set();
    }
    producedFields() {
        return new Set();
    }
    hash() {
        return `SampleTransform ${util_hash(this.transform)}`;
    }
    assemble() {
        return {
            type: 'sample',
            size: this.transform.sample
        };
    }
}
//# sourceMappingURL=sample.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/assemble.js






























function makeWalkTree(data) {
    // to name datasources
    let datasetIndex = 0;
    /**
     * Recursively walk down the tree.
     */
    function walkTree(node, dataSource) {
        if (node instanceof SourceNode) {
            // If the source is a named data source or a data source with values, we need
            // to put it in a different data source. Otherwise, Vega may override the data.
            if (!node.isGenerator && !isUrlData(node.data)) {
                data.push(dataSource);
                const newData = {
                    name: null,
                    source: dataSource.name,
                    transform: []
                };
                dataSource = newData;
            }
        }
        if (node instanceof ParseNode) {
            if (node.parent instanceof SourceNode && !dataSource.source) {
                // If node's parent is a root source and the data source does not refer to another data source, use normal format parse
                dataSource.format = {
                    ...dataSource.format,
                    parse: node.assembleFormatParse()
                };
                // add calculates for all nested fields
                dataSource.transform.push(...node.assembleTransforms(true));
            }
            else {
                // Otherwise use Vega expression to parse
                dataSource.transform.push(...node.assembleTransforms());
            }
        }
        if (node instanceof FacetNode) {
            if (!dataSource.name) {
                dataSource.name = `data_${datasetIndex++}`;
            }
            if (!dataSource.source || dataSource.transform.length > 0) {
                data.push(dataSource);
                node.data = dataSource.name;
            }
            else {
                node.data = dataSource.source;
            }
            data.push(...node.assemble());
            // break here because the rest of the tree has to be taken care of by the facet.
            return;
        }
        if (node instanceof GraticuleNode ||
            node instanceof SequenceNode ||
            node instanceof FilterInvalidNode ||
            node instanceof FilterNode ||
            node instanceof CalculateNode ||
            node instanceof GeoPointNode ||
            node instanceof AggregateNode ||
            node instanceof LookupNode ||
            node instanceof WindowTransformNode ||
            node instanceof JoinAggregateTransformNode ||
            node instanceof FoldTransformNode ||
            node instanceof FlattenTransformNode ||
            node instanceof DensityTransformNode ||
            node instanceof LoessTransformNode ||
            node instanceof QuantileTransformNode ||
            node instanceof RegressionTransformNode ||
            node instanceof IdentifierNode ||
            node instanceof SampleTransformNode ||
            node instanceof PivotTransformNode ||
            node instanceof ExtentTransformNode) {
            dataSource.transform.push(node.assemble());
        }
        if (node instanceof BinNode ||
            node instanceof TimeUnitNode ||
            node instanceof ImputeNode ||
            node instanceof StackNode ||
            node instanceof GeoJSONNode) {
            dataSource.transform.push(...node.assemble());
        }
        if (node instanceof OutputNode) {
            if (dataSource.source && dataSource.transform.length === 0) {
                node.setSource(dataSource.source);
            }
            else if (node.parent instanceof OutputNode) {
                // Note that an output node may be required but we still do not assemble a
                // separate data source for it.
                node.setSource(dataSource.name);
            }
            else {
                if (!dataSource.name) {
                    dataSource.name = `data_${datasetIndex++}`;
                }
                // Here we set the name of the datasource we generated. From now on
                // other assemblers can use it.
                node.setSource(dataSource.name);
                // if this node has more than one child, we will add a datasource automatically
                if (node.numChildren() === 1) {
                    data.push(dataSource);
                    const newData = {
                        name: null,
                        source: dataSource.name,
                        transform: []
                    };
                    dataSource = newData;
                }
            }
        }
        switch (node.numChildren()) {
            case 0:
                // done
                if (node instanceof OutputNode && (!dataSource.source || dataSource.transform.length > 0)) {
                    // do not push empty datasources that are simply references
                    data.push(dataSource);
                }
                break;
            case 1:
                walkTree(node.children[0], dataSource);
                break;
            default: {
                if (!dataSource.name) {
                    dataSource.name = `data_${datasetIndex++}`;
                }
                let source = dataSource.name;
                if (!dataSource.source || dataSource.transform.length > 0) {
                    data.push(dataSource);
                }
                else {
                    source = dataSource.source;
                }
                for (const child of node.children) {
                    const newData = {
                        name: null,
                        source,
                        transform: []
                    };
                    walkTree(child, newData);
                }
                break;
            }
        }
    }
    return walkTree;
}
/**
 * Assemble data sources that are derived from faceted data.
 */
function assembleFacetData(root) {
    const data = [];
    const walkTree = makeWalkTree(data);
    for (const child of root.children) {
        walkTree(child, {
            source: root.name,
            name: null,
            transform: []
        });
    }
    return data;
}
/**
 * Create Vega data array from a given compiled model and append all of them to the given array
 *
 * @param  model
 * @param  data array
 * @return modified data array
 */
function assembleRootData(dataComponent, datasets) {
    const data = [];
    // dataComponent.sources.forEach(debug);
    // draw(dataComponent.sources);
    const walkTree = makeWalkTree(data);
    let sourceIndex = 0;
    for (const root of dataComponent.sources) {
        // assign a name if the source does not have a name yet
        if (!root.hasName()) {
            root.dataName = `source_${sourceIndex++}`;
        }
        const newData = root.assemble();
        walkTree(root, newData);
    }
    // remove empty transform arrays for cleaner output
    for (const d of data) {
        if (d.transform.length === 0) {
            delete d.transform;
        }
    }
    // move sources without transforms (the ones that are potentially used in lookups) to the beginning
    let whereTo = 0;
    for (const [i, d] of data.entries()) {
        if ((d.transform ?? []).length === 0 && !d.source) {
            data.splice(whereTo++, 0, data.splice(i, 1)[0]);
        }
    }
    // now fix the from references in lookup transforms
    for (const d of data) {
        for (const t of d.transform ?? []) {
            if (t.type === 'lookup') {
                t.from = dataComponent.outputNodes[t.from].getSource();
            }
        }
    }
    // inline values for datasets that are in the datastore
    for (const d of data) {
        if (d.name in datasets) {
            d.values = datasets[d.name];
        }
    }
    return data;
}
//# sourceMappingURL=assemble.js.map
;// ../../node_modules/vega-lite/build/src/compile/header/parse.js








function getHeaderType(orient) {
    if (orient === 'top' || orient === 'left' || isSignalRef(orient)) {
        // we always use header for orient signal since we can't dynamically make header becomes footer
        return 'header';
    }
    return 'footer';
}
function parseFacetHeaders(model) {
    for (const channel of FACET_CHANNELS) {
        parseFacetHeader(model, channel);
    }
    mergeChildAxis(model, 'x');
    mergeChildAxis(model, 'y');
}
function parseFacetHeader(model, channel) {
    const { facet, config, child, component } = model;
    if (model.channelHasField(channel)) {
        const fieldDef = facet[channel];
        const titleConfig = getHeaderProperty('title', null, config, channel);
        let title = channeldef_title(fieldDef, config, {
            allowDisabling: true,
            includeDefault: titleConfig === undefined || !!titleConfig
        });
        if (child.component.layoutHeaders[channel].title) {
            // TODO: better handle multiline titles
            title = vega_util_module_isArray(title) ? title.join(', ') : title;
            // merge title with child to produce "Title / Subtitle / Sub-subtitle"
            title += ` / ${child.component.layoutHeaders[channel].title}`;
            child.component.layoutHeaders[channel].title = null;
        }
        const labelOrient = getHeaderProperty('labelOrient', fieldDef.header, config, channel);
        const labels = fieldDef.header !== null ? getFirstDefined(fieldDef.header?.labels, config.header.labels, true) : false;
        const headerType = util_contains(['bottom', 'right'], labelOrient) ? 'footer' : 'header';
        component.layoutHeaders[channel] = {
            title: fieldDef.header !== null ? title : null,
            facetFieldDef: fieldDef,
            [headerType]: channel === 'facet' ? [] : [makeHeaderComponent(model, channel, labels)]
        };
    }
}
function makeHeaderComponent(model, channel, labels) {
    const sizeType = channel === 'row' ? 'height' : 'width';
    return {
        labels,
        sizeSignal: model.child.component.layoutSize.get(sizeType) ? model.child.getSizeSignalRef(sizeType) : undefined,
        axes: []
    };
}
function mergeChildAxis(model, channel) {
    const { child } = model;
    if (child.component.axes[channel]) {
        const { layoutHeaders, resolve } = model.component;
        resolve.axis[channel] = parseGuideResolve(resolve, channel);
        if (resolve.axis[channel] === 'shared') {
            // For shared axis, move the axes to facet's header or footer
            const headerChannel = channel === 'x' ? 'column' : 'row';
            const layoutHeader = layoutHeaders[headerChannel];
            for (const axisComponent of child.component.axes[channel]) {
                const headerType = getHeaderType(axisComponent.get('orient'));
                layoutHeader[headerType] ?? (layoutHeader[headerType] = [makeHeaderComponent(model, headerChannel, false)]);
                // FIXME: assemble shouldn't be called here, but we do it this way so we only extract the main part of the axes
                const mainAxis = assembleAxis(axisComponent, 'main', model.config, { header: true });
                if (mainAxis) {
                    // LayoutHeader no longer keep track of property precedence, thus let's combine.
                    layoutHeader[headerType][0].axes.push(mainAxis);
                }
                axisComponent.mainExtracted = true;
            }
        }
        else {
            // Otherwise do nothing for independent axes
        }
    }
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/layoutsize/parse.js








function parseLayerLayoutSize(model) {
    parseChildrenLayoutSize(model);
    parseNonUnitLayoutSizeForChannel(model, 'width');
    parseNonUnitLayoutSizeForChannel(model, 'height');
}
function parseConcatLayoutSize(model) {
    parseChildrenLayoutSize(model);
    // for columns === 1 (vconcat), we can completely merge width. Otherwise, we can treat merged width as childWidth.
    const widthType = model.layout.columns === 1 ? 'width' : 'childWidth';
    // for columns === undefined (hconcat), we can completely merge height. Otherwise, we can treat merged height as childHeight.
    const heightType = model.layout.columns === undefined ? 'height' : 'childHeight';
    parseNonUnitLayoutSizeForChannel(model, widthType);
    parseNonUnitLayoutSizeForChannel(model, heightType);
}
function parseChildrenLayoutSize(model) {
    for (const child of model.children) {
        child.parseLayoutSize();
    }
}
/**
 * Merge child layout size (width or height).
 */
function parseNonUnitLayoutSizeForChannel(model, layoutSizeType) {
    /*
     * For concat, the parent width or height might not be the same as the children's shared height.
     * For example, hconcat's subviews may share width, but the shared width is not the hconcat view's width.
     *
     * layoutSizeType represents the output of the view (could be childWidth/childHeight/width/height)
     * while the sizeType represents the properties of the child.
     */
    const sizeType = getSizeTypeFromLayoutSizeType(layoutSizeType);
    const channel = getPositionScaleChannel(sizeType);
    const resolve = model.component.resolve;
    const layoutSizeCmpt = model.component.layoutSize;
    let mergedSize;
    // Try to merge layout size
    for (const child of model.children) {
        const childSize = child.component.layoutSize.getWithExplicit(sizeType);
        const scaleResolve = resolve.scale[channel] ?? defaultScaleResolve(channel, model);
        if (scaleResolve === 'independent' && childSize.value === 'step') {
            // Do not merge independent scales with range-step as their size depends
            // on the scale domains, which can be different between scales.
            mergedSize = undefined;
            break;
        }
        if (mergedSize) {
            if (scaleResolve === 'independent' && mergedSize.value !== childSize.value) {
                // For independent scale, only merge if all the sizes are the same.
                // If the values are different, abandon the merge!
                mergedSize = undefined;
                break;
            }
            mergedSize = mergeValuesWithExplicit(mergedSize, childSize, sizeType, '');
        }
        else {
            mergedSize = childSize;
        }
    }
    if (mergedSize) {
        // If merged, rename size and set size of all children.
        for (const child of model.children) {
            model.renameSignal(child.getName(sizeType), model.getName(layoutSizeType));
            child.component.layoutSize.set(sizeType, 'merged', false);
        }
        layoutSizeCmpt.setWithExplicit(layoutSizeType, mergedSize);
    }
    else {
        layoutSizeCmpt.setWithExplicit(layoutSizeType, {
            explicit: false,
            value: undefined
        });
    }
}
function parseUnitLayoutSize(model) {
    const { size, component } = model;
    for (const channel of POSITION_SCALE_CHANNELS) {
        const sizeType = getSizeChannel(channel);
        if (size[sizeType]) {
            const specifiedSize = size[sizeType];
            component.layoutSize.set(sizeType, isStep(specifiedSize) ? 'step' : specifiedSize, true);
        }
        else {
            const defaultSize = defaultUnitSize(model, sizeType);
            component.layoutSize.set(sizeType, defaultSize, false);
        }
    }
}
function defaultUnitSize(model, sizeType) {
    const channel = sizeType === 'width' ? 'x' : 'y';
    const config = model.config;
    const scaleComponent = model.getScaleComponent(channel);
    if (scaleComponent) {
        const scaleType = scaleComponent.get('type');
        const range = scaleComponent.get('range');
        if (hasDiscreteDomain(scaleType)) {
            const size = getViewConfigDiscreteSize(config.view, sizeType);
            if (isVgRangeStep(range) || isStep(size)) {
                // For discrete domain with range.step, use dynamic width/height
                return 'step';
            }
            else {
                return size;
            }
        }
        else {
            return getViewConfigContinuousSize(config.view, sizeType);
        }
    }
    else if (model.hasProjection || model.mark === 'arc') {
        // arc should use continuous size by default otherwise the pie is extremely small
        return getViewConfigContinuousSize(config.view, sizeType);
    }
    else {
        const size = getViewConfigDiscreteSize(config.view, sizeType);
        return isStep(size) ? size.step : size;
    }
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/facet.js

























function facetSortFieldName(fieldDef, sort, opt) {
    return vgField(sort, { suffix: `by_${vgField(fieldDef)}`, ...opt });
}
class FacetModel extends ModelWithField {
    constructor(spec, parent, parentGivenName, config) {
        super(spec, 'facet', parent, parentGivenName, config, spec.resolve);
        this.child = buildModel(spec.spec, this, this.getName('child'), undefined, config);
        this.children = [this.child];
        this.facet = this.initFacet(spec.facet);
    }
    initFacet(facet) {
        // clone to prevent side effect to the original spec
        if (!isFacetMapping(facet)) {
            return { facet: this.initFacetFieldDef(facet, 'facet') };
        }
        const channels = util_keys(facet);
        const normalizedFacet = {};
        for (const channel of channels) {
            if (![ROW, COLUMN].includes(channel)) {
                // Drop unsupported channel
                log_warn(incompatibleChannel(channel, 'facet'));
                break;
            }
            const fieldDef = facet[channel];
            if (fieldDef.field === undefined) {
                log_warn(emptyFieldDef(fieldDef, channel));
                break;
            }
            normalizedFacet[channel] = this.initFacetFieldDef(fieldDef, channel);
        }
        return normalizedFacet;
    }
    initFacetFieldDef(fieldDef, channel) {
        // Cast because we call initFieldDef, which assumes general FieldDef.
        // However, FacetFieldDef is a bit more constrained than the general FieldDef
        const facetFieldDef = initFieldDef(fieldDef, channel);
        if (facetFieldDef.header) {
            facetFieldDef.header = replaceExprRef(facetFieldDef.header);
        }
        else if (facetFieldDef.header === null) {
            facetFieldDef.header = null;
        }
        return facetFieldDef;
    }
    channelHasField(channel) {
        return util_hasProperty(this.facet, channel);
    }
    fieldDef(channel) {
        return this.facet[channel];
    }
    parseData() {
        this.component.data = parse_parseData(this);
        this.child.parseData();
    }
    parseLayoutSize() {
        parseChildrenLayoutSize(this);
    }
    parseSelections() {
        // As a facet has a single child, the selection components are the same.
        // The child maintains its selections to assemble signals, which remain
        // within its unit.
        this.child.parseSelections();
        this.component.selection = this.child.component.selection;
        if (Object.values(this.component.selection).some(selCmpt => isTimerSelection(selCmpt))) {
            log_error(MULTI_VIEW_ANIMATION_UNSUPPORTED);
        }
    }
    parseMarkGroup() {
        this.child.parseMarkGroup();
    }
    parseAxesAndHeaders() {
        this.child.parseAxesAndHeaders();
        parseFacetHeaders(this);
    }
    assembleSelectionTopLevelSignals(signals) {
        return this.child.assembleSelectionTopLevelSignals(signals);
    }
    assembleSignals() {
        this.child.assembleSignals();
        return [];
    }
    assembleSelectionData(data) {
        return this.child.assembleSelectionData(data);
    }
    getHeaderLayoutMixins() {
        const layoutMixins = {};
        for (const channel of FACET_CHANNELS) {
            for (const headerType of HEADER_TYPES) {
                const layoutHeaderComponent = this.component.layoutHeaders[channel];
                const headerComponent = layoutHeaderComponent[headerType];
                const { facetFieldDef } = layoutHeaderComponent;
                if (facetFieldDef) {
                    const titleOrient = getHeaderProperty('titleOrient', facetFieldDef.header, this.config, channel);
                    if (['right', 'bottom'].includes(titleOrient)) {
                        const headerChannel = getHeaderChannel(channel, titleOrient);
                        layoutMixins.titleAnchor ?? (layoutMixins.titleAnchor = {});
                        layoutMixins.titleAnchor[headerChannel] = 'end';
                    }
                }
                if (headerComponent?.[0]) {
                    // set header/footerBand
                    const sizeType = channel === 'row' ? 'height' : 'width';
                    const bandType = headerType === 'header' ? 'headerBand' : 'footerBand';
                    if (channel !== 'facet' && !this.child.component.layoutSize.get(sizeType)) {
                        // If facet child does not have size signal, then apply headerBand
                        layoutMixins[bandType] ?? (layoutMixins[bandType] = {});
                        layoutMixins[bandType][channel] = 0.5;
                    }
                    if (layoutHeaderComponent.title) {
                        layoutMixins.offset ?? (layoutMixins.offset = {});
                        layoutMixins.offset[channel === 'row' ? 'rowTitle' : 'columnTitle'] = 10;
                    }
                }
            }
        }
        return layoutMixins;
    }
    assembleDefaultLayout() {
        const { column, row } = this.facet;
        const columns = column ? this.columnDistinctSignal() : row ? 1 : undefined;
        let align = 'all';
        // Do not align the cells if the scale corresponding to the direction is indepent.
        // We always align when we facet into both row and column.
        if (!row && this.component.resolve.scale.x === 'independent') {
            align = 'none';
        }
        else if (!column && this.component.resolve.scale.y === 'independent') {
            align = 'none';
        }
        return {
            ...this.getHeaderLayoutMixins(),
            ...(columns ? { columns } : {}),
            bounds: 'full',
            align
        };
    }
    assembleLayoutSignals() {
        // FIXME(https://github.com/vega/vega-lite/issues/1193): this can be incorrect if we have independent scales.
        return this.child.assembleLayoutSignals();
    }
    columnDistinctSignal() {
        if (this.parent && this.parent instanceof FacetModel) {
            // For nested facet, we will add columns to group mark instead
            // See discussion in https://github.com/vega/vega/issues/952
            // and https://github.com/vega/vega-view/releases/tag/v1.2.6
            return undefined;
        }
        else {
            // In facetNode.assemble(), the name is always this.getName('column') + '_layout'.
            const facetLayoutDataName = this.getName('column_domain');
            return { signal: `length(data('${facetLayoutDataName}'))` };
        }
    }
    assembleGroupStyle() {
        return undefined;
    }
    assembleGroup(signals) {
        if (this.parent && this.parent instanceof FacetModel) {
            // Provide number of columns for layout.
            // See discussion in https://github.com/vega/vega/issues/952
            // and https://github.com/vega/vega-view/releases/tag/v1.2.6
            return {
                ...(this.channelHasField('column')
                    ? {
                        encode: {
                            update: {
                                // TODO(https://github.com/vega/vega-lite/issues/2759):
                                // Correct the signal for facet of concat of facet_column
                                columns: { field: vgField(this.facet.column, { prefix: 'distinct' }) }
                            }
                        }
                    }
                    : {}),
                ...super.assembleGroup(signals)
            };
        }
        return super.assembleGroup(signals);
    }
    /**
     * Aggregate cardinality for calculating size
     */
    getCardinalityAggregateForChild() {
        const fields = [];
        const ops = [];
        const as = [];
        if (this.child instanceof FacetModel) {
            if (this.child.channelHasField('column')) {
                const field = vgField(this.child.facet.column);
                fields.push(field);
                ops.push('distinct');
                as.push(`distinct_${field}`);
            }
        }
        else {
            for (const channel of POSITION_SCALE_CHANNELS) {
                const childScaleComponent = this.child.component.scales[channel];
                if (childScaleComponent && !childScaleComponent.merged) {
                    const type = childScaleComponent.get('type');
                    const range = childScaleComponent.get('range');
                    if (hasDiscreteDomain(type) && isVgRangeStep(range)) {
                        const domain = assembleDomain(this.child, channel);
                        const field = getFieldFromDomain(domain);
                        if (field) {
                            fields.push(field);
                            ops.push('distinct');
                            as.push(`distinct_${field}`);
                        }
                        else {
                            log_warn(unknownField(channel));
                        }
                    }
                }
            }
        }
        return { fields, ops, as };
    }
    assembleFacet() {
        const { name, data } = this.component.data.facetRoot;
        const { row, column } = this.facet;
        const { fields, ops, as } = this.getCardinalityAggregateForChild();
        const groupby = [];
        for (const channel of FACET_CHANNELS) {
            const fieldDef = this.facet[channel];
            if (fieldDef) {
                groupby.push(vgField(fieldDef));
                const { bin, sort } = fieldDef;
                if (isBinning(bin)) {
                    groupby.push(vgField(fieldDef, { binSuffix: 'end' }));
                }
                if (isSortField(sort)) {
                    const { field, op = DEFAULT_SORT_OP } = sort;
                    const outputName = facetSortFieldName(fieldDef, sort);
                    if (row && column) {
                        // For crossed facet, use pre-calculate field as it requires a different groupby
                        // For each calculated field, apply max and assign them to the same name as
                        // all values of the same group should be the same anyway.
                        fields.push(outputName);
                        ops.push('max');
                        as.push(outputName);
                    }
                    else {
                        fields.push(field);
                        ops.push(op);
                        as.push(outputName);
                    }
                }
                else if (vega_util_module_isArray(sort)) {
                    const outputName = sortArrayIndexField(fieldDef, channel);
                    fields.push(outputName);
                    ops.push('max');
                    as.push(outputName);
                }
            }
        }
        const cross = !!row && !!column;
        return {
            name,
            data,
            groupby,
            ...(cross || fields.length > 0
                ? {
                    aggregate: {
                        ...(cross ? { cross } : {}),
                        ...(fields.length ? { fields, ops, as } : {})
                    }
                }
                : {})
        };
    }
    facetSortFields(channel) {
        const { facet } = this;
        const fieldDef = facet[channel];
        if (fieldDef) {
            if (isSortField(fieldDef.sort)) {
                return [facetSortFieldName(fieldDef, fieldDef.sort, { expr: 'datum' })];
            }
            else if (vega_util_module_isArray(fieldDef.sort)) {
                return [sortArrayIndexField(fieldDef, channel, { expr: 'datum' })];
            }
            return [vgField(fieldDef, { expr: 'datum' })];
        }
        return [];
    }
    facetSortOrder(channel) {
        const { facet } = this;
        const fieldDef = facet[channel];
        if (fieldDef) {
            const { sort } = fieldDef;
            const order = (isSortField(sort) ? sort.order : !vega_util_module_isArray(sort) && sort) || 'ascending';
            return [order];
        }
        return [];
    }
    assembleLabelTitle() {
        const { facet, config } = this;
        if (facet.facet) {
            // Facet always uses title to display labels
            return assembleLabelTitle(facet.facet, 'facet', config);
        }
        const ORTHOGONAL_ORIENT = {
            row: ['top', 'bottom'],
            column: ['left', 'right']
        };
        for (const channel of HEADER_CHANNELS) {
            if (facet[channel]) {
                const labelOrient = getHeaderProperty('labelOrient', facet[channel]?.header, config, channel);
                if (ORTHOGONAL_ORIENT[channel].includes(labelOrient)) {
                    // Row/Column with orthogonal labelOrient must use title to display labels
                    return assembleLabelTitle(facet[channel], channel, config);
                }
            }
        }
        return undefined;
    }
    assembleMarks() {
        const { child } = this;
        // If we facet by two dimensions, we need to add a cross operator to the aggregation
        // so that we create all groups
        const facetRoot = this.component.data.facetRoot;
        const data = assembleFacetData(facetRoot);
        const encodeEntry = child.assembleGroupEncodeEntry(false);
        const title = this.assembleLabelTitle() || child.assembleTitle();
        const style = child.assembleGroupStyle();
        const markGroup = {
            name: this.getName('cell'),
            type: 'group',
            ...(title ? { title } : {}),
            ...(style ? { style } : {}),
            from: {
                facet: this.assembleFacet()
            },
            // TODO: move this to after data
            sort: {
                field: FACET_CHANNELS.map(c => this.facetSortFields(c)).flat(),
                order: FACET_CHANNELS.map(c => this.facetSortOrder(c)).flat()
            },
            ...(data.length > 0 ? { data } : {}),
            ...(encodeEntry ? { encode: { update: encodeEntry } } : {}),
            ...child.assembleGroup(assembleFacetSignals(this, []))
        };
        return [markGroup];
    }
    getMapping() {
        return this.facet;
    }
}
//# sourceMappingURL=facet.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/joinaggregatefacet.js




function makeJoinAggregateFromFacet(parent, facet) {
    const { row, column } = facet;
    if (row && column) {
        let newParent = null;
        // only need to make one for crossed facet
        for (const fieldDef of [row, column]) {
            if (isSortField(fieldDef.sort)) {
                const { field, op = DEFAULT_SORT_OP } = fieldDef.sort;
                parent = newParent = new JoinAggregateTransformNode(parent, {
                    joinaggregate: [
                        {
                            op,
                            field,
                            as: facetSortFieldName(fieldDef, fieldDef.sort, { forAs: true })
                        }
                    ],
                    groupby: [vgField(fieldDef)]
                });
            }
        }
        return newParent;
    }
    return null;
}
//# sourceMappingURL=joinaggregatefacet.js.map
;// ../../node_modules/vega-lite/build/src/compile/data/parse.js









































function findSource(data, sources) {
    for (const other of sources) {
        const otherData = other.data;
        // if both datasets have a name defined, we cannot merge
        if (data.name && other.hasName() && data.name !== other.dataName) {
            continue;
        }
        const formatMesh = data.format?.mesh;
        const otherFeature = otherData.format?.feature;
        // feature and mesh are mutually exclusive
        if (formatMesh && otherFeature) {
            continue;
        }
        // we have to extract the same feature or mesh
        const formatFeature = data.format?.feature;
        if ((formatFeature || otherFeature) && formatFeature !== otherFeature) {
            continue;
        }
        const otherMesh = otherData.format?.mesh;
        if ((formatMesh || otherMesh) && formatMesh !== otherMesh) {
            continue;
        }
        if (isInlineData(data) && isInlineData(otherData)) {
            if (util_deepEqual(data.values, otherData.values)) {
                return other;
            }
        }
        else if (isUrlData(data) && isUrlData(otherData)) {
            if (data.url === otherData.url) {
                return other;
            }
        }
        else if (isNamedData(data)) {
            if (data.name === other.dataName) {
                return other;
            }
        }
    }
    return null;
}
function parseRoot(model, sources) {
    if (model.data || !model.parent) {
        // if the model defines a data source or is the root, create a source node
        if (model.data === null) {
            // data: null means we should ignore the parent's data so we just create a new data source
            const source = new SourceNode({ values: [] });
            sources.push(source);
            return source;
        }
        const existingSource = findSource(model.data, sources);
        if (existingSource) {
            if (!isGenerator(model.data)) {
                existingSource.data.format = mergeDeep({}, model.data.format, existingSource.data.format);
            }
            // if the new source has a name but the existing one does not, we can set it
            if (!existingSource.hasName() && model.data.name) {
                existingSource.dataName = model.data.name;
            }
            return existingSource;
        }
        else {
            const source = new SourceNode(model.data);
            sources.push(source);
            return source;
        }
    }
    else {
        // If we don't have a source defined (overriding parent's data), use the parent's facet root or main.
        return model.parent.component.data.facetRoot
            ? model.parent.component.data.facetRoot
            : model.parent.component.data.main;
    }
}
/**
 * Parses a transform array into a chain of connected dataflow nodes.
 */
function parseTransformArray(head, model, ancestorParse) {
    let lookupCounter = 0;
    for (const t of model.transforms) {
        let derivedType = undefined;
        let transformNode;
        if (isCalculate(t)) {
            transformNode = head = new CalculateNode(head, t);
            derivedType = 'derived';
        }
        else if (isFilter(t)) {
            const implicit = getImplicitFromFilterTransform(t);
            transformNode = head = ParseNode.makeWithAncestors(head, {}, implicit, ancestorParse) ?? head;
            head = new FilterNode(head, model, t.filter);
        }
        else if (isBin(t)) {
            transformNode = head = BinNode.makeFromTransform(head, t, model);
            derivedType = 'number';
        }
        else if (isTimeUnit(t)) {
            derivedType = 'date';
            const parsedAs = ancestorParse.getWithExplicit(t.field);
            // Create parse node because the input to time unit is always date.
            if (parsedAs.value === undefined) {
                head = new ParseNode(head, { [t.field]: derivedType });
                ancestorParse.set(t.field, derivedType, false);
            }
            transformNode = head = TimeUnitNode.makeFromTransform(head, t);
        }
        else if (transform_isAggregate(t)) {
            transformNode = head = AggregateNode.makeFromTransform(head, t);
            derivedType = 'number';
            if (requiresSelectionId(model)) {
                head = new IdentifierNode(head);
            }
        }
        else if (isLookup(t)) {
            transformNode = head = LookupNode.make(head, model, t, lookupCounter++);
            derivedType = 'derived';
        }
        else if (isWindow(t)) {
            transformNode = head = new WindowTransformNode(head, t);
            derivedType = 'number';
        }
        else if (isJoinAggregate(t)) {
            transformNode = head = new JoinAggregateTransformNode(head, t);
            derivedType = 'number';
        }
        else if (isStack(t)) {
            transformNode = head = StackNode.makeFromTransform(head, t);
            derivedType = 'derived';
        }
        else if (isFold(t)) {
            transformNode = head = new FoldTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isExtent(t)) {
            transformNode = head = new ExtentTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isFlatten(t)) {
            transformNode = head = new FlattenTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isPivot(t)) {
            transformNode = head = new PivotTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isSample(t)) {
            head = new SampleTransformNode(head, t);
        }
        else if (isImpute(t)) {
            transformNode = head = ImputeNode.makeFromTransform(head, t);
            derivedType = 'derived';
        }
        else if (isDensity(t)) {
            transformNode = head = new DensityTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (transform_isQuantile(t)) {
            transformNode = head = new QuantileTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isRegression(t)) {
            transformNode = head = new RegressionTransformNode(head, t);
            derivedType = 'derived';
        }
        else if (isLoess(t)) {
            transformNode = head = new LoessTransformNode(head, t);
            derivedType = 'derived';
        }
        else {
            log_warn(invalidTransformIgnored(t));
            continue;
        }
        if (transformNode && derivedType !== undefined) {
            for (const field of transformNode.producedFields() ?? []) {
                ancestorParse.set(field, derivedType, false);
            }
        }
    }
    return head;
}
/*
Description of the dataflow (http://asciiflow.com/):
     +--------+
     | Source |
     +---+----+
         |
         v
     FormatParse
     (explicit)
         |
         v
     Transforms
(Filter, Calculate, Binning, TimeUnit, Aggregate, Window, ...)
         |
         v
     FormatParse
     (implicit)
         |
         v
 Binning (in `encoding`)
         |
         v
 Timeunit (in `encoding`)
         |
         v
Formula From Sort Array
         |
         v
      +--+--+
      | Raw |
      +-----+
         |
         v
  Aggregate (in `encoding`)
         |
         v
  Stack (in `encoding`)
         |
         v
+- - - - - - - - - - -+
|   PreFilterInvalid  | - - - -> scale domains
|(when scales need it)|
+- - - - - - - - - - -+
         |
         v
  Invalid Filter (if the main data source needs it)
         |
         v
   +----------+
   |   Main   | - - - -> scale domains
   +----------+
         |
         v
+- - - - - - - - - - -+
|   PostFilterInvalid | - - - -> scale domains
|(when scales need it)|
+- - - - - - - - - - -+
         |
         v
     +-------+
     | Facet |----> "column", "column-layout", and "row"
     +-------+
         |
         v
  ...Child data...
*/
function parse_parseData(model) {
    let head = parseRoot(model, model.component.data.sources);
    const { outputNodes, outputNodeRefCounts } = model.component.data;
    const data = model.data;
    const newData = data && (isGenerator(data) || isUrlData(data) || isInlineData(data));
    const ancestorParse = !newData && model.parent ? model.parent.component.data.ancestorParse.clone() : new AncestorParse();
    if (isGenerator(data)) {
        // insert generator transform
        if (isSequenceGenerator(data)) {
            head = new SequenceNode(head, data.sequence);
        }
        else if (isGraticuleGenerator(data)) {
            head = new GraticuleNode(head, data.graticule);
        }
        // no parsing necessary for generator
        ancestorParse.parseNothing = true;
    }
    else if (data?.format?.parse === null) {
        // format.parse: null means disable parsing
        ancestorParse.parseNothing = true;
    }
    head = ParseNode.makeExplicit(head, model, ancestorParse) ?? head;
    // Default discrete selections require an identifer transform to
    // uniquely identify data points. Add this transform at the head of
    // the pipeline such that the identifier field is available for all
    // subsequent datasets. During optimization, we will remove this
    // transform if it proves to be unnecessary. Additional identifier
    // transforms will be necessary when new tuples are constructed
    // (e.g., post-aggregation).
    head = new IdentifierNode(head);
    // HACK: This is equivalent for merging bin extent for union scale.
    // FIXME(https://github.com/vega/vega-lite/issues/2270): Correctly merge extent / bin node for shared bin scale
    const parentIsLayer = model.parent && isLayerModel(model.parent);
    if (isUnitModel(model) || isFacetModel(model)) {
        if (parentIsLayer) {
            head = BinNode.makeFromEncoding(head, model) ?? head;
        }
    }
    if (model.transforms.length > 0) {
        head = parseTransformArray(head, model, ancestorParse);
    }
    // create parse nodes for fields that need to be parsed (or flattened) implicitly
    const implicitSelection = getImplicitFromSelection(model);
    const implicitEncoding = getImplicitFromEncoding(model);
    head = ParseNode.makeWithAncestors(head, {}, { ...implicitSelection, ...implicitEncoding }, ancestorParse) ?? head;
    if (isUnitModel(model)) {
        head = GeoJSONNode.parseAll(head, model);
        head = GeoPointNode.parseAll(head, model);
    }
    if (isUnitModel(model) || isFacetModel(model)) {
        if (!parentIsLayer) {
            head = BinNode.makeFromEncoding(head, model) ?? head;
        }
        head = TimeUnitNode.makeFromEncoding(head, model) ?? head;
        head = CalculateNode.parseAllForSortIndex(head, model);
    }
    // add an output node pre aggregation
    const raw = (head = makeOutputNode(DataSourceType.Raw, model, head));
    if (isUnitModel(model)) {
        const agg = AggregateNode.makeFromEncoding(head, model);
        if (agg) {
            head = agg;
            if (requiresSelectionId(model)) {
                head = new IdentifierNode(head);
            }
        }
        head = ImputeNode.makeFromEncoding(head, model) ?? head;
        head = StackNode.makeFromEncoding(head, model) ?? head;
    }
    let preFilterInvalid;
    let dataSourcesForHandlingInvalidValues;
    if (isUnitModel(model)) {
        const { markDef, mark, config } = model;
        const invalid = getMarkPropOrConfig('invalid', markDef, config);
        const { marks, scales } = (dataSourcesForHandlingInvalidValues = getDataSourcesForHandlingInvalidValues({
            invalid,
            isPath: isPathMark(mark)
        }));
        if (marks !== scales && scales === 'include-invalid-values') {
            // Create a seperate preFilterInvalid dataSource if scales need pre-filter data but marks needs post-filter.
            preFilterInvalid = head = makeOutputNode(DataSourceType.PreFilterInvalid, model, head);
        }
        if (marks === 'exclude-invalid-values') {
            head = FilterInvalidNode.make(head, model, dataSourcesForHandlingInvalidValues) ?? head;
        }
    }
    // output "main" node for marks
    const main = (head = makeOutputNode(DataSourceType.Main, model, head));
    let postFilterInvalid;
    if (isUnitModel(model) && dataSourcesForHandlingInvalidValues) {
        const { marks, scales } = dataSourcesForHandlingInvalidValues;
        if (marks === 'include-invalid-values' && scales === 'exclude-invalid-values') {
            // Create a seperate postFilterInvalid dataSource if scales need post-filter data but marks needs pre-filter.
            head = FilterInvalidNode.make(head, model, dataSourcesForHandlingInvalidValues) ?? head;
            postFilterInvalid = head = makeOutputNode(DataSourceType.PostFilterInvalid, model, head);
        }
    }
    if (isUnitModel(model)) {
        materializeSelections(model, main);
    }
    // add facet marker
    let facetRoot = null;
    if (isFacetModel(model)) {
        const facetName = model.getName('facet');
        // Derive new aggregate for facet's sort field
        // augment data source with new fields for crossed facet
        head = makeJoinAggregateFromFacet(head, model.facet) ?? head;
        facetRoot = new FacetNode(head, model, facetName, main.getSource());
        outputNodes[facetName] = facetRoot;
    }
    return {
        ...model.component.data,
        outputNodes,
        outputNodeRefCounts,
        raw,
        main,
        facetRoot,
        ancestorParse,
        preFilterInvalid,
        postFilterInvalid
    };
}
function makeOutputNode(dataSourceType, model, head) {
    const { outputNodes, outputNodeRefCounts } = model.component.data;
    const name = model.getDataName(dataSourceType);
    const node = new OutputNode(head, name, dataSourceType, outputNodeRefCounts);
    outputNodes[name] = node;
    return node;
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/concat.js










class ConcatModel extends Model {
    constructor(spec, parent, parentGivenName, config) {
        super(spec, 'concat', parent, parentGivenName, config, spec.resolve);
        if (spec.resolve?.axis?.x === 'shared' || spec.resolve?.axis?.y === 'shared') {
            log_warn(CONCAT_CANNOT_SHARE_AXIS);
        }
        this.children = this.getChildren(spec).map((child, i) => {
            return buildModel(child, this, this.getName(`concat_${i}`), undefined, config);
        });
    }
    parseData() {
        this.component.data = parse_parseData(this);
        for (const child of this.children) {
            child.parseData();
        }
    }
    parseSelections() {
        // Merge selections up the hierarchy so that they may be referenced
        // across unit specs. Persist their definitions within each child
        // to assemble signals which remain within output Vega unit groups.
        this.component.selection = {};
        for (const child of this.children) {
            child.parseSelections();
            for (const key of util_keys(child.component.selection)) {
                this.component.selection[key] = child.component.selection[key];
            }
        }
        if (Object.values(this.component.selection).some(selCmpt => isTimerSelection(selCmpt))) {
            log_error(MULTI_VIEW_ANIMATION_UNSUPPORTED);
        }
    }
    parseMarkGroup() {
        for (const child of this.children) {
            child.parseMarkGroup();
        }
    }
    parseAxesAndHeaders() {
        for (const child of this.children) {
            child.parseAxesAndHeaders();
        }
        // TODO(#2415): support shared axes
    }
    getChildren(spec) {
        if (isVConcatSpec(spec)) {
            return spec.vconcat;
        }
        else if (isHConcatSpec(spec)) {
            return spec.hconcat;
        }
        return spec.concat;
    }
    parseLayoutSize() {
        parseConcatLayoutSize(this);
    }
    parseAxisGroup() {
        return null;
    }
    assembleSelectionTopLevelSignals(signals) {
        return this.children.reduce((sg, child) => child.assembleSelectionTopLevelSignals(sg), signals);
    }
    assembleSignals() {
        this.children.forEach(child => child.assembleSignals());
        return [];
    }
    assembleLayoutSignals() {
        const layoutSignals = assembleLayoutSignals(this);
        for (const child of this.children) {
            layoutSignals.push(...child.assembleLayoutSignals());
        }
        return layoutSignals;
    }
    assembleSelectionData(data) {
        return this.children.reduce((db, child) => child.assembleSelectionData(db), data);
    }
    assembleMarks() {
        // only children have marks
        return this.children.map(child => {
            const title = child.assembleTitle();
            const style = child.assembleGroupStyle();
            const encodeEntry = child.assembleGroupEncodeEntry(false);
            return {
                type: 'group',
                name: child.getName('group'),
                ...(title ? { title } : {}),
                ...(style ? { style } : {}),
                ...(encodeEntry ? { encode: { update: encodeEntry } } : {}),
                ...child.assembleGroup()
            };
        });
    }
    assembleGroupStyle() {
        return undefined;
    }
    assembleDefaultLayout() {
        const columns = this.layout.columns;
        return {
            ...(columns != null ? { columns } : {}),
            bounds: 'full',
            // Use align each so it can work with multiple plots with different size
            align: 'each'
        };
    }
}
//# sourceMappingURL=concat.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/component.js




function isFalseOrNull(v) {
    return v === false || v === null;
}
const AXIS_COMPONENT_PROPERTIES_INDEX = {
    disable: 1,
    gridScale: 1,
    scale: 1,
    ...COMMON_AXIS_PROPERTIES_INDEX,
    labelExpr: 1,
    encode: 1
};
const AXIS_COMPONENT_PROPERTIES = util_keys(AXIS_COMPONENT_PROPERTIES_INDEX);
class AxisComponent extends Split {
    constructor(explicit = {}, implicit = {}, mainExtracted = false) {
        super();
        this.explicit = explicit;
        this.implicit = implicit;
        this.mainExtracted = mainExtracted;
    }
    clone() {
        return new AxisComponent(duplicate(this.explicit), duplicate(this.implicit), this.mainExtracted);
    }
    hasAxisPart(part) {
        // FIXME(https://github.com/vega/vega-lite/issues/2552) this method can be wrong if users use a Vega theme.
        if (part === 'axis') {
            // always has the axis container part
            return true;
        }
        if (part === 'grid' || part === 'title') {
            return !!this.get(part);
        }
        // Other parts are enabled by default, so they should not be false or null.
        return !isFalseOrNull(this.get(part));
    }
    hasOrientSignalRef() {
        return isSignalRef(this.explicit.orient);
    }
}
//# sourceMappingURL=component.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/encode.js



function encode_labels(model, channel, specifiedLabelsSpec) {
    const { encoding, config } = model;
    const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]) ?? getFieldOrDatumDef(encoding[getSecondaryRangeChannel(channel)]);
    const axis = model.axis(channel) || {};
    const { format, formatType } = axis;
    if (isCustomFormatType(formatType)) {
        return {
            text: formatCustomType({
                fieldOrDatumDef,
                field: 'datum.value',
                format,
                formatType,
                config
            }),
            ...specifiedLabelsSpec
        };
    }
    else if (format === undefined && formatType === undefined && config.customFormatTypes) {
        if (channelDefType(fieldOrDatumDef) === 'quantitative') {
            if (isPositionFieldOrDatumDef(fieldOrDatumDef) &&
                fieldOrDatumDef.stack === 'normalize' &&
                config.normalizedNumberFormatType) {
                return {
                    text: formatCustomType({
                        fieldOrDatumDef,
                        field: 'datum.value',
                        format: config.normalizedNumberFormat,
                        formatType: config.normalizedNumberFormatType,
                        config
                    }),
                    ...specifiedLabelsSpec
                };
            }
            else if (config.numberFormatType) {
                return {
                    text: formatCustomType({
                        fieldOrDatumDef,
                        field: 'datum.value',
                        format: config.numberFormat,
                        formatType: config.numberFormatType,
                        config
                    }),
                    ...specifiedLabelsSpec
                };
            }
        }
        if (channelDefType(fieldOrDatumDef) === 'temporal' &&
            config.timeFormatType &&
            isFieldDef(fieldOrDatumDef) &&
            !fieldOrDatumDef.timeUnit) {
            return {
                text: formatCustomType({
                    fieldOrDatumDef,
                    field: 'datum.value',
                    format: config.timeFormat,
                    formatType: config.timeFormatType,
                    config
                }),
                ...specifiedLabelsSpec
            };
        }
    }
    return specifiedLabelsSpec;
}
//# sourceMappingURL=encode.js.map
;// ../../node_modules/vega-lite/build/src/compile/axis/parse.js














function parseUnitAxes(model) {
    return POSITION_SCALE_CHANNELS.reduce((axis, channel) => {
        if (model.component.scales[channel]) {
            axis[channel] = [parse_parseAxis(channel, model)];
        }
        return axis;
    }, {});
}
const OPPOSITE_ORIENT = {
    bottom: 'top',
    top: 'bottom',
    left: 'right',
    right: 'left'
};
function parseLayerAxes(model) {
    const { axes, resolve } = model.component;
    const axisCount = { top: 0, bottom: 0, right: 0, left: 0 };
    for (const child of model.children) {
        child.parseAxesAndHeaders();
        for (const channel of util_keys(child.component.axes)) {
            resolve.axis[channel] = parseGuideResolve(model.component.resolve, channel);
            if (resolve.axis[channel] === 'shared') {
                // If the resolve says shared (and has not been overridden)
                // We will try to merge and see if there is a conflict
                axes[channel] = mergeAxisComponents(axes[channel], child.component.axes[channel]);
                if (!axes[channel]) {
                    // If merge returns nothing, there is a conflict so we cannot make the axis shared.
                    // Thus, mark axis as independent and remove the axis component.
                    resolve.axis[channel] = 'independent';
                    delete axes[channel];
                }
            }
        }
    }
    // Move axes to layer's axis component and merge shared axes
    for (const channel of POSITION_SCALE_CHANNELS) {
        for (const child of model.children) {
            if (!child.component.axes[channel]) {
                // skip if the child does not have a particular axis
                continue;
            }
            if (resolve.axis[channel] === 'independent') {
                // If axes are independent, concat the axisComponent array.
                axes[channel] = (axes[channel] ?? []).concat(child.component.axes[channel]);
                // Automatically adjust orient
                for (const axisComponent of child.component.axes[channel]) {
                    const { value: orient, explicit } = axisComponent.getWithExplicit('orient');
                    if (isSignalRef(orient)) {
                        continue;
                    }
                    if (axisCount[orient] > 0 && !explicit) {
                        // Change axis orient if the number do not match
                        const oppositeOrient = OPPOSITE_ORIENT[orient];
                        if (axisCount[orient] > axisCount[oppositeOrient]) {
                            axisComponent.set('orient', oppositeOrient, false);
                        }
                    }
                    axisCount[orient]++;
                    // TODO(https://github.com/vega/vega-lite/issues/2634): automatically add extra offset?
                }
            }
            // After merging, make sure to remove axes from child
            delete child.component.axes[channel];
        }
        // Show gridlines for first axis only for dual-axis chart
        if (resolve.axis[channel] === 'independent' && axes[channel] && axes[channel].length > 1) {
            for (const [index, axisCmpt] of (axes[channel] || []).entries()) {
                if (index > 0 && !!axisCmpt.get('grid') && !axisCmpt.explicit.grid) {
                    axisCmpt.implicit.grid = false;
                }
            }
        }
    }
}
function mergeAxisComponents(mergedAxisCmpts, childAxisCmpts) {
    if (mergedAxisCmpts) {
        // FIXME: this is a bit wrong once we support multiple axes
        if (mergedAxisCmpts.length !== childAxisCmpts.length) {
            return undefined; // Cannot merge axis component with different number of axes.
        }
        const length = mergedAxisCmpts.length;
        for (let i = 0; i < length; i++) {
            const merged = mergedAxisCmpts[i];
            const child = childAxisCmpts[i];
            if (!!merged !== !!child) {
                return undefined;
            }
            else if (merged && child) {
                const mergedOrient = merged.getWithExplicit('orient');
                const childOrient = child.getWithExplicit('orient');
                if (mergedOrient.explicit && childOrient.explicit && mergedOrient.value !== childOrient.value) {
                    // TODO: throw warning if resolve is explicit (We don't have info about explicit/implicit resolve yet.)
                    // Cannot merge due to inconsistent orient
                    return undefined;
                }
                else {
                    mergedAxisCmpts[i] = mergeAxisComponent(merged, child);
                }
            }
        }
    }
    else {
        // For first one, return a copy of the child
        return childAxisCmpts.map(axisComponent => axisComponent.clone());
    }
    return mergedAxisCmpts;
}
function mergeAxisComponent(merged, child) {
    for (const prop of AXIS_COMPONENT_PROPERTIES) {
        const mergedValueWithExplicit = mergeValuesWithExplicit(merged.getWithExplicit(prop), child.getWithExplicit(prop), prop, 'axis', 
        // Tie breaker function
        (v1, v2) => {
            switch (prop) {
                case 'title':
                    return mergeTitleComponent(v1, v2);
                case 'gridScale':
                    return {
                        explicit: v1.explicit, // keep the old explicit
                        value: getFirstDefined(v1.value, v2.value)
                    };
            }
            return defaultTieBreaker(v1, v2, prop, 'axis');
        });
        merged.setWithExplicit(prop, mergedValueWithExplicit);
    }
    return merged;
}
function parse_isExplicit(value, property, axis, model, channel) {
    if (property === 'disable') {
        return axis !== undefined; // if axis is specified or null/false, then its enable/disable state is explicit
    }
    axis = axis || {};
    switch (property) {
        case 'titleAngle':
        case 'labelAngle':
            return value === (isSignalRef(axis.labelAngle) ? axis.labelAngle : normalizeAngle(axis.labelAngle));
        case 'values':
            return !!axis.values;
        // specified axis.values is already respected, but may get transformed.
        case 'encode':
            // both VL axis.encoding and axis.labelAngle affect VG axis.encode
            return !!axis.encoding || !!axis.labelAngle;
        case 'title':
            // title can be explicit if fieldDef.title is set
            if (value === getFieldDefTitle(model, channel)) {
                return true;
            }
    }
    // Otherwise, things are explicit if the returned value matches the specified property
    return value === axis[property];
}
/**
 * Properties to always include values from config
 */
const propsToAlwaysIncludeConfig = new Set([
    'grid', // Grid is an exception because we need to set grid = true to generate another grid axis
    'translate', // translate has dependent logic for bar's bin position and it's 0.5 by default in Vega. If a config overrides this value, we need to know.
    // the rest are not axis configs in Vega, but are in VL, so we need to set too.
    'format',
    'formatType',
    'orient',
    'labelExpr',
    'tickCount',
    'position',
    'tickMinStep'
]);
function parse_parseAxis(channel, model) {
    let axis = model.axis(channel);
    const axisComponent = new AxisComponent();
    const fieldOrDatumDef = getFieldOrDatumDef(model.encoding[channel]);
    const { mark, config } = model;
    const orient = axis?.orient ||
        config[channel === 'x' ? 'axisX' : 'axisY']?.orient ||
        config.axis?.orient ||
        defaultOrient(channel);
    const scaleType = model.getScaleComponent(channel).get('type');
    const axisConfigs = getAxisConfigs(channel, scaleType, orient, model.config);
    const disable = axis !== undefined ? !axis : getAxisConfig('disable', config.style, axis?.style, axisConfigs).configValue;
    axisComponent.set('disable', disable, axis !== undefined);
    if (disable) {
        return axisComponent;
    }
    axis = axis || {};
    const labelAngle = getLabelAngle(fieldOrDatumDef, axis, channel, config.style, axisConfigs);
    const formatType = guideFormatType(axis.formatType, fieldOrDatumDef, scaleType);
    const format = guideFormat(fieldOrDatumDef, fieldOrDatumDef.type, axis.format, axis.formatType, config, true);
    const ruleParams = {
        fieldOrDatumDef,
        axis,
        channel,
        model,
        scaleType,
        orient,
        labelAngle,
        format,
        formatType,
        mark,
        config
    };
    // 1.2. Add properties
    for (const property of AXIS_COMPONENT_PROPERTIES) {
        const value = property in axisRules ? axisRules[property](ruleParams) : isAxisProperty(property) ? axis[property] : undefined;
        const hasValue = value !== undefined;
        const explicit = parse_isExplicit(value, property, axis, model, channel);
        if (hasValue && explicit) {
            axisComponent.set(property, value, explicit);
        }
        else {
            const { configValue = undefined, configFrom = undefined } = isAxisProperty(property) && property !== 'values'
                ? getAxisConfig(property, config.style, axis.style, axisConfigs)
                : {};
            const hasConfigValue = configValue !== undefined;
            if (hasValue && !hasConfigValue) {
                // only set property if it is explicitly set or has no config value (otherwise we will accidentally override config)
                axisComponent.set(property, value, explicit);
            }
            else if (
            // Cases need implicit values
            // 1. Axis config that aren't available in Vega
            !(configFrom === 'vgAxisConfig') ||
                // 2. Certain properties are always included (see `propsToAlwaysIncludeConfig`'s declaration for more details)
                (propsToAlwaysIncludeConfig.has(property) && hasConfigValue) ||
                // 3. Conditional axis values and signals
                isConditionalAxisValue(configValue) ||
                isSignalRef(configValue)) {
                // If a config is specified and is conditional, copy conditional value from axis config
                axisComponent.set(property, configValue, false);
            }
        }
    }
    // 2) Add guide encode definition groups
    const axisEncoding = axis.encoding ?? {};
    const axisEncode = AXIS_PARTS.reduce((e, part) => {
        if (!axisComponent.hasAxisPart(part)) {
            // No need to create encode for a disabled part.
            return e;
        }
        const axisEncodingPart = guideEncodeEntry(axisEncoding[part] ?? {}, model);
        const value = part === 'labels' ? encode_labels(model, channel, axisEncodingPart) : axisEncodingPart;
        if (value !== undefined && !isEmpty(value)) {
            e[part] = { update: value };
        }
        return e;
    }, {});
    // FIXME: By having encode as one property, we won't have fine grained encode merging.
    if (!isEmpty(axisEncode)) {
        axisComponent.set('encode', axisEncode, !!axis.encoding || axis.labelAngle !== undefined);
    }
    return axisComponent;
}
//# sourceMappingURL=parse.js.map
;// ../../node_modules/vega-lite/build/src/compile/layoutsize/init.js




function initLayoutSize({ encoding, size }) {
    for (const channel of POSITION_SCALE_CHANNELS) {
        const sizeType = getSizeChannel(channel);
        if (isStep(size[sizeType])) {
            if (isContinuousFieldOrDatumDef(encoding[channel])) {
                delete size[sizeType];
                log_warn(stepDropped(sizeType));
            }
        }
    }
    return size;
}
//# sourceMappingURL=init.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/arc.js

const arc_arc = {
    vgMark: 'arc',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                size: 'ignore',
                orient: 'ignore',
                theta: 'ignore'
            }),
            ...pointPosition('x', model, { defaultPos: 'mid' }),
            ...pointPosition('y', model, { defaultPos: 'mid' }),
            // arcs are rectangles in polar coordinates
            ...rectPosition(model, 'radius'),
            ...rectPosition(model, 'theta')
        };
    }
};
//# sourceMappingURL=arc.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/area.js

const area_area = {
    vgMark: 'area',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                orient: 'include',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...pointOrRangePosition('x', model, {
                defaultPos: 'zeroOrMin',
                defaultPos2: 'zeroOrMin',
                range: model.markDef.orient === 'horizontal'
            }),
            ...pointOrRangePosition('y', model, {
                defaultPos: 'zeroOrMin',
                defaultPos2: 'zeroOrMin',
                range: model.markDef.orient === 'vertical'
            }),
            ...defined(model)
        };
    }
};
//# sourceMappingURL=area.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/bar.js

const bar = {
    vgMark: 'rect',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                orient: 'ignore',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...rectPosition(model, 'x'),
            ...rectPosition(model, 'y')
        };
    }
};
//# sourceMappingURL=bar.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/geoshape.js



const geoshape = {
    vgMark: 'shape',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                size: 'ignore',
                orient: 'ignore',
                theta: 'ignore'
            })
        };
    },
    postEncodingTransform: (model) => {
        const { encoding } = model;
        const shapeDef = encoding.shape;
        const transform = {
            type: 'geoshape',
            projection: model.projectionName(),
            // as: 'shape',
            ...(shapeDef && isFieldDef(shapeDef) && shapeDef.type === GEOJSON
                ? { field: vgField(shapeDef, { expr: 'datum' }) }
                : {})
        };
        return [transform];
    }
};
//# sourceMappingURL=geoshape.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/image.js

const image_image = {
    vgMark: 'image',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'ignore',
                orient: 'ignore',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...rectPosition(model, 'x'),
            ...rectPosition(model, 'y'),
            ...text_text(model, 'url')
        };
    }
};
//# sourceMappingURL=image.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/line.js

const line_line = {
    vgMark: 'line',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                size: 'ignore',
                orient: 'ignore',
                theta: 'ignore'
            }),
            ...pointPosition('x', model, { defaultPos: 'mid' }),
            ...pointPosition('y', model, { defaultPos: 'mid' }),
            ...nonPosition('size', model, {
                vgChannel: 'strokeWidth' // VL's line size is strokeWidth
            }),
            ...defined(model)
        };
    }
};
const line_trail = {
    vgMark: 'trail',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                size: 'include',
                orient: 'ignore',
                theta: 'ignore'
            }),
            ...pointPosition('x', model, { defaultPos: 'mid' }),
            ...pointPosition('y', model, { defaultPos: 'mid' }),
            ...nonPosition('size', model),
            ...defined(model)
        };
    }
};
//# sourceMappingURL=line.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/point.js

function encodeEntry(model, fixedShape) {
    const { config } = model;
    return {
        ...baseEncodeEntry(model, {
            align: 'ignore',
            baseline: 'ignore',
            color: 'include',
            size: 'include',
            orient: 'ignore',
            theta: 'ignore'
        }),
        ...pointPosition('x', model, { defaultPos: 'mid' }),
        ...pointPosition('y', model, { defaultPos: 'mid' }),
        ...nonPosition('size', model),
        ...nonPosition('angle', model),
        ...shapeMixins(model, config, fixedShape)
    };
}
function shapeMixins(model, config, fixedShape) {
    if (fixedShape) {
        return { shape: { value: fixedShape } };
    }
    return nonPosition('shape', model);
}
const mark_point_point = {
    vgMark: 'symbol',
    encodeEntry: (model) => {
        return encodeEntry(model);
    }
};
const point_circle = {
    vgMark: 'symbol',
    encodeEntry: (model) => {
        return encodeEntry(model, 'circle');
    }
};
const point_square = {
    vgMark: 'symbol',
    encodeEntry: (model) => {
        return encodeEntry(model, 'square');
    }
};
//# sourceMappingURL=point.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/rect.js

const rect_rect = {
    vgMark: 'rect',
    encodeEntry: (model) => {
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                orient: 'ignore',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...rectPosition(model, 'x'),
            ...rectPosition(model, 'y')
        };
    }
};
//# sourceMappingURL=rect.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/rule.js

const rule_rule = {
    vgMark: 'rule',
    encodeEntry: (model) => {
        const { markDef } = model;
        const orient = markDef.orient;
        if (!model.encoding.x && !model.encoding.y && !model.encoding.latitude && !model.encoding.longitude) {
            // Show nothing if we have none of x, y, lat, and long.
            return {};
        }
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                orient: 'ignore',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...pointOrRangePosition('x', model, {
                defaultPos: orient === 'horizontal' ? 'zeroOrMax' : 'mid',
                defaultPos2: 'zeroOrMin',
                range: orient !== 'vertical' // include x2 for horizontal or line segment rule
            }),
            ...pointOrRangePosition('y', model, {
                defaultPos: orient === 'vertical' ? 'zeroOrMax' : 'mid',
                defaultPos2: 'zeroOrMin',
                range: orient !== 'horizontal' // include y2 for vertical or line segment rule
            }),
            ...nonPosition('size', model, {
                vgChannel: 'strokeWidth' // VL's rule size is strokeWidth
            })
        };
    }
};
//# sourceMappingURL=rule.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/text.js


const mark_text_text = {
    vgMark: 'text',
    encodeEntry: (model) => {
        const { config, encoding } = model;
        return {
            ...baseEncodeEntry(model, {
                align: 'include',
                baseline: 'include',
                color: 'include',
                size: 'ignore',
                orient: 'ignore',
                theta: 'include'
            }),
            ...pointPosition('x', model, { defaultPos: 'mid' }),
            ...pointPosition('y', model, { defaultPos: 'mid' }),
            ...text_text(model),
            ...nonPosition('size', model, {
                vgChannel: 'fontSize' // VL's text size is fontSize
            }),
            ...nonPosition('angle', model),
            ...valueIfDefined('align', text_align(model.markDef, encoding, config)),
            ...valueIfDefined('baseline', text_baseline(model.markDef, encoding, config)),
            ...pointPosition('radius', model, { defaultPos: null }),
            ...pointPosition('theta', model, { defaultPos: null })
        };
    }
};
function text_align(markDef, encoding, config) {
    const a = getMarkPropOrConfig('align', markDef, config);
    if (a === undefined) {
        return 'center';
    }
    // If there is a config, Vega-parser will process this already.
    return undefined;
}
function text_baseline(markDef, encoding, config) {
    const b = getMarkPropOrConfig('baseline', markDef, config);
    if (b === undefined) {
        return 'middle';
    }
    // If there is a config, Vega-parser will process this already.
    return undefined;
}
//# sourceMappingURL=text.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/tick.js


const tick_tick = {
    vgMark: 'rect',
    encodeEntry: (model) => {
        const { config, markDef } = model;
        const orient = markDef.orient;
        const vgSizeAxisChannel = orient === 'horizontal' ? 'x' : 'y';
        const vgThicknessAxisChannel = orient === 'horizontal' ? 'y' : 'x';
        const vgThicknessChannel = orient === 'horizontal' ? 'height' : 'width';
        return {
            ...baseEncodeEntry(model, {
                align: 'ignore',
                baseline: 'ignore',
                color: 'include',
                orient: 'ignore',
                size: 'ignore',
                theta: 'ignore'
            }),
            ...rectPosition(model, vgSizeAxisChannel),
            ...pointPosition(vgThicknessAxisChannel, model, {
                defaultPos: 'mid',
                vgChannel: vgThicknessAxisChannel === 'y' ? 'yc' : 'xc'
            }),
            [vgThicknessChannel]: signalOrValueRef(getMarkPropOrConfig('thickness', markDef, config))
        };
    }
};
//# sourceMappingURL=tick.js.map
;// ../../node_modules/vega-lite/build/src/compile/mark/mark.js



















const markCompiler = {
    arc: arc_arc,
    area: area_area,
    bar: bar,
    circle: point_circle,
    geoshape: geoshape,
    image: image_image,
    line: line_line,
    point: mark_point_point,
    rect: rect_rect,
    rule: rule_rule,
    square: point_square,
    text: mark_text_text,
    tick: tick_tick,
    trail: line_trail
};
function parseMarkGroups(model) {
    if (util_contains([LINE, AREA, TRAIL], model.mark)) {
        const details = pathGroupingFields(model.mark, model.encoding);
        if (details.length > 0) {
            return getPathGroups(model, details);
        }
        // otherwise use standard mark groups
    }
    else if (model.mark === BAR) {
        const hasCornerRadius = VG_CORNERRADIUS_CHANNELS.some(prop => getMarkPropOrConfig(prop, model.markDef, model.config));
        if (model.stack && !model.fieldDef('size') && hasCornerRadius) {
            return getGroupsForStackedBarWithCornerRadius(model);
        }
    }
    return getMarkGroup(model);
}
const FACETED_PATH_PREFIX = 'faceted_path_';
function getPathGroups(model, details) {
    // TODO: for non-stacked plot, map order to zindex. (Maybe rename order for layer to zindex?)
    return [
        {
            name: model.getName('pathgroup'),
            type: 'group',
            from: {
                facet: {
                    name: FACETED_PATH_PREFIX + model.requestDataName(DataSourceType.Main),
                    data: model.requestDataName(DataSourceType.Main),
                    groupby: details
                }
            },
            encode: {
                update: {
                    width: { field: { group: 'width' } },
                    height: { field: { group: 'height' } }
                }
            },
            // With subfacet for line/area group, need to use faceted data from above.
            marks: getMarkGroup(model, { fromPrefix: FACETED_PATH_PREFIX })
        }
    ];
}
const STACK_GROUP_PREFIX = 'stack_group_';
/**
 * We need to put stacked bars into groups in order to enable cornerRadius for stacks.
 * If stack is used and the model doesn't have size encoding, we put the mark into groups,
 * and apply cornerRadius properties at the group.
 */
function getGroupsForStackedBarWithCornerRadius(model) {
    // Generate the mark
    const [mark] = getMarkGroup(model, { fromPrefix: STACK_GROUP_PREFIX });
    // Get the scale for the stacked field
    const fieldScale = model.scaleName(model.stack.fieldChannel);
    const stackField = (opt = {}) => model.vgField(model.stack.fieldChannel, opt);
    // Find the min/max of the pixel value on the stacked direction
    const stackFieldGroup = (func, expr) => {
        const vgFieldMinMax = [
            stackField({ prefix: 'min', suffix: 'start', expr }),
            stackField({ prefix: 'max', suffix: 'start', expr }),
            stackField({ prefix: 'min', suffix: 'end', expr }),
            stackField({ prefix: 'max', suffix: 'end', expr })
        ];
        return `${func}(${vgFieldMinMax.map(field => `scale('${fieldScale}',${field})`).join(',')})`;
    };
    let groupUpdate;
    let innerGroupUpdate;
    // Build the encoding for group and an inner group
    if (model.stack.fieldChannel === 'x') {
        // Move cornerRadius, y/yc/y2/height properties to group
        // Group x/x2 should be the min/max of the marks within
        groupUpdate = {
            ...util_pick(mark.encode.update, ['y', 'yc', 'y2', 'height', ...VG_CORNERRADIUS_CHANNELS]),
            x: { signal: stackFieldGroup('min', 'datum') },
            x2: { signal: stackFieldGroup('max', 'datum') },
            clip: { value: true }
        };
        // Inner group should revert the x translation, and pass height through
        innerGroupUpdate = {
            x: { field: { group: 'x' }, mult: -1 },
            height: { field: { group: 'height' } }
        };
        // The marks should use the same height as group, without y/yc/y2 properties (because it's already done by group)
        // This is why size encoding is not supported yet
        mark.encode.update = {
            ...omit(mark.encode.update, ['y', 'yc', 'y2']),
            height: { field: { group: 'height' } }
        };
    }
    else {
        groupUpdate = {
            ...util_pick(mark.encode.update, ['x', 'xc', 'x2', 'width']),
            y: { signal: stackFieldGroup('min', 'datum') },
            y2: { signal: stackFieldGroup('max', 'datum') },
            clip: { value: true }
        };
        innerGroupUpdate = {
            y: { field: { group: 'y' }, mult: -1 },
            width: { field: { group: 'width' } }
        };
        mark.encode.update = {
            ...omit(mark.encode.update, ['x', 'xc', 'x2']),
            width: { field: { group: 'width' } }
        };
    }
    // Deal with cornerRadius properties
    for (const key of VG_CORNERRADIUS_CHANNELS) {
        const configValue = getMarkConfig(key, model.markDef, model.config);
        // Move from mark to group
        if (mark.encode.update[key]) {
            groupUpdate[key] = mark.encode.update[key];
            delete mark.encode.update[key];
        }
        else if (configValue) {
            groupUpdate[key] = signalOrValueRef(configValue);
        }
        // Overwrite any cornerRadius on mark set by config --- they are already moved to the group
        if (configValue) {
            mark.encode.update[key] = { value: 0 };
        }
    }
    const groupby = [];
    if (model.stack.groupbyChannels?.length > 0) {
        for (const groupbyChannel of model.stack.groupbyChannels) {
            // For bin and time unit, we have to add bin/timeunit -end channels.
            const groupByField = model.fieldDef(groupbyChannel);
            const field = vgField(groupByField);
            if (field) {
                groupby.push(field);
            }
            if (groupByField?.bin || groupByField?.timeUnit) {
                groupby.push(vgField(groupByField, { binSuffix: 'end' }));
            }
        }
    }
    const strokeProperties = [
        'stroke',
        'strokeWidth',
        'strokeJoin',
        'strokeCap',
        'strokeDash',
        'strokeDashOffset',
        'strokeMiterLimit',
        'strokeOpacity'
    ];
    // Generate stroke properties for the group
    groupUpdate = strokeProperties.reduce((encode, prop) => {
        if (mark.encode.update[prop]) {
            return { ...encode, [prop]: mark.encode.update[prop] };
        }
        else {
            const configValue = getMarkConfig(prop, model.markDef, model.config);
            if (configValue !== undefined) {
                return { ...encode, [prop]: signalOrValueRef(configValue) };
            }
            else {
                return encode;
            }
        }
    }, groupUpdate);
    // Apply strokeForeground and strokeOffset if stroke is used
    if (groupUpdate.stroke) {
        groupUpdate.strokeForeground = { value: true };
        groupUpdate.strokeOffset = { value: 0 };
    }
    return [
        {
            type: 'group',
            from: {
                facet: {
                    data: model.requestDataName(DataSourceType.Main),
                    name: STACK_GROUP_PREFIX + model.requestDataName(DataSourceType.Main),
                    groupby,
                    aggregate: {
                        fields: [
                            stackField({ suffix: 'start' }),
                            stackField({ suffix: 'start' }),
                            stackField({ suffix: 'end' }),
                            stackField({ suffix: 'end' })
                        ],
                        ops: ['min', 'max', 'min', 'max']
                    }
                }
            },
            encode: {
                update: groupUpdate
            },
            marks: [
                {
                    type: 'group',
                    encode: { update: innerGroupUpdate },
                    marks: [mark]
                }
            ]
        }
    ];
}
function mark_getSort(model) {
    const { encoding, stack, mark, markDef, config } = model;
    const order = encoding.order;
    if ((!vega_util_module_isArray(order) && isValueDef(order) && isNullOrFalse(order.value)) ||
        (!order && isNullOrFalse(getMarkPropOrConfig('order', markDef, config)))) {
        return undefined;
    }
    else if ((vega_util_module_isArray(order) || isFieldDef(order)) && !stack) {
        // Sort by the order field if it is specified and the field is not stacked. (For stacked field, order specify stack order.)
        return sortParams(order, { expr: 'datum' });
    }
    else if (isPathMark(mark)) {
        // For both line and area, we sort values based on dimension by default
        const dimensionChannel = markDef.orient === 'horizontal' ? 'y' : 'x';
        const dimensionChannelDef = encoding[dimensionChannel];
        if (isFieldDef(dimensionChannelDef)) {
            return { field: dimensionChannel };
        }
    }
    return undefined;
}
function getMarkGroup(model, opt = { fromPrefix: '' }) {
    const { mark, markDef, encoding, config } = model;
    const clip = getFirstDefined(markDef.clip, scaleClip(model), projectionClip(model));
    const style = getStyles(markDef);
    const key = encoding.key;
    const sort = mark_getSort(model);
    const interactive = interactiveFlag(model);
    const aria = getMarkPropOrConfig('aria', markDef, config);
    const postEncodingTransform = markCompiler[mark].postEncodingTransform
        ? markCompiler[mark].postEncodingTransform(model)
        : null;
    return [
        {
            name: model.getName('marks'),
            type: markCompiler[mark].vgMark,
            ...(clip ? { clip } : {}),
            ...(style ? { style } : {}),
            ...(key ? { key: key.field } : {}),
            ...(sort ? { sort } : {}),
            ...(interactive ? interactive : {}),
            ...(aria === false ? { aria } : {}),
            from: { data: opt.fromPrefix + model.requestDataName(DataSourceType.Main) },
            encode: {
                update: markCompiler[mark].encodeEntry(model)
            },
            ...(postEncodingTransform
                ? {
                    transform: postEncodingTransform
                }
                : {})
        }
    ];
}
/**
 * If scales are bound to interval selections, we want to automatically clip
 * marks to account for panning/zooming interactions. We identify bound scales
 * by the selectionExtent property, which gets added during scale parsing.
 */
function scaleClip(model) {
    const xScale = model.getScaleComponent('x');
    const yScale = model.getScaleComponent('y');
    return xScale?.get('selectionExtent') || yScale?.get('selectionExtent') ? true : undefined;
}
/**
 * If we use a custom projection with auto-fitting to the geodata extent,
 * we need to clip to ensure the chart size doesn't explode.
 */
function projectionClip(model) {
    const projection = model.component.projection;
    return projection && !projection.isFit ? true : undefined;
}
/**
 * Only output interactive flags if we have selections defined somewhere in our model hierarchy.
 */
function interactiveFlag(model) {
    if (!model.component.selection)
        return null;
    const unitCount = util_keys(model.component.selection).length;
    let parentCount = unitCount;
    let parent = model.parent;
    while (parent && parentCount === 0) {
        parentCount = util_keys(parent.component.selection).length;
        parent = parent.parent;
    }
    return parentCount
        ? {
            interactive: unitCount > 0 || model.mark === 'geoshape' || !!model.encoding.tooltip || !!model.markDef.tooltip
        }
        : null;
}
//# sourceMappingURL=mark.js.map
;// ../../node_modules/vega-lite/build/src/compile/unit.js


























/**
 * Internal model of Vega-Lite specification for the compiler.
 */
class UnitModel extends ModelWithField {
    constructor(spec, parent, parentGivenName, parentGivenSize = {}, config) {
        super(spec, 'unit', parent, parentGivenName, config, undefined, isFrameMixins(spec) ? spec.view : undefined);
        this.specifiedScales = {};
        this.specifiedAxes = {};
        this.specifiedLegends = {};
        this.specifiedProjection = {};
        this.selection = [];
        this.children = [];
        /**
         * Corrects the data references in marks after assemble.
         */
        this.correctDataNames = (mark) => {
            // for normal data references
            if (mark.from?.data) {
                mark.from.data = this.lookupDataSource(mark.from.data);
                if ('time' in this.encoding) {
                    mark.from.data = mark.from.data + CURR;
                }
            }
            // for access to facet data
            if (mark.from?.facet?.data) {
                mark.from.facet.data = this.lookupDataSource(mark.from.facet.data);
                // TOOD(jzong) uncomment this when it's time to implement facet animation
                // if ('time' in this.encoding) {
                //   mark.from.facet.data = mark.from.facet.data + CURR;
                // }
            }
            return mark;
        };
        const markDef = isMarkDef(spec.mark) ? { ...spec.mark } : { type: spec.mark };
        const mark = markDef.type;
        // Need to init filled before other mark properties because encoding depends on filled but other mark properties depend on types inside encoding
        if (markDef.filled === undefined) {
            markDef.filled = defaultFilled(markDef, config, {
                graticule: spec.data && isGraticuleGenerator(spec.data)
            });
        }
        const encoding = (this.encoding = initEncoding(spec.encoding || {}, mark, markDef.filled, config));
        this.markDef = initMarkdef(markDef, encoding, config);
        this.size = initLayoutSize({
            encoding,
            size: isFrameMixins(spec)
                ? {
                    ...parentGivenSize,
                    ...(spec.width ? { width: spec.width } : {}),
                    ...(spec.height ? { height: spec.height } : {})
                }
                : parentGivenSize
        });
        // calculate stack properties
        this.stack = stack(this.markDef, encoding);
        this.specifiedScales = this.initScales(mark, encoding);
        this.specifiedAxes = this.initAxes(encoding);
        this.specifiedLegends = this.initLegends(encoding);
        this.specifiedProjection = spec.projection;
        // Selections will be initialized upon parse.
        this.selection = (spec.params ?? []).filter(p => isSelectionParameter(p));
    }
    get hasProjection() {
        const { encoding } = this;
        const isGeoShapeMark = this.mark === GEOSHAPE;
        const hasGeoPosition = encoding && GEOPOSITION_CHANNELS.some(channel => isFieldOrDatumDef(encoding[channel]));
        return isGeoShapeMark || hasGeoPosition;
    }
    /**
     * Return specified Vega-Lite scale domain for a particular channel
     * @param channel
     */
    scaleDomain(channel) {
        const scale = this.specifiedScales[channel];
        return scale ? scale.domain : undefined;
    }
    axis(channel) {
        return this.specifiedAxes[channel];
    }
    legend(channel) {
        return this.specifiedLegends[channel];
    }
    initScales(mark, encoding) {
        return SCALE_CHANNELS.reduce((scales, channel) => {
            const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]);
            if (fieldOrDatumDef) {
                scales[channel] = this.initScale(fieldOrDatumDef.scale ?? {});
            }
            return scales;
        }, {});
    }
    initScale(scale) {
        const { domain, range } = scale;
        // TODO: we could simplify this function if we had a recursive replace function
        const scaleInternal = replaceExprRef(scale);
        if (vega_util_module_isArray(domain)) {
            scaleInternal.domain = domain.map(signalRefOrValue);
        }
        if (vega_util_module_isArray(range)) {
            scaleInternal.range = range.map(signalRefOrValue);
        }
        return scaleInternal;
    }
    initAxes(encoding) {
        return POSITION_SCALE_CHANNELS.reduce((_axis, channel) => {
            // Position Axis
            // TODO: handle ConditionFieldDef
            const channelDef = encoding[channel];
            if (isFieldOrDatumDef(channelDef) ||
                (channel === channel_X && isFieldOrDatumDef(encoding.x2)) ||
                (channel === channel_Y && isFieldOrDatumDef(encoding.y2))) {
                const axisSpec = isFieldOrDatumDef(channelDef) ? channelDef.axis : undefined;
                _axis[channel] = axisSpec
                    ? this.initAxis({ ...axisSpec }) // convert truthy value to object
                    : axisSpec;
            }
            return _axis;
        }, {});
    }
    initAxis(axis) {
        const props = util_keys(axis);
        const axisInternal = {};
        for (const prop of props) {
            const val = axis[prop];
            axisInternal[prop] = isConditionalAxisValue(val)
                ? signalOrValueRefWithCondition(val)
                : signalRefOrValue(val);
        }
        return axisInternal;
    }
    initLegends(encoding) {
        return NONPOSITION_SCALE_CHANNELS.reduce((_legend, channel) => {
            const fieldOrDatumDef = getFieldOrDatumDef(encoding[channel]);
            if (fieldOrDatumDef && supportLegend(channel)) {
                const legend = fieldOrDatumDef.legend;
                _legend[channel] = legend
                    ? replaceExprRef(legend) // convert truthy value to object
                    : legend;
            }
            return _legend;
        }, {});
    }
    parseData() {
        this.component.data = parse_parseData(this);
    }
    parseLayoutSize() {
        parseUnitLayoutSize(this);
    }
    parseSelections() {
        this.component.selection = parseUnitSelection(this, this.selection);
    }
    parseMarkGroup() {
        this.component.mark = parseMarkGroups(this);
    }
    parseAxesAndHeaders() {
        this.component.axes = parseUnitAxes(this);
    }
    assembleSelectionTopLevelSignals(signals) {
        return assembleTopLevelSignals(this, signals);
    }
    assembleSignals() {
        return [...assembleAxisSignals(this), ...assembleUnitSelectionSignals(this, [])];
    }
    assembleSelectionData(data) {
        return assembleUnitSelectionData(this, data);
    }
    assembleLayout() {
        return null;
    }
    assembleLayoutSignals() {
        return assembleLayoutSignals(this);
    }
    assembleMarks() {
        let marks = this.component.mark ?? [];
        // If this unit is part of a layer, selections should augment
        // all in concert rather than each unit individually. This
        // ensures correct interleaving of clipping and brushed marks.
        if (!this.parent || !isLayerModel(this.parent)) {
            marks = assembleUnitSelectionMarks(this, marks);
        }
        return marks.map(this.correctDataNames);
    }
    assembleGroupStyle() {
        const { style } = this.view || {};
        if (style !== undefined) {
            return style;
        }
        if (this.encoding.x || this.encoding.y) {
            return 'cell';
        }
        else {
            return 'view';
        }
    }
    getMapping() {
        return this.encoding;
    }
    get mark() {
        return this.markDef.type;
    }
    channelHasField(channel) {
        return channelHasField(this.encoding, channel);
    }
    fieldDef(channel) {
        const channelDef = this.encoding[channel];
        return getFieldDef(channelDef);
    }
    typedFieldDef(channel) {
        const fieldDef = this.fieldDef(channel);
        if (isTypedFieldDef(fieldDef)) {
            return fieldDef;
        }
        return null;
    }
}
//# sourceMappingURL=unit.js.map
;// ../../node_modules/vega-lite/build/src/compile/layer.js















class LayerModel extends Model {
    constructor(spec, parent, parentGivenName, parentGivenSize, config) {
        super(spec, 'layer', parent, parentGivenName, config, spec.resolve, spec.view);
        const layoutSize = {
            ...parentGivenSize,
            ...(spec.width ? { width: spec.width } : {}),
            ...(spec.height ? { height: spec.height } : {})
        };
        this.children = spec.layer.map((layer, i) => {
            if (isLayerSpec(layer)) {
                return new LayerModel(layer, this, this.getName(`layer_${i}`), layoutSize, config);
            }
            else if (isUnitSpec(layer)) {
                return new UnitModel(layer, this, this.getName(`layer_${i}`), layoutSize, config);
            }
            throw new Error(invalidSpec(layer));
        });
    }
    parseData() {
        this.component.data = parse_parseData(this);
        for (const child of this.children) {
            child.parseData();
        }
    }
    parseLayoutSize() {
        parseLayerLayoutSize(this);
    }
    parseSelections() {
        // Merge selections up the hierarchy so that they may be referenced
        // across unit specs. Persist their definitions within each child
        // to assemble signals which remain within output Vega unit groups.
        this.component.selection = {};
        for (const child of this.children) {
            child.parseSelections();
            for (const key of util_keys(child.component.selection)) {
                this.component.selection[key] = child.component.selection[key];
            }
        }
        if (Object.values(this.component.selection).some(selCmpt => isTimerSelection(selCmpt))) {
            log_error(MULTI_VIEW_ANIMATION_UNSUPPORTED);
        }
    }
    parseMarkGroup() {
        for (const child of this.children) {
            child.parseMarkGroup();
        }
    }
    parseAxesAndHeaders() {
        parseLayerAxes(this);
    }
    assembleSelectionTopLevelSignals(signals) {
        return this.children.reduce((sg, child) => child.assembleSelectionTopLevelSignals(sg), signals);
    }
    // TODO: Support same named selections across children.
    assembleSignals() {
        return this.children.reduce((signals, child) => {
            return signals.concat(child.assembleSignals());
        }, assembleAxisSignals(this));
    }
    assembleLayoutSignals() {
        return this.children.reduce((signals, child) => {
            return signals.concat(child.assembleLayoutSignals());
        }, assembleLayoutSignals(this));
    }
    assembleSelectionData(data) {
        return this.children.reduce((db, child) => child.assembleSelectionData(db), data);
    }
    assembleGroupStyle() {
        const uniqueStyles = new Set();
        for (const child of this.children) {
            for (const style of vega_util_module_array(child.assembleGroupStyle())) {
                uniqueStyles.add(style);
            }
        }
        const styles = Array.from(uniqueStyles);
        return styles.length > 1 ? styles : styles.length === 1 ? styles[0] : undefined;
    }
    assembleTitle() {
        let title = super.assembleTitle();
        if (title) {
            return title;
        }
        // If title does not provide layer, look into children
        for (const child of this.children) {
            title = child.assembleTitle();
            if (title) {
                return title;
            }
        }
        return undefined;
    }
    assembleLayout() {
        return null;
    }
    assembleMarks() {
        return assembleLayerSelectionMarks(this, this.children.flatMap(child => {
            return child.assembleMarks();
        }));
    }
    assembleLegends() {
        return this.children.reduce((legends, child) => {
            return legends.concat(child.assembleLegends());
        }, assembleLegends(this));
    }
}
//# sourceMappingURL=layer.js.map
;// ../../node_modules/vega-lite/build/src/compile/buildmodel.js






function buildModel(spec, parent, parentGivenName, unitSize, config) {
    if (isFacetSpec(spec)) {
        return new FacetModel(spec, parent, parentGivenName, config);
    }
    else if (isLayerSpec(spec)) {
        return new LayerModel(spec, parent, parentGivenName, unitSize, config);
    }
    else if (isUnitSpec(spec)) {
        return new UnitModel(spec, parent, parentGivenName, unitSize, config);
    }
    else if (isAnyConcatSpec(spec)) {
        return new ConcatModel(spec, parent, parentGivenName, config);
    }
    throw new Error(invalidSpec(spec));
}
//# sourceMappingURL=buildmodel.js.map
;// ../../node_modules/vega-lite/build/src/compile/compile.js












/**
 * Vega-Lite's main function, for compiling Vega-Lite spec into Vega spec.
 *
 * At a high-level, we make the following transformations in different phases:
 *
 * Input spec
 *     |
 *     |  (Normalization)
 *     v
 * Normalized Spec (Row/Column channels in single-view specs becomes faceted specs, composite marks becomes layered specs.)
 *     |
 *     |  (Build Model)
 *     v
 * A model tree of the spec
 *     |
 *     |  (Parse)
 *     v
 * A model tree with parsed components (intermediate structure of visualization primitives in a format that can be easily merged)
 *     |
 *     | (Optimize)
 *     v
 * A model tree with parsed components with the data component optimized
 *     |
 *     | (Assemble)
 *     v
 * Vega spec
 *
 * @param inputSpec The Vega-Lite specification.
 * @param opt       Optional arguments passed to the Vega-Lite compiler.
 * @returns         An object containing the compiled Vega spec and normalized Vega-Lite spec.
 */
function compile_compile(inputSpec, opt = {}) {
    // 0. Augment opt with default opts
    if (opt.logger) {
        // set the singleton logger to the provided logger
        log_set(opt.logger);
    }
    if (opt.fieldTitle) {
        // set the singleton field title formatter
        setTitleFormatter(opt.fieldTitle);
    }
    try {
        // 1. Initialize config by deep merging default config with the config provided via option and the input spec.
        const config = initConfig(mergeConfig(opt.config, inputSpec.config));
        // 2. Normalize: Convert input spec -> normalized spec
        // - Decompose all extended unit specs into composition of unit spec. For example, a box plot get expanded into multiple layers of bars, ticks, and rules. The shorthand row/column channel is also expanded to a facet spec.
        // - Normalize autosize and width or height spec
        const spec = normalize_normalize(inputSpec, config);
        // 3. Build Model: normalized spec -> Model (a tree structure)
        // This phases instantiates the models with default config by doing a top-down traversal. This allows us to pass properties that child models derive from their parents via their constructors.
        // See the abstract `Model` class and its children (UnitModel, LayerModel, FacetModel, ConcatModel) for different types of models.
        const model = buildModel(spec, null, '', undefined, config);
        // 4 Parse: Model --> Model with components
        // Note that components = intermediate representations that are equivalent to Vega specs.
        // We need these intermediate representation because we need to merge many visualization "components" like projections, scales, axes, and legends.
        // We will later convert these components into actual Vega specs in the assemble phase.
        // In this phase, we do a bottom-up traversal over the whole tree to
        // parse for each type of components once (e.g., data, layout, mark, scale).
        // By doing bottom-up traversal, we start parsing components of unit specs and
        // then merge child components of parent composite specs.
        //
        // Please see inside model.parse() for order of different components parsed.
        model.parse();
        // drawDataflow(model.component.data.sources);
        // 5. Optimize the dataflow. This will modify the data component of the model.
        optimizeDataflow(model.component.data, model);
        // drawDataflow(model.component.data.sources);
        // 6. Assemble: convert model components --> Vega Spec.
        const vgSpec = assembleTopLevelModel(model, getTopLevelProperties(inputSpec, spec.autosize, config, model), inputSpec.datasets, inputSpec.usermeta);
        return {
            spec: vgSpec,
            normalized: spec
        };
    }
    finally {
        // Reset the singleton logger if a logger is provided
        if (opt.logger) {
            log_reset();
        }
        // Reset the singleton field title formatter if provided
        if (opt.fieldTitle) {
            resetTitleFormatter();
        }
    }
}
function getTopLevelProperties(inputSpec, autosize, config, model) {
    const width = model.component.layoutSize.get('width');
    const height = model.component.layoutSize.get('height');
    if (autosize === undefined) {
        autosize = { type: 'pad' };
        if (model.hasAxisOrientSignalRef()) {
            autosize.resize = true;
        }
    }
    else if (vega_util_module_isString(autosize)) {
        autosize = { type: autosize };
    }
    if (width && height && isFitType(autosize.type)) {
        if (width === 'step' && height === 'step') {
            log_warn(droppingFit());
            autosize.type = 'pad';
        }
        else if (width === 'step' || height === 'step') {
            // effectively XOR, because else if
            // get step dimension
            const sizeType = width === 'step' ? 'width' : 'height';
            // log that we're dropping fit for respective channel
            log_warn(droppingFit(getPositionScaleChannel(sizeType)));
            // setting type to inverse fit (so if we dropped fit-x, type is now fit-y)
            const inverseSizeType = sizeType === 'width' ? 'height' : 'width';
            autosize.type = getFitType(inverseSizeType);
        }
    }
    return {
        ...(util_keys(autosize).length === 1 && autosize.type
            ? autosize.type === 'pad'
                ? {}
                : { autosize: autosize.type }
            : { autosize }),
        ...extractTopLevelProperties(config, false),
        ...extractTopLevelProperties(inputSpec, true)
    };
}
/*
 * Assemble the top-level model to a Vega spec.
 *
 * Note: this couldn't be `model.assemble()` since the top-level model
 * needs some special treatment to generate top-level properties.
 */
function assembleTopLevelModel(model, topLevelProperties, datasets = {}, usermeta) {
    // Config with Vega-Lite only config removed.
    const vgConfig = model.config ? stripAndRedirectConfig(model.config) : undefined;
    const rootData = assembleRootData(model.component.data, datasets);
    const data = model.assembleSelectionData(rootData);
    const projections = model.assembleProjections();
    const title = model.assembleTitle();
    const style = model.assembleGroupStyle();
    const encodeEntry = model.assembleGroupEncodeEntry(true);
    let layoutSignals = model.assembleLayoutSignals();
    // move width and height signals with values to top level
    layoutSignals = layoutSignals.filter(signal => {
        if ((signal.name === 'width' || signal.name === 'height') && signal.value !== undefined) {
            topLevelProperties[signal.name] = +signal.value;
            return false;
        }
        return true;
    });
    const { params, ...otherTopLevelProps } = topLevelProperties;
    return {
        $schema: 'https://vega.github.io/schema/vega/v5.json',
        ...(model.description ? { description: model.description } : {}),
        ...otherTopLevelProps,
        ...(title ? { title } : {}),
        ...(style ? { style } : {}),
        ...(encodeEntry ? { encode: { update: encodeEntry } } : {}),
        data,
        ...(projections.length > 0 ? { projections } : {}),
        ...model.assembleGroup([
            ...layoutSignals,
            ...model.assembleSelectionTopLevelSignals([]),
            ...assembleParameterSignals(params)
        ]),
        ...(vgConfig ? { config: vgConfig } : {}),
        ...(usermeta ? { usermeta } : {})
    };
}
//# sourceMappingURL=compile.js.map
;// ../../node_modules/vega-lite/build/src/index.js

const src_version = package_namespaceObject.rE;



//# sourceMappingURL=index.js.map
;// ../../node_modules/vega-schema-url-parser/dist/parser.module.js
function e(e){const[n,r]=/schema\/([\w-]+)\/([\w\.\-]+)\.json$/g.exec(e).slice(1,3);return{library:n,version:r}}/* harmony default export */ const parser_module = (e);
//# sourceMappingURL=parser.module.js.map

;// ../../node_modules/vega-themes/build/vega-themes.module.js
var vega_themes_module_name = "vega-themes";
var version$1 = "2.15.0";
var vega_themes_module_description = "Themes for stylized Vega and Vega-Lite visualizations.";
var vega_themes_module_keywords = ["vega", "vega-lite", "themes", "style"];
var license = "BSD-3-Clause";
var author = {
  name: "UW Interactive Data Lab",
  url: "https://idl.cs.washington.edu"
};
var contributors = [{
  name: "Emily Gu",
  url: "https://github.com/emilygu"
}, {
  name: "Arvind Satyanarayan",
  url: "http://arvindsatya.com"
}, {
  name: "Jeffrey Heer",
  url: "https://idl.cs.washington.edu"
}, {
  name: "Dominik Moritz",
  url: "https://www.domoritz.de"
}];
var vega_themes_module_main = "build/vega-themes.js";
var vega_themes_module_module = "build/vega-themes.module.js";
var unpkg = "build/vega-themes.min.js";
var jsdelivr = "build/vega-themes.min.js";
var vega_themes_module_types = "build/vega-themes.module.d.ts";
var repository = {
  type: "git",
  url: "https://github.com/vega/vega-themes.git"
};
var files = ["src", "build"];
var scripts = {
  prebuild: "yarn clean",
  build: "rollup -c",
  clean: "rimraf build && rimraf examples/build",
  "copy:data": "rsync -r node_modules/vega-datasets/data/* examples/data",
  "copy:build": "rsync -r build/* examples/build",
  "deploy:gh": "yarn build && mkdir -p examples/build && rsync -r build/* examples/build && gh-pages -d examples",
  preversion: "yarn lint",
  serve: "browser-sync start -s -f build examples --serveStatic examples",
  start: "yarn build && concurrently --kill-others -n Server,Rollup 'yarn serve' 'rollup -c -w'",
  format: "eslint . --fix",
  lint: "eslint .",
  release: "release-it"
};
var devDependencies = {
  "@babel/core": "^7.24.6",
  "@babel/plugin-transform-runtime": "^7.24.6",
  "@babel/preset-env": "^7.24.6",
  "@babel/preset-typescript": "^7.24.6",
  "@release-it/conventional-changelog": "^8.0.1",
  "@rollup/plugin-json": "^6.1.0",
  "@rollup/plugin-node-resolve": "^15.2.3",
  "@rollup/plugin-terser": "^0.4.4",
  "@typescript-eslint/eslint-plugin": "^7.11.0",
  "@typescript-eslint/parser": "^7.11.0",
  "browser-sync": "^3.0.2",
  concurrently: "^8.2.2",
  eslint: "^8.45.0",
  "eslint-config-prettier": "^9.1.0",
  "eslint-plugin-prettier": "^5.1.3",
  "gh-pages": "^6.1.1",
  prettier: "^3.2.5",
  "release-it": "^17.3.0",
  rollup: "^4.18.0",
  "rollup-plugin-bundle-size": "^1.0.3",
  "rollup-plugin-ts": "^3.4.5",
  typescript: "^5.4.5",
  vega: "^5.25.0",
  "vega-lite": "^5.9.3"
};
var peerDependencies = {
  vega: "*",
  "vega-lite": "*"
};
var dependencies = {};
var pkg = {
  name: vega_themes_module_name,
  version: version$1,
  description: vega_themes_module_description,
  keywords: vega_themes_module_keywords,
  license: license,
  author: author,
  contributors: contributors,
  main: vega_themes_module_main,
  module: vega_themes_module_module,
  unpkg: unpkg,
  jsdelivr: jsdelivr,
  types: vega_themes_module_types,
  repository: repository,
  files: files,
  scripts: scripts,
  devDependencies: devDependencies,
  peerDependencies: peerDependencies,
  dependencies: dependencies
};

const lightColor = '#fff';
const medColor = '#888';
const darkTheme = {
  background: '#333',
  view: {
    stroke: medColor
  },
  title: {
    color: lightColor,
    subtitleColor: lightColor
  },
  style: {
    'guide-label': {
      fill: lightColor
    },
    'guide-title': {
      fill: lightColor
    }
  },
  axis: {
    domainColor: lightColor,
    gridColor: medColor,
    tickColor: lightColor
  }
};

const markColor$7 = '#4572a7';
const excelTheme = {
  background: '#fff',
  arc: {
    fill: markColor$7
  },
  area: {
    fill: markColor$7
  },
  line: {
    stroke: markColor$7,
    strokeWidth: 2
  },
  path: {
    stroke: markColor$7
  },
  rect: {
    fill: markColor$7
  },
  shape: {
    stroke: markColor$7
  },
  symbol: {
    fill: markColor$7,
    strokeWidth: 1.5,
    size: 50
  },
  axis: {
    bandPosition: 0.5,
    grid: true,
    gridColor: '#000000',
    gridOpacity: 1,
    gridWidth: 0.5,
    labelPadding: 10,
    tickSize: 5,
    tickWidth: 0.5
  },
  axisBand: {
    grid: false,
    tickExtra: true
  },
  legend: {
    labelBaseline: 'middle',
    labelFontSize: 11,
    symbolSize: 50,
    symbolType: 'square'
  },
  range: {
    category: ['#4572a7', '#aa4643', '#8aa453', '#71598e', '#4598ae', '#d98445', '#94aace', '#d09393', '#b9cc98', '#a99cbc']
  }
};

const markColor$6 = '#30a2da';
const axisColor$2 = '#cbcbcb';
const guideLabelColor = '#999';
const guideTitleColor = '#333';
const backgroundColor$2 = '#f0f0f0';
const blackTitle = '#333';
const fiveThirtyEightTheme = {
  arc: {
    fill: markColor$6
  },
  area: {
    fill: markColor$6
  },
  axis: {
    domainColor: axisColor$2,
    grid: true,
    gridColor: axisColor$2,
    gridWidth: 1,
    labelColor: guideLabelColor,
    labelFontSize: 10,
    titleColor: guideTitleColor,
    tickColor: axisColor$2,
    tickSize: 10,
    titleFontSize: 14,
    titlePadding: 10,
    labelPadding: 4
  },
  axisBand: {
    grid: false
  },
  background: backgroundColor$2,
  group: {
    fill: backgroundColor$2
  },
  legend: {
    labelColor: blackTitle,
    labelFontSize: 11,
    padding: 1,
    symbolSize: 30,
    symbolType: 'square',
    titleColor: blackTitle,
    titleFontSize: 14,
    titlePadding: 10
  },
  line: {
    stroke: markColor$6,
    strokeWidth: 2
  },
  path: {
    stroke: markColor$6,
    strokeWidth: 0.5
  },
  rect: {
    fill: markColor$6
  },
  range: {
    category: ['#30a2da', '#fc4f30', '#e5ae38', '#6d904f', '#8b8b8b', '#b96db8', '#ff9e27', '#56cc60', '#52d2ca', '#52689e', '#545454', '#9fe4f8'],
    diverging: ['#cc0020', '#e77866', '#f6e7e1', '#d6e8ed', '#91bfd9', '#1d78b5'],
    heatmap: ['#d6e8ed', '#cee0e5', '#91bfd9', '#549cc6', '#1d78b5']
  },
  point: {
    filled: true,
    shape: 'circle'
  },
  shape: {
    stroke: markColor$6
  },
  bar: {
    binSpacing: 2,
    fill: markColor$6,
    stroke: null
  },
  title: {
    anchor: 'start',
    fontSize: 24,
    fontWeight: 600,
    offset: 20
  }
};

const markColor$5 = '#000';
const ggplot2Theme = {
  group: {
    fill: '#e5e5e5'
  },
  arc: {
    fill: markColor$5
  },
  area: {
    fill: markColor$5
  },
  line: {
    stroke: markColor$5
  },
  path: {
    stroke: markColor$5
  },
  rect: {
    fill: markColor$5
  },
  shape: {
    stroke: markColor$5
  },
  symbol: {
    fill: markColor$5,
    size: 40
  },
  axis: {
    domain: false,
    grid: true,
    gridColor: '#FFFFFF',
    gridOpacity: 1,
    labelColor: '#7F7F7F',
    labelPadding: 4,
    tickColor: '#7F7F7F',
    tickSize: 5.67,
    titleFontSize: 16,
    titleFontWeight: 'normal'
  },
  legend: {
    labelBaseline: 'middle',
    labelFontSize: 11,
    symbolSize: 40
  },
  range: {
    category: ['#000000', '#7F7F7F', '#1A1A1A', '#999999', '#333333', '#B0B0B0', '#4D4D4D', '#C9C9C9', '#666666', '#DCDCDC']
  }
};

const headlineFontSize = 22;
const headlineFontWeight = 'normal';
const labelFont$1 = 'Benton Gothic, sans-serif';
const labelFontSize = 11.5;
const labelFontWeight = 'normal';
const markColor$4 = '#82c6df';
// const markHighlight = '#006d8f';
// const markDemocrat = '#5789b8';
// const markRepublican = '#d94f54';
const titleFont = 'Benton Gothic Bold, sans-serif';
const titleFontWeight = 'normal';
const titleFontSize$1 = 13;
const colorSchemes$1 = {
  'category-6': ['#ec8431', '#829eb1', '#c89d29', '#3580b1', '#adc839', '#ab7fb4'],
  'fire-7': ['#fbf2c7', '#f9e39c', '#f8d36e', '#f4bb6a', '#e68a4f', '#d15a40', '#ab4232'],
  'fireandice-6': ['#e68a4f', '#f4bb6a', '#f9e39c', '#dadfe2', '#a6b7c6', '#849eae'],
  'ice-7': ['#edefee', '#dadfe2', '#c4ccd2', '#a6b7c6', '#849eae', '#607785', '#47525d']
};
const latimesTheme = {
  background: '#ffffff',
  title: {
    anchor: 'start',
    color: '#000000',
    font: titleFont,
    fontSize: headlineFontSize,
    fontWeight: headlineFontWeight
  },
  arc: {
    fill: markColor$4
  },
  area: {
    fill: markColor$4
  },
  line: {
    stroke: markColor$4,
    strokeWidth: 2
  },
  path: {
    stroke: markColor$4
  },
  rect: {
    fill: markColor$4
  },
  shape: {
    stroke: markColor$4
  },
  symbol: {
    fill: markColor$4,
    size: 30
  },
  axis: {
    labelFont: labelFont$1,
    labelFontSize,
    labelFontWeight,
    titleFont,
    titleFontSize: titleFontSize$1,
    titleFontWeight
  },
  axisX: {
    labelAngle: 0,
    labelPadding: 4,
    tickSize: 3
  },
  axisY: {
    labelBaseline: 'middle',
    maxExtent: 45,
    minExtent: 45,
    tickSize: 2,
    titleAlign: 'left',
    titleAngle: 0,
    titleX: -45,
    titleY: -11
  },
  legend: {
    labelFont: labelFont$1,
    labelFontSize,
    symbolType: 'square',
    titleFont,
    titleFontSize: titleFontSize$1,
    titleFontWeight
  },
  range: {
    category: colorSchemes$1['category-6'],
    diverging: colorSchemes$1['fireandice-6'],
    heatmap: colorSchemes$1['fire-7'],
    ordinal: colorSchemes$1['fire-7'],
    ramp: colorSchemes$1['fire-7']
  }
};

const markColor$3 = '#ab5787';
const axisColor$1 = '#979797';
const quartzTheme = {
  background: '#f9f9f9',
  arc: {
    fill: markColor$3
  },
  area: {
    fill: markColor$3
  },
  line: {
    stroke: markColor$3
  },
  path: {
    stroke: markColor$3
  },
  rect: {
    fill: markColor$3
  },
  shape: {
    stroke: markColor$3
  },
  symbol: {
    fill: markColor$3,
    size: 30
  },
  axis: {
    domainColor: axisColor$1,
    domainWidth: 0.5,
    gridWidth: 0.2,
    labelColor: axisColor$1,
    tickColor: axisColor$1,
    tickWidth: 0.2,
    titleColor: axisColor$1
  },
  axisBand: {
    grid: false
  },
  axisX: {
    grid: true,
    tickSize: 10
  },
  axisY: {
    domain: false,
    grid: true,
    tickSize: 0
  },
  legend: {
    labelFontSize: 11,
    padding: 1,
    symbolSize: 30,
    symbolType: 'square'
  },
  range: {
    category: ['#ab5787', '#51b2e5', '#703c5c', '#168dd9', '#d190b6', '#00609f', '#d365ba', '#154866', '#666666', '#c4c4c4']
  }
};

const markColor$2 = '#3e5c69';
const voxTheme = {
  background: '#fff',
  arc: {
    fill: markColor$2
  },
  area: {
    fill: markColor$2
  },
  line: {
    stroke: markColor$2
  },
  path: {
    stroke: markColor$2
  },
  rect: {
    fill: markColor$2
  },
  shape: {
    stroke: markColor$2
  },
  symbol: {
    fill: markColor$2
  },
  axis: {
    domainWidth: 0.5,
    grid: true,
    labelPadding: 2,
    tickSize: 5,
    tickWidth: 0.5,
    titleFontWeight: 'normal'
  },
  axisBand: {
    grid: false
  },
  axisX: {
    gridWidth: 0.2
  },
  axisY: {
    gridDash: [3],
    gridWidth: 0.4
  },
  legend: {
    labelFontSize: 11,
    padding: 1,
    symbolType: 'square'
  },
  range: {
    category: ['#3e5c69', '#6793a6', '#182429', '#0570b0', '#3690c0', '#74a9cf', '#a6bddb', '#e2ddf2']
  }
};

const markColor$1 = '#1696d2';
const axisColor = '#000000';
const backgroundColor$1 = '#FFFFFF';
const vega_themes_module_font = 'Lato';
const labelFont = 'Lato';
const sourceFont = 'Lato';
const gridColor$1 = '#DEDDDD';
const titleFontSize = 18;
const colorSchemes = {
  'main-colors': ['#1696d2', '#d2d2d2', '#000000', '#fdbf11', '#ec008b', '#55b748', '#5c5859', '#db2b27'],
  'shades-blue': ['#CFE8F3', '#A2D4EC', '#73BFE2', '#46ABDB', '#1696D2', '#12719E', '#0A4C6A', '#062635'],
  'shades-gray': ['#F5F5F5', '#ECECEC', '#E3E3E3', '#DCDBDB', '#D2D2D2', '#9D9D9D', '#696969', '#353535'],
  'shades-yellow': ['#FFF2CF', '#FCE39E', '#FDD870', '#FCCB41', '#FDBF11', '#E88E2D', '#CA5800', '#843215'],
  'shades-magenta': ['#F5CBDF', '#EB99C2', '#E46AA7', '#E54096', '#EC008B', '#AF1F6B', '#761548', '#351123'],
  'shades-green': ['#DCEDD9', '#BCDEB4', '#98CF90', '#78C26D', '#55B748', '#408941', '#2C5C2D', '#1A2E19'],
  'shades-black': ['#D5D5D4', '#ADABAC', '#848081', '#5C5859', '#332D2F', '#262223', '#1A1717', '#0E0C0D'],
  'shades-red': ['#F8D5D4', '#F1AAA9', '#E9807D', '#E25552', '#DB2B27', '#A4201D', '#6E1614', '#370B0A'],
  'one-group': ['#1696d2', '#000000'],
  'two-groups-cat-1': ['#1696d2', '#000000'],
  'two-groups-cat-2': ['#1696d2', '#fdbf11'],
  'two-groups-cat-3': ['#1696d2', '#db2b27'],
  'two-groups-seq': ['#a2d4ec', '#1696d2'],
  'three-groups-cat': ['#1696d2', '#fdbf11', '#000000'],
  'three-groups-seq': ['#a2d4ec', '#1696d2', '#0a4c6a'],
  'four-groups-cat-1': ['#000000', '#d2d2d2', '#fdbf11', '#1696d2'],
  'four-groups-cat-2': ['#1696d2', '#ec0008b', '#fdbf11', '#5c5859'],
  'four-groups-seq': ['#cfe8f3', '#73bf42', '#1696d2', '#0a4c6a'],
  'five-groups-cat-1': ['#1696d2', '#fdbf11', '#d2d2d2', '#ec008b', '#000000'],
  'five-groups-cat-2': ['#1696d2', '#0a4c6a', '#d2d2d2', '#fdbf11', '#332d2f'],
  'five-groups-seq': ['#cfe8f3', '#73bf42', '#1696d2', '#0a4c6a', '#000000'],
  'six-groups-cat-1': ['#1696d2', '#ec008b', '#fdbf11', '#000000', '#d2d2d2', '#55b748'],
  'six-groups-cat-2': ['#1696d2', '#d2d2d2', '#ec008b', '#fdbf11', '#332d2f', '#0a4c6a'],
  'six-groups-seq': ['#cfe8f3', '#a2d4ec', '#73bfe2', '#46abdb', '#1696d2', '#12719e'],
  'diverging-colors': ['#ca5800', '#fdbf11', '#fdd870', '#fff2cf', '#cfe8f3', '#73bfe2', '#1696d2', '#0a4c6a']
};
const urbanInstituteTheme = {
  background: backgroundColor$1,
  title: {
    anchor: 'start',
    fontSize: titleFontSize,
    font: vega_themes_module_font
  },
  axisX: {
    domain: true,
    domainColor: axisColor,
    domainWidth: 1,
    grid: false,
    labelFontSize: 12,
    labelFont: labelFont,
    labelAngle: 0,
    tickColor: axisColor,
    tickSize: 5,
    titleFontSize: 12,
    titlePadding: 10,
    titleFont: vega_themes_module_font
  },
  axisY: {
    domain: false,
    domainWidth: 1,
    grid: true,
    gridColor: gridColor$1,
    gridWidth: 1,
    labelFontSize: 12,
    labelFont: labelFont,
    labelPadding: 8,
    ticks: false,
    titleFontSize: 12,
    titlePadding: 10,
    titleFont: vega_themes_module_font,
    titleAngle: 0,
    titleY: -10,
    titleX: 18
  },
  legend: {
    labelFontSize: 12,
    labelFont: labelFont,
    symbolSize: 100,
    titleFontSize: 12,
    titlePadding: 10,
    titleFont: vega_themes_module_font,
    orient: 'right',
    offset: 10
  },
  view: {
    stroke: 'transparent'
  },
  range: {
    category: colorSchemes['six-groups-cat-1'],
    diverging: colorSchemes['diverging-colors'],
    heatmap: colorSchemes['diverging-colors'],
    ordinal: colorSchemes['six-groups-seq'],
    ramp: colorSchemes['shades-blue']
  },
  area: {
    fill: markColor$1
  },
  rect: {
    fill: markColor$1
  },
  line: {
    color: markColor$1,
    stroke: markColor$1,
    strokeWidth: 5
  },
  trail: {
    color: markColor$1,
    stroke: markColor$1,
    strokeWidth: 0,
    size: 1
  },
  path: {
    stroke: markColor$1,
    strokeWidth: 0.5
  },
  point: {
    filled: true
  },
  text: {
    font: sourceFont,
    color: markColor$1,
    fontSize: 11,
    align: 'center',
    fontWeight: 400,
    size: 11
  },
  style: {
    bar: {
      fill: markColor$1,
      stroke: null
    }
  },
  arc: {
    fill: markColor$1
  },
  shape: {
    stroke: markColor$1
  },
  symbol: {
    fill: markColor$1,
    size: 30
  }
};

/**
 * Copyright 2020 Google LLC.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

const markColor = '#3366CC';
const gridColor = '#ccc';
const defaultFont$1 = 'Arial, sans-serif';
const googlechartsTheme = {
  arc: {
    fill: markColor
  },
  area: {
    fill: markColor
  },
  path: {
    stroke: markColor
  },
  rect: {
    fill: markColor
  },
  shape: {
    stroke: markColor
  },
  symbol: {
    stroke: markColor
  },
  circle: {
    fill: markColor
  },
  background: '#fff',
  padding: {
    top: 10,
    right: 10,
    bottom: 10,
    left: 10
  },
  style: {
    'guide-label': {
      font: defaultFont$1,
      fontSize: 12
    },
    'guide-title': {
      font: defaultFont$1,
      fontSize: 12
    },
    'group-title': {
      font: defaultFont$1,
      fontSize: 12
    }
  },
  title: {
    font: defaultFont$1,
    fontSize: 14,
    fontWeight: 'bold',
    dy: -3,
    anchor: 'start'
  },
  axis: {
    gridColor: gridColor,
    tickColor: gridColor,
    domain: false,
    grid: true
  },
  range: {
    category: ['#4285F4', '#DB4437', '#F4B400', '#0F9D58', '#AB47BC', '#00ACC1', '#FF7043', '#9E9D24', '#5C6BC0', '#F06292', '#00796B', '#C2185B'],
    heatmap: ['#c6dafc', '#5e97f6', '#2a56c6']
  }
};

const ptToPx = value => value * (1 / 3 + 1);
const fontSmallPx = ptToPx(9);
const legendFontPx = ptToPx(10);
const fontLargePx = ptToPx(12);
const fontStandard = 'Segoe UI';
const fontTitle = 'wf_standard-font, helvetica, arial, sans-serif';
const firstLevelElementColor = '#252423';
const secondLevelElementColor = '#605E5C';
const backgroundColor = 'transparent';
const backgroundSecondaryColor = '#C8C6C4';
const paletteColor1 = '#118DFF';
const paletteColor2 = '#12239E';
const paletteColor3 = '#E66C37';
const paletteColor4 = '#6B007B';
const paletteColor5 = '#E044A7';
const paletteColor6 = '#744EC2';
const paletteColor7 = '#D9B300';
const paletteColor8 = '#D64550';
const divergentColorMax = paletteColor1;
const divergentColorMin = '#DEEFFF';
const divergentPalette = [divergentColorMin, divergentColorMax];
const ordinalPalette = [divergentColorMin, '#c7e4ff', '#b0d9ff', '#9aceff', '#83c3ff', '#6cb9ff', '#55aeff', '#3fa3ff', '#2898ff', divergentColorMax];
const powerbiTheme = {
  view: {
    stroke: backgroundColor
  },
  background: backgroundColor,
  font: fontStandard,
  header: {
    titleFont: fontTitle,
    titleFontSize: fontLargePx,
    titleColor: firstLevelElementColor,
    labelFont: fontStandard,
    labelFontSize: legendFontPx,
    labelColor: secondLevelElementColor
  },
  axis: {
    ticks: false,
    grid: false,
    domain: false,
    labelColor: secondLevelElementColor,
    labelFontSize: fontSmallPx,
    titleFont: fontTitle,
    titleColor: firstLevelElementColor,
    titleFontSize: fontLargePx,
    titleFontWeight: 'normal'
  },
  axisQuantitative: {
    tickCount: 3,
    grid: true,
    gridColor: backgroundSecondaryColor,
    gridDash: [1, 5],
    labelFlush: false
  },
  axisBand: {
    tickExtra: true
  },
  axisX: {
    labelPadding: 5
  },
  axisY: {
    labelPadding: 10
  },
  bar: {
    fill: paletteColor1
  },
  line: {
    stroke: paletteColor1,
    strokeWidth: 3,
    strokeCap: 'round',
    strokeJoin: 'round'
  },
  text: {
    font: fontStandard,
    fontSize: fontSmallPx,
    fill: secondLevelElementColor
  },
  arc: {
    fill: paletteColor1
  },
  area: {
    fill: paletteColor1,
    line: true,
    opacity: 0.6
  },
  path: {
    stroke: paletteColor1
  },
  rect: {
    fill: paletteColor1
  },
  point: {
    fill: paletteColor1,
    filled: true,
    size: 75
  },
  shape: {
    stroke: paletteColor1
  },
  symbol: {
    fill: paletteColor1,
    strokeWidth: 1.5,
    size: 50
  },
  legend: {
    titleFont: fontStandard,
    titleFontWeight: 'bold',
    titleColor: secondLevelElementColor,
    labelFont: fontStandard,
    labelFontSize: legendFontPx,
    labelColor: secondLevelElementColor,
    symbolType: 'circle',
    symbolSize: 75
  },
  range: {
    category: [paletteColor1, paletteColor2, paletteColor3, paletteColor4, paletteColor5, paletteColor6, paletteColor7, paletteColor8],
    diverging: divergentPalette,
    heatmap: divergentPalette,
    ordinal: ordinalPalette
  }
};

const defaultFont = 'IBM Plex Sans,system-ui,-apple-system,BlinkMacSystemFont,".sfnstext-regular",sans-serif';
const condensedFont = 'IBM Plex Sans Condensed, system-ui, -apple-system, BlinkMacSystemFont, ".SFNSText-Regular", sans-serif';
const fontWeight = 400;
const TOKENS = {
  textPrimary: {
    g90: '#f4f4f4',
    g100: '#f4f4f4',
    white: '#161616',
    g10: '#161616'
  },
  textSecondary: {
    g90: '#c6c6c6',
    g100: '#c6c6c6',
    white: '#525252',
    g10: '#525252'
  },
  // layer
  layerAccent01: {
    white: '#e0e0e0',
    g10: '#e0e0e0',
    g90: '#525252',
    g100: '#393939'
  },
  // grid
  gridBg: {
    white: '#ffffff',
    g10: '#ffffff',
    g90: '#161616',
    g100: '#161616'
  }
};
const darkCategories = ['#8a3ffc', '#33b1ff', '#007d79', '#ff7eb6', '#fa4d56', '#fff1f1', '#6fdc8c', '#4589ff', '#d12771', '#d2a106', '#08bdba', '#bae6ff', '#ba4e00', '#d4bbff'];
const lightCategories = ['#6929c4', '#1192e8', '#005d5d', '#9f1853', '#fa4d56', '#570408', '#198038', '#002d9c', '#ee538b', '#b28600', '#009d9a', '#012749', '#8a3800', '#a56eff'];
function genCarbonConfig({
  theme,
  background
}) {
  const type = ['white', 'g10'].includes(theme) ? 'light' : 'dark';
  const viewbg = TOKENS.gridBg[theme];
  const titleColor = TOKENS.textPrimary[theme];
  const textColor = TOKENS.textSecondary[theme];
  const category = type === 'dark' ? darkCategories : lightCategories;
  const markColor = type === 'dark' ? '#d4bbff' : '#6929c4';
  return {
    background,
    arc: {
      fill: markColor
    },
    area: {
      fill: markColor
    },
    path: {
      stroke: markColor
    },
    rect: {
      fill: markColor
    },
    shape: {
      stroke: markColor
    },
    symbol: {
      stroke: markColor
    },
    circle: {
      fill: markColor
    },
    view: {
      fill: viewbg,
      stroke: viewbg
    },
    group: {
      fill: viewbg
    },
    title: {
      color: titleColor,
      anchor: 'start',
      dy: -15,
      fontSize: 16,
      font: defaultFont,
      fontWeight: 600
    },
    axis: {
      // Axis labels
      labelColor: textColor,
      labelFontSize: 12,
      labelFont: condensedFont,
      labelFontWeight: fontWeight,
      // Axis titles
      titleColor: titleColor,
      titleFontWeight: 600,
      titleFontSize: 12,
      // MISC
      grid: true,
      gridColor: TOKENS.layerAccent01[theme],
      labelAngle: 0
    },
    axisX: {
      titlePadding: 10
    },
    axisY: {
      titlePadding: 2.5
    },
    style: {
      'guide-label': {
        font: defaultFont,
        fill: textColor,
        fontWeight: fontWeight
      },
      'guide-title': {
        font: defaultFont,
        fill: textColor,
        fontWeight: fontWeight
      }
    },
    range: {
      category,
      diverging: ['#750e13', '#a2191f', '#da1e28', '#fa4d56', '#ff8389', '#ffb3b8', '#ffd7d9', '#fff1f1', '#e5f6ff', '#bae6ff', '#82cfff', '#33b1ff', '#1192e8', '#0072c3', '#00539a', '#003a6d'],
      heatmap: ['#f6f2ff', '#e8daff', '#d4bbff', '#be95ff', '#a56eff', '#8a3ffc', '#6929c4', '#491d8b', '#31135e', '#1c0f30']
    }
  };
}

const carbonwhite = genCarbonConfig({
  theme: 'white',
  background: '#ffffff'
});

const carbong10 = genCarbonConfig({
  theme: 'g10',
  background: '#f4f4f4'
});

const carbong90 = genCarbonConfig({
  theme: 'g90',
  background: '#262626'
});

const carbong100 = genCarbonConfig({
  theme: 'g100',
  background: '#161616'
});

const vega_themes_module_version = pkg.version;



;// ../../node_modules/vega-tooltip/build/vega-tooltip.module.js


var vega_tooltip_module_name = "vega-tooltip";
var vega_tooltip_module_version$1 = "0.35.2";
var vega_tooltip_module_description = "A tooltip plugin for Vega-Lite and Vega visualizations.";
var vega_tooltip_module_keywords = [
	"vega-lite",
	"vega",
	"tooltip"
];
var vega_tooltip_module_repository = {
	type: "git",
	url: "https://github.com/vega/vega-tooltip.git"
};
var vega_tooltip_module_author = {
	name: "UW Interactive Data Lab",
	url: "https://idl.cs.washington.edu"
};
var collaborators = [
	"Dominik Moritz",
	"Sira Horradarn",
	"Zening Qu",
	"Kanit Wongsuphasawat",
	"Yuri Astrakhan",
	"Jeffrey Heer"
];
var vega_tooltip_module_license = "BSD-3-Clause";
var bugs = {
	url: "https://github.com/vega/vega-tooltip/issues"
};
var homepage = "https://github.com/vega/vega-tooltip#readme";
var vega_tooltip_module_main = "build/vega-tooltip.js";
var vega_tooltip_module_module = "build/vega-tooltip.module.js";
var vega_tooltip_module_unpkg = "build/vega-tooltip.min.js";
var vega_tooltip_module_jsdelivr = "build/vega-tooltip.min.js";
var vega_tooltip_module_types = "build/src/index.d.ts";
var vega_tooltip_module_files = [
	"src",
	"build",
	"types"
];
var vega_tooltip_module_scripts = {
	prebuild: "npm run clean && npm run build:style",
	build: "rollup -c",
	"build:style": "./build-style.sh",
	clean: "rimraf build && rimraf src/style.ts",
	"copy:data": "cp -R node_modules/vega-datasets/data examples",
	"copy:build": "cp -R build examples",
	"deploy:gh": "npm run build && npm run copy:build && gh-pages -d examples && npm run clean",
	prepublishOnly: "npm run clean && npm run build",
	preversion: "npm run lint && npm run test",
	serve: "browser-sync start -s -f build examples --serveStatic examples",
	start: "npm run build && concurrently --kill-others -n Server,Rollup 'npm run serve' 'rollup -c -w'",
	pretest: "npm run build:style",
	test: "jest",
	"test:inspect": "node --inspect-brk ./node_modules/.bin/jest --runInBand",
	prepare: "npm run copy:data",
	prettierbase: "prettier '*.{css,scss,html}'",
	format: "eslint . --fix && npm run prettierbase -- --write",
	lint: "eslint . && npm run prettierbase -- --check",
	release: "release-it"
};
var vega_tooltip_module_devDependencies = {
	"@babel/core": "^7.26.0",
	"@babel/plugin-proposal-async-generator-functions": "^7.20.7",
	"@babel/plugin-proposal-json-strings": "^7.18.6",
	"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
	"@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
	"@babel/plugin-syntax-dynamic-import": "^7.8.3",
	"@babel/plugin-transform-runtime": "^7.25.9",
	"@babel/preset-env": "^7.26.0",
	"@babel/preset-typescript": "^7.26.0",
	"@release-it/conventional-changelog": "^9.0.2",
	"@rollup/plugin-json": "^6.1.0",
	"@rollup/plugin-node-resolve": "^15.3.0",
	"@rollup/plugin-terser": "^0.4.4",
	"@rollup/plugin-typescript": "^12.1.1",
	"@types/jest": "^29.5.14",
	"@typescript-eslint/eslint-plugin": "^8.13.0",
	"@typescript-eslint/parser": "^8.13.0",
	"browser-sync": "^3.0.3",
	concurrently: "^9.1.0",
	eslint: "^8.46.0",
	"eslint-config-prettier": "^9.1.0",
	"eslint-plugin-jest": "^28.8.3",
	"eslint-plugin-prettier": "^5.2.1",
	"gh-pages": "^6.2.0",
	jest: "^29.7.0",
	"jest-environment-jsdom": "^29.7.0",
	path: "^0.12.7",
	prettier: "^3.3.3",
	"release-it": "^17.10.0",
	rollup: "^4.24.4",
	"rollup-plugin-bundle-size": "^1.0.3",
	sass: "^1.80.6",
	typescript: "~5.6.3",
	"vega-datasets": "^2.9.0",
	"vega-typings": "^1.3.1"
};
var vega_tooltip_module_dependencies = {
	"vega-util": "^1.17.2"
};
var optionalDependencies = {
	"@rollup/rollup-linux-x64-gnu": "^4.24.4"
};
var vega_tooltip_module_pkg = {
	name: vega_tooltip_module_name,
	version: vega_tooltip_module_version$1,
	description: vega_tooltip_module_description,
	keywords: vega_tooltip_module_keywords,
	repository: vega_tooltip_module_repository,
	author: vega_tooltip_module_author,
	collaborators: collaborators,
	license: vega_tooltip_module_license,
	bugs: bugs,
	homepage: homepage,
	main: vega_tooltip_module_main,
	module: vega_tooltip_module_module,
	unpkg: vega_tooltip_module_unpkg,
	jsdelivr: vega_tooltip_module_jsdelivr,
	types: vega_tooltip_module_types,
	files: vega_tooltip_module_files,
	scripts: vega_tooltip_module_scripts,
	devDependencies: vega_tooltip_module_devDependencies,
	dependencies: vega_tooltip_module_dependencies,
	optionalDependencies: optionalDependencies
};

/**
 * Format the value to be shown in the tooltip.
 *
 * @param value The value to show in the tooltip.
 * @param valueToHtml Function to convert a single cell value to an HTML string
 */
function vega_tooltip_module_formatValue(value, valueToHtml, maxDepth, baseURL) {
    if (vega_util_module_isArray(value)) {
        return `[${value.map((v) => valueToHtml(vega_util_module_isString(v) ? v : vega_tooltip_module_stringify(v, maxDepth))).join(', ')}]`;
    }
    if (vega_util_module_isObject(value)) {
        let content = '';
        const { title, image, ...rest } = value;
        if (title) {
            content += `<h2>${valueToHtml(title)}</h2>`;
        }
        if (image) {
            content += `<img src="${new URL(valueToHtml(image), baseURL || location.href).href}">`;
        }
        const keys = Object.keys(rest);
        if (keys.length > 0) {
            content += '<table>';
            for (const key of keys) {
                let val = rest[key];
                // ignore undefined properties
                if (val === undefined) {
                    continue;
                }
                if (vega_util_module_isObject(val)) {
                    val = vega_tooltip_module_stringify(val, maxDepth);
                }
                content += `<tr><td class="key">${valueToHtml(key)}</td><td class="value">${valueToHtml(val)}</td></tr>`;
            }
            content += `</table>`;
        }
        return content || '{}'; // show empty object if there are no properties
    }
    return valueToHtml(value);
}
function replacer(maxDepth) {
    const stack = [];
    return function (key, value) {
        if (typeof value !== 'object' || value === null) {
            return value;
        }
        const pos = stack.indexOf(this) + 1;
        stack.length = pos;
        if (stack.length > maxDepth) {
            return '[Object]';
        }
        if (stack.indexOf(value) >= 0) {
            return '[Circular]';
        }
        stack.push(value);
        return value;
    };
}
/**
 * Stringify any JS object to valid JSON
 */
function vega_tooltip_module_stringify(obj, maxDepth) {
    return JSON.stringify(obj, replacer(maxDepth));
}

// generated with build-style.sh
var defaultStyle = `#vg-tooltip-element {
  visibility: hidden;
  padding: 8px;
  position: fixed;
  z-index: 1000;
  font-family: sans-serif;
  font-size: 11px;
  border-radius: 3px;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
  /* The default theme is the light theme. */
  background-color: rgba(255, 255, 255, 0.95);
  border: 1px solid #d9d9d9;
  color: black;
}
#vg-tooltip-element.visible {
  visibility: visible;
}
#vg-tooltip-element h2 {
  margin-top: 0;
  margin-bottom: 10px;
  font-size: 13px;
}
#vg-tooltip-element table {
  border-spacing: 0;
}
#vg-tooltip-element table tr {
  border: none;
}
#vg-tooltip-element table tr td {
  overflow: hidden;
  text-overflow: ellipsis;
  padding-top: 2px;
  padding-bottom: 2px;
}
#vg-tooltip-element table tr td.key {
  color: #808080;
  max-width: 150px;
  text-align: right;
  padding-right: 4px;
}
#vg-tooltip-element table tr td.value {
  display: block;
  max-width: 300px;
  max-height: 7em;
  text-align: left;
}
#vg-tooltip-element.dark-theme {
  background-color: rgba(32, 32, 32, 0.9);
  border: 1px solid #f5f5f5;
  color: white;
}
#vg-tooltip-element.dark-theme td.key {
  color: #bfbfbf;
}
`;

const EL_ID = 'vg-tooltip-element';
const DEFAULT_OPTIONS = {
    offsetX: 10,
    offsetY: 10,
    id: EL_ID,
    styleId: 'vega-tooltip-style',
    theme: 'light',
    disableDefaultStyle: false,
    sanitize: escapeHTML,
    maxDepth: 2,
    formatTooltip: vega_tooltip_module_formatValue,
    baseURL: '',
    anchor: 'cursor',
    position: ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
};
/**
 * Escape special HTML characters.
 *
 * @param value A value to convert to string and HTML-escape.
 */
function escapeHTML(value) {
    return String(value).replace(/&/g, '&amp;').replace(/</g, '&lt;');
}
function createDefaultStyle(id) {
    // Just in case this id comes from a user, ensure these is no security issues
    if (!/^[A-Za-z]+[-:.\w]*$/.test(id)) {
        throw new Error('Invalid HTML ID');
    }
    return defaultStyle.toString().replace(EL_ID, id);
}

/**
 * Position the tooltip
 *
 * @param event The mouse event.
 * @param tooltipBox
 * @param options Tooltip handler options.
 */
function calculatePositionRelativeToCursor(event, tooltipBox, { offsetX, offsetY }) {
    // the possible positions for the tooltip
    const positions = getPositions({ x1: event.clientX, x2: event.clientX, y1: event.clientY, y2: event.clientY }, tooltipBox, offsetX, offsetY);
    // order of positions to try
    const postionArr = ['bottom-right', 'bottom-left', 'top-right', 'top-left'];
    // test positions till a valid one is found
    for (const p of postionArr) {
        if (tooltipIsInViewport(positions[p], tooltipBox)) {
            return positions[p];
        }
    }
    // default to top-left if a valid position is not found
    // this is legacy behavior
    return positions['top-left'];
}
/**
 * Calculates the position of the tooltip relative to the mark.
 * @param handler The handler instance.
 * @param event The mouse event.
 * @param item The item that the tooltip is being shown for.
 * @param tooltipBox Client rect of the tooltip element.
 * @param options Tooltip handler options.
 * @returns
 */
function calculatePositionRelativeToMark(handler, event, item, tooltipBox, options) {
    const { position, offsetX, offsetY } = options;
    const containerBox = handler._el.getBoundingClientRect();
    const origin = handler._origin;
    // bounds of the mark relative to the viewport
    const markBounds = getMarkBounds(containerBox, origin, item);
    // the possible positions for the tooltip
    const positions = getPositions(markBounds, tooltipBox, offsetX, offsetY);
    // positions to test
    const positionArr = Array.isArray(position) ? position : [position];
    // test positions till a valid one is found
    for (const p of positionArr) {
        // verify that the tooltip is in the view and the mouse is not where the tooltip would be
        if (tooltipIsInViewport(positions[p], tooltipBox) && !mouseIsOnTooltip(event, positions[p], tooltipBox)) {
            return positions[p];
        }
    }
    // default to cursor position if a valid position is not found
    return calculatePositionRelativeToCursor(event, tooltipBox, options);
}
// Calculates the bounds of the mark relative to the viewport.
function getMarkBounds(containerBox, origin, item) {
    // if this is a voronoi mark, we want to use the bounds of the point that voronoi cell represents
    const markBounds = item.isVoronoi ? item.datum.bounds : item.bounds;
    let left = containerBox.left + origin[0] + markBounds.x1;
    let top = containerBox.top + origin[1] + markBounds.y1;
    // traverse mark groups, summing their offsets to get the total offset
    // item bounds are relative to their group so if there are multiple nested groups we need to add them all
    let parentItem = item;
    while (parentItem.mark.group) {
        parentItem = parentItem.mark.group;
        left += parentItem.x ?? 0;
        top += parentItem.y ?? 0;
    }
    const markWidth = markBounds.x2 - markBounds.x1;
    const markHeight = markBounds.y2 - markBounds.y1;
    return {
        x1: left,
        x2: left + markWidth,
        y1: top,
        y2: top + markHeight,
    };
}
// Calculates the tooltip xy for each possible position.
function getPositions(markBounds, tooltipBox, offsetX, offsetY) {
    const xc = (markBounds.x1 + markBounds.x2) / 2;
    const yc = (markBounds.y1 + markBounds.y2) / 2;
    // x positions
    const left = markBounds.x1 - tooltipBox.width - offsetX;
    const center = xc - tooltipBox.width / 2;
    const right = markBounds.x2 + offsetX;
    // y positions
    const top = markBounds.y1 - tooltipBox.height - offsetY;
    const middle = yc - tooltipBox.height / 2;
    const bottom = markBounds.y2 + offsetY;
    const positions = {
        top: { x: center, y: top },
        bottom: { x: center, y: bottom },
        left: { x: left, y: middle },
        right: { x: right, y: middle },
        'top-left': { x: left, y: top },
        'top-right': { x: right, y: top },
        'bottom-left': { x: left, y: bottom },
        'bottom-right': { x: right, y: bottom },
    };
    return positions;
}
// Checks if the tooltip would be in the viewport at the given position
function tooltipIsInViewport(position, tooltipBox) {
    return (position.x >= 0 &&
        position.y >= 0 &&
        position.x + tooltipBox.width <= window.innerWidth &&
        position.y + tooltipBox.height <= window.innerHeight);
}
// Checks if the mouse is within the tooltip area
function mouseIsOnTooltip(event, position, tooltipBox) {
    return (event.clientX >= position.x &&
        event.clientX <= position.x + tooltipBox.width &&
        event.clientY >= position.y &&
        event.clientY <= position.y + tooltipBox.height);
}

/**
 * The tooltip handler class.
 */
class vega_tooltip_module_Handler {
    /**
     * Create the tooltip handler and initialize the element and style.
     *
     * @param options Tooltip Options
     */
    constructor(options) {
        this.options = { ...DEFAULT_OPTIONS, ...options };
        const elementId = this.options.id;
        this.el = null;
        // bind this to call
        this.call = this.tooltipHandler.bind(this);
        // prepend a default stylesheet for tooltips to the head
        if (!this.options.disableDefaultStyle && !document.getElementById(this.options.styleId)) {
            const style = document.createElement('style');
            style.setAttribute('id', this.options.styleId);
            style.innerHTML = createDefaultStyle(elementId);
            const head = document.head;
            if (head.childNodes.length > 0) {
                head.insertBefore(style, head.childNodes[0]);
            }
            else {
                head.appendChild(style);
            }
        }
    }
    /**
     * The tooltip handler function.
     */
    tooltipHandler(handler, event, item, value) {
        // append a div element that we use as a tooltip unless it already exists
        this.el = document.getElementById(this.options.id);
        if (!this.el) {
            this.el = document.createElement('div');
            this.el.setAttribute('id', this.options.id);
            this.el.classList.add('vg-tooltip');
            const tooltipContainer = document.fullscreenElement ?? document.body;
            tooltipContainer.appendChild(this.el);
        }
        // hide tooltip for null, undefined, or empty string values
        if (value == null || value === '') {
            this.el.classList.remove('visible', `${this.options.theme}-theme`);
            return;
        }
        // set the tooltip content
        this.el.innerHTML = this.options.formatTooltip(value, this.options.sanitize, this.options.maxDepth, this.options.baseURL);
        // make the tooltip visible
        this.el.classList.add('visible', `${this.options.theme}-theme`);
        const { x, y } = this.options.anchor === 'mark'
            ? calculatePositionRelativeToMark(handler, event, item, this.el.getBoundingClientRect(), this.options)
            : calculatePositionRelativeToCursor(event, this.el.getBoundingClientRect(), this.options);
        this.el.style.top = `${y}px`;
        this.el.style.left = `${x}px`;
    }
}

const vega_tooltip_module_version = vega_tooltip_module_pkg.version;
/**
 * Create a tooltip handler and register it with the provided view.
 *
 * @param view The Vega view.
 * @param opt Tooltip options.
 */
function vega_tooltip_module_index (view, opt) {
    const handler = new vega_tooltip_module_Handler(opt);
    view.tooltip(handler.call).run();
    return handler;
}


//# sourceMappingURL=vega-tooltip.module.js.map

;// ../../node_modules/vega-embed/build/vega-embed.module.js









/*!
 * https://github.com/Starcounter-Jack/JSON-Patch
 * (c) 2017-2022 Joachim Wester
 * MIT licensed
 */
var __extends = ( false) || (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 __());
    };
})();
var _hasOwnProperty = Object.prototype.hasOwnProperty;
function vega_embed_module_hasOwnProperty(obj, key) {
    return _hasOwnProperty.call(obj, key);
}
function _objectKeys(obj) {
    if (Array.isArray(obj)) {
        var keys_1 = new Array(obj.length);
        for (var k = 0; k < keys_1.length; k++) {
            keys_1[k] = "" + k;
        }
        return keys_1;
    }
    if (Object.keys) {
        return Object.keys(obj);
    }
    var keys = [];
    for (var i in obj) {
        if (vega_embed_module_hasOwnProperty(obj, i)) {
            keys.push(i);
        }
    }
    return keys;
}
/**
* Deeply clone the object.
* https://jsperf.com/deep-copy-vs-json-stringify-json-parse/25 (recursiveDeepCopy)
* @param  {any} obj value to clone
* @return {any} cloned obj
*/
function _deepClone(obj) {
    switch (typeof obj) {
        case "object":
            return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5
        case "undefined":
            return null; //this is how JSON.stringify behaves for array items
        default:
            return obj; //no need to clone primitives
    }
}
//3x faster than cached /^\d+$/.test(str)
function vega_embed_module_isInteger(str) {
    var i = 0;
    var len = str.length;
    var charCode;
    while (i < len) {
        charCode = str.charCodeAt(i);
        if (charCode >= 48 && charCode <= 57) {
            i++;
            continue;
        }
        return false;
    }
    return true;
}
/**
* Escapes a json pointer path
* @param path The raw pointer
* @return the Escaped path
*/
function escapePathComponent(path) {
    if (path.indexOf('/') === -1 && path.indexOf('~') === -1)
        return path;
    return path.replace(/~/g, '~0').replace(/\//g, '~1');
}
/**
 * Unescapes a json pointer path
 * @param path The escaped pointer
 * @return The unescaped path
 */
function unescapePathComponent(path) {
    return path.replace(/~1/g, '/').replace(/~0/g, '~');
}
/**
* Recursively checks whether an object has any undefined values inside.
*/
function hasUndefined(obj) {
    if (obj === undefined) {
        return true;
    }
    if (obj) {
        if (Array.isArray(obj)) {
            for (var i_1 = 0, len = obj.length; i_1 < len; i_1++) {
                if (hasUndefined(obj[i_1])) {
                    return true;
                }
            }
        }
        else if (typeof obj === "object") {
            var objKeys = _objectKeys(obj);
            var objKeysLength = objKeys.length;
            for (var i = 0; i < objKeysLength; i++) {
                if (hasUndefined(obj[objKeys[i]])) {
                    return true;
                }
            }
        }
    }
    return false;
}
function patchErrorMessageFormatter(message, args) {
    var messageParts = [message];
    for (var key in args) {
        var value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print
        if (typeof value !== 'undefined') {
            messageParts.push(key + ": " + value);
        }
    }
    return messageParts.join('\n');
}
var PatchError = /** @class */ (function (_super) {
    __extends(PatchError, _super);
    function PatchError(message, name, index, operation, tree) {
        var _newTarget = this.constructor;
        var _this = _super.call(this, patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree })) || this;
        _this.name = name;
        _this.index = index;
        _this.operation = operation;
        _this.tree = tree;
        Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359
        _this.message = patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree });
        return _this;
    }
    return PatchError;
}(Error));

var JsonPatchError = PatchError;
var deepClone = _deepClone;
/* We use a Javascript hash to store each
 function. Each hash entry (property) uses
 the operation identifiers specified in rfc6902.
 In this way, we can map each patch operation
 to its dedicated function in efficient way.
 */
/* The operations applicable to an object */
var objOps = {
    add: function (obj, key, document) {
        obj[key] = this.value;
        return { newDocument: document };
    },
    remove: function (obj, key, document) {
        var removed = obj[key];
        delete obj[key];
        return { newDocument: document, removed: removed };
    },
    replace: function (obj, key, document) {
        var removed = obj[key];
        obj[key] = this.value;
        return { newDocument: document, removed: removed };
    },
    move: function (obj, key, document) {
        /* in case move target overwrites an existing value,
        return the removed value, this can be taxing performance-wise,
        and is potentially unneeded */
        var removed = getValueByPointer(document, this.path);
        if (removed) {
            removed = _deepClone(removed);
        }
        var originalValue = applyOperation(document, { op: "remove", path: this.from }).removed;
        applyOperation(document, { op: "add", path: this.path, value: originalValue });
        return { newDocument: document, removed: removed };
    },
    copy: function (obj, key, document) {
        var valueToCopy = getValueByPointer(document, this.from);
        // enforce copy by value so further operations don't affect source (see issue #177)
        applyOperation(document, { op: "add", path: this.path, value: _deepClone(valueToCopy) });
        return { newDocument: document };
    },
    test: function (obj, key, document) {
        return { newDocument: document, test: _areEquals(obj[key], this.value) };
    },
    _get: function (obj, key, document) {
        this.value = obj[key];
        return { newDocument: document };
    }
};
/* The operations applicable to an array. Many are the same as for the object */
var arrOps = {
    add: function (arr, i, document) {
        if (vega_embed_module_isInteger(i)) {
            arr.splice(i, 0, this.value);
        }
        else { // array props
            arr[i] = this.value;
        }
        // this may be needed when using '-' in an array
        return { newDocument: document, index: i };
    },
    remove: function (arr, i, document) {
        var removedList = arr.splice(i, 1);
        return { newDocument: document, removed: removedList[0] };
    },
    replace: function (arr, i, document) {
        var removed = arr[i];
        arr[i] = this.value;
        return { newDocument: document, removed: removed };
    },
    move: objOps.move,
    copy: objOps.copy,
    test: objOps.test,
    _get: objOps._get
};
/**
 * Retrieves a value from a JSON document by a JSON pointer.
 * Returns the value.
 *
 * @param document The document to get the value from
 * @param pointer an escaped JSON pointer
 * @return The retrieved value
 */
function getValueByPointer(document, pointer) {
    if (pointer == '') {
        return document;
    }
    var getOriginalDestination = { op: "_get", path: pointer };
    applyOperation(document, getOriginalDestination);
    return getOriginalDestination.value;
}
/**
 * Apply a single JSON Patch Operation on a JSON document.
 * Returns the {newDocument, result} of the operation.
 * It modifies the `document` and `operation` objects - it gets the values by reference.
 * If you would like to avoid touching your values, clone them:
 * `jsonpatch.applyOperation(document, jsonpatch._deepClone(operation))`.
 *
 * @param document The document to patch
 * @param operation The operation to apply
 * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation.
 * @param mutateDocument Whether to mutate the original document or clone it before applying
 * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`.
 * @return `{newDocument, result}` after the operation
 */
function applyOperation(document, operation, validateOperation, mutateDocument, banPrototypeModifications, index) {
    if (validateOperation === void 0) { validateOperation = false; }
    if (mutateDocument === void 0) { mutateDocument = true; }
    if (banPrototypeModifications === void 0) { banPrototypeModifications = true; }
    if (index === void 0) { index = 0; }
    if (validateOperation) {
        if (typeof validateOperation == 'function') {
            validateOperation(operation, 0, document, operation.path);
        }
        else {
            validator(operation, 0);
        }
    }
    /* ROOT OPERATIONS */
    if (operation.path === "") {
        var returnValue = { newDocument: document };
        if (operation.op === 'add') {
            returnValue.newDocument = operation.value;
            return returnValue;
        }
        else if (operation.op === 'replace') {
            returnValue.newDocument = operation.value;
            returnValue.removed = document; //document we removed
            return returnValue;
        }
        else if (operation.op === 'move' || operation.op === 'copy') { // it's a move or copy to root
            returnValue.newDocument = getValueByPointer(document, operation.from); // get the value by json-pointer in `from` field
            if (operation.op === 'move') { // report removed item
                returnValue.removed = document;
            }
            return returnValue;
        }
        else if (operation.op === 'test') {
            returnValue.test = _areEquals(document, operation.value);
            if (returnValue.test === false) {
                throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document);
            }
            returnValue.newDocument = document;
            return returnValue;
        }
        else if (operation.op === 'remove') { // a remove on root
            returnValue.removed = document;
            returnValue.newDocument = null;
            return returnValue;
        }
        else if (operation.op === '_get') {
            operation.value = document;
            return returnValue;
        }
        else { /* bad operation */
            if (validateOperation) {
                throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document);
            }
            else {
                return returnValue;
            }
        }
    } /* END ROOT OPERATIONS */
    else {
        if (!mutateDocument) {
            document = _deepClone(document);
        }
        var path = operation.path || "";
        var keys = path.split('/');
        var obj = document;
        var t = 1; //skip empty element - http://jsperf.com/to-shift-or-not-to-shift
        var len = keys.length;
        var existingPathFragment = undefined;
        var key = void 0;
        var validateFunction = void 0;
        if (typeof validateOperation == 'function') {
            validateFunction = validateOperation;
        }
        else {
            validateFunction = validator;
        }
        while (true) {
            key = keys[t];
            if (key && key.indexOf('~') != -1) {
                key = unescapePathComponent(key);
            }
            if (banPrototypeModifications &&
                (key == '__proto__' ||
                    (key == 'prototype' && t > 0 && keys[t - 1] == 'constructor'))) {
                throw new TypeError('JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README');
            }
            if (validateOperation) {
                if (existingPathFragment === undefined) {
                    if (obj[key] === undefined) {
                        existingPathFragment = keys.slice(0, t).join('/');
                    }
                    else if (t == len - 1) {
                        existingPathFragment = operation.path;
                    }
                    if (existingPathFragment !== undefined) {
                        validateFunction(operation, 0, document, existingPathFragment);
                    }
                }
            }
            t++;
            if (Array.isArray(obj)) {
                if (key === '-') {
                    key = obj.length;
                }
                else {
                    if (validateOperation && !vega_embed_module_isInteger(key)) {
                        throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", index, operation, document);
                    } // only parse key when it's an integer for `arr.prop` to work
                    else if (vega_embed_module_isInteger(key)) {
                        key = ~~key;
                    }
                }
                if (t >= len) {
                    if (validateOperation && operation.op === "add" && key > obj.length) {
                        throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document);
                    }
                    var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch
                    if (returnValue.test === false) {
                        throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document);
                    }
                    return returnValue;
                }
            }
            else {
                if (t >= len) {
                    var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch
                    if (returnValue.test === false) {
                        throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document);
                    }
                    return returnValue;
                }
            }
            obj = obj[key];
            // If we have more keys in the path, but the next value isn't a non-null object,
            // throw an OPERATION_PATH_UNRESOLVABLE error instead of iterating again.
            if (validateOperation && t < len && (!obj || typeof obj !== "object")) {
                throw new JsonPatchError('Cannot perform operation at the desired path', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document);
            }
        }
    }
}
/**
 * Apply a full JSON Patch array on a JSON document.
 * Returns the {newDocument, result} of the patch.
 * It modifies the `document` object and `patch` - it gets the values by reference.
 * If you would like to avoid touching your values, clone them:
 * `jsonpatch.applyPatch(document, jsonpatch._deepClone(patch))`.
 *
 * @param document The document to patch
 * @param patch The patch to apply
 * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation.
 * @param mutateDocument Whether to mutate the original document or clone it before applying
 * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`.
 * @return An array of `{newDocument, result}` after the patch
 */
function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) {
    if (mutateDocument === void 0) { mutateDocument = true; }
    if (banPrototypeModifications === void 0) { banPrototypeModifications = true; }
    if (validateOperation) {
        if (!Array.isArray(patch)) {
            throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY');
        }
    }
    if (!mutateDocument) {
        document = _deepClone(document);
    }
    var results = new Array(patch.length);
    for (var i = 0, length_1 = patch.length; i < length_1; i++) {
        // we don't need to pass mutateDocument argument because if it was true, we already deep cloned the object, we'll just pass `true`
        results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i);
        document = results[i].newDocument; // in case root was replaced
    }
    results.newDocument = document;
    return results;
}
/**
 * Apply a single JSON Patch Operation on a JSON document.
 * Returns the updated document.
 * Suitable as a reducer.
 *
 * @param document The document to patch
 * @param operation The operation to apply
 * @return The updated document
 */
function applyReducer(document, operation, index) {
    var operationResult = applyOperation(document, operation);
    if (operationResult.test === false) { // failed test
        throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document);
    }
    return operationResult.newDocument;
}
/**
 * Validates a single operation. Called from `jsonpatch.validate`. Throws `JsonPatchError` in case of an error.
 * @param {object} operation - operation object (patch)
 * @param {number} index - index of operation in the sequence
 * @param {object} [document] - object where the operation is supposed to be applied
 * @param {string} [existingPathFragment] - comes along with `document`
 */
function validator(operation, index, document, existingPathFragment) {
    if (typeof operation !== 'object' || operation === null || Array.isArray(operation)) {
        throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document);
    }
    else if (!objOps[operation.op]) {
        throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document);
    }
    else if (typeof operation.path !== 'string') {
        throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document);
    }
    else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) {
        // paths that aren't empty string should start with "/"
        throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document);
    }
    else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') {
        throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document);
    }
    else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) {
        throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document);
    }
    else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && hasUndefined(operation.value)) {
        throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document);
    }
    else if (document) {
        if (operation.op == "add") {
            var pathLen = operation.path.split("/").length;
            var existingPathLen = existingPathFragment.split("/").length;
            if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) {
                throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document);
            }
        }
        else if (operation.op === 'replace' || operation.op === 'remove' || operation.op === '_get') {
            if (operation.path !== existingPathFragment) {
                throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document);
            }
        }
        else if (operation.op === 'move' || operation.op === 'copy') {
            var existingValue = { op: "_get", path: operation.from, value: undefined };
            var error = validate([existingValue], document);
            if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') {
                throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document);
            }
        }
    }
}
/**
 * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document.
 * If error is encountered, returns a JsonPatchError object
 * @param sequence
 * @param document
 * @returns {JsonPatchError|undefined}
 */
function validate(sequence, document, externalValidator) {
    try {
        if (!Array.isArray(sequence)) {
            throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY');
        }
        if (document) {
            //clone document and sequence so that we can safely try applying operations
            applyPatch(_deepClone(document), _deepClone(sequence), externalValidator || true);
        }
        else {
            externalValidator = externalValidator || validator;
            for (var i = 0; i < sequence.length; i++) {
                externalValidator(sequence[i], i, document, undefined);
            }
        }
    }
    catch (e) {
        if (e instanceof JsonPatchError) {
            return e;
        }
        else {
            throw e;
        }
    }
}
// based on https://github.com/epoberezkin/fast-deep-equal
// MIT License
// Copyright (c) 2017 Evgeny Poberezkin
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
function _areEquals(a, b) {
    if (a === b)
        return true;
    if (a && b && typeof a == 'object' && typeof b == 'object') {
        var arrA = Array.isArray(a), arrB = Array.isArray(b), i, length, key;
        if (arrA && arrB) {
            length = a.length;
            if (length != b.length)
                return false;
            for (i = length; i-- !== 0;)
                if (!_areEquals(a[i], b[i]))
                    return false;
            return true;
        }
        if (arrA != arrB)
            return false;
        var keys = Object.keys(a);
        length = keys.length;
        if (length !== Object.keys(b).length)
            return false;
        for (i = length; i-- !== 0;)
            if (!b.hasOwnProperty(keys[i]))
                return false;
        for (i = length; i-- !== 0;) {
            key = keys[i];
            if (!_areEquals(a[key], b[key]))
                return false;
        }
        return true;
    }
    return a !== a && b !== b;
}

var core = /*#__PURE__*/Object.freeze({
    __proto__: null,
    JsonPatchError: JsonPatchError,
    _areEquals: _areEquals,
    applyOperation: applyOperation,
    applyPatch: applyPatch,
    applyReducer: applyReducer,
    deepClone: deepClone,
    getValueByPointer: getValueByPointer,
    validate: validate,
    validator: validator
});

/*!
 * https://github.com/Starcounter-Jack/JSON-Patch
 * (c) 2017-2021 Joachim Wester
 * MIT license
 */
var beforeDict = new WeakMap();
var Mirror = /** @class */ (function () {
    function Mirror(obj) {
        this.observers = new Map();
        this.obj = obj;
    }
    return Mirror;
}());
var ObserverInfo = /** @class */ (function () {
    function ObserverInfo(callback, observer) {
        this.callback = callback;
        this.observer = observer;
    }
    return ObserverInfo;
}());
function getMirror(obj) {
    return beforeDict.get(obj);
}
function getObserverFromMirror(mirror, callback) {
    return mirror.observers.get(callback);
}
function removeObserverFromMirror(mirror, observer) {
    mirror.observers.delete(observer.callback);
}
/**
 * Detach an observer from an object
 */
function unobserve(root, observer) {
    observer.unobserve();
}
/**
 * Observes changes made to an object, which can then be retrieved using generate
 */
function observe(obj, callback) {
    var patches = [];
    var observer;
    var mirror = getMirror(obj);
    if (!mirror) {
        mirror = new Mirror(obj);
        beforeDict.set(obj, mirror);
    }
    else {
        var observerInfo = getObserverFromMirror(mirror, callback);
        observer = observerInfo && observerInfo.observer;
    }
    if (observer) {
        return observer;
    }
    observer = {};
    mirror.value = _deepClone(obj);
    if (callback) {
        observer.callback = callback;
        observer.next = null;
        var dirtyCheck = function () {
            vega_embed_module_generate(observer);
        };
        var fastCheck = function () {
            clearTimeout(observer.next);
            observer.next = setTimeout(dirtyCheck);
        };
        if (typeof window !== 'undefined') { //not Node
            window.addEventListener('mouseup', fastCheck);
            window.addEventListener('keyup', fastCheck);
            window.addEventListener('mousedown', fastCheck);
            window.addEventListener('keydown', fastCheck);
            window.addEventListener('change', fastCheck);
        }
    }
    observer.patches = patches;
    observer.object = obj;
    observer.unobserve = function () {
        vega_embed_module_generate(observer);
        clearTimeout(observer.next);
        removeObserverFromMirror(mirror, observer);
        if (typeof window !== 'undefined') {
            window.removeEventListener('mouseup', fastCheck);
            window.removeEventListener('keyup', fastCheck);
            window.removeEventListener('mousedown', fastCheck);
            window.removeEventListener('keydown', fastCheck);
            window.removeEventListener('change', fastCheck);
        }
    };
    mirror.observers.set(callback, new ObserverInfo(callback, observer));
    return observer;
}
/**
 * Generate an array of patches from an observer
 */
function vega_embed_module_generate(observer, invertible) {
    if (invertible === void 0) { invertible = false; }
    var mirror = beforeDict.get(observer.object);
    _generate(mirror.value, observer.object, observer.patches, "", invertible);
    if (observer.patches.length) {
        applyPatch(mirror.value, observer.patches);
    }
    var temp = observer.patches;
    if (temp.length > 0) {
        observer.patches = [];
        if (observer.callback) {
            observer.callback(temp);
        }
    }
    return temp;
}
// Dirty check if obj is different from mirror, generate patches and update mirror
function _generate(mirror, obj, patches, path, invertible) {
    if (obj === mirror) {
        return;
    }
    if (typeof obj.toJSON === "function") {
        obj = obj.toJSON();
    }
    var newKeys = _objectKeys(obj);
    var oldKeys = _objectKeys(mirror);
    var deleted = false;
    //if ever "move" operation is implemented here, make sure this test runs OK: "should not generate the same patch twice (move)"
    for (var t = oldKeys.length - 1; t >= 0; t--) {
        var key = oldKeys[t];
        var oldVal = mirror[key];
        if (vega_embed_module_hasOwnProperty(obj, key) && !(obj[key] === undefined && oldVal !== undefined && Array.isArray(obj) === false)) {
            var newVal = obj[key];
            if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null && Array.isArray(oldVal) === Array.isArray(newVal)) {
                _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key), invertible);
            }
            else {
                if (oldVal !== newVal) {
                    if (invertible) {
                        patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) });
                    }
                    patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: _deepClone(newVal) });
                }
            }
        }
        else if (Array.isArray(mirror) === Array.isArray(obj)) {
            if (invertible) {
                patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) });
            }
            patches.push({ op: "remove", path: path + "/" + escapePathComponent(key) });
            deleted = true; // property has been deleted
        }
        else {
            if (invertible) {
                patches.push({ op: "test", path: path, value: mirror });
            }
            patches.push({ op: "replace", path: path, value: obj });
        }
    }
    if (!deleted && newKeys.length == oldKeys.length) {
        return;
    }
    for (var t = 0; t < newKeys.length; t++) {
        var key = newKeys[t];
        if (!vega_embed_module_hasOwnProperty(mirror, key) && obj[key] !== undefined) {
            patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: _deepClone(obj[key]) });
        }
    }
}
/**
 * Create an array of patches from the differences in two objects
 */
function vega_embed_module_compare(tree1, tree2, invertible) {
    if (invertible === void 0) { invertible = false; }
    var patches = [];
    _generate(tree1, tree2, patches, '', invertible);
    return patches;
}

var duplex = /*#__PURE__*/Object.freeze({
    __proto__: null,
    compare: vega_embed_module_compare,
    generate: vega_embed_module_generate,
    observe: observe,
    unobserve: unobserve
});

Object.assign({}, core, duplex, {
    JsonPatchError: PatchError,
    deepClone: _deepClone,
    escapePathComponent,
    unescapePathComponent
});

function getDefaultExportFromCjs (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

var lrucache;
var hasRequiredLrucache;

function requireLrucache () {
	if (hasRequiredLrucache) return lrucache;
	hasRequiredLrucache = 1;
	class LRUCache {
	  constructor () {
	    this.max = 1000;
	    this.map = new Map();
	  }

	  get (key) {
	    const value = this.map.get(key);
	    if (value === undefined) {
	      return undefined
	    } else {
	      // Remove the key from the map and add it to the end
	      this.map.delete(key);
	      this.map.set(key, value);
	      return value
	    }
	  }

	  delete (key) {
	    return this.map.delete(key)
	  }

	  set (key, value) {
	    const deleted = this.delete(key);

	    if (!deleted && value !== undefined) {
	      // If cache is full, delete the least recently used item
	      if (this.map.size >= this.max) {
	        const firstKey = this.map.keys().next().value;
	        this.delete(firstKey);
	      }

	      this.map.set(key, value);
	    }

	    return this
	  }
	}

	lrucache = LRUCache;
	return lrucache;
}

var parseOptions_1;
var hasRequiredParseOptions;

function requireParseOptions () {
	if (hasRequiredParseOptions) return parseOptions_1;
	hasRequiredParseOptions = 1;
	// parse out just the options we care about
	const looseOption = Object.freeze({ loose: true });
	const emptyOpts = Object.freeze({ });
	const parseOptions = options => {
	  if (!options) {
	    return emptyOpts
	  }

	  if (typeof options !== 'object') {
	    return looseOption
	  }

	  return options
	};
	parseOptions_1 = parseOptions;
	return parseOptions_1;
}

var vega_embed_module_re = {exports: {}};

var vega_embed_module_constants;
var hasRequiredConstants;

function requireConstants () {
	if (hasRequiredConstants) return vega_embed_module_constants;
	hasRequiredConstants = 1;
	// Note: this is the semver.org version of the spec that it implements
	// Not necessarily the package version of this code.
	const SEMVER_SPEC_VERSION = '2.0.0';

	const MAX_LENGTH = 256;
	const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
	/* istanbul ignore next */ 9007199254740991;

	// Max safe segment length for coercion.
	const MAX_SAFE_COMPONENT_LENGTH = 16;

	// Max safe length for a build identifier. The max length minus 6 characters for
	// the shortest version with a build 0.0.0+BUILD.
	const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6;

	const RELEASE_TYPES = [
	  'major',
	  'premajor',
	  'minor',
	  'preminor',
	  'patch',
	  'prepatch',
	  'prerelease',
	];

	vega_embed_module_constants = {
	  MAX_LENGTH,
	  MAX_SAFE_COMPONENT_LENGTH,
	  MAX_SAFE_BUILD_LENGTH,
	  MAX_SAFE_INTEGER,
	  RELEASE_TYPES,
	  SEMVER_SPEC_VERSION,
	  FLAG_INCLUDE_PRERELEASE: 0b001,
	  FLAG_LOOSE: 0b010,
	};
	return vega_embed_module_constants;
}

var debug_1;
var hasRequiredDebug;

function requireDebug () {
	if (hasRequiredDebug) return debug_1;
	hasRequiredDebug = 1;
	const debug = (
	  typeof process === 'object' &&
	  process.env &&
	  process.env.NODE_DEBUG &&
	  /\bsemver\b/i.test(process.env.NODE_DEBUG)
	) ? (...args) => console.error('SEMVER', ...args)
	  : () => {};

	debug_1 = debug;
	return debug_1;
}

var hasRequiredRe;

function requireRe () {
	if (hasRequiredRe) return vega_embed_module_re.exports;
	hasRequiredRe = 1;
	(function (module, exports) {
		const {
		  MAX_SAFE_COMPONENT_LENGTH,
		  MAX_SAFE_BUILD_LENGTH,
		  MAX_LENGTH,
		} = requireConstants();
		const debug = requireDebug();
		exports = module.exports = {};

		// The actual regexps go on exports.re
		const re = exports.re = [];
		const safeRe = exports.safeRe = [];
		const src = exports.src = [];
		const t = exports.t = {};
		let R = 0;

		const LETTERDASHNUMBER = '[a-zA-Z0-9-]';

		// Replace some greedy regex tokens to prevent regex dos issues. These regex are
		// used internally via the safeRe object since all inputs in this library get
		// normalized first to trim and collapse all extra whitespace. The original
		// regexes are exported for userland consumption and lower level usage. A
		// future breaking change could export the safer regex only with a note that
		// all input should have extra whitespace removed.
		const safeRegexReplacements = [
		  ['\\s', 1],
		  ['\\d', MAX_LENGTH],
		  [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
		];

		const makeSafeRegex = (value) => {
		  for (const [token, max] of safeRegexReplacements) {
		    value = value
		      .split(`${token}*`).join(`${token}{0,${max}}`)
		      .split(`${token}+`).join(`${token}{1,${max}}`);
		  }
		  return value
		};

		const createToken = (name, value, isGlobal) => {
		  const safe = makeSafeRegex(value);
		  const index = R++;
		  debug(name, index, value);
		  t[name] = index;
		  src[index] = value;
		  re[index] = new RegExp(value, isGlobal ? 'g' : undefined);
		  safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined);
		};

		// The following Regular Expressions can be used for tokenizing,
		// validating, and parsing SemVer version strings.

		// ## Numeric Identifier
		// A single `0`, or a non-zero digit followed by zero or more digits.

		createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*');
		createToken('NUMERICIDENTIFIERLOOSE', '\\d+');

		// ## Non-numeric Identifier
		// Zero or more digits, followed by a letter or hyphen, and then zero or
		// more letters, digits, or hyphens.

		createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`);

		// ## Main Version
		// Three dot-separated numeric identifiers.

		createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
		                   `(${src[t.NUMERICIDENTIFIER]})\\.` +
		                   `(${src[t.NUMERICIDENTIFIER]})`);

		createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
		                        `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
		                        `(${src[t.NUMERICIDENTIFIERLOOSE]})`);

		// ## Pre-release Version Identifier
		// A numeric identifier, or a non-numeric identifier.

		createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER]
		}|${src[t.NONNUMERICIDENTIFIER]})`);

		createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE]
		}|${src[t.NONNUMERICIDENTIFIER]})`);

		// ## Pre-release Version
		// Hyphen, followed by one or more dot-separated pre-release version
		// identifiers.

		createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
		}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`);

		createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
		}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`);

		// ## Build Metadata Identifier
		// Any combination of digits, letters, or hyphens.

		createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`);

		// ## Build Metadata
		// Plus sign, followed by one or more period-separated build metadata
		// identifiers.

		createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
		}(?:\\.${src[t.BUILDIDENTIFIER]})*))`);

		// ## Full Version String
		// A main version, followed optionally by a pre-release version and
		// build metadata.

		// Note that the only major, minor, patch, and pre-release sections of
		// the version string are capturing groups.  The build metadata is not a
		// capturing group, because it should not ever be used in version
		// comparison.

		createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
		}${src[t.PRERELEASE]}?${
		  src[t.BUILD]}?`);

		createToken('FULL', `^${src[t.FULLPLAIN]}$`);

		// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
		// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
		// common in the npm registry.
		createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
		}${src[t.PRERELEASELOOSE]}?${
		  src[t.BUILD]}?`);

		createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`);

		createToken('GTLT', '((?:<|>)?=?)');

		// Something like "2.*" or "1.2.x".
		// Note that "x.x" is a valid xRange identifer, meaning "any version"
		// Only the first item is strictly required.
		createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
		createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`);

		createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
		                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
		                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
		                   `(?:${src[t.PRERELEASE]})?${
		                     src[t.BUILD]}?` +
		                   `)?)?`);

		createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
		                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
		                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
		                        `(?:${src[t.PRERELEASELOOSE]})?${
		                          src[t.BUILD]}?` +
		                        `)?)?`);

		createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`);
		createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`);

		// Coercion.
		// Extract anything that could conceivably be a part of a valid semver
		createToken('COERCEPLAIN', `${'(^|[^\\d])' +
		              '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
		              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
		              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`);
		createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`);
		createToken('COERCEFULL', src[t.COERCEPLAIN] +
		              `(?:${src[t.PRERELEASE]})?` +
		              `(?:${src[t.BUILD]})?` +
		              `(?:$|[^\\d])`);
		createToken('COERCERTL', src[t.COERCE], true);
		createToken('COERCERTLFULL', src[t.COERCEFULL], true);

		// Tilde ranges.
		// Meaning is "reasonably at or greater than"
		createToken('LONETILDE', '(?:~>?)');

		createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true);
		exports.tildeTrimReplace = '$1~';

		createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`);
		createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`);

		// Caret ranges.
		// Meaning is "at least and backwards compatible with"
		createToken('LONECARET', '(?:\\^)');

		createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true);
		exports.caretTrimReplace = '$1^';

		createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`);
		createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`);

		// A simple gt/lt/eq thing, or just "" to indicate "any version"
		createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`);
		createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`);

		// An expression to strip any whitespace between the gtlt and the thing
		// it modifies, so that `> 1.2.3` ==> `>1.2.3`
		createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
		}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true);
		exports.comparatorTrimReplace = '$1$2$3';

		// Something like `1.2.3 - 1.2.4`
		// Note that these all use the loose form, because they'll be
		// checked against either the strict or loose comparator form
		// later.
		createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
		                   `\\s+-\\s+` +
		                   `(${src[t.XRANGEPLAIN]})` +
		                   `\\s*$`);

		createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
		                        `\\s+-\\s+` +
		                        `(${src[t.XRANGEPLAINLOOSE]})` +
		                        `\\s*$`);

		// Star ranges basically just allow anything at all.
		createToken('STAR', '(<|>)?=?\\s*\\*');
		// >=0.0.0 is like a star
		createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$');
		createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$'); 
	} (vega_embed_module_re, vega_embed_module_re.exports));
	return vega_embed_module_re.exports;
}

var identifiers;
var hasRequiredIdentifiers;

function requireIdentifiers () {
	if (hasRequiredIdentifiers) return identifiers;
	hasRequiredIdentifiers = 1;
	const numeric = /^[0-9]+$/;
	const compareIdentifiers = (a, b) => {
	  const anum = numeric.test(a);
	  const bnum = numeric.test(b);

	  if (anum && bnum) {
	    a = +a;
	    b = +b;
	  }

	  return a === b ? 0
	    : (anum && !bnum) ? -1
	    : (bnum && !anum) ? 1
	    : a < b ? -1
	    : 1
	};

	const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a);

	identifiers = {
	  compareIdentifiers,
	  rcompareIdentifiers,
	};
	return identifiers;
}

var semver;
var hasRequiredSemver;

function requireSemver () {
	if (hasRequiredSemver) return semver;
	hasRequiredSemver = 1;
	const debug = requireDebug();
	const { MAX_LENGTH, MAX_SAFE_INTEGER } = requireConstants();
	const { safeRe: re, t } = requireRe();

	const parseOptions = requireParseOptions();
	const { compareIdentifiers } = requireIdentifiers();
	class SemVer {
	  constructor (version, options) {
	    options = parseOptions(options);

	    if (version instanceof SemVer) {
	      if (version.loose === !!options.loose &&
	          version.includePrerelease === !!options.includePrerelease) {
	        return version
	      } else {
	        version = version.version;
	      }
	    } else if (typeof version !== 'string') {
	      throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
	    }

	    if (version.length > MAX_LENGTH) {
	      throw new TypeError(
	        `version is longer than ${MAX_LENGTH} characters`
	      )
	    }

	    debug('SemVer', version, options);
	    this.options = options;
	    this.loose = !!options.loose;
	    // this isn't actually relevant for versions, but keep it so that we
	    // don't run into trouble passing this.options around.
	    this.includePrerelease = !!options.includePrerelease;

	    const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]);

	    if (!m) {
	      throw new TypeError(`Invalid Version: ${version}`)
	    }

	    this.raw = version;

	    // these are actually numbers
	    this.major = +m[1];
	    this.minor = +m[2];
	    this.patch = +m[3];

	    if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
	      throw new TypeError('Invalid major version')
	    }

	    if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
	      throw new TypeError('Invalid minor version')
	    }

	    if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
	      throw new TypeError('Invalid patch version')
	    }

	    // numberify any prerelease numeric ids
	    if (!m[4]) {
	      this.prerelease = [];
	    } else {
	      this.prerelease = m[4].split('.').map((id) => {
	        if (/^[0-9]+$/.test(id)) {
	          const num = +id;
	          if (num >= 0 && num < MAX_SAFE_INTEGER) {
	            return num
	          }
	        }
	        return id
	      });
	    }

	    this.build = m[5] ? m[5].split('.') : [];
	    this.format();
	  }

	  format () {
	    this.version = `${this.major}.${this.minor}.${this.patch}`;
	    if (this.prerelease.length) {
	      this.version += `-${this.prerelease.join('.')}`;
	    }
	    return this.version
	  }

	  toString () {
	    return this.version
	  }

	  compare (other) {
	    debug('SemVer.compare', this.version, this.options, other);
	    if (!(other instanceof SemVer)) {
	      if (typeof other === 'string' && other === this.version) {
	        return 0
	      }
	      other = new SemVer(other, this.options);
	    }

	    if (other.version === this.version) {
	      return 0
	    }

	    return this.compareMain(other) || this.comparePre(other)
	  }

	  compareMain (other) {
	    if (!(other instanceof SemVer)) {
	      other = new SemVer(other, this.options);
	    }

	    return (
	      compareIdentifiers(this.major, other.major) ||
	      compareIdentifiers(this.minor, other.minor) ||
	      compareIdentifiers(this.patch, other.patch)
	    )
	  }

	  comparePre (other) {
	    if (!(other instanceof SemVer)) {
	      other = new SemVer(other, this.options);
	    }

	    // NOT having a prerelease is > having one
	    if (this.prerelease.length && !other.prerelease.length) {
	      return -1
	    } else if (!this.prerelease.length && other.prerelease.length) {
	      return 1
	    } else if (!this.prerelease.length && !other.prerelease.length) {
	      return 0
	    }

	    let i = 0;
	    do {
	      const a = this.prerelease[i];
	      const b = other.prerelease[i];
	      debug('prerelease compare', i, a, b);
	      if (a === undefined && b === undefined) {
	        return 0
	      } else if (b === undefined) {
	        return 1
	      } else if (a === undefined) {
	        return -1
	      } else if (a === b) {
	        continue
	      } else {
	        return compareIdentifiers(a, b)
	      }
	    } while (++i)
	  }

	  compareBuild (other) {
	    if (!(other instanceof SemVer)) {
	      other = new SemVer(other, this.options);
	    }

	    let i = 0;
	    do {
	      const a = this.build[i];
	      const b = other.build[i];
	      debug('build compare', i, a, b);
	      if (a === undefined && b === undefined) {
	        return 0
	      } else if (b === undefined) {
	        return 1
	      } else if (a === undefined) {
	        return -1
	      } else if (a === b) {
	        continue
	      } else {
	        return compareIdentifiers(a, b)
	      }
	    } while (++i)
	  }

	  // preminor will bump the version up to the next minor release, and immediately
	  // down to pre-release. premajor and prepatch work the same way.
	  inc (release, identifier, identifierBase) {
	    switch (release) {
	      case 'premajor':
	        this.prerelease.length = 0;
	        this.patch = 0;
	        this.minor = 0;
	        this.major++;
	        this.inc('pre', identifier, identifierBase);
	        break
	      case 'preminor':
	        this.prerelease.length = 0;
	        this.patch = 0;
	        this.minor++;
	        this.inc('pre', identifier, identifierBase);
	        break
	      case 'prepatch':
	        // If this is already a prerelease, it will bump to the next version
	        // drop any prereleases that might already exist, since they are not
	        // relevant at this point.
	        this.prerelease.length = 0;
	        this.inc('patch', identifier, identifierBase);
	        this.inc('pre', identifier, identifierBase);
	        break
	      // If the input is a non-prerelease version, this acts the same as
	      // prepatch.
	      case 'prerelease':
	        if (this.prerelease.length === 0) {
	          this.inc('patch', identifier, identifierBase);
	        }
	        this.inc('pre', identifier, identifierBase);
	        break

	      case 'major':
	        // If this is a pre-major version, bump up to the same major version.
	        // Otherwise increment major.
	        // 1.0.0-5 bumps to 1.0.0
	        // 1.1.0 bumps to 2.0.0
	        if (
	          this.minor !== 0 ||
	          this.patch !== 0 ||
	          this.prerelease.length === 0
	        ) {
	          this.major++;
	        }
	        this.minor = 0;
	        this.patch = 0;
	        this.prerelease = [];
	        break
	      case 'minor':
	        // If this is a pre-minor version, bump up to the same minor version.
	        // Otherwise increment minor.
	        // 1.2.0-5 bumps to 1.2.0
	        // 1.2.1 bumps to 1.3.0
	        if (this.patch !== 0 || this.prerelease.length === 0) {
	          this.minor++;
	        }
	        this.patch = 0;
	        this.prerelease = [];
	        break
	      case 'patch':
	        // If this is not a pre-release version, it will increment the patch.
	        // If it is a pre-release it will bump up to the same patch version.
	        // 1.2.0-5 patches to 1.2.0
	        // 1.2.0 patches to 1.2.1
	        if (this.prerelease.length === 0) {
	          this.patch++;
	        }
	        this.prerelease = [];
	        break
	      // This probably shouldn't be used publicly.
	      // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
	      case 'pre': {
	        const base = Number(identifierBase) ? 1 : 0;

	        if (!identifier && identifierBase === false) {
	          throw new Error('invalid increment argument: identifier is empty')
	        }

	        if (this.prerelease.length === 0) {
	          this.prerelease = [base];
	        } else {
	          let i = this.prerelease.length;
	          while (--i >= 0) {
	            if (typeof this.prerelease[i] === 'number') {
	              this.prerelease[i]++;
	              i = -2;
	            }
	          }
	          if (i === -1) {
	            // didn't increment anything
	            if (identifier === this.prerelease.join('.') && identifierBase === false) {
	              throw new Error('invalid increment argument: identifier already exists')
	            }
	            this.prerelease.push(base);
	          }
	        }
	        if (identifier) {
	          // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
	          // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
	          let prerelease = [identifier, base];
	          if (identifierBase === false) {
	            prerelease = [identifier];
	          }
	          if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
	            if (isNaN(this.prerelease[1])) {
	              this.prerelease = prerelease;
	            }
	          } else {
	            this.prerelease = prerelease;
	          }
	        }
	        break
	      }
	      default:
	        throw new Error(`invalid increment argument: ${release}`)
	    }
	    this.raw = this.format();
	    if (this.build.length) {
	      this.raw += `+${this.build.join('.')}`;
	    }
	    return this
	  }
	}

	semver = SemVer;
	return semver;
}

var compare_1;
var hasRequiredCompare;

function requireCompare () {
	if (hasRequiredCompare) return compare_1;
	hasRequiredCompare = 1;
	const SemVer = requireSemver();
	const compare = (a, b, loose) =>
	  new SemVer(a, loose).compare(new SemVer(b, loose));

	compare_1 = compare;
	return compare_1;
}

var eq_1;
var hasRequiredEq;

function requireEq () {
	if (hasRequiredEq) return eq_1;
	hasRequiredEq = 1;
	const compare = requireCompare();
	const eq = (a, b, loose) => compare(a, b, loose) === 0;
	eq_1 = eq;
	return eq_1;
}

var neq_1;
var hasRequiredNeq;

function requireNeq () {
	if (hasRequiredNeq) return neq_1;
	hasRequiredNeq = 1;
	const compare = requireCompare();
	const neq = (a, b, loose) => compare(a, b, loose) !== 0;
	neq_1 = neq;
	return neq_1;
}

var gt_1;
var hasRequiredGt;

function requireGt () {
	if (hasRequiredGt) return gt_1;
	hasRequiredGt = 1;
	const compare = requireCompare();
	const gt = (a, b, loose) => compare(a, b, loose) > 0;
	gt_1 = gt;
	return gt_1;
}

var gte_1;
var hasRequiredGte;

function requireGte () {
	if (hasRequiredGte) return gte_1;
	hasRequiredGte = 1;
	const compare = requireCompare();
	const gte = (a, b, loose) => compare(a, b, loose) >= 0;
	gte_1 = gte;
	return gte_1;
}

var lt_1;
var hasRequiredLt;

function requireLt () {
	if (hasRequiredLt) return lt_1;
	hasRequiredLt = 1;
	const compare = requireCompare();
	const lt = (a, b, loose) => compare(a, b, loose) < 0;
	lt_1 = lt;
	return lt_1;
}

var lte_1;
var hasRequiredLte;

function requireLte () {
	if (hasRequiredLte) return lte_1;
	hasRequiredLte = 1;
	const compare = requireCompare();
	const lte = (a, b, loose) => compare(a, b, loose) <= 0;
	lte_1 = lte;
	return lte_1;
}

var cmp_1;
var hasRequiredCmp;

function requireCmp () {
	if (hasRequiredCmp) return cmp_1;
	hasRequiredCmp = 1;
	const eq = requireEq();
	const neq = requireNeq();
	const gt = requireGt();
	const gte = requireGte();
	const lt = requireLt();
	const lte = requireLte();

	const cmp = (a, op, b, loose) => {
	  switch (op) {
	    case '===':
	      if (typeof a === 'object') {
	        a = a.version;
	      }
	      if (typeof b === 'object') {
	        b = b.version;
	      }
	      return a === b

	    case '!==':
	      if (typeof a === 'object') {
	        a = a.version;
	      }
	      if (typeof b === 'object') {
	        b = b.version;
	      }
	      return a !== b

	    case '':
	    case '=':
	    case '==':
	      return eq(a, b, loose)

	    case '!=':
	      return neq(a, b, loose)

	    case '>':
	      return gt(a, b, loose)

	    case '>=':
	      return gte(a, b, loose)

	    case '<':
	      return lt(a, b, loose)

	    case '<=':
	      return lte(a, b, loose)

	    default:
	      throw new TypeError(`Invalid operator: ${op}`)
	  }
	};
	cmp_1 = cmp;
	return cmp_1;
}

var vega_embed_module_comparator;
var hasRequiredComparator;

function requireComparator () {
	if (hasRequiredComparator) return vega_embed_module_comparator;
	hasRequiredComparator = 1;
	const ANY = Symbol('SemVer ANY');
	// hoisted class for cyclic dependency
	class Comparator {
	  static get ANY () {
	    return ANY
	  }

	  constructor (comp, options) {
	    options = parseOptions(options);

	    if (comp instanceof Comparator) {
	      if (comp.loose === !!options.loose) {
	        return comp
	      } else {
	        comp = comp.value;
	      }
	    }

	    comp = comp.trim().split(/\s+/).join(' ');
	    debug('comparator', comp, options);
	    this.options = options;
	    this.loose = !!options.loose;
	    this.parse(comp);

	    if (this.semver === ANY) {
	      this.value = '';
	    } else {
	      this.value = this.operator + this.semver.version;
	    }

	    debug('comp', this);
	  }

	  parse (comp) {
	    const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR];
	    const m = comp.match(r);

	    if (!m) {
	      throw new TypeError(`Invalid comparator: ${comp}`)
	    }

	    this.operator = m[1] !== undefined ? m[1] : '';
	    if (this.operator === '=') {
	      this.operator = '';
	    }

	    // if it literally is just '>' or '' then allow anything.
	    if (!m[2]) {
	      this.semver = ANY;
	    } else {
	      this.semver = new SemVer(m[2], this.options.loose);
	    }
	  }

	  toString () {
	    return this.value
	  }

	  test (version) {
	    debug('Comparator.test', version, this.options.loose);

	    if (this.semver === ANY || version === ANY) {
	      return true
	    }

	    if (typeof version === 'string') {
	      try {
	        version = new SemVer(version, this.options);
	      } catch (er) {
	        return false
	      }
	    }

	    return cmp(version, this.operator, this.semver, this.options)
	  }

	  intersects (comp, options) {
	    if (!(comp instanceof Comparator)) {
	      throw new TypeError('a Comparator is required')
	    }

	    if (this.operator === '') {
	      if (this.value === '') {
	        return true
	      }
	      return new Range(comp.value, options).test(this.value)
	    } else if (comp.operator === '') {
	      if (comp.value === '') {
	        return true
	      }
	      return new Range(this.value, options).test(comp.semver)
	    }

	    options = parseOptions(options);

	    // Special cases where nothing can possibly be lower
	    if (options.includePrerelease &&
	      (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
	      return false
	    }
	    if (!options.includePrerelease &&
	      (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
	      return false
	    }

	    // Same direction increasing (> or >=)
	    if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
	      return true
	    }
	    // Same direction decreasing (< or <=)
	    if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
	      return true
	    }
	    // same SemVer and both sides are inclusive (<= or >=)
	    if (
	      (this.semver.version === comp.semver.version) &&
	      this.operator.includes('=') && comp.operator.includes('=')) {
	      return true
	    }
	    // opposite directions less than
	    if (cmp(this.semver, '<', comp.semver, options) &&
	      this.operator.startsWith('>') && comp.operator.startsWith('<')) {
	      return true
	    }
	    // opposite directions greater than
	    if (cmp(this.semver, '>', comp.semver, options) &&
	      this.operator.startsWith('<') && comp.operator.startsWith('>')) {
	      return true
	    }
	    return false
	  }
	}

	vega_embed_module_comparator = Comparator;

	const parseOptions = requireParseOptions();
	const { safeRe: re, t } = requireRe();
	const cmp = requireCmp();
	const debug = requireDebug();
	const SemVer = requireSemver();
	const Range = requireRange();
	return vega_embed_module_comparator;
}

var vega_embed_module_range;
var hasRequiredRange;

function requireRange () {
	if (hasRequiredRange) return vega_embed_module_range;
	hasRequiredRange = 1;
	const SPACE_CHARACTERS = /\s+/g;

	// hoisted class for cyclic dependency
	class Range {
	  constructor (range, options) {
	    options = parseOptions(options);

	    if (range instanceof Range) {
	      if (
	        range.loose === !!options.loose &&
	        range.includePrerelease === !!options.includePrerelease
	      ) {
	        return range
	      } else {
	        return new Range(range.raw, options)
	      }
	    }

	    if (range instanceof Comparator) {
	      // just put it in the set and return
	      this.raw = range.value;
	      this.set = [[range]];
	      this.formatted = undefined;
	      return this
	    }

	    this.options = options;
	    this.loose = !!options.loose;
	    this.includePrerelease = !!options.includePrerelease;

	    // First reduce all whitespace as much as possible so we do not have to rely
	    // on potentially slow regexes like \s*. This is then stored and used for
	    // future error messages as well.
	    this.raw = range.trim().replace(SPACE_CHARACTERS, ' ');

	    // First, split on ||
	    this.set = this.raw
	      .split('||')
	      // map the range to a 2d array of comparators
	      .map(r => this.parseRange(r.trim()))
	      // throw out any comparator lists that are empty
	      // this generally means that it was not a valid range, which is allowed
	      // in loose mode, but will still throw if the WHOLE range is invalid.
	      .filter(c => c.length);

	    if (!this.set.length) {
	      throw new TypeError(`Invalid SemVer Range: ${this.raw}`)
	    }

	    // if we have any that are not the null set, throw out null sets.
	    if (this.set.length > 1) {
	      // keep the first one, in case they're all null sets
	      const first = this.set[0];
	      this.set = this.set.filter(c => !isNullSet(c[0]));
	      if (this.set.length === 0) {
	        this.set = [first];
	      } else if (this.set.length > 1) {
	        // if we have any that are *, then the range is just *
	        for (const c of this.set) {
	          if (c.length === 1 && isAny(c[0])) {
	            this.set = [c];
	            break
	          }
	        }
	      }
	    }

	    this.formatted = undefined;
	  }

	  get range () {
	    if (this.formatted === undefined) {
	      this.formatted = '';
	      for (let i = 0; i < this.set.length; i++) {
	        if (i > 0) {
	          this.formatted += '||';
	        }
	        const comps = this.set[i];
	        for (let k = 0; k < comps.length; k++) {
	          if (k > 0) {
	            this.formatted += ' ';
	          }
	          this.formatted += comps[k].toString().trim();
	        }
	      }
	    }
	    return this.formatted
	  }

	  format () {
	    return this.range
	  }

	  toString () {
	    return this.range
	  }

	  parseRange (range) {
	    // memoize range parsing for performance.
	    // this is a very hot path, and fully deterministic.
	    const memoOpts =
	      (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) |
	      (this.options.loose && FLAG_LOOSE);
	    const memoKey = memoOpts + ':' + range;
	    const cached = cache.get(memoKey);
	    if (cached) {
	      return cached
	    }

	    const loose = this.options.loose;
	    // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
	    const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE];
	    range = range.replace(hr, hyphenReplace(this.options.includePrerelease));
	    debug('hyphen replace', range);

	    // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
	    range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace);
	    debug('comparator trim', range);

	    // `~ 1.2.3` => `~1.2.3`
	    range = range.replace(re[t.TILDETRIM], tildeTrimReplace);
	    debug('tilde trim', range);

	    // `^ 1.2.3` => `^1.2.3`
	    range = range.replace(re[t.CARETTRIM], caretTrimReplace);
	    debug('caret trim', range);

	    // At this point, the range is completely trimmed and
	    // ready to be split into comparators.

	    let rangeList = range
	      .split(' ')
	      .map(comp => parseComparator(comp, this.options))
	      .join(' ')
	      .split(/\s+/)
	      // >=0.0.0 is equivalent to *
	      .map(comp => replaceGTE0(comp, this.options));

	    if (loose) {
	      // in loose mode, throw out any that are not valid comparators
	      rangeList = rangeList.filter(comp => {
	        debug('loose invalid filter', comp, this.options);
	        return !!comp.match(re[t.COMPARATORLOOSE])
	      });
	    }
	    debug('range list', rangeList);

	    // if any comparators are the null set, then replace with JUST null set
	    // if more than one comparator, remove any * comparators
	    // also, don't include the same comparator more than once
	    const rangeMap = new Map();
	    const comparators = rangeList.map(comp => new Comparator(comp, this.options));
	    for (const comp of comparators) {
	      if (isNullSet(comp)) {
	        return [comp]
	      }
	      rangeMap.set(comp.value, comp);
	    }
	    if (rangeMap.size > 1 && rangeMap.has('')) {
	      rangeMap.delete('');
	    }

	    const result = [...rangeMap.values()];
	    cache.set(memoKey, result);
	    return result
	  }

	  intersects (range, options) {
	    if (!(range instanceof Range)) {
	      throw new TypeError('a Range is required')
	    }

	    return this.set.some((thisComparators) => {
	      return (
	        isSatisfiable(thisComparators, options) &&
	        range.set.some((rangeComparators) => {
	          return (
	            isSatisfiable(rangeComparators, options) &&
	            thisComparators.every((thisComparator) => {
	              return rangeComparators.every((rangeComparator) => {
	                return thisComparator.intersects(rangeComparator, options)
	              })
	            })
	          )
	        })
	      )
	    })
	  }

	  // if ANY of the sets match ALL of its comparators, then pass
	  test (version) {
	    if (!version) {
	      return false
	    }

	    if (typeof version === 'string') {
	      try {
	        version = new SemVer(version, this.options);
	      } catch (er) {
	        return false
	      }
	    }

	    for (let i = 0; i < this.set.length; i++) {
	      if (testSet(this.set[i], version, this.options)) {
	        return true
	      }
	    }
	    return false
	  }
	}

	vega_embed_module_range = Range;

	const LRU = requireLrucache();
	const cache = new LRU();

	const parseOptions = requireParseOptions();
	const Comparator = requireComparator();
	const debug = requireDebug();
	const SemVer = requireSemver();
	const {
	  safeRe: re,
	  t,
	  comparatorTrimReplace,
	  tildeTrimReplace,
	  caretTrimReplace,
	} = requireRe();
	const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = requireConstants();

	const isNullSet = c => c.value === '<0.0.0-0';
	const isAny = c => c.value === '';

	// take a set of comparators and determine whether there
	// exists a version which can satisfy it
	const isSatisfiable = (comparators, options) => {
	  let result = true;
	  const remainingComparators = comparators.slice();
	  let testComparator = remainingComparators.pop();

	  while (result && remainingComparators.length) {
	    result = remainingComparators.every((otherComparator) => {
	      return testComparator.intersects(otherComparator, options)
	    });

	    testComparator = remainingComparators.pop();
	  }

	  return result
	};

	// comprised of xranges, tildes, stars, and gtlt's at this point.
	// already replaced the hyphen ranges
	// turn into a set of JUST comparators.
	const parseComparator = (comp, options) => {
	  debug('comp', comp, options);
	  comp = replaceCarets(comp, options);
	  debug('caret', comp);
	  comp = replaceTildes(comp, options);
	  debug('tildes', comp);
	  comp = replaceXRanges(comp, options);
	  debug('xrange', comp);
	  comp = replaceStars(comp, options);
	  debug('stars', comp);
	  return comp
	};

	const isX = id => !id || id.toLowerCase() === 'x' || id === '*';

	// ~, ~> --> * (any, kinda silly)
	// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
	// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
	// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
	// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
	// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
	// ~0.0.1 --> >=0.0.1 <0.1.0-0
	const replaceTildes = (comp, options) => {
	  return comp
	    .trim()
	    .split(/\s+/)
	    .map((c) => replaceTilde(c, options))
	    .join(' ')
	};

	const replaceTilde = (comp, options) => {
	  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
	  return comp.replace(r, (_, M, m, p, pr) => {
	    debug('tilde', comp, _, M, m, p, pr);
	    let ret;

	    if (isX(M)) {
	      ret = '';
	    } else if (isX(m)) {
	      ret = `>=${M}.0.0 <${+M + 1}.0.0-0`;
	    } else if (isX(p)) {
	      // ~1.2 == >=1.2.0 <1.3.0-0
	      ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`;
	    } else if (pr) {
	      debug('replaceTilde pr', pr);
	      ret = `>=${M}.${m}.${p}-${pr
	      } <${M}.${+m + 1}.0-0`;
	    } else {
	      // ~1.2.3 == >=1.2.3 <1.3.0-0
	      ret = `>=${M}.${m}.${p
	      } <${M}.${+m + 1}.0-0`;
	    }

	    debug('tilde return', ret);
	    return ret
	  })
	};

	// ^ --> * (any, kinda silly)
	// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
	// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
	// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
	// ^1.2.3 --> >=1.2.3 <2.0.0-0
	// ^1.2.0 --> >=1.2.0 <2.0.0-0
	// ^0.0.1 --> >=0.0.1 <0.0.2-0
	// ^0.1.0 --> >=0.1.0 <0.2.0-0
	const replaceCarets = (comp, options) => {
	  return comp
	    .trim()
	    .split(/\s+/)
	    .map((c) => replaceCaret(c, options))
	    .join(' ')
	};

	const replaceCaret = (comp, options) => {
	  debug('caret', comp, options);
	  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
	  const z = options.includePrerelease ? '-0' : '';
	  return comp.replace(r, (_, M, m, p, pr) => {
	    debug('caret', comp, _, M, m, p, pr);
	    let ret;

	    if (isX(M)) {
	      ret = '';
	    } else if (isX(m)) {
	      ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`;
	    } else if (isX(p)) {
	      if (M === '0') {
	        ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
	      } else {
	        ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
	      }
	    } else if (pr) {
	      debug('replaceCaret pr', pr);
	      if (M === '0') {
	        if (m === '0') {
	          ret = `>=${M}.${m}.${p}-${pr
	          } <${M}.${m}.${+p + 1}-0`;
	        } else {
	          ret = `>=${M}.${m}.${p}-${pr
	          } <${M}.${+m + 1}.0-0`;
	        }
	      } else {
	        ret = `>=${M}.${m}.${p}-${pr
	        } <${+M + 1}.0.0-0`;
	      }
	    } else {
	      debug('no pr');
	      if (M === '0') {
	        if (m === '0') {
	          ret = `>=${M}.${m}.${p
	          }${z} <${M}.${m}.${+p + 1}-0`;
	        } else {
	          ret = `>=${M}.${m}.${p
	          }${z} <${M}.${+m + 1}.0-0`;
	        }
	      } else {
	        ret = `>=${M}.${m}.${p
	        } <${+M + 1}.0.0-0`;
	      }
	    }

	    debug('caret return', ret);
	    return ret
	  })
	};

	const replaceXRanges = (comp, options) => {
	  debug('replaceXRanges', comp, options);
	  return comp
	    .split(/\s+/)
	    .map((c) => replaceXRange(c, options))
	    .join(' ')
	};

	const replaceXRange = (comp, options) => {
	  comp = comp.trim();
	  const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE];
	  return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
	    debug('xRange', comp, ret, gtlt, M, m, p, pr);
	    const xM = isX(M);
	    const xm = xM || isX(m);
	    const xp = xm || isX(p);
	    const anyX = xp;

	    if (gtlt === '=' && anyX) {
	      gtlt = '';
	    }

	    // if we're including prereleases in the match, then we need
	    // to fix this to -0, the lowest possible prerelease value
	    pr = options.includePrerelease ? '-0' : '';

	    if (xM) {
	      if (gtlt === '>' || gtlt === '<') {
	        // nothing is allowed
	        ret = '<0.0.0-0';
	      } else {
	        // nothing is forbidden
	        ret = '*';
	      }
	    } else if (gtlt && anyX) {
	      // we know patch is an x, because we have any x at all.
	      // replace X with 0
	      if (xm) {
	        m = 0;
	      }
	      p = 0;

	      if (gtlt === '>') {
	        // >1 => >=2.0.0
	        // >1.2 => >=1.3.0
	        gtlt = '>=';
	        if (xm) {
	          M = +M + 1;
	          m = 0;
	          p = 0;
	        } else {
	          m = +m + 1;
	          p = 0;
	        }
	      } else if (gtlt === '<=') {
	        // <=0.7.x is actually <0.8.0, since any 0.7.x should
	        // pass.  Similarly, <=7.x is actually <8.0.0, etc.
	        gtlt = '<';
	        if (xm) {
	          M = +M + 1;
	        } else {
	          m = +m + 1;
	        }
	      }

	      if (gtlt === '<') {
	        pr = '-0';
	      }

	      ret = `${gtlt + M}.${m}.${p}${pr}`;
	    } else if (xm) {
	      ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`;
	    } else if (xp) {
	      ret = `>=${M}.${m}.0${pr
	      } <${M}.${+m + 1}.0-0`;
	    }

	    debug('xRange return', ret);

	    return ret
	  })
	};

	// Because * is AND-ed with everything else in the comparator,
	// and '' means "any version", just remove the *s entirely.
	const replaceStars = (comp, options) => {
	  debug('replaceStars', comp, options);
	  // Looseness is ignored here.  star is always as loose as it gets!
	  return comp
	    .trim()
	    .replace(re[t.STAR], '')
	};

	const replaceGTE0 = (comp, options) => {
	  debug('replaceGTE0', comp, options);
	  return comp
	    .trim()
	    .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
	};

	// This function is passed to string.replace(re[t.HYPHENRANGE])
	// M, m, patch, prerelease, build
	// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
	// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
	// 1.2 - 3.4 => >=1.2.0 <3.5.0-0
	// TODO build?
	const hyphenReplace = incPr => ($0,
	  from, fM, fm, fp, fpr, fb,
	  to, tM, tm, tp, tpr) => {
	  if (isX(fM)) {
	    from = '';
	  } else if (isX(fm)) {
	    from = `>=${fM}.0.0${incPr ? '-0' : ''}`;
	  } else if (isX(fp)) {
	    from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`;
	  } else if (fpr) {
	    from = `>=${from}`;
	  } else {
	    from = `>=${from}${incPr ? '-0' : ''}`;
	  }

	  if (isX(tM)) {
	    to = '';
	  } else if (isX(tm)) {
	    to = `<${+tM + 1}.0.0-0`;
	  } else if (isX(tp)) {
	    to = `<${tM}.${+tm + 1}.0-0`;
	  } else if (tpr) {
	    to = `<=${tM}.${tm}.${tp}-${tpr}`;
	  } else if (incPr) {
	    to = `<${tM}.${tm}.${+tp + 1}-0`;
	  } else {
	    to = `<=${to}`;
	  }

	  return `${from} ${to}`.trim()
	};

	const testSet = (set, version, options) => {
	  for (let i = 0; i < set.length; i++) {
	    if (!set[i].test(version)) {
	      return false
	    }
	  }

	  if (version.prerelease.length && !options.includePrerelease) {
	    // Find the set of versions that are allowed to have prereleases
	    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
	    // That should allow `1.2.3-pr.2` to pass.
	    // However, `1.2.4-alpha.notready` should NOT be allowed,
	    // even though it's within the range set by the comparators.
	    for (let i = 0; i < set.length; i++) {
	      debug(set[i].semver);
	      if (set[i].semver === Comparator.ANY) {
	        continue
	      }

	      if (set[i].semver.prerelease.length > 0) {
	        const allowed = set[i].semver;
	        if (allowed.major === version.major &&
	            allowed.minor === version.minor &&
	            allowed.patch === version.patch) {
	          return true
	        }
	      }
	    }

	    // Version has a -pre, but it's not one of the ones we like.
	    return false
	  }

	  return true
	};
	return vega_embed_module_range;
}

var satisfies_1;
var hasRequiredSatisfies;

function requireSatisfies () {
	if (hasRequiredSatisfies) return satisfies_1;
	hasRequiredSatisfies = 1;
	const Range = requireRange();
	const satisfies = (version, range, options) => {
	  try {
	    range = new Range(range, options);
	  } catch (er) {
	    return false
	  }
	  return range.test(version)
	};
	satisfies_1 = satisfies;
	return satisfies_1;
}

var satisfiesExports = requireSatisfies();
var satisfies = /*@__PURE__*/getDefaultExportFromCjs(satisfiesExports);

/**
 * Open editor url in a new window, and pass a message.
 */
function post (window, url, data) {
    const editor = window.open(url);
    const wait = 10000;
    const step = 250;
    const { origin } = new URL(url);
    let count = ~~(wait / step);
    function listen(evt) {
        if (evt.source === editor) {
            count = 0;
            window.removeEventListener('message', listen, false);
        }
    }
    window.addEventListener('message', listen, false);
    // send message
    // periodically resend until ack received or timeout
    function send() {
        if (count <= 0) {
            return;
        }
        editor.postMessage(data, origin);
        setTimeout(send, step);
        count -= 1;
    }
    setTimeout(send, step);
}

// generated with build-style.sh
var embedStyle = `.vega-embed {
  position: relative;
  display: inline-block;
  box-sizing: border-box;
}
.vega-embed.has-actions {
  padding-right: 38px;
}
.vega-embed details:not([open]) > :not(summary) {
  display: none !important;
}
.vega-embed summary {
  list-style: none;
  position: absolute;
  top: 0;
  right: 0;
  padding: 6px;
  z-index: 1000;
  background: white;
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
  color: #1b1e23;
  border: 1px solid #aaa;
  border-radius: 999px;
  opacity: 0.2;
  transition: opacity 0.4s ease-in;
  cursor: pointer;
  line-height: 0px;
}
.vega-embed summary::-webkit-details-marker {
  display: none;
}
.vega-embed summary:active {
  box-shadow: #aaa 0px 0px 0px 1px inset;
}
.vega-embed summary svg {
  width: 14px;
  height: 14px;
}
.vega-embed details[open] summary {
  opacity: 0.7;
}
.vega-embed:hover summary, .vega-embed:focus-within summary {
  opacity: 1 !important;
  transition: opacity 0.2s ease;
}
.vega-embed .vega-actions {
  position: absolute;
  z-index: 1001;
  top: 35px;
  right: -9px;
  display: flex;
  flex-direction: column;
  padding-bottom: 8px;
  padding-top: 8px;
  border-radius: 4px;
  box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);
  border: 1px solid #d9d9d9;
  background: white;
  animation-duration: 0.15s;
  animation-name: scale-in;
  animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5);
  text-align: left;
}
.vega-embed .vega-actions a {
  padding: 8px 16px;
  font-family: sans-serif;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  color: #434a56;
  text-decoration: none;
}
.vega-embed .vega-actions a:hover, .vega-embed .vega-actions a:focus {
  background-color: #f7f7f9;
  color: black;
}
.vega-embed .vega-actions::before, .vega-embed .vega-actions::after {
  content: "";
  display: inline-block;
  position: absolute;
}
.vega-embed .vega-actions::before {
  left: auto;
  right: 14px;
  top: -16px;
  border: 8px solid rgba(0, 0, 0, 0);
  border-bottom-color: #d9d9d9;
}
.vega-embed .vega-actions::after {
  left: auto;
  right: 15px;
  top: -14px;
  border: 7px solid rgba(0, 0, 0, 0);
  border-bottom-color: #fff;
}
.vega-embed .chart-wrapper.fit-x {
  width: 100%;
}
.vega-embed .chart-wrapper.fit-y {
  height: 100%;
}

.vega-embed-wrapper {
  max-width: 100%;
  overflow: auto;
  padding-right: 14px;
}

@keyframes scale-in {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
`;

function vega_embed_module_mergeDeep(dest, ...src) {
    for (const s of src) {
        vega_embed_module_deepMerge_(dest, s);
    }
    return dest;
}
function vega_embed_module_deepMerge_(dest, src) {
    for (const property of Object.keys(src)) {
        writeConfig(dest, property, src[property], true);
    }
}

var vega_embed_module_name = "vega-embed";
var vega_embed_module_version$1 = "6.29.0";
var vega_embed_module_description = "Publish Vega visualizations as embedded web components.";
var vega_embed_module_keywords = [
	"vega",
	"data",
	"visualization",
	"component",
	"embed"
];
var vega_embed_module_repository = {
	type: "git",
	url: "http://github.com/vega/vega-embed.git"
};
var vega_embed_module_author = {
	name: "UW Interactive Data Lab",
	url: "http://idl.cs.washington.edu"
};
var vega_embed_module_contributors = [
	{
		name: "Dominik Moritz",
		url: "https://www.domoritz.de"
	}
];
var vega_embed_module_bugs = {
	url: "https://github.com/vega/vega-embed/issues"
};
var vega_embed_module_homepage = "https://github.com/vega/vega-embed#readme";
var vega_embed_module_license = "BSD-3-Clause";
var vega_embed_module_main = "build/vega-embed.js";
var vega_embed_module_module = "build/vega-embed.module.js";
var vega_embed_module_unpkg = "build/vega-embed.min.js";
var vega_embed_module_jsdelivr = "build/vega-embed.min.js";
var vega_embed_module_types = "build/src/embed.d.ts";
var vega_embed_module_files = [
	"src",
	"build"
];
var vega_embed_module_exports = {
	".": {
		"import": {
			types: "./build/src/embed.d.ts",
			"default": "./build/vega-embed.module.js"
		},
		require: {
			"default": "./build/vega-embed.js"
		}
	}
};
var vega_embed_module_devDependencies = {
	"@babel/core": "^7.26.0",
	"@babel/eslint-parser": "^7.25.9",
	"@babel/plugin-syntax-dynamic-import": "^7.8.3",
	"@babel/plugin-transform-runtime": "^7.25.9",
	"@babel/preset-env": "^7.26.0",
	"@babel/preset-typescript": "^7.26.0",
	"@release-it/conventional-changelog": "^9.0.3",
	"@rollup/plugin-commonjs": "28.0.1",
	"@rollup/plugin-json": "^6.1.0",
	"@rollup/plugin-node-resolve": "^15.3.0",
	"@rollup/plugin-terser": "^0.4.4",
	"@rollup/plugin-typescript": "^12.1.1",
	"@types/semver": "^7.5.8",
	"@typescript-eslint/parser": "^8.15.0",
	"@vitest/coverage-istanbul": "^2.1.5",
	"browser-sync": "^3.0.3",
	concurrently: "^9.1.0",
	"del-cli": "^6.0.0",
	"eslint-config-prettier": "^9.1.0",
	"eslint-plugin-prettier": "^5.2.1",
	"eslint-plugin-vitest": "^0.5.4",
	eslint: "^9.15.0",
	jsdom: "^25.0.1",
	"postinstall-postinstall": "^2.1.0",
	prettier: "^3.3.3",
	"release-it": "^17.10.0",
	"rollup-plugin-bundle-size": "^1.0.3",
	rollup: "4.27.3",
	sass: "^1.81.0",
	"typescript-eslint": "^8.15.0",
	typescript: "^5.6.3",
	"vega-lite": "^5.21.0",
	vega: "^5.30.0",
	"vitest-canvas-mock": "^0.3.3",
	vitest: "^2.1.5"
};
var vega_embed_module_peerDependencies = {
	vega: "^5.21.0",
	"vega-lite": "*"
};
var vega_embed_module_dependencies = {
	"fast-json-patch": "^3.1.1",
	"json-stringify-pretty-compact": "^4.0.0",
	semver: "^7.6.3",
	tslib: "^2.8.1",
	"vega-interpreter": "^1.0.5",
	"vega-schema-url-parser": "^2.2.0",
	"vega-themes": "^2.15.0",
	"vega-tooltip": "^0.35.2"
};
var vega_embed_module_scripts = {
	prebuild: "npm run clean && npm run build:style",
	build: "rollup -c",
	"build:style": "./build-style.sh",
	clean: "del-cli build src/style.ts",
	prepublishOnly: "npm run clean && npm run build",
	preversion: "npm run lint && npm run test",
	serve: "browser-sync start --directory -s -f build *.html",
	start: "npm run build && concurrently --kill-others -n Server,Rollup 'npm run serve' 'rollup -c -w'",
	pretest: "npm run build:style",
	test: "vitest run",
	prettierbase: "prettier '*.{css,scss,html}'",
	format: "eslint . --fix && npm run prettierbase -- --write",
	lint: "eslint . && npm run prettierbase -- --check",
	release: "release-it"
};
var vega_embed_module_pkg = {
	name: vega_embed_module_name,
	version: vega_embed_module_version$1,
	description: vega_embed_module_description,
	keywords: vega_embed_module_keywords,
	repository: vega_embed_module_repository,
	author: vega_embed_module_author,
	contributors: vega_embed_module_contributors,
	bugs: vega_embed_module_bugs,
	homepage: vega_embed_module_homepage,
	license: vega_embed_module_license,
	main: vega_embed_module_main,
	module: vega_embed_module_module,
	unpkg: vega_embed_module_unpkg,
	jsdelivr: vega_embed_module_jsdelivr,
	types: vega_embed_module_types,
	files: vega_embed_module_files,
	exports: vega_embed_module_exports,
	devDependencies: vega_embed_module_devDependencies,
	peerDependencies: vega_embed_module_peerDependencies,
	dependencies: vega_embed_module_dependencies,
	scripts: vega_embed_module_scripts
};

const vega_embed_module_version = vega_embed_module_pkg.version;
const vega = vega_module_namespaceObject;
let vegaLite = build_src_namespaceObject;
// For backwards compatibility with Vega-Lite before v4.
const vega_embed_module_w = (typeof window !== 'undefined' ? window : undefined);
if (vegaLite === undefined && vega_embed_module_w?.vl?.compile) {
    vegaLite = vega_embed_module_w.vl;
}
const DEFAULT_ACTIONS = { export: { svg: true, png: true }, source: true, compiled: true, editor: true };
const I18N = {
    CLICK_TO_VIEW_ACTIONS: 'Click to view actions',
    COMPILED_ACTION: 'View Compiled Vega',
    EDITOR_ACTION: 'Open in Vega Editor',
    PNG_ACTION: 'Save as PNG',
    SOURCE_ACTION: 'View Source',
    SVG_ACTION: 'Save as SVG',
};
const NAMES = {
    vega: 'Vega',
    'vega-lite': 'Vega-Lite',
};
const vega_embed_module_VERSION = {
    vega: vega.version,
    'vega-lite': vegaLite ? vegaLite.version : 'not available',
};
const PREPROCESSOR = {
    vega: (vgSpec) => vgSpec,
    'vega-lite': (vlSpec, config) => vegaLite.compile(vlSpec, { config: config }).spec,
};
const SVG_CIRCLES = `
<svg viewBox="0 0 16 16" fill="currentColor" stroke="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
  <circle r="2" cy="8" cx="2"></circle>
  <circle r="2" cy="8" cx="8"></circle>
  <circle r="2" cy="8" cx="14"></circle>
</svg>`;
const CHART_WRAPPER_CLASS = 'chart-wrapper';
function isTooltipHandler(h) {
    return typeof h === 'function';
}
function viewSource(source, sourceHeader, sourceFooter, mode) {
    const header = `<html><head>${sourceHeader}</head><body><pre><code class="json">`;
    const footer = `</code></pre>${sourceFooter}</body></html>`;
    const win = window.open('');
    win.document.write(header + source + footer);
    win.document.title = `${NAMES[mode]} JSON Source`;
}
/**
 * Try to guess the type of spec.
 *
 * @param spec Vega or Vega-Lite spec.
 */
function guessMode(spec, providedMode) {
    // Decide mode
    if (spec.$schema) {
        const parsed = parser_module(spec.$schema);
        if (providedMode && providedMode !== parsed.library) {
            console.warn(`The given visualization spec is written in ${NAMES[parsed.library]}, but mode argument sets ${NAMES[providedMode] ?? providedMode}.`);
        }
        const mode = parsed.library;
        if (!satisfies(vega_embed_module_VERSION[mode], `^${parsed.version.slice(1)}`)) {
            console.warn(`The input spec uses ${NAMES[mode]} ${parsed.version}, but the current version of ${NAMES[mode]} is v${vega_embed_module_VERSION[mode]}.`);
        }
        return mode;
    }
    // try to guess from the provided spec
    if ('mark' in spec ||
        'encoding' in spec ||
        'layer' in spec ||
        'hconcat' in spec ||
        'vconcat' in spec ||
        'facet' in spec ||
        'repeat' in spec) {
        return 'vega-lite';
    }
    if ('marks' in spec || 'signals' in spec || 'scales' in spec || 'axes' in spec) {
        return 'vega';
    }
    return providedMode ?? 'vega';
}
function isLoader(o) {
    return !!(o && 'load' in o);
}
function createLoader(opts) {
    return isLoader(opts) ? opts : vega.loader(opts);
}
function embedOptionsFromUsermeta(parsedSpec) {
    const opts = parsedSpec.usermeta?.embedOptions ?? {};
    if (vega_util_module_isString(opts.defaultStyle)) {
        // we don't allow styles set via usermeta since it would allow injection of logic (we set the style via innerHTML)
        opts.defaultStyle = false;
    }
    return opts;
}
/**
 * Embed a Vega visualization component in a web page. This function returns a promise.
 *
 * @param el        DOM element in which to place component (DOM node or CSS selector).
 * @param spec      String : A URL string from which to load the Vega specification.
 *                  Object : The Vega/Vega-Lite specification as a parsed JSON object.
 * @param opts       A JavaScript object containing options for embedding.
 */
async function vega_embed_module_embed(el, spec, opts = {}) {
    let parsedSpec;
    let loader;
    if (vega_util_module_isString(spec)) {
        loader = createLoader(opts.loader);
        parsedSpec = JSON.parse(await loader.load(spec));
    }
    else {
        parsedSpec = spec;
    }
    const loadedEmbedOptions = embedOptionsFromUsermeta(parsedSpec);
    const usermetaLoader = loadedEmbedOptions.loader;
    // either create the loader for the first time or create a new loader if the spec has new loader options
    if (!loader || usermetaLoader) {
        loader = createLoader(opts.loader ?? usermetaLoader);
    }
    const usermetaOpts = await loadOpts(loadedEmbedOptions, loader);
    const parsedOpts = await loadOpts(opts, loader);
    const mergedOpts = {
        ...vega_embed_module_mergeDeep(parsedOpts, usermetaOpts),
        config: mergeConfig(parsedOpts.config ?? {}, usermetaOpts.config ?? {}),
    };
    return await _embed(el, parsedSpec, mergedOpts, loader);
}
async function loadOpts(opt, loader) {
    const config = vega_util_module_isString(opt.config) ? JSON.parse(await loader.load(opt.config)) : (opt.config ?? {});
    const patch = vega_util_module_isString(opt.patch) ? JSON.parse(await loader.load(opt.patch)) : opt.patch;
    return {
        ...opt,
        ...(patch ? { patch } : {}),
        ...(config ? { config } : {}),
    };
}
function getRoot(el) {
    const possibleRoot = el.getRootNode ? el.getRootNode() : document;
    return possibleRoot instanceof ShadowRoot
        ? { root: possibleRoot, rootContainer: possibleRoot }
        : { root: document, rootContainer: document.head ?? document.body };
}
async function _embed(el, spec, opts = {}, loader) {
    const config = opts.theme ? mergeConfig(vega_themes_module_namespaceObject[opts.theme], opts.config ?? {}) : opts.config;
    const actions = isBoolean(opts.actions) ? opts.actions : vega_embed_module_mergeDeep({}, DEFAULT_ACTIONS, opts.actions ?? {});
    const i18n = { ...I18N, ...opts.i18n };
    const renderer = opts.renderer ?? 'canvas';
    const logLevel = opts.logLevel ?? vega.Warn;
    const downloadFileName = opts.downloadFileName ?? 'visualization';
    const element = typeof el === 'string' ? document.querySelector(el) : el;
    if (!element) {
        throw new Error(`${el} does not exist`);
    }
    if (opts.defaultStyle !== false) {
        const ID = 'vega-embed-style';
        const { root, rootContainer } = getRoot(element);
        if (!root.getElementById(ID)) {
            const style = document.createElement('style');
            style.id = ID;
            style.innerHTML =
                opts.defaultStyle === undefined || opts.defaultStyle === true
                    ? (embedStyle).toString()
                    : opts.defaultStyle;
            rootContainer.appendChild(style);
        }
    }
    const mode = guessMode(spec, opts.mode);
    let vgSpec = PREPROCESSOR[mode](spec, config);
    if (mode === 'vega-lite') {
        if (vgSpec.$schema) {
            const parsed = parser_module(vgSpec.$schema);
            if (!satisfies(vega_embed_module_VERSION.vega, `^${parsed.version.slice(1)}`)) {
                console.warn(`The compiled spec uses Vega ${parsed.version}, but current version is v${vega_embed_module_VERSION.vega}.`);
            }
        }
    }
    element.classList.add('vega-embed');
    if (actions) {
        element.classList.add('has-actions');
    }
    element.innerHTML = ''; // clear container
    let container = element;
    if (actions) {
        const chartWrapper = document.createElement('div');
        chartWrapper.classList.add(CHART_WRAPPER_CLASS);
        element.appendChild(chartWrapper);
        container = chartWrapper;
    }
    const patch = opts.patch;
    if (patch) {
        vgSpec = patch instanceof Function ? patch(vgSpec) : applyPatch(vgSpec, patch, true, false).newDocument;
    }
    // Set locale. Note that this is a global setting.
    if (opts.formatLocale) {
        vega.formatLocale(opts.formatLocale);
    }
    if (opts.timeFormatLocale) {
        vega.timeFormatLocale(opts.timeFormatLocale);
    }
    // Set custom expression functions
    if (opts.expressionFunctions) {
        for (const name in opts.expressionFunctions) {
            const expressionFunction = opts.expressionFunctions[name];
            if ('fn' in expressionFunction) {
                vega.expressionFunction(name, expressionFunction.fn, expressionFunction['visitor']);
            }
            else if (expressionFunction instanceof Function) {
                vega.expressionFunction(name, expressionFunction);
            }
        }
    }
    const { ast } = opts;
    // Do not apply the config to Vega when we have already applied it to Vega-Lite.
    // This call may throw an Error if parsing fails.
    const runtime = vega.parse(vgSpec, mode === 'vega-lite' ? {} : config, { ast });
    const view = new (opts.viewClass || vega.View)(runtime, {
        loader,
        logLevel,
        renderer,
        ...(ast ? { expr: vega.expressionInterpreter ?? opts.expr ?? vega_interpreter_module_expression } : {}),
    });
    view.addSignalListener('autosize', (_, autosize) => {
        const { type } = autosize;
        if (type == 'fit-x') {
            container.classList.add('fit-x');
            container.classList.remove('fit-y');
        }
        else if (type == 'fit-y') {
            container.classList.remove('fit-x');
            container.classList.add('fit-y');
        }
        else if (type == 'fit') {
            container.classList.add('fit-x', 'fit-y');
        }
        else {
            container.classList.remove('fit-x', 'fit-y');
        }
    });
    if (opts.tooltip !== false) {
        const { loader: loader_, tooltip } = opts;
        const baseURL = loader_ && !isLoader(loader_) ? loader_?.baseURL : undefined;
        const handler = isTooltipHandler(tooltip)
            ? tooltip
            : // user provided boolean true or tooltip options
                new vega_tooltip_module_Handler({ baseURL, ...(tooltip === true ? {} : tooltip) }).call;
        view.tooltip(handler);
    }
    let { hover } = opts;
    if (hover === undefined) {
        hover = mode === 'vega';
    }
    if (hover) {
        const { hoverSet, updateSet } = (typeof hover === 'boolean' ? {} : hover);
        view.hover(hoverSet, updateSet);
    }
    if (opts) {
        if (opts.width != null) {
            view.width(opts.width);
        }
        if (opts.height != null) {
            view.height(opts.height);
        }
        if (opts.padding != null) {
            view.padding(opts.padding);
        }
    }
    await view.initialize(container, opts.bind).runAsync();
    let documentClickHandler;
    if (actions !== false) {
        let wrapper = element;
        if (opts.defaultStyle !== false || opts.forceActionsMenu) {
            const details = document.createElement('details');
            details.title = i18n.CLICK_TO_VIEW_ACTIONS;
            element.append(details);
            wrapper = details;
            const summary = document.createElement('summary');
            summary.innerHTML = SVG_CIRCLES;
            details.append(summary);
            documentClickHandler = (ev) => {
                if (!details.contains(ev.target)) {
                    details.removeAttribute('open');
                }
            };
            document.addEventListener('click', documentClickHandler);
        }
        const ctrl = document.createElement('div');
        wrapper.append(ctrl);
        ctrl.classList.add('vega-actions');
        // add 'Export' action
        if (actions === true || actions.export !== false) {
            for (const ext of ['svg', 'png']) {
                if (actions === true || actions.export === true || actions.export[ext]) {
                    const i18nExportAction = i18n[`${ext.toUpperCase()}_ACTION`];
                    const exportLink = document.createElement('a');
                    const scaleFactor = vega_util_module_isObject(opts.scaleFactor) ? opts.scaleFactor[ext] : opts.scaleFactor;
                    exportLink.text = i18nExportAction;
                    exportLink.href = '#';
                    exportLink.target = '_blank';
                    exportLink.download = `${downloadFileName}.${ext}`;
                    // add link on mousedown so that it's correct when the click happens
                    exportLink.addEventListener('mousedown', async function (e) {
                        e.preventDefault();
                        const url = await view.toImageURL(ext, scaleFactor);
                        this.href = url;
                    });
                    ctrl.append(exportLink);
                }
            }
        }
        // add 'View Source' action
        if (actions === true || actions.source !== false) {
            const viewSourceLink = document.createElement('a');
            viewSourceLink.text = i18n.SOURCE_ACTION;
            viewSourceLink.href = '#';
            viewSourceLink.addEventListener('click', function (e) {
                viewSource(stringify(spec), opts.sourceHeader ?? '', opts.sourceFooter ?? '', mode);
                e.preventDefault();
            });
            ctrl.append(viewSourceLink);
        }
        // add 'View Compiled' action
        if (mode === 'vega-lite' && (actions === true || actions.compiled !== false)) {
            const compileLink = document.createElement('a');
            compileLink.text = i18n.COMPILED_ACTION;
            compileLink.href = '#';
            compileLink.addEventListener('click', function (e) {
                viewSource(stringify(vgSpec), opts.sourceHeader ?? '', opts.sourceFooter ?? '', 'vega');
                e.preventDefault();
            });
            ctrl.append(compileLink);
        }
        // add 'Open in Vega Editor' action
        if (actions === true || actions.editor !== false) {
            const editorUrl = opts.editorUrl ?? 'https://vega.github.io/editor/';
            const editorLink = document.createElement('a');
            editorLink.text = i18n.EDITOR_ACTION;
            editorLink.href = '#';
            editorLink.addEventListener('click', function (e) {
                post(window, editorUrl, {
                    config: config,
                    mode: patch ? 'vega' : mode,
                    renderer,
                    spec: stringify(patch ? vgSpec : spec),
                });
                e.preventDefault();
            });
            ctrl.append(editorLink);
        }
    }
    function finalize() {
        if (documentClickHandler) {
            document.removeEventListener('click', documentClickHandler);
        }
        view.finalize();
    }
    return { view, spec, vgSpec, finalize, embedOptions: opts };
}


//# sourceMappingURL=vega-embed.module.js.map

;// ../../node_modules/svelte-vega/dist/constants.js
const WIDTH_HEIGHT = new Set(["width", "height"]);
//# sourceMappingURL=constants.js.map
// EXTERNAL MODULE: ../../node_modules/fast-deep-equal/index.js
var fast_deep_equal = __webpack_require__(8792);
;// ../../node_modules/svelte-vega/dist/utils.js


function updateMultipleDatasetsInView(view, data) {
    for (const [name, value] of Object.entries(data)) {
        const getType = {};
        if (value) {
            if (!!value && getType.toString.call(value) === "[object Function]") {
                const parsedValue = value;
                parsedValue(view.data(name));
            }
            else {
                view.change(name, vega
                    .changeset()
                    .remove(() => true)
                    .insert(value));
            }
        }
    }
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function shallowEqual(a = {}, b = {}, ignore = new Set()) {
    const aKeys = Object.keys(a);
    const bKeys = Object.keys(b);
    return (a === b ||
        (aKeys.length === bKeys.length &&
            aKeys.filter((k) => !ignore.has(k)).every((key) => a[key] === b[key])));
}
function removeSignalListenersFromView(view, signalListeners) {
    const signalNames = Object.keys(signalListeners);
    for (const signalName of signalNames) {
        try {
            view.removeSignalListener(signalName, signalListeners[signalName]);
        }
        catch (error) {
            // eslint-disable-next-line no-console
            console.warn("Cannot remove invalid signal listener.", error);
        }
    }
    return signalNames.length > 0;
}
function addSignalListenersToView(view, signalListeners) {
    const signalNames = Object.keys(signalListeners);
    for (const signalName of signalNames) {
        try {
            view.addSignalListener(signalName, signalListeners[signalName]);
        }
        catch (error) {
            console.warn("Cannot add invalid signal listener.", error);
        }
    }
    return signalNames.length > 0;
}
function getUniqueFieldNames(specs) {
    return new Set(specs.flatMap((o) => Object.keys(o)));
}
function computeSpecChanges(newSpec, oldSpec) {
    if (newSpec === oldSpec)
        return false;
    const changes = {
        width: false,
        height: false,
        isExpensive: false,
    };
    const hasWidth = "width" in newSpec || "width" in oldSpec;
    const hasHeight = "height" in newSpec || "height" in oldSpec;
    if (hasWidth &&
        (!("width" in newSpec) ||
            !("width" in oldSpec) ||
            newSpec.width !== oldSpec.width)) {
        if ("width" in newSpec && typeof newSpec.width === "number") {
            changes.width = newSpec.width;
        }
        else {
            changes.isExpensive = true;
        }
    }
    if (hasHeight &&
        (!("height" in newSpec) ||
            !("height" in oldSpec) ||
            newSpec.height !== oldSpec.height)) {
        if ("height" in newSpec && typeof newSpec.height === "number") {
            changes.height = newSpec.height;
        }
        else {
            changes.isExpensive = true;
        }
    }
    const fieldNames = [...getUniqueFieldNames([newSpec, oldSpec])].filter((f) => f !== "width" && f !== "height");
    if (fieldNames.some((field) => !(field in newSpec) ||
        !(field in oldSpec) ||
        !fast_deep_equal(newSpec[field], oldSpec[field]))) {
        changes.isExpensive = true;
    }
    return changes.width !== false ||
        changes.height !== false ||
        changes.isExpensive
        ? changes
        : false;
}
function combineSpecWithDimension(spec, options) {
    const { width, height } = options;
    if (typeof width !== "undefined" && typeof height !== "undefined") {
        return { ...spec, width, height };
    }
    if (typeof width !== "undefined") {
        return { ...spec, width };
    }
    if (typeof height !== "undefined") {
        return { ...spec, height };
    }
    return spec;
}
//# sourceMappingURL=utils.js.map
;// ../../node_modules/svelte-vega/dist/VegaEmbed.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-vega/dist/VegaEmbed.svelte generated by Svelte v4.2.19 */









function VegaEmbed_svelte_create_fragment(ctx) {
	let div;

	return {
		c() {
			div = dom_element("div");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			/*div_binding*/ ctx[11](div);
		},
		p: utils_noop,
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			/*div_binding*/ ctx[11](null);
		}
	};
}

function VegaEmbed_svelte_instance($$self, $$props, $$invalidate) {
	let { options } = $$props;
	let { spec } = $$props;
	let { view } = $$props;
	let { signalListeners = {} } = $$props;
	let { data = {} } = $$props;
	const dispatch = createEventDispatcher();
	let result = undefined;
	let prevOptions = {};
	let prevSignalListeners = {};
	let prevSpec = {};
	let prevData = {};
	let chartContainer;

	onDestroy(() => {
		clearView();
	});

	async function createView() {
		clearView();

		try {
			$$invalidate(6, result = await vega_embed_module_embed(chartContainer, spec, options));
			$$invalidate(1, view = result.view);

			if (addSignalListenersToView(view, signalListeners)) {
				view.runAsync();
			}

			onNewView(view);
		} catch(e) {
			handleError(e);
		}
	}

	function clearView() {
		if (result) {
			result.finalize();
			$$invalidate(6, result = undefined);
			$$invalidate(1, view = undefined);
		}
	}

	function handleError(error) {
		dispatch("onError", { error });
		console.warn(error);
	}

	function onNewView(view) {
		update();
		dispatch("onNewView", { view });
	}

	async function update() {
		if (data && Object.keys(data).length > 0 && result !== undefined) {
			$$invalidate(1, view = result.view);
			updateMultipleDatasetsInView(view, data);
			await view.resize().runAsync();
		}
	}

	function div_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			chartContainer = $$value;
			$$invalidate(0, chartContainer);
		});
	}

	$$self.$$set = $$props => {
		if ('options' in $$props) $$invalidate(2, options = $$props.options);
		if ('spec' in $$props) $$invalidate(3, spec = $$props.spec);
		if ('view' in $$props) $$invalidate(1, view = $$props.view);
		if ('signalListeners' in $$props) $$invalidate(4, signalListeners = $$props.signalListeners);
		if ('data' in $$props) $$invalidate(5, data = $$props.data);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*data, prevData*/ 1056) {
			$: {
				if (!shallowEqual(data, prevData)) {
					update();
				}

				$$invalidate(10, prevData = data);
			}
		}

		if ($$self.$$.dirty & /*chartContainer, options, prevOptions, spec, prevSpec, signalListeners, prevSignalListeners, result, view*/ 991) {
			$: {
				if (chartContainer !== undefined) {
					// only create a new view if neccessary
					if (!shallowEqual(options, prevOptions, WIDTH_HEIGHT)) {
						createView();
					} else {
						const specChanges = computeSpecChanges(combineSpecWithDimension(spec, options), combineSpecWithDimension(prevSpec, prevOptions));
						const newSignalListeners = signalListeners;
						const oldSignalListeners = prevSignalListeners;

						if (specChanges) {
							if (specChanges.isExpensive) {
								createView();
							} else if (result !== undefined) {
								const areSignalListenersChanged = !shallowEqual(newSignalListeners, oldSignalListeners);
								$$invalidate(1, view = result.view);

								if (specChanges.width !== false) {
									view.width(specChanges.width);
								}

								if (specChanges.height !== false) {
									view.height(specChanges.height);
								}

								if (areSignalListenersChanged) {
									if (oldSignalListeners) {
										removeSignalListenersFromView(view, oldSignalListeners);
									}

									if (newSignalListeners) {
										addSignalListenersToView(view, newSignalListeners);
									}
								}

								view.runAsync();
							}
						} else if (!shallowEqual(newSignalListeners, oldSignalListeners) && result !== undefined) {
							$$invalidate(1, view = result.view);

							if (oldSignalListeners) {
								removeSignalListenersFromView(view, oldSignalListeners);
							}

							if (newSignalListeners) {
								addSignalListenersToView(view, newSignalListeners);
							}

							view.runAsync();
						}
					}

					$$invalidate(7, prevOptions = options);
					$$invalidate(8, prevSignalListeners = signalListeners);
					$$invalidate(9, prevSpec = spec);
				}
			}
		}
	};

	return [
		chartContainer,
		view,
		options,
		spec,
		signalListeners,
		data,
		result,
		prevOptions,
		prevSignalListeners,
		prevSpec,
		prevData,
		div_binding
	];
}

class VegaEmbed extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, VegaEmbed_svelte_instance, VegaEmbed_svelte_create_fragment, safe_not_equal, {
			options: 2,
			spec: 3,
			view: 1,
			signalListeners: 4,
			data: 5
		});
	}
}

/* harmony default export */ const VegaEmbed_svelte = (VegaEmbed);
;// ../../node_modules/svelte-vega/dist/Vega.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-vega/dist/Vega.svelte generated by Svelte v4.2.19 */





function Vega_svelte_create_fragment(ctx) {
	let vegaembed;
	let updating_view;
	let current;

	function vegaembed_view_binding(value) {
		/*vegaembed_view_binding*/ ctx[6](value);
	}

	let vegaembed_props = {
		spec: /*spec*/ ctx[1],
		data: /*data*/ ctx[2],
		signalListeners: /*signalListeners*/ ctx[3],
		options: /*vegaOptions*/ ctx[4]
	};

	if (/*view*/ ctx[0] !== void 0) {
		vegaembed_props.view = /*view*/ ctx[0];
	}

	vegaembed = new VegaEmbed_svelte({ props: vegaembed_props });
	binding_callbacks.push(() => bind(vegaembed, 'view', vegaembed_view_binding));
	vegaembed.$on("onNewView", /*onNewView_handler*/ ctx[7]);
	vegaembed.$on("onError", /*onError_handler*/ ctx[8]);

	return {
		c() {
			create_component(vegaembed.$$.fragment);
		},
		m(target, anchor) {
			mount_component(vegaembed, target, anchor);
			current = true;
		},
		p(ctx, [dirty]) {
			const vegaembed_changes = {};
			if (dirty & /*spec*/ 2) vegaembed_changes.spec = /*spec*/ ctx[1];
			if (dirty & /*data*/ 4) vegaembed_changes.data = /*data*/ ctx[2];
			if (dirty & /*signalListeners*/ 8) vegaembed_changes.signalListeners = /*signalListeners*/ ctx[3];
			if (dirty & /*vegaOptions*/ 16) vegaembed_changes.options = /*vegaOptions*/ ctx[4];

			if (!updating_view && dirty & /*view*/ 1) {
				updating_view = true;
				vegaembed_changes.view = /*view*/ ctx[0];
				add_flush_callback(() => updating_view = false);
			}

			vegaembed.$set(vegaembed_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(vegaembed.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(vegaembed.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(vegaembed, detaching);
		}
	};
}

const mode = "vega";

function Vega_svelte_instance($$self, $$props, $$invalidate) {
	let vegaOptions;
	let { spec } = $$props;
	let { options = {} } = $$props;
	let { data = {} } = $$props;
	let { signalListeners = {} } = $$props;
	let { view = undefined } = $$props;

	function vegaembed_view_binding(value) {
		view = value;
		$$invalidate(0, view);
	}

	function onNewView_handler(event) {
		bubble.call(this, $$self, event);
	}

	function onError_handler(event) {
		bubble.call(this, $$self, event);
	}

	$$self.$$set = $$props => {
		if ('spec' in $$props) $$invalidate(1, spec = $$props.spec);
		if ('options' in $$props) $$invalidate(5, options = $$props.options);
		if ('data' in $$props) $$invalidate(2, data = $$props.data);
		if ('signalListeners' in $$props) $$invalidate(3, signalListeners = $$props.signalListeners);
		if ('view' in $$props) $$invalidate(0, view = $$props.view);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*options*/ 32) {
			$: $$invalidate(4, vegaOptions = { ...options, mode });
		}
	};

	return [
		view,
		spec,
		data,
		signalListeners,
		vegaOptions,
		options,
		vegaembed_view_binding,
		onNewView_handler,
		onError_handler
	];
}

class Vega extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, Vega_svelte_instance, Vega_svelte_create_fragment, safe_not_equal, {
			spec: 1,
			options: 5,
			data: 2,
			signalListeners: 3,
			view: 0
		});
	}
}

/* harmony default export */ const Vega_svelte = ((/* unused pure expression or super */ null && (Vega)));
;// ../../node_modules/svelte-vega/dist/VegaLite.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/node_modules/svelte-vega/dist/VegaLite.svelte generated by Svelte v4.2.19 */





function VegaLite_svelte_create_fragment(ctx) {
	let vegaembed;
	let updating_view;
	let current;

	function vegaembed_view_binding(value) {
		/*vegaembed_view_binding*/ ctx[6](value);
	}

	let vegaembed_props = {
		spec: /*spec*/ ctx[1],
		data: /*data*/ ctx[2],
		signalListeners: /*signalListeners*/ ctx[3],
		options: /*vegaLiteOptions*/ ctx[4]
	};

	if (/*view*/ ctx[0] !== void 0) {
		vegaembed_props.view = /*view*/ ctx[0];
	}

	vegaembed = new VegaEmbed_svelte({ props: vegaembed_props });
	binding_callbacks.push(() => bind(vegaembed, 'view', vegaembed_view_binding));
	vegaembed.$on("onNewView", /*onNewView_handler*/ ctx[7]);
	vegaembed.$on("onError", /*onError_handler*/ ctx[8]);

	return {
		c() {
			create_component(vegaembed.$$.fragment);
		},
		m(target, anchor) {
			mount_component(vegaembed, target, anchor);
			current = true;
		},
		p(ctx, [dirty]) {
			const vegaembed_changes = {};
			if (dirty & /*spec*/ 2) vegaembed_changes.spec = /*spec*/ ctx[1];
			if (dirty & /*data*/ 4) vegaembed_changes.data = /*data*/ ctx[2];
			if (dirty & /*signalListeners*/ 8) vegaembed_changes.signalListeners = /*signalListeners*/ ctx[3];
			if (dirty & /*vegaLiteOptions*/ 16) vegaembed_changes.options = /*vegaLiteOptions*/ ctx[4];

			if (!updating_view && dirty & /*view*/ 1) {
				updating_view = true;
				vegaembed_changes.view = /*view*/ ctx[0];
				add_flush_callback(() => updating_view = false);
			}

			vegaembed.$set(vegaembed_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(vegaembed.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(vegaembed.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(vegaembed, detaching);
		}
	};
}

const VegaLite_svelte_mode = "vega-lite";

function VegaLite_svelte_instance($$self, $$props, $$invalidate) {
	let vegaLiteOptions;
	let { spec } = $$props;
	let { options = {} } = $$props;
	let { data = {} } = $$props;
	let { signalListeners = {} } = $$props;
	let { view = undefined } = $$props;

	function vegaembed_view_binding(value) {
		view = value;
		$$invalidate(0, view);
	}

	function onNewView_handler(event) {
		bubble.call(this, $$self, event);
	}

	function onError_handler(event) {
		bubble.call(this, $$self, event);
	}

	$$self.$$set = $$props => {
		if ('spec' in $$props) $$invalidate(1, spec = $$props.spec);
		if ('options' in $$props) $$invalidate(5, options = $$props.options);
		if ('data' in $$props) $$invalidate(2, data = $$props.data);
		if ('signalListeners' in $$props) $$invalidate(3, signalListeners = $$props.signalListeners);
		if ('view' in $$props) $$invalidate(0, view = $$props.view);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*options*/ 32) {
			$: $$invalidate(4, vegaLiteOptions = { ...options, mode: VegaLite_svelte_mode });
		}
	};

	return [
		view,
		spec,
		data,
		signalListeners,
		vegaLiteOptions,
		options,
		vegaembed_view_binding,
		onNewView_handler,
		onError_handler
	];
}

class VegaLite extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, VegaLite_svelte_instance, VegaLite_svelte_create_fragment, safe_not_equal, {
			spec: 1,
			options: 5,
			data: 2,
			signalListeners: 3,
			view: 0
		});
	}
}

/* harmony default export */ const VegaLite_svelte = (VegaLite);
;// ../../node_modules/svelte-vega/dist/index.js



//# sourceMappingURL=index.js.map
;// ../../canvas_viz/dist/elements/CanvasVegaLite.svelte
/* media/satish/DATA/Development/workspace/projects/exploratory_data_analysis/deepview/src/deepview_canvas/canvas_viz/dist/elements/CanvasVegaLite.svelte generated by Svelte v4.2.19 */









function CanvasVegaLite_svelte_create_fragment(ctx) {
	let vegalite;
	let current;

	vegalite = new VegaLite_svelte({
			props: {
				spec: /*parsedSpec*/ ctx[1],
				data: /*parsedData*/ ctx[0],
				options: /*options*/ ctx[2],
				signalListeners: {
					select: /*handleSelect*/ ctx[3],
					brush: /*handleBrush*/ ctx[4]
				}
			}
		});

	return {
		c() {
			create_component(vegalite.$$.fragment);
		},
		m(target, anchor) {
			mount_component(vegalite, target, anchor);
			current = true;
		},
		p(ctx, [dirty]) {
			const vegalite_changes = {};
			if (dirty & /*parsedSpec*/ 2) vegalite_changes.spec = /*parsedSpec*/ ctx[1];
			if (dirty & /*parsedData*/ 1) vegalite_changes.data = /*parsedData*/ ctx[0];
			if (dirty & /*options*/ 4) vegalite_changes.options = /*options*/ ctx[2];
			vegalite.$set(vegalite_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(vegalite.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(vegalite.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(vegalite, detaching);
		}
	};
}

function binnedStringResolver(resolver, table) {
	const reduced_table = table.groupby(resolver.columnName).count();
	return { values: reduced_table };
}

function CanvasVegaLite_svelte_instance($$self, $$props, $$invalidate) {
	let reducedData;
	let { data = {} } = $$props;
	let { spec } = $$props;
	let { table } = $$props;
	let { filteredTable } = $$props;
	let { showUnfilteredData } = $$props;
	let { width = undefined } = $$props;
	let { height = undefined } = $$props;
	let { resolver = undefined } = $$props;
	const dispatch = createEventDispatcher();
	let parsedData = {};
	let parsedSpec = undefined;
	let parsedSpecRaw = undefined;
	let parsedSpecFiltered = undefined;
	let options = { actions: false };

	function parseSpecs(spec, data, reducedData, showUnfilteredData) {
		// Add signals to the spec
		const specWithSignals = Object.assign(Object.assign({}, spec), {
			params: [
				{
					name: "select",
					select: { "type": "point", "encodings": ["x", "y"] }
				},
				{
					name: "brush",
					select: {
						"type": "interval",
						"encodings": ["x", "y"]
					}
				}
			]
		});

		$$invalidate(1, parsedSpec = specWithSignals);
		parsedSpecRaw = Object.assign(Object.assign({}, specWithSignals), { params: [] });
		parsedSpecFiltered = Object.assign({}, specWithSignals);
		$$invalidate(0, parsedData = data);

		if (typeof data.values === "string") {
			const stringData = data.values;

			if (stringData && stringData === "arrow_table") {
				parsedSpecFiltered.data = reducedData.filtered;
				parsedSpecRaw.data = reducedData.raw;

				if (showUnfilteredData) {
					parsedSpecRaw.mark = Object.assign(Object.assign({}, parsedSpecRaw.mark), { color: "#dcdcdc" });

					$$invalidate(1, parsedSpec = {
						layer: [
							Object.assign({}, parsedSpecRaw),
							Object.assign({}, parsedSpecFiltered)
						]
					});
				} else {
					$$invalidate(1, parsedSpec = Object.assign({}, parsedSpecFiltered));
				}

				$$invalidate(0, parsedData = {});
			}
		}
	}

	function extractData(resolver, table, filteredTable) {
		if (resolver === undefined) {
			return {
				filtered: { values: filteredTable },
				raw: { values: table }
			};
		}

		switch (resolver.type) {
			case ResolverType.NUMBER:
				return {
					filtered: numberResolver(resolver, filteredTable),
					raw: numberResolver(resolver, table)
				};
			default:
				return {
					filtered: binnedStringResolver(resolver, filteredTable),
					raw: binnedStringResolver(resolver, table)
				};
		}
	}

	function numberResolver(resolver, table) {
		const reducedTable = table.groupby({
			bin_0: bin_bin(resolver.columnName, { maxbins: 20 }),
			bin_1: bin_bin(resolver.columnName, { maxbins: 20, offset: 1 })
		}).count();

		return { values: reducedTable };
	}

	function handleSelect(_, value) {
		dispatch("select", { value });
	}

	function handleBrush(_, value) {
		dispatch("brush", { value });
	}

	$$self.$$set = $$props => {
		if ('data' in $$props) $$invalidate(5, data = $$props.data);
		if ('spec' in $$props) $$invalidate(6, spec = $$props.spec);
		if ('table' in $$props) $$invalidate(7, table = $$props.table);
		if ('filteredTable' in $$props) $$invalidate(8, filteredTable = $$props.filteredTable);
		if ('showUnfilteredData' in $$props) $$invalidate(9, showUnfilteredData = $$props.showUnfilteredData);
		if ('width' in $$props) $$invalidate(10, width = $$props.width);
		if ('height' in $$props) $$invalidate(11, height = $$props.height);
		if ('resolver' in $$props) $$invalidate(12, resolver = $$props.resolver);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*width*/ 1024) {
			$: if (width) $$invalidate(2, options.width = width, options);
		}

		if ($$self.$$.dirty & /*height*/ 2048) {
			$: if (height) $$invalidate(2, options.height = height, options);
		}

		if ($$self.$$.dirty & /*resolver, table, filteredTable*/ 4480) {
			$: $$invalidate(13, reducedData = extractData(resolver, table, filteredTable));
		}

		if ($$self.$$.dirty & /*spec, data, reducedData, showUnfilteredData*/ 8800) {
			$: parseSpecs(spec, data, reducedData, showUnfilteredData);
		}
	};

	return [
		parsedData,
		parsedSpec,
		options,
		handleSelect,
		handleBrush,
		data,
		spec,
		table,
		filteredTable,
		showUnfilteredData,
		width,
		height,
		resolver,
		reducedData
	];
}

class CanvasVegaLite extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, CanvasVegaLite_svelte_instance, CanvasVegaLite_svelte_create_fragment, safe_not_equal, {
			data: 5,
			spec: 6,
			table: 7,
			filteredTable: 8,
			showUnfilteredData: 9,
			width: 10,
			height: 11,
			resolver: 12
		});
	}
}

/* harmony default export */ const CanvasVegaLite_svelte = (CanvasVegaLite);
;// ./src/SummaryListElement.svelte
/* src/SummaryListElement.svelte generated by Svelte v4.2.19 */






function SummaryListElement_svelte_create_if_block(ctx) {
	let div1;
	let div0;
	let textfield;
	let updating_value;
	let current;

	function textfield_value_binding(value) {
		/*textfield_value_binding*/ ctx[8](value);
	}

	let textfield_props = { placeholder: "Chart Title" };

	if (/*value*/ ctx[4] !== void 0) {
		textfield_props.value = /*value*/ ctx[4];
	}

	textfield = new TextField_svelte({ props: textfield_props });
	binding_callbacks.push(() => bind(textfield, 'value', textfield_value_binding));

	return {
		c() {
			div1 = dom_element("div");
			div0 = dom_element("div");
			create_component(textfield.$$.fragment);
			dom_attr(div0, "class", "flex-grow");
			dom_attr(div1, "class", "flex m-1");
		},
		m(target, anchor) {
			dom_insert(target, div1, anchor);
			dom_append(div1, div0);
			mount_component(textfield, div0, null);
			current = true;
		},
		p(ctx, dirty) {
			const textfield_changes = {};

			if (!updating_value && dirty & /*value*/ 16) {
				updating_value = true;
				textfield_changes.value = /*value*/ ctx[4];
				add_flush_callback(() => updating_value = false);
			}

			textfield.$set(textfield_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(textfield.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(textfield.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div1);
			}

			destroy_component(textfield);
		}
	};
}

function SummaryListElement_svelte_create_fragment(ctx) {
	let div;
	let t;
	let canvasvegalite;
	let div_class_value;
	let current;
	let if_block = /*editMode*/ ctx[3] && SummaryListElement_svelte_create_if_block(ctx);

	canvasvegalite = new CanvasVegaLite_svelte({
			props: {
				data: /*typedData*/ ctx[5].data,
				spec: /*typedData*/ ctx[5].spec,
				resolver: /*typedData*/ ctx[5].resolver,
				table: /*table*/ ctx[1],
				filteredTable: /*filteredTable*/ ctx[2],
				showUnfilteredData: /*canvasSpec*/ ctx[0].showUnfilteredData
			}
		});

	return {
		c() {
			div = dom_element("div");
			if (if_block) if_block.c();
			t = space();
			create_component(canvasvegalite.$$.fragment);

			dom_attr(div, "class", div_class_value = "" + ((/*editMode*/ ctx[3]
			? 'border border-button_outline'
			: '') + " rounded m-1 flex flex-col"));
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			if (if_block) if_block.m(div, null);
			dom_append(div, t);
			mount_component(canvasvegalite, div, null);
			current = true;
		},
		p(ctx, [dirty]) {
			if (/*editMode*/ ctx[3]) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*editMode*/ 8) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = SummaryListElement_svelte_create_if_block(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}

			const canvasvegalite_changes = {};
			if (dirty & /*typedData*/ 32) canvasvegalite_changes.data = /*typedData*/ ctx[5].data;
			if (dirty & /*typedData*/ 32) canvasvegalite_changes.spec = /*typedData*/ ctx[5].spec;
			if (dirty & /*typedData*/ 32) canvasvegalite_changes.resolver = /*typedData*/ ctx[5].resolver;
			if (dirty & /*table*/ 2) canvasvegalite_changes.table = /*table*/ ctx[1];
			if (dirty & /*filteredTable*/ 4) canvasvegalite_changes.filteredTable = /*filteredTable*/ ctx[2];
			if (dirty & /*canvasSpec*/ 1) canvasvegalite_changes.showUnfilteredData = /*canvasSpec*/ ctx[0].showUnfilteredData;
			canvasvegalite.$set(canvasvegalite_changes);

			if (!current || dirty & /*editMode*/ 8 && div_class_value !== (div_class_value = "" + ((/*editMode*/ ctx[3]
			? 'border border-button_outline'
			: '') + " rounded m-1 flex flex-col"))) {
				dom_attr(div, "class", div_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			transitions_transition_in(canvasvegalite.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			transitions_transition_out(canvasvegalite.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			if (if_block) if_block.d();
			destroy_component(canvasvegalite);
		}
	};
}

function SummaryListElement_svelte_instance($$self, $$props, $$invalidate) {
	let typedData;
	let title;
	let { canvasSpec } = $$props;
	let { element } = $$props;
	let { table } = $$props;
	let { filteredTable } = $$props;
	let { editMode = false } = $$props;
	let value = '';
	const dispatch = createEventDispatcher();

	function textfield_value_binding(value$1) {
		value = value$1;
		((($$invalidate(4, value), $$invalidate(7, title)), $$invalidate(5, typedData)), $$invalidate(6, element));
	}

	$$self.$$set = $$props => {
		if ('canvasSpec' in $$props) $$invalidate(0, canvasSpec = $$props.canvasSpec);
		if ('element' in $$props) $$invalidate(6, element = $$props.element);
		if ('table' in $$props) $$invalidate(1, table = $$props.table);
		if ('filteredTable' in $$props) $$invalidate(2, filteredTable = $$props.filteredTable);
		if ('editMode' in $$props) $$invalidate(3, editMode = $$props.editMode);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*element*/ 64) {
			$: $$invalidate(5, typedData = element.data);
		}

		if ($$self.$$.dirty & /*typedData*/ 32) {
			$: $$invalidate(7, title = typedData.spec.title === undefined
			? ''
			: typedData.spec.title);
		}

		if ($$self.$$.dirty & /*title*/ 128) {
			$: $$invalidate(4, value = title);
		}

		if ($$self.$$.dirty & /*value, typedData, element*/ 112) {
			$: {
				if (value !== typedData.spec.title) {
					dispatch('update', {
						element: Object.assign(Object.assign({}, element), {
							data: Object.assign(Object.assign({}, typedData), {
								spec: Object.assign(Object.assign({}, typedData.spec), { title: value })
							})
						}),
						oldElement: element
					});
				}
			}
		}
	};

	return [
		canvasSpec,
		table,
		filteredTable,
		editMode,
		value,
		typedData,
		element,
		title,
		textfield_value_binding
	];
}

class SummaryListElement extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, SummaryListElement_svelte_instance, SummaryListElement_svelte_create_fragment, safe_not_equal, {
			canvasSpec: 0,
			element: 6,
			table: 1,
			filteredTable: 2,
			editMode: 3
		});
	}
}

/* harmony default export */ const SummaryListElement_svelte = (SummaryListElement);
;// ./src/SummaryNumberElement.svelte
/* src/SummaryNumberElement.svelte generated by Svelte v4.2.19 */




function SummaryNumberElement_svelte_create_fragment(ctx) {
	let div;
	let p0;
	let t0;
	let t1;
	let t2;
	let p1;
	let t3_value = /*data*/ ctx[0].toLocaleString() + "";
	let t3;
	let div_class_value;

	return {
		c() {
			div = dom_element("div");
			p0 = dom_element("p");
			t0 = dom_text(/*name*/ ctx[1]);
			t1 = dom_text(":");
			t2 = space();
			p1 = dom_element("p");
			t3 = dom_text(t3_value);
			dom_attr(p0, "class", "font-bold mr-2");

			dom_attr(div, "class", div_class_value = "" + ((/*editMode*/ ctx[2]
			? 'border border-button_outline '
			: '') + " flex p-2 m-1 rounded"));
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			dom_append(div, p0);
			dom_append(p0, t0);
			dom_append(p0, t1);
			dom_append(div, t2);
			dom_append(div, p1);
			dom_append(p1, t3);
		},
		p(ctx, [dirty]) {
			if (dirty & /*name*/ 2) set_data(t0, /*name*/ ctx[1]);
			if (dirty & /*data*/ 1 && t3_value !== (t3_value = /*data*/ ctx[0].toLocaleString() + "")) set_data(t3, t3_value);

			if (dirty & /*editMode*/ 4 && div_class_value !== (div_class_value = "" + ((/*editMode*/ ctx[2]
			? 'border border-button_outline '
			: '') + " flex p-2 m-1 rounded"))) {
				dom_attr(div, "class", div_class_value);
			}
		},
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}
		}
	};
}

function SummaryNumberElement_svelte_instance($$self, $$props, $$invalidate) {
	let { data } = $$props;
	let { name } = $$props;
	let { editMode } = $$props;

	$$self.$$set = $$props => {
		if ('data' in $$props) $$invalidate(0, data = $$props.data);
		if ('name' in $$props) $$invalidate(1, name = $$props.name);
		if ('editMode' in $$props) $$invalidate(2, editMode = $$props.editMode);
	};

	return [data, name, editMode];
}

class SummaryNumberElement extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, SummaryNumberElement_svelte_instance, SummaryNumberElement_svelte_create_fragment, safe_not_equal, { data: 0, name: 1, editMode: 2 });
	}
}

/* harmony default export */ const SummaryNumberElement_svelte = (SummaryNumberElement);
;// ./src/SelectedQueries.svelte
/* src/SelectedQueries.svelte generated by Svelte v4.2.19 */







function SelectedQueries_svelte_get_each_context(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[4] = list[i];
	return child_ctx;
}

// (32:6) {#if query.icon !== undefined}
function SelectedQueries_svelte_create_if_block(ctx) {
	let fa;
	let current;
	fa = new dist({ props: { icon: /*query*/ ctx[4].icon } });

	return {
		c() {
			create_component(fa.$$.fragment);
		},
		m(target, anchor) {
			mount_component(fa, target, anchor);
			current = true;
		},
		p(ctx, dirty) {
			const fa_changes = {};
			if (dirty & /*selectedQueries*/ 1) fa_changes.icon = /*query*/ ctx[4].icon;
			fa.$set(fa_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(fa, detaching);
		}
	};
}

// (26:2) {#each selectedQueries as query}
function SelectedQueries_svelte_create_each_block(ctx) {
	let div;
	let t0;
	let span;
	let t1_value = /*query*/ ctx[4].name + "";
	let t1;
	let t2;
	let div_transition;
	let current;
	let mounted;
	let dispose;
	let if_block = /*query*/ ctx[4].icon !== undefined && SelectedQueries_svelte_create_if_block(ctx);

	function click_handler() {
		return /*click_handler*/ ctx[2](/*query*/ ctx[4]);
	}

	return {
		c() {
			div = dom_element("div");
			if (if_block) if_block.c();
			t0 = space();
			span = dom_element("span");
			t1 = dom_text(t1_value);
			t2 = space();
			dom_attr(span, "class", "pl-1");
			dom_attr(div, "class", "flex flex-grow justify-center items-center m-1 p-1 border rounded cursor-pointer bg-midgrey");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			if (if_block) if_block.m(div, null);
			dom_append(div, t0);
			dom_append(div, span);
			dom_append(span, t1);
			dom_append(div, t2);
			current = true;

			if (!mounted) {
				dispose = dom_listen(div, "click", click_handler);
				mounted = true;
			}
		},
		p(new_ctx, dirty) {
			ctx = new_ctx;

			if (/*query*/ ctx[4].icon !== undefined) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*selectedQueries*/ 1) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = SelectedQueries_svelte_create_if_block(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t0);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}

			if ((!current || dirty & /*selectedQueries*/ 1) && t1_value !== (t1_value = /*query*/ ctx[4].name + "")) set_data(t1, t1_value);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);

			if (local) {
				scheduler_add_render_callback(() => {
					if (!current) return;
					if (!div_transition) div_transition = create_bidirectional_transition(div, slide, {}, true);
					div_transition.run(1);
				});
			}

			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);

			if (local) {
				if (!div_transition) div_transition = create_bidirectional_transition(div, slide, {}, false);
				div_transition.run(0);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			if (if_block) if_block.d();
			if (detaching && div_transition) div_transition.end();
			mounted = false;
			dispose();
		}
	};
}

function SelectedQueries_svelte_create_fragment(ctx) {
	let div;
	let current;
	let each_value = each_ensure_array_like(/*selectedQueries*/ ctx[0]);
	let each_blocks = [];

	for (let i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = SelectedQueries_svelte_create_each_block(SelectedQueries_svelte_get_each_context(ctx, each_value, i));
	}

	const out = i => transitions_transition_out(each_blocks[i], 1, 1, () => {
		each_blocks[i] = null;
	});

	return {
		c() {
			div = dom_element("div");

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			dom_attr(div, "class", "flex flex-col");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(div, null);
				}
			}

			current = true;
		},
		p(ctx, [dirty]) {
			if (dirty & /*previousQuery, selectedQueries, undefined*/ 3) {
				each_value = each_ensure_array_like(/*selectedQueries*/ ctx[0]);
				let i;

				for (i = 0; i < each_value.length; i += 1) {
					const child_ctx = SelectedQueries_svelte_get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
						transitions_transition_in(each_blocks[i], 1);
					} else {
						each_blocks[i] = SelectedQueries_svelte_create_each_block(child_ctx);
						each_blocks[i].c();
						transitions_transition_in(each_blocks[i], 1);
						each_blocks[i].m(div, null);
					}
				}

				group_outros();

				for (i = each_value.length; i < each_blocks.length; i += 1) {
					out(i);
				}

				check_outros();
			}
		},
		i(local) {
			if (current) return;

			for (let i = 0; i < each_value.length; i += 1) {
				transitions_transition_in(each_blocks[i]);
			}

			current = true;
		},
		o(local) {
			each_blocks = each_blocks.filter(Boolean);

			for (let i = 0; i < each_blocks.length; i += 1) {
				transitions_transition_out(each_blocks[i]);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_each(each_blocks, detaching);
		}
	};
}

function SelectedQueries_svelte_instance($$self, $$props, $$invalidate) {
	let { selectedQueries } = $$props;
	const dispatch = createEventDispatcher();

	function previousQuery(query) {
		dispatch('previousQuery', { query });
	}

	const click_handler = query => previousQuery(query);

	$$self.$$set = $$props => {
		if ('selectedQueries' in $$props) $$invalidate(0, selectedQueries = $$props.selectedQueries);
	};

	return [selectedQueries, previousQuery, click_handler];
}

class SelectedQueries extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, SelectedQueries_svelte_instance, SelectedQueries_svelte_create_fragment, safe_not_equal, { selectedQueries: 0 });
	}
}

/* harmony default export */ const SelectedQueries_svelte = (SelectedQueries);
;// ./src/NextQueries.svelte
/* src/NextQueries.svelte generated by Svelte v4.2.19 */







function NextQueries_svelte_get_each_context(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[5] = list[i];
	return child_ctx;
}

// (32:6) {#if query.icon !== undefined}
function NextQueries_svelte_create_if_block(ctx) {
	let fa;
	let current;

	fa = new dist({
			props: {
				color: "#7f7f7f",
				icon: /*query*/ ctx[5].icon
			}
		});

	return {
		c() {
			create_component(fa.$$.fragment);
		},
		m(target, anchor) {
			mount_component(fa, target, anchor);
			current = true;
		},
		p(ctx, dirty) {
			const fa_changes = {};
			if (dirty & /*nextQueries*/ 1) fa_changes.icon = /*query*/ ctx[5].icon;
			fa.$set(fa_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(fa, detaching);
		}
	};
}

// (27:2) {#each nextQueries as query}
function NextQueries_svelte_create_each_block(ctx) {
	let div;
	let t0;
	let span;
	let t1_value = /*query*/ ctx[5].name + "";
	let t1;
	let t2;
	let current;
	let mounted;
	let dispose;
	let if_block = /*query*/ ctx[5].icon !== undefined && NextQueries_svelte_create_if_block(ctx);

	function click_handler() {
		return /*click_handler*/ ctx[3](/*query*/ ctx[5]);
	}

	return {
		c() {
			div = dom_element("div");
			if (if_block) if_block.c();
			t0 = space();
			span = dom_element("span");
			t1 = dom_text(t1_value);
			t2 = space();
			dom_attr(span, "class", "pl-1 text-darkgrey");
			dom_attr(div, "class", "flex flex-grow justify-center items-center m-1 p-1 border border-midgrey rounded cursor-pointer");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			if (if_block) if_block.m(div, null);
			dom_append(div, t0);
			dom_append(div, span);
			dom_append(span, t1);
			dom_append(div, t2);
			current = true;

			if (!mounted) {
				dispose = dom_listen(div, "click", click_handler);
				mounted = true;
			}
		},
		p(new_ctx, dirty) {
			ctx = new_ctx;

			if (/*query*/ ctx[5].icon !== undefined) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*nextQueries*/ 1) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = NextQueries_svelte_create_if_block(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t0);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}

			if ((!current || dirty & /*nextQueries*/ 1) && t1_value !== (t1_value = /*query*/ ctx[5].name + "")) set_data(t1, t1_value);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(if_block);
			current = true;
		},
		o(local) {
			transitions_transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			if (if_block) if_block.d();
			mounted = false;
			dispose();
		}
	};
}

function NextQueries_svelte_create_fragment(ctx) {
	let div;
	let div_transition;
	let current;
	let each_value = each_ensure_array_like(/*nextQueries*/ ctx[0]);
	let each_blocks = [];

	for (let i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = NextQueries_svelte_create_each_block(NextQueries_svelte_get_each_context(ctx, each_value, i));
	}

	const out = i => transitions_transition_out(each_blocks[i], 1, 1, () => {
		each_blocks[i] = null;
	});

	return {
		c() {
			div = dom_element("div");

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			dom_attr(div, "class", "flex flex-wrap");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(div, null);
				}
			}

			current = true;
		},
		p(ctx, [dirty]) {
			if (dirty & /*querySelected, nextQueries, undefined*/ 3) {
				each_value = each_ensure_array_like(/*nextQueries*/ ctx[0]);
				let i;

				for (i = 0; i < each_value.length; i += 1) {
					const child_ctx = NextQueries_svelte_get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
						transitions_transition_in(each_blocks[i], 1);
					} else {
						each_blocks[i] = NextQueries_svelte_create_each_block(child_ctx);
						each_blocks[i].c();
						transitions_transition_in(each_blocks[i], 1);
						each_blocks[i].m(div, null);
					}
				}

				group_outros();

				for (i = each_value.length; i < each_blocks.length; i += 1) {
					out(i);
				}

				check_outros();
			}
		},
		i(local) {
			if (current) return;

			for (let i = 0; i < each_value.length; i += 1) {
				transitions_transition_in(each_blocks[i]);
			}

			if (local) {
				scheduler_add_render_callback(() => {
					if (!current) return;
					if (!div_transition) div_transition = create_bidirectional_transition(div, fade, {}, true);
					div_transition.run(1);
				});
			}

			current = true;
		},
		o(local) {
			each_blocks = each_blocks.filter(Boolean);

			for (let i = 0; i < each_blocks.length; i += 1) {
				transitions_transition_out(each_blocks[i]);
			}

			if (local) {
				if (!div_transition) div_transition = create_bidirectional_transition(div, fade, {}, false);
				div_transition.run(0);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_each(each_blocks, detaching);
			if (detaching && div_transition) div_transition.end();
		}
	};
}

function NextQueries_svelte_instance($$self, $$props, $$invalidate) {
	let nextQueries;
	let { currentQuery } = $$props;
	const dispatch = createEventDispatcher();

	function querySelected(query) {
		dispatch('querySelected', { query });
	}

	const click_handler = query => querySelected(query);

	$$self.$$set = $$props => {
		if ('currentQuery' in $$props) $$invalidate(2, currentQuery = $$props.currentQuery);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*currentQuery*/ 4) {
			$: $$invalidate(0, nextQueries = currentQuery.next);
		}
	};

	return [nextQueries, querySelected, currentQuery, click_handler];
}

class NextQueries extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, NextQueries_svelte_instance, NextQueries_svelte_create_fragment, safe_not_equal, { currentQuery: 2 });
	}
}

/* harmony default export */ const NextQueries_svelte = (NextQueries);
;// ./src/SummaryChartSelection.svelte
/* src/SummaryChartSelection.svelte generated by Svelte v4.2.19 */









function SummaryChartSelection_svelte_create_fragment(ctx) {
	let div1;
	let div0;
	let selectedqueries;
	let t;
	let nextqueries;
	let div1_transition;
	let current;

	selectedqueries = new SelectedQueries_svelte({
			props: {
				selectedQueries: /*selectedQueries*/ ctx[0]
			}
		});

	selectedqueries.$on("previousQuery", /*previousQuery*/ ctx[3]);

	nextqueries = new NextQueries_svelte({
			props: { currentQuery: /*currentQuery*/ ctx[1] }
		});

	nextqueries.$on("querySelected", /*querySelected*/ ctx[2]);

	return {
		c() {
			div1 = dom_element("div");
			div0 = dom_element("div");
			create_component(selectedqueries.$$.fragment);
			t = space();
			create_component(nextqueries.$$.fragment);
			dom_attr(div0, "class", "flex flex-col");
			dom_attr(div1, "class", "flex flex-col p-2 bg-lightgrey border-midgrey border-2 rounded select-none");
		},
		m(target, anchor) {
			dom_insert(target, div1, anchor);
			dom_append(div1, div0);
			mount_component(selectedqueries, div0, null);
			dom_append(div0, t);
			mount_component(nextqueries, div0, null);
			current = true;
		},
		p(ctx, [dirty]) {
			const selectedqueries_changes = {};
			if (dirty & /*selectedQueries*/ 1) selectedqueries_changes.selectedQueries = /*selectedQueries*/ ctx[0];
			selectedqueries.$set(selectedqueries_changes);
			const nextqueries_changes = {};
			if (dirty & /*currentQuery*/ 2) nextqueries_changes.currentQuery = /*currentQuery*/ ctx[1];
			nextqueries.$set(nextqueries_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(selectedqueries.$$.fragment, local);
			transitions_transition_in(nextqueries.$$.fragment, local);

			if (local) {
				scheduler_add_render_callback(() => {
					if (!current) return;
					if (!div1_transition) div1_transition = create_bidirectional_transition(div1, fade, {}, true);
					div1_transition.run(1);
				});
			}

			current = true;
		},
		o(local) {
			transitions_transition_out(selectedqueries.$$.fragment, local);
			transitions_transition_out(nextqueries.$$.fragment, local);

			if (local) {
				if (!div1_transition) div1_transition = create_bidirectional_transition(div1, fade, {}, false);
				div1_transition.run(0);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div1);
			}

			destroy_component(selectedqueries);
			destroy_component(nextqueries);
			if (detaching && div1_transition) div1_transition.end();
		}
	};
}

function SummaryChartSelection_svelte_instance($$self, $$props, $$invalidate) {
	let { table } = $$props;
	const dispatch = createEventDispatcher();
	let selectedQueries = [];
	let currentQuery = getQueryTree(table);

	function querySelected(event) {
		const query = event.detail.query;

		if (typeof query.next === 'function') {
			dispatch('elementSelected', {
				element: query.next(selectedQueries.map(query => query.name), table)
			});

			$$invalidate(1, currentQuery = getQueryTree(table));
			$$invalidate(0, selectedQueries = []);
		} else {
			$$invalidate(0, selectedQueries = [...selectedQueries, query]);
			$$invalidate(1, currentQuery = query);
		}
	}

	function previousQuery(event) {
		const previousQuery = event.detail.query;
		const index = selectedQueries.findIndex(query => query === previousQuery);

		if (index === 0) {
			$$invalidate(1, currentQuery = getQueryTree(table));
			$$invalidate(0, selectedQueries = []);
		} else {
			$$invalidate(1, currentQuery = selectedQueries[index - 1]);
			selectedQueries.slice(index - 1);
		}
	}

	$$self.$$set = $$props => {
		if ('table' in $$props) $$invalidate(4, table = $$props.table);
	};

	return [selectedQueries, currentQuery, querySelected, previousQuery, table];
}

class SummaryChartSelection extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, SummaryChartSelection_svelte_instance, SummaryChartSelection_svelte_create_fragment, safe_not_equal, { table: 4 });
	}
}

/* harmony default export */ const SummaryChartSelection_svelte = (SummaryChartSelection);
;// ./src/CanvasSummary.svelte
/* src/CanvasSummary.svelte generated by Svelte v4.2.19 */
















function CanvasSummary_svelte_get_each_context(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[24] = list[i];
	return child_ctx;
}

function CanvasSummary_svelte_get_each_context_1(ctx, list, i) {
	const child_ctx = ctx.slice();
	child_ctx[24] = list[i];
	return child_ctx;
}

// (73:8) 
function CanvasSummary_svelte_create_icon_slot(ctx) {
	let fa;
	let current;

	fa = new dist({
			props: {
				icon: /*editMode*/ ctx[6] ? faCheck/* faCheck */.e6 : faEdit/* faEdit */.MT,
				slot: "icon"
			}
		});

	return {
		c() {
			create_component(fa.$$.fragment);
		},
		m(target, anchor) {
			mount_component(fa, target, anchor);
			current = true;
		},
		p(ctx, dirty) {
			const fa_changes = {};
			if (dirty & /*editMode*/ 64) fa_changes.icon = /*editMode*/ ctx[6] ? faCheck/* faCheck */.e6 : faEdit/* faEdit */.MT;
			fa.$set(fa_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(fa, detaching);
		}
	};
}

// (74:8) 
function CanvasSummary_svelte_create_text_slot(ctx) {
	let span;
	let t_value = (/*editMode*/ ctx[6] ? 'Done' : 'Edit') + "";
	let t;

	return {
		c() {
			span = dom_element("span");
			t = dom_text(t_value);
			dom_attr(span, "slot", "text");
		},
		m(target, anchor) {
			dom_insert(target, span, anchor);
			dom_append(span, t);
		},
		p(ctx, dirty) {
			if (dirty & /*editMode*/ 64 && t_value !== (t_value = (/*editMode*/ ctx[6] ? 'Done' : 'Edit') + "")) set_data(t, t_value);
		},
		d(detaching) {
			if (detaching) {
				dom_detach(span);
			}
		}
	};
}

// (66:2) <ComponentHeader     title={'Summary'}     description={widgetSpec.description}     {container}   >
function create_default_slot(ctx) {
	let div;
	let iconbutton;
	let current;

	iconbutton = new IconButton_svelte({
			props: {
				$$slots: {
					text: [CanvasSummary_svelte_create_text_slot],
					icon: [CanvasSummary_svelte_create_icon_slot]
				},
				$$scope: { ctx }
			}
		});

	iconbutton.$on("click", /*click_handler*/ ctx[17]);

	return {
		c() {
			div = dom_element("div");
			create_component(iconbutton.$$.fragment);
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(iconbutton, div, null);
			current = true;
		},
		p(ctx, dirty) {
			const iconbutton_changes = {};

			if (dirty & /*$$scope, editMode*/ 536870976) {
				iconbutton_changes.$$scope = { dirty, ctx };
			}

			iconbutton.$set(iconbutton_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(iconbutton.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(iconbutton.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(iconbutton);
		}
	};
}

// (78:2) {#if editMode}
function create_if_block_3(ctx) {
	let summarychartselection;
	let current;
	summarychartselection = new SummaryChartSelection_svelte({ props: { table: /*$table*/ ctx[5] } });
	summarychartselection.$on("elementSelected", /*addElement*/ ctx[13]);

	return {
		c() {
			create_component(summarychartselection.$$.fragment);
		},
		m(target, anchor) {
			mount_component(summarychartselection, target, anchor);
			current = true;
		},
		p(ctx, dirty) {
			const summarychartselection_changes = {};
			if (dirty & /*$table*/ 32) summarychartselection_changes.table = /*$table*/ ctx[5];
			summarychartselection.$set(summarychartselection_changes);
		},
		i(local) {
			if (current) return;
			transitions_transition_in(summarychartselection.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(summarychartselection.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			destroy_component(summarychartselection, detaching);
		}
	};
}

// (125:4) {:else}
function CanvasSummary_svelte_create_else_block(ctx) {
	let p;

	return {
		c() {
			p = dom_element("p");
			p.textContent = "There was no data found to display in the summary charts.";
		},
		m(target, anchor) {
			dom_insert(target, p, anchor);
		},
		p: utils_noop,
		i: utils_noop,
		o: utils_noop,
		d(detaching) {
			if (detaching) {
				dom_detach(p);
			}
		}
	};
}

// (82:4) {#if CharacterData.length > 0 || numberData.length > 0}
function CanvasSummary_svelte_create_if_block(ctx) {
	let div0;
	let t;
	let div1;
	let current;
	let each_value_1 = each_ensure_array_like(/*numberData*/ ctx[9]);
	let each_blocks_1 = [];

	for (let i = 0; i < each_value_1.length; i += 1) {
		each_blocks_1[i] = CanvasSummary_svelte_create_each_block_1(CanvasSummary_svelte_get_each_context_1(ctx, each_value_1, i));
	}

	const out = i => transitions_transition_out(each_blocks_1[i], 1, 1, () => {
		each_blocks_1[i] = null;
	});

	let each_value = each_ensure_array_like(/*chartData*/ ctx[8]);
	let each_blocks = [];

	for (let i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = CanvasSummary_svelte_create_each_block(CanvasSummary_svelte_get_each_context(ctx, each_value, i));
	}

	const out_1 = i => transitions_transition_out(each_blocks[i], 1, 1, () => {
		each_blocks[i] = null;
	});

	return {
		c() {
			div0 = dom_element("div");

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				each_blocks_1[i].c();
			}

			t = space();
			div1 = dom_element("div");

			for (let i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}

			dom_attr(div0, "class", "flex flex-wrap");
			dom_attr(div1, "class", "flex flex-wrap");
		},
		m(target, anchor) {
			dom_insert(target, div0, anchor);

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				if (each_blocks_1[i]) {
					each_blocks_1[i].m(div0, null);
				}
			}

			dom_insert(target, t, anchor);
			dom_insert(target, div1, anchor);

			for (let i = 0; i < each_blocks.length; i += 1) {
				if (each_blocks[i]) {
					each_blocks[i].m(div1, null);
				}
			}

			current = true;
		},
		p(ctx, dirty) {
			if (dirty & /*removeElement, numberData, editMode*/ 4672) {
				each_value_1 = each_ensure_array_like(/*numberData*/ ctx[9]);
				let i;

				for (i = 0; i < each_value_1.length; i += 1) {
					const child_ctx = CanvasSummary_svelte_get_each_context_1(ctx, each_value_1, i);

					if (each_blocks_1[i]) {
						each_blocks_1[i].p(child_ctx, dirty);
						transitions_transition_in(each_blocks_1[i], 1);
					} else {
						each_blocks_1[i] = CanvasSummary_svelte_create_each_block_1(child_ctx);
						each_blocks_1[i].c();
						transitions_transition_in(each_blocks_1[i], 1);
						each_blocks_1[i].m(div0, null);
					}
				}

				group_outros();

				for (i = each_value_1.length; i < each_blocks_1.length; i += 1) {
					out(i);
				}

				check_outros();
			}

			if (dirty & /*removeElement, chartData, editMode, $table, $filteredTable, $canvasSpec, updateElement*/ 23904) {
				each_value = each_ensure_array_like(/*chartData*/ ctx[8]);
				let i;

				for (i = 0; i < each_value.length; i += 1) {
					const child_ctx = CanvasSummary_svelte_get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(child_ctx, dirty);
						transitions_transition_in(each_blocks[i], 1);
					} else {
						each_blocks[i] = CanvasSummary_svelte_create_each_block(child_ctx);
						each_blocks[i].c();
						transitions_transition_in(each_blocks[i], 1);
						each_blocks[i].m(div1, null);
					}
				}

				group_outros();

				for (i = each_value.length; i < each_blocks.length; i += 1) {
					out_1(i);
				}

				check_outros();
			}
		},
		i(local) {
			if (current) return;

			for (let i = 0; i < each_value_1.length; i += 1) {
				transitions_transition_in(each_blocks_1[i]);
			}

			for (let i = 0; i < each_value.length; i += 1) {
				transitions_transition_in(each_blocks[i]);
			}

			current = true;
		},
		o(local) {
			each_blocks_1 = each_blocks_1.filter(Boolean);

			for (let i = 0; i < each_blocks_1.length; i += 1) {
				transitions_transition_out(each_blocks_1[i]);
			}

			each_blocks = each_blocks.filter(Boolean);

			for (let i = 0; i < each_blocks.length; i += 1) {
				transitions_transition_out(each_blocks[i]);
			}

			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div0);
				dom_detach(t);
				dom_detach(div1);
			}

			destroy_each(each_blocks_1, detaching);
			destroy_each(each_blocks, detaching);
		}
	};
}

// (91:12) {#if editMode}
function CanvasSummary_svelte_create_if_block_2(ctx) {
	let button;
	let fa;
	let current;
	let mounted;
	let dispose;
	fa = new dist({ props: { icon: faTimes/* faTimes */.GR } });

	function click_handler_1() {
		return /*click_handler_1*/ ctx[18](/*element*/ ctx[24]);
	}

	return {
		c() {
			button = dom_element("button");
			create_component(fa.$$.fragment);
			dom_attr(button, "class", "absolute top-0 right-0");
		},
		m(target, anchor) {
			dom_insert(target, button, anchor);
			mount_component(fa, button, null);
			current = true;

			if (!mounted) {
				dispose = dom_listen(button, "click", click_handler_1);
				mounted = true;
			}
		},
		p(new_ctx, dirty) {
			ctx = new_ctx;
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(button);
			}

			destroy_component(fa);
			mounted = false;
			dispose();
		}
	};
}

// (84:8) {#each numberData as element}
function CanvasSummary_svelte_create_each_block_1(ctx) {
	let div;
	let summarynumberelement;
	let t0;
	let t1;
	let current;

	summarynumberelement = new SummaryNumberElement_svelte({
			props: {
				data: /*element*/ ctx[24].data,
				name: /*element*/ ctx[24].name,
				editMode: /*editMode*/ ctx[6]
			}
		});

	let if_block = /*editMode*/ ctx[6] && CanvasSummary_svelte_create_if_block_2(ctx);

	return {
		c() {
			div = dom_element("div");
			create_component(summarynumberelement.$$.fragment);
			t0 = space();
			if (if_block) if_block.c();
			t1 = space();
			dom_attr(div, "class", "relative");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(summarynumberelement, div, null);
			dom_append(div, t0);
			if (if_block) if_block.m(div, null);
			dom_append(div, t1);
			current = true;
		},
		p(ctx, dirty) {
			const summarynumberelement_changes = {};
			if (dirty & /*numberData*/ 512) summarynumberelement_changes.data = /*element*/ ctx[24].data;
			if (dirty & /*numberData*/ 512) summarynumberelement_changes.name = /*element*/ ctx[24].name;
			if (dirty & /*editMode*/ 64) summarynumberelement_changes.editMode = /*editMode*/ ctx[6];
			summarynumberelement.$set(summarynumberelement_changes);

			if (/*editMode*/ ctx[6]) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*editMode*/ 64) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = CanvasSummary_svelte_create_if_block_2(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t1);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(summarynumberelement.$$.fragment, local);
			transitions_transition_in(if_block);
			current = true;
		},
		o(local) {
			transitions_transition_out(summarynumberelement.$$.fragment, local);
			transitions_transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(summarynumberelement);
			if (if_block) if_block.d();
		}
	};
}

// (114:12) {#if editMode}
function CanvasSummary_svelte_create_if_block_1(ctx) {
	let button;
	let fa;
	let current;
	let mounted;
	let dispose;
	fa = new dist({ props: { icon: faTimes/* faTimes */.GR } });

	function click_handler_2() {
		return /*click_handler_2*/ ctx[20](/*element*/ ctx[24]);
	}

	return {
		c() {
			button = dom_element("button");
			create_component(fa.$$.fragment);
			dom_attr(button, "class", "absolute top-0 right-0");
		},
		m(target, anchor) {
			dom_insert(target, button, anchor);
			mount_component(fa, button, null);
			current = true;

			if (!mounted) {
				dispose = dom_listen(button, "click", click_handler_2);
				mounted = true;
			}
		},
		p(new_ctx, dirty) {
			ctx = new_ctx;
		},
		i(local) {
			if (current) return;
			transitions_transition_in(fa.$$.fragment, local);
			current = true;
		},
		o(local) {
			transitions_transition_out(fa.$$.fragment, local);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(button);
			}

			destroy_component(fa);
			mounted = false;
			dispose();
		}
	};
}

// (103:8) {#each chartData as element}
function CanvasSummary_svelte_create_each_block(ctx) {
	let div;
	let summarylistelement;
	let t0;
	let t1;
	let current;

	summarylistelement = new SummaryListElement_svelte({
			props: {
				table: /*$table*/ ctx[5],
				filteredTable: /*$filteredTable*/ ctx[10],
				canvasSpec: /*$canvasSpec*/ ctx[11],
				element: /*element*/ ctx[24],
				editMode: /*editMode*/ ctx[6]
			}
		});

	summarylistelement.$on("update", /*update_handler*/ ctx[19]);
	let if_block = /*editMode*/ ctx[6] && CanvasSummary_svelte_create_if_block_1(ctx);

	return {
		c() {
			div = dom_element("div");
			create_component(summarylistelement.$$.fragment);
			t0 = space();
			if (if_block) if_block.c();
			t1 = space();
			dom_attr(div, "class", "relative");
		},
		m(target, anchor) {
			dom_insert(target, div, anchor);
			mount_component(summarylistelement, div, null);
			dom_append(div, t0);
			if (if_block) if_block.m(div, null);
			dom_append(div, t1);
			current = true;
		},
		p(ctx, dirty) {
			const summarylistelement_changes = {};
			if (dirty & /*$table*/ 32) summarylistelement_changes.table = /*$table*/ ctx[5];
			if (dirty & /*$filteredTable*/ 1024) summarylistelement_changes.filteredTable = /*$filteredTable*/ ctx[10];
			if (dirty & /*$canvasSpec*/ 2048) summarylistelement_changes.canvasSpec = /*$canvasSpec*/ ctx[11];
			if (dirty & /*chartData*/ 256) summarylistelement_changes.element = /*element*/ ctx[24];
			if (dirty & /*editMode*/ 64) summarylistelement_changes.editMode = /*editMode*/ ctx[6];
			summarylistelement.$set(summarylistelement_changes);

			if (/*editMode*/ ctx[6]) {
				if (if_block) {
					if_block.p(ctx, dirty);

					if (dirty & /*editMode*/ 64) {
						transitions_transition_in(if_block, 1);
					}
				} else {
					if_block = CanvasSummary_svelte_create_if_block_1(ctx);
					if_block.c();
					transitions_transition_in(if_block, 1);
					if_block.m(div, t1);
				}
			} else if (if_block) {
				group_outros();

				transitions_transition_out(if_block, 1, 1, () => {
					if_block = null;
				});

				check_outros();
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(summarylistelement.$$.fragment, local);
			transitions_transition_in(if_block);
			current = true;
		},
		o(local) {
			transitions_transition_out(summarylistelement.$$.fragment, local);
			transitions_transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div);
			}

			destroy_component(summarylistelement);
			if (if_block) if_block.d();
		}
	};
}

function CanvasSummary_svelte_create_fragment(ctx) {
	let div1;
	let componentheader;
	let t0;
	let t1;
	let div0;
	let current_block_type_index;
	let if_block1;
	let div1_class_value;
	let current;

	componentheader = new ComponentHeader_svelte({
			props: {
				title: 'Summary',
				description: /*widgetSpec*/ ctx[3].description,
				container: /*container*/ ctx[7],
				$$slots: { default: [create_default_slot] },
				$$scope: { ctx }
			}
		});

	let if_block0 = /*editMode*/ ctx[6] && create_if_block_3(ctx);
	const if_block_creators = [CanvasSummary_svelte_create_if_block, CanvasSummary_svelte_create_else_block];
	const if_blocks = [];

	function select_block_type(ctx, dirty) {
		if (CharacterData.length > 0 || /*numberData*/ ctx[9].length > 0) return 0;
		return 1;
	}

	current_block_type_index = select_block_type(ctx, -1);
	if_block1 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);

	return {
		c() {
			div1 = dom_element("div");
			create_component(componentheader.$$.fragment);
			t0 = space();
			if (if_block0) if_block0.c();
			t1 = space();
			div0 = dom_element("div");
			if_block1.c();
			dom_attr(div0, "class", "flex flex-col overflow-auto");

			dom_attr(div1, "class", div1_class_value = "flex flex-col p-2 " + (/*fullSize*/ ctx[4]
			? 'h-full'
			: mapHeight(/*widgetSpec*/ ctx[3].height)));
		},
		m(target, anchor) {
			dom_insert(target, div1, anchor);
			mount_component(componentheader, div1, null);
			dom_append(div1, t0);
			if (if_block0) if_block0.m(div1, null);
			dom_append(div1, t1);
			dom_append(div1, div0);
			if_blocks[current_block_type_index].m(div0, null);
			/*div0_binding*/ ctx[21](div0);
			current = true;
		},
		p(ctx, [dirty]) {
			const componentheader_changes = {};
			if (dirty & /*widgetSpec*/ 8) componentheader_changes.description = /*widgetSpec*/ ctx[3].description;
			if (dirty & /*container*/ 128) componentheader_changes.container = /*container*/ ctx[7];

			if (dirty & /*$$scope, editMode*/ 536870976) {
				componentheader_changes.$$scope = { dirty, ctx };
			}

			componentheader.$set(componentheader_changes);

			if (/*editMode*/ ctx[6]) {
				if (if_block0) {
					if_block0.p(ctx, dirty);

					if (dirty & /*editMode*/ 64) {
						transitions_transition_in(if_block0, 1);
					}
				} else {
					if_block0 = create_if_block_3(ctx);
					if_block0.c();
					transitions_transition_in(if_block0, 1);
					if_block0.m(div1, t1);
				}
			} else if (if_block0) {
				group_outros();

				transitions_transition_out(if_block0, 1, 1, () => {
					if_block0 = null;
				});

				check_outros();
			}

			let previous_block_index = current_block_type_index;
			current_block_type_index = select_block_type(ctx, dirty);

			if (current_block_type_index === previous_block_index) {
				if_blocks[current_block_type_index].p(ctx, dirty);
			} else {
				group_outros();

				transitions_transition_out(if_blocks[previous_block_index], 1, 1, () => {
					if_blocks[previous_block_index] = null;
				});

				check_outros();
				if_block1 = if_blocks[current_block_type_index];

				if (!if_block1) {
					if_block1 = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
					if_block1.c();
				} else {
					if_block1.p(ctx, dirty);
				}

				transitions_transition_in(if_block1, 1);
				if_block1.m(div0, null);
			}

			if (!current || dirty & /*fullSize, widgetSpec*/ 24 && div1_class_value !== (div1_class_value = "flex flex-col p-2 " + (/*fullSize*/ ctx[4]
			? 'h-full'
			: mapHeight(/*widgetSpec*/ ctx[3].height)))) {
				dom_attr(div1, "class", div1_class_value);
			}
		},
		i(local) {
			if (current) return;
			transitions_transition_in(componentheader.$$.fragment, local);
			transitions_transition_in(if_block0);
			transitions_transition_in(if_block1);
			current = true;
		},
		o(local) {
			transitions_transition_out(componentheader.$$.fragment, local);
			transitions_transition_out(if_block0);
			transitions_transition_out(if_block1);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				dom_detach(div1);
			}

			destroy_component(componentheader);
			if (if_block0) if_block0.d();
			if_blocks[current_block_type_index].d();
			/*div0_binding*/ ctx[21](null);
		}
	};
}

function CanvasSummary_svelte_instance($$self, $$props, $$invalidate) {
	let elements;
	let numberData;
	let chartData;

	let $table,
		$$unsubscribe_table = utils_noop,
		$$subscribe_table = () => ($$unsubscribe_table(), $$unsubscribe_table = subscribe(table, $$value => $$invalidate(5, $table = $$value)), table);

	let $filteredTable,
		$$unsubscribe_filteredTable = utils_noop,
		$$subscribe_filteredTable = () => ($$unsubscribe_filteredTable(), $$unsubscribe_filteredTable = subscribe(filteredTable, $$value => $$invalidate(10, $filteredTable = $$value)), filteredTable);

	let $canvasSpec,
		$$unsubscribe_canvasSpec = utils_noop,
		$$subscribe_canvasSpec = () => ($$unsubscribe_canvasSpec(), $$unsubscribe_canvasSpec = subscribe(canvasSpec, $$value => $$invalidate(11, $canvasSpec = $$value)), canvasSpec);

	$$self.$$.on_destroy.push(() => $$unsubscribe_table());
	$$self.$$.on_destroy.push(() => $$unsubscribe_filteredTable());
	$$self.$$.on_destroy.push(() => $$unsubscribe_canvasSpec());
	let { canvasSpec } = $$props;
	$$subscribe_canvasSpec();
	let { table } = $$props;
	$$subscribe_table();
	let { filteredTable } = $$props;
	$$subscribe_filteredTable();
	let { widgetSpec } = $$props;
	let { fullSize = false } = $$props;
	const dispatch = createEventDispatcher();
	let editMode = false;
	let userSpecUpdate = false;
	let container;

	function updateSpecElements(newElements) {
		const newSpec = Object.assign(Object.assign({}, widgetSpec), { summaryElements: newElements });
		dispatch('specChanged', { spec: newSpec });
	}

	function removeElement(element) {
		$$invalidate(15, userSpecUpdate = true);
		let newElements = elements.filter(el => el.name !== element.name || el.data !== element.data);
		updateSpecElements(newElements);
	}

	function addElement(event) {
		$$invalidate(15, userSpecUpdate = true);
		let newElements = [...elements, event.detail.element];
		updateSpecElements(newElements);
	}

	function updateElement(element, oldElement) {
		$$invalidate(15, userSpecUpdate = true);
		let elementIndex = elements.findIndex(el => el.name === oldElement.name && el.data === oldElement.data);
		const newElements = elements.slice();
		newElements[elementIndex] = element;
		updateSpecElements(newElements);
	}

	const click_handler = () => $$invalidate(6, editMode = !editMode);
	const click_handler_1 = element => removeElement(element);
	const update_handler = event => updateElement(event.detail.element, event.detail.oldElement);
	const click_handler_2 = element => removeElement(element);

	function div0_binding($$value) {
		binding_callbacks[$$value ? 'unshift' : 'push'](() => {
			container = $$value;
			$$invalidate(7, container);
		});
	}

	$$self.$$set = $$props => {
		if ('canvasSpec' in $$props) $$subscribe_canvasSpec($$invalidate(0, canvasSpec = $$props.canvasSpec));
		if ('table' in $$props) $$subscribe_table($$invalidate(1, table = $$props.table));
		if ('filteredTable' in $$props) $$subscribe_filteredTable($$invalidate(2, filteredTable = $$props.filteredTable));
		if ('widgetSpec' in $$props) $$invalidate(3, widgetSpec = $$props.widgetSpec);
		if ('fullSize' in $$props) $$invalidate(4, fullSize = $$props.fullSize);
	};

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*widgetSpec, userSpecUpdate, $table*/ 32808) {
			$: $$invalidate(16, elements = widgetSpec.summaryElements.length === 0 && !userSpecUpdate
			? extractColumnElements($table)
			: widgetSpec.summaryElements);
		}

		if ($$self.$$.dirty & /*elements*/ 65536) {
			$: $$invalidate(9, numberData = elements.filter(row => typeof row.data === 'number'));
		}

		if ($$self.$$.dirty & /*elements*/ 65536) {
			$: $$invalidate(8, chartData = elements.filter(row => typeof row.data !== 'number'));
		}
	};

	return [
		canvasSpec,
		table,
		filteredTable,
		widgetSpec,
		fullSize,
		$table,
		editMode,
		container,
		chartData,
		numberData,
		$filteredTable,
		$canvasSpec,
		removeElement,
		addElement,
		updateElement,
		userSpecUpdate,
		elements,
		click_handler,
		click_handler_1,
		update_handler,
		click_handler_2,
		div0_binding
	];
}

class CanvasSummary extends SvelteComponent {
	constructor(options) {
		super();

		init(this, options, CanvasSummary_svelte_instance, CanvasSummary_svelte_create_fragment, safe_not_equal, {
			canvasSpec: 0,
			table: 1,
			filteredTable: 2,
			widgetSpec: 3,
			fullSize: 4
		});
	}
}

/* harmony default export */ const CanvasSummary_svelte = (CanvasSummary);
;// ./src/widget.ts
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */




class CanvasSummaryModel extends base_.DOMWidgetModel {
    defaults() {
        return Object.assign(Object.assign({}, super.defaults()), { _model_name: CanvasSummaryModel.model_name, _model_module: CanvasSummaryModel.model_module, _model_module_version: CanvasSummaryModel.model_module_version, _view_name: CanvasSummaryModel.view_name, _view_module: CanvasSummaryModel.view_module, _view_module_version: CanvasSummaryModel.view_module_version });
    }
}
CanvasSummaryModel.serializers = serializers;
CanvasSummaryModel.model_name = 'CanvasSummaryModel';
CanvasSummaryModel.model_module = MODULE_NAME;
CanvasSummaryModel.model_module_version = MODULE_VERSION;
CanvasSummaryModel.view_name = 'CanvasSummaryView'; // Set to null if no view
CanvasSummaryModel.view_module = MODULE_NAME; // Set to null if no view
CanvasSummaryModel.view_module_version = MODULE_VERSION;
class CanvasSummaryView extends CanvasBaseDomWidgetView {
    render() {
        this.setupWidget(this.model, CanvasSummary_svelte);
    }
}

;// ./src/index.ts
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



;// ./src/extension.ts
/**
 * Copyright 2024 BetterWithData
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Entry point for the notebook bundle containing custom model definitions.
//
// Setup notebook base URL
//
// Some static assets may be required by the custom widget javascript. The base
// url for the notebook is not known at build time and is therefore computed
// dynamically.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
window.__webpack_public_path__ =
    document.querySelector('body').getAttribute('data-base-url') +
        'nbextensions/canvas_summary';


})();

/******/ 	return __webpack_exports__;
/******/ })()
;
});;