UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

21,343 lines 894 kB
/**
 * ag-charts-community - Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue * @version v5.0.0
 * @link http://www.ag-grid.com/
' * @license MIT
 */

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

    var __assign = (undefined && undefined.__assign) || function () {
        __assign = Object.assign || function(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);
    };
    var Observable = /** @class */ (function () {
        function Observable() {
            // Note that these maps can't be specified generically, so they are kept untyped.
            // Some methods in this class only need generics in their signatures, the generics inside the methods
            // are just for clarity. The generics in signatures allow for static type checking of user provided
            // listeners and for type inference, so that the users wouldn't have to specify the type of parameters
            // of their inline lambdas.
            this.allPropertyListeners = new Map(); // property name => property change listener => scopes
            this.allEventListeners = new Map(); // event type => event listener => scopes
        }
        Observable.prototype.addPropertyListener = function (name, listener, scope) {
            if (scope === void 0) { scope = this; }
            var allPropertyListeners = this.allPropertyListeners;
            var propertyListeners = allPropertyListeners.get(name);
            if (!propertyListeners) {
                propertyListeners = new Map();
                allPropertyListeners.set(name, propertyListeners);
            }
            if (!propertyListeners.has(listener)) {
                var scopes_1 = new Set();
                propertyListeners.set(listener, scopes_1);
            }
            var scopes = propertyListeners.get(listener);
            if (scopes) {
                scopes.add(scope);
            }
        };
        Observable.prototype.removePropertyListener = function (name, listener, scope) {
            if (scope === void 0) { scope = this; }
            var allPropertyListeners = this.allPropertyListeners;
            var propertyListeners = allPropertyListeners.get(name);
            if (propertyListeners) {
                if (listener) {
                    var scopes = propertyListeners.get(listener);
                    if (scopes) {
                        scopes.delete(scope);
                        if (!scopes.size) {
                            propertyListeners.delete(listener);
                        }
                    }
                }
                else {
                    propertyListeners.clear();
                }
            }
        };
        Observable.prototype.notifyPropertyListeners = function (name, oldValue, value) {
            var _this = this;
            var allPropertyListeners = this.allPropertyListeners;
            var propertyListeners = allPropertyListeners.get(name);
            if (propertyListeners) {
                propertyListeners.forEach(function (scopes, listener) {
                    scopes.forEach(function (scope) { return listener.call(scope, { type: name, source: _this, value: value, oldValue: oldValue }); });
                });
            }
        };
        Observable.prototype.addEventListener = function (type, listener, scope) {
            if (scope === void 0) { scope = this; }
            var allEventListeners = this.allEventListeners;
            var eventListeners = allEventListeners.get(type);
            if (!eventListeners) {
                eventListeners = new Map();
                allEventListeners.set(type, eventListeners);
            }
            if (!eventListeners.has(listener)) {
                var scopes_2 = new Set();
                eventListeners.set(listener, scopes_2);
            }
            var scopes = eventListeners.get(listener);
            if (scopes) {
                scopes.add(scope);
            }
        };
        Observable.prototype.removeEventListener = function (type, listener, scope) {
            if (scope === void 0) { scope = this; }
            var allEventListeners = this.allEventListeners;
            var eventListeners = allEventListeners.get(type);
            if (eventListeners) {
                if (listener) {
                    var scopes = eventListeners.get(listener);
                    if (scopes) {
                        scopes.delete(scope);
                        if (!scopes.size) {
                            eventListeners.delete(listener);
                        }
                    }
                }
                else {
                    eventListeners.clear();
                }
            }
        };
        Observable.prototype.notifyEventListeners = function (types) {
            var _this = this;
            var allEventListeners = this.allEventListeners;
            types.forEach(function (type) {
                var listeners = allEventListeners.get(type);
                if (listeners) {
                    listeners.forEach(function (scopes, listener) {
                        scopes.forEach(function (scope) { return listener.call(scope, { type: type, source: _this }); });
                    });
                }
            });
        };
        // 'source' is added automatically and is always the object this method belongs to.
        Observable.prototype.fireEvent = function (event) {
            var _this = this;
            var listeners = this.allEventListeners.get(event.type);
            if (listeners) {
                listeners.forEach(function (scopes, listener) {
                    scopes.forEach(function (scope) { return listener.call(scope, __assign(__assign({}, event), { source: _this })); });
                });
            }
        };
        Observable.privateKeyPrefix = '_';
        return Observable;
    }());
    function reactive() {
        var events = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            events[_i] = arguments[_i];
        }
        var debug = events.indexOf('debugger') >= 0;
        return function (target, key) {
            // `target` is either a constructor (static member) or prototype (instance member)
            var privateKey = Observable.privateKeyPrefix + key;
            var privateKeyEvents = privateKey + 'Events';
            if (!target[key]) {
                if (events) {
                    target[privateKeyEvents] = events;
                }
                Object.defineProperty(target, key, {
                    set: function (value) {
                        var oldValue = this[privateKey];
                        // This is a way to stop inside the setter by adding the special
                        // 'debugger' event to a reactive property, for example:
                        //  @reactive('layoutChange', 'debugger') title?: Caption;
                        if (debug) { // DO NOT REMOVE
                            debugger;
                        }
                        if (value !== oldValue || (typeof value === 'object' && value !== null)) {
                            this[privateKey] = value;
                            this.notifyPropertyListeners(key, oldValue, value);
                            var events_1 = this[privateKeyEvents];
                            if (events_1) {
                                this.notifyEventListeners(events_1);
                            }
                        }
                    },
                    get: function () {
                        return this[privateKey];
                    },
                    enumerable: true,
                    configurable: true
                });
            }
        };
    }

    var __extends = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var Padding = /** @class */ (function (_super) {
        __extends(Padding, _super);
        function Padding(top, right, bottom, left) {
            if (top === void 0) { top = 0; }
            if (right === void 0) { right = top; }
            if (bottom === void 0) { bottom = top; }
            if (left === void 0) { left = right; }
            var _this = _super.call(this) || this;
            _this.top = top;
            _this.right = right;
            _this.bottom = bottom;
            _this.left = left;
            return _this;
        }
        Padding.prototype.clear = function () {
            this.top = this.right = this.bottom = this.left = 0;
        };
        __decorate([
            reactive('layoutChange')
        ], Padding.prototype, "top", void 0);
        __decorate([
            reactive('layoutChange')
        ], Padding.prototype, "right", void 0);
        __decorate([
            reactive('layoutChange')
        ], Padding.prototype, "bottom", void 0);
        __decorate([
            reactive('layoutChange')
        ], Padding.prototype, "left", void 0);
        return Padding;
    }(Observable));

    // For small data structs like a bounding box, objects are superior to arrays
    // in terms of performance (by 3-4% in Chrome 71, Safari 12 and by 20% in Firefox 64).
    // They are also self descriptive and harder to abuse.
    // For example, one has to do:
    // `ctx.strokeRect(bbox.x, bbox.y, bbox.width, bbox.height);`
    // rather than become enticed by the much slower:
    // `ctx.strokeRect(...bbox);`
    // https://jsperf.com/array-vs-object-create-access
    var BBox = /** @class */ (function () {
        function BBox(x, y, width, height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }
        BBox.prototype.isValid = function () {
            return isFinite(this.x) && isFinite(this.y) && isFinite(this.width) && isFinite(this.height);
        };
        BBox.prototype.dilate = function (value) {
            this.x -= value;
            this.y -= value;
            this.width += value * 2;
            this.height += value * 2;
        };
        BBox.prototype.containsPoint = function (x, y) {
            return x >= this.x && x <= (this.x + this.width)
                && y >= this.y && y <= (this.y + this.height);
        };
        BBox.prototype.render = function (ctx, params) {
            if (params === void 0) { params = BBox.noParams; }
            ctx.save();
            if (params.resetTransform) {
                ctx.setTransform(1, 0, 0, 1, 0, 0);
            }
            ctx.strokeStyle = params.strokeStyle || 'cyan';
            ctx.lineWidth = params.lineWidth || 1;
            ctx.strokeRect(this.x, this.y, this.width, this.height);
            if (params.label) {
                ctx.fillStyle = params.fillStyle || 'black';
                ctx.textBaseline = 'bottom';
                ctx.fillText(params.label, this.x, this.y);
            }
            ctx.restore();
        };
        BBox.noParams = {};
        return BBox;
    }());

    var __read = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    /**
     * As of Jan 8, 2019, Firefox still doesn't implement
     * `getTransform(): DOMMatrix;`
     * `setTransform(transform?: DOMMatrix2DInit)`
     * in the `CanvasRenderingContext2D`.
     * Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=928150
     * IE11 and Edge 44 also don't have the support.
     * Thus this class, to keep track of the current transform and
     * combine transformations.
     * Standards:
     * https://html.spec.whatwg.org/dev/canvas.html
     * https://www.w3.org/TR/geometry-1/
     */
    var Matrix = /** @class */ (function () {
        function Matrix(elements) {
            if (elements === void 0) { elements = [1, 0, 0, 1, 0, 0]; }
            this.elements = elements;
        }
        Matrix.prototype.setElements = function (elements) {
            var e = this.elements;
            // `this.elements = elements.slice()` is 4-5 times slower
            // (in Chrome 71 and FF 64) than manually copying elements,
            // since slicing allocates new memory.
            // The performance of passing parameters individually
            // vs as an array is about the same in both browsers, so we
            // go with a single (array of elements) parameter, because
            // `setElements(elements)` and `setElements([a, b, c, d, e, f])`
            // calls give us roughly the same performance, versus
            // `setElements(...elements)` and `setElements(a, b, c, d, e, f)`,
            // where the spread operator causes a 20-30x performance drop
            // (30x when compiled to ES5's `.apply(this, elements)`
            //  20x when used natively).
            e[0] = elements[0];
            e[1] = elements[1];
            e[2] = elements[2];
            e[3] = elements[3];
            e[4] = elements[4];
            e[5] = elements[5];
            return this;
        };
        Matrix.prototype.setIdentityElements = function () {
            var e = this.elements;
            e[0] = 1;
            e[1] = 0;
            e[2] = 0;
            e[3] = 1;
            e[4] = 0;
            e[5] = 0;
            return this;
        };
        Object.defineProperty(Matrix.prototype, "identity", {
            get: function () {
                var e = this.elements;
                return e[0] === 1 && e[1] === 0 && e[2] === 0 &&
                    e[3] === 1 && e[4] === 0 && e[5] === 0;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "a", {
            get: function () {
                return this.elements[0];
            },
            set: function (value) {
                this.elements[0] = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "b", {
            get: function () {
                return this.elements[1];
            },
            set: function (value) {
                this.elements[1] = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "c", {
            get: function () {
                return this.elements[2];
            },
            set: function (value) {
                this.elements[2] = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "d", {
            get: function () {
                return this.elements[3];
            },
            set: function (value) {
                this.elements[3] = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "e", {
            get: function () {
                return this.elements[4];
            },
            set: function (value) {
                this.elements[4] = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Matrix.prototype, "f", {
            get: function () {
                return this.elements[5];
            },
            set: function (value) {
                this.elements[5] = value;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Performs the AxB matrix multiplication and saves the result
         * to `C`, if given, or to `A` otherwise.
         */
        Matrix.prototype.AxB = function (A, B, C) {
            var _a = __read(A, 6), m11 = _a[0], m12 = _a[1], m21 = _a[2], m22 = _a[3], m31 = _a[4], m32 = _a[5];
            var _b = __read(B, 6), o11 = _b[0], o12 = _b[1], o21 = _b[2], o22 = _b[3], o31 = _b[4], o32 = _b[5];
            C = C || A;
            C[0] = m11 * o11 + m21 * o12;
            C[1] = m12 * o11 + m22 * o12;
            C[2] = m11 * o21 + m21 * o22;
            C[3] = m12 * o21 + m22 * o22;
            C[4] = m11 * o31 + m21 * o32 + m31;
            C[5] = m12 * o31 + m22 * o32 + m32;
        };
        /**
         * The `other` matrix gets post-multiplied to the current matrix.
         * Returns the current matrix.
         * @param other
         */
        Matrix.prototype.multiplySelf = function (other) {
            this.AxB(this.elements, other.elements);
            return this;
        };
        /**
         * The `other` matrix gets post-multiplied to the current matrix.
         * Returns a new matrix.
         * @param other
         */
        Matrix.prototype.multiply = function (other) {
            var elements = new Array(6);
            this.AxB(this.elements, other.elements, elements);
            return new Matrix(elements);
        };
        Matrix.prototype.preMultiplySelf = function (other) {
            this.AxB(other.elements, this.elements, this.elements);
            return this;
        };
        /**
         * Returns the inverse of this matrix as a new matrix.
         */
        Matrix.prototype.inverse = function () {
            var _a = __read(this.elements, 6), a = _a[0], b = _a[1], c = _a[2], d = _a[3], e = _a[4], f = _a[5];
            var rD = 1 / (a * d - b * c); // reciprocal of determinant
            a *= rD;
            b *= rD;
            c *= rD;
            d *= rD;
            return new Matrix([d, -b, -c, a, c * f - d * e, b * e - a * f]);
        };
        /**
         * Save the inverse of this matrix to the given matrix.
         */
        Matrix.prototype.inverseTo = function (other) {
            var _a = __read(this.elements, 6), a = _a[0], b = _a[1], c = _a[2], d = _a[3], e = _a[4], f = _a[5];
            var rD = 1 / (a * d - b * c); // reciprocal of determinant
            a *= rD;
            b *= rD;
            c *= rD;
            d *= rD;
            other.setElements([d, -b, -c, a, c * f - d * e, b * e - a * f]);
            return this;
        };
        Matrix.prototype.invertSelf = function () {
            var elements = this.elements;
            var _a = __read(elements, 6), a = _a[0], b = _a[1], c = _a[2], d = _a[3], e = _a[4], f = _a[5];
            var rD = 1 / (a * d - b * c); // reciprocal of determinant
            a *= rD;
            b *= rD;
            c *= rD;
            d *= rD;
            elements[0] = d;
            elements[1] = -b;
            elements[2] = -c;
            elements[3] = a;
            elements[4] = c * f - d * e;
            elements[5] = b * e - a * f;
            return this;
        };
        Matrix.prototype.clone = function () {
            return new Matrix(this.elements.slice());
        };
        Matrix.prototype.transformPoint = function (x, y) {
            var e = this.elements;
            return {
                x: x * e[0] + y * e[2] + e[4],
                y: x * e[1] + y * e[3] + e[5]
            };
        };
        Matrix.prototype.transformBBox = function (bbox, radius, target) {
            if (radius === void 0) { radius = 0; }
            var elements = this.elements;
            var xx = elements[0];
            var xy = elements[1];
            var yx = elements[2];
            var yy = elements[3];
            var h_w = bbox.width * 0.5;
            var h_h = bbox.height * 0.5;
            var cx = bbox.x + h_w;
            var cy = bbox.y + h_h;
            var w, h;
            if (radius) {
                h_w -= radius;
                h_h -= radius;
                var sx = Math.sqrt(xx * xx + yx * yx);
                var sy = Math.sqrt(xy * xy + yy * yy);
                w = Math.abs(h_w * xx) + Math.abs(h_h * yx) + Math.abs(sx * radius);
                h = Math.abs(h_w * xy) + Math.abs(h_h * yy) + Math.abs(sy * radius);
            }
            else {
                w = Math.abs(h_w * xx) + Math.abs(h_h * yx);
                h = Math.abs(h_w * xy) + Math.abs(h_h * yy);
            }
            if (!target) {
                target = new BBox(0, 0, 0, 0);
            }
            target.x = cx * xx + cy * yx + elements[4] - w;
            target.y = cx * xy + cy * yy + elements[5] - h;
            target.width = w + w;
            target.height = h + h;
            return target;
        };
        Matrix.prototype.toContext = function (ctx) {
            // It's fair to say that matrix multiplications are not cheap.
            // However, updating path definitions on every frame isn't either, so
            // it may be cheaper to just translate paths. It's also fair to
            // say, that most paths will have to be re-rendered anyway, say
            // rectangle paths in a bar chart, where an animation would happen when
            // the data set changes and existing bars are morphed into new ones.
            // Or a pie chart, where old sectors are also morphed into new ones.
            // Same for the line chart. The only plausible case where translating
            // existing paths would be enough, is the scatter chart, where marker
            // icons, typically circles, stay the same size. But if circle radii
            // are bound to some data points, even circle paths would have to be
            // updated. And thus it makes sense to optimize for fewer matrix
            // transforms, where transform matrices of paths are mostly identity
            // matrices and `x`/`y`, `centerX`/`centerY` and similar properties
            // are used to define a path at specific coordinates. And only groups
            // are used to collectively apply a transform to a set of nodes.
            // If the matrix is mostly identity (95% of the time),
            // the `if (this.isIdentity)` check can make this call 3-4 times
            // faster on average: https://jsperf.com/matrix-check-first-vs-always-set
            if (this.identity) {
                return;
            }
            var e = this.elements;
            ctx.transform(e[0], e[1], e[2], e[3], e[4], e[5]);
        };
        Matrix.flyweight = function (elements) {
            if (elements) {
                if (elements instanceof Matrix) {
                    Matrix.matrix.setElements(elements.elements);
                }
                else {
                    Matrix.matrix.setElements(elements);
                }
            }
            else {
                Matrix.matrix.setIdentityElements();
            }
            return Matrix.matrix;
        };
        Matrix.matrix = new Matrix();
        return Matrix;
    }());

    function createId(instance) {
        var constructor = instance.constructor;
        var className = constructor.className;
        if (!className) {
            throw new Error("The " + constructor + " is missing the 'className' property.");
        }
        return className + '-' + (constructor.id = (constructor.id || 0) + 1);
    }

    var __read$1 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var PointerEvents;
    (function (PointerEvents) {
        PointerEvents[PointerEvents["All"] = 0] = "All";
        PointerEvents[PointerEvents["None"] = 1] = "None";
    })(PointerEvents || (PointerEvents = {}));
    /**
     * Abstract scene graph node.
     * Each node can have zero or one parent and belong to zero or one scene.
     */
    var Node = /** @class */ (function () {
        function Node() {
            /**
             * Unique node ID in the form `ClassName-NaturalNumber`.
             */
            this.id = createId(this);
            /**
             * Some number to identify this node, typically within a `Group` node.
             * Usually this will be some enum value used as a selector.
             */
            this.tag = NaN;
            /**
             * To simplify the type system (especially in Selections) we don't have the `Parent` node
             * (one that has children). Instead, we mimic HTML DOM, where any node can have children.
             * But we still need to distinguish regular leaf nodes from container leafs somehow.
             */
            this.isContainerNode = false;
            this._children = [];
            // Used to check for duplicate nodes.
            this.childSet = {}; // new Set<Node>()
            // These matrices may need to have package level visibility
            // for performance optimization purposes.
            this.matrix = new Matrix();
            this.inverseMatrix = new Matrix();
            this._dirtyTransform = false;
            this._scalingX = 1;
            this._scalingY = 1;
            /**
             * The center of scaling.
             * The default value of `null` means the scaling center will be
             * determined automatically, as the center of the bounding box
             * of a node.
             */
            this._scalingCenterX = null;
            this._scalingCenterY = null;
            this._rotationCenterX = null;
            this._rotationCenterY = null;
            /**
             * Rotation angle in radians.
             * The value is set as is. No normalization to the [-180, 180) or [0, 360)
             * interval is performed.
             */
            this._rotation = 0;
            this._translationX = 0;
            this._translationY = 0;
            /**
             * Each time a property of the node that effects how it renders changes
             * the `dirty` property of the node should be set to `true`. The change
             * to the `dirty` property of the node will propagate up to its parents
             * and eventually to the scene, at which point an animation frame callback
             * will be scheduled to rerender the scene and its nodes and reset the `dirty`
             * flags of all nodes and the {@link Scene._dirty | Scene} back to `false`.
             * Since changes to node properties are not rendered immediately, it's possible
             * to change as many properties on as many nodes as needed and the rendering
             * will still only happen once in the next animation frame callback.
             * The animation frame callback is only scheduled if it hasn't been already.
             */
            this._dirty = true;
            this._visible = true;
            this.dirtyZIndex = false;
            this._zIndex = 0;
            this.pointerEvents = PointerEvents.All;
        }
        /**
         * This is meaningfully faster than `instanceof` and should be the preferred way
         * of checking inside loops.
         * @param node
         */
        Node.isNode = function (node) {
            return node ? node.matrix !== undefined : false;
        };
        Node.prototype._setScene = function (value) {
            this._scene = value;
            var children = this.children;
            var n = children.length;
            for (var i = 0; i < n; i++) {
                children[i]._setScene(value);
            }
        };
        Object.defineProperty(Node.prototype, "scene", {
            get: function () {
                return this._scene;
            },
            enumerable: true,
            configurable: true
        });
        Node.prototype._setParent = function (value) {
            this._parent = value;
        };
        Object.defineProperty(Node.prototype, "parent", {
            get: function () {
                return this._parent;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "children", {
            get: function () {
                return this._children;
            },
            enumerable: true,
            configurable: true
        });
        Node.prototype.countChildren = function (depth) {
            if (depth === void 0) { depth = Node.MAX_SAFE_INTEGER; }
            if (depth <= 0) {
                return 0;
            }
            var children = this.children;
            var n = children.length;
            var size = n;
            for (var i = 0; i < n; i++) {
                size += children[i].countChildren(depth - 1);
            }
            return size;
        };
        /**
         * Appends one or more new node instances to this parent.
         * If one needs to:
         * - move a child to the end of the list of children
         * - move a child from one parent to another (including parents in other scenes)
         * one should use the {@link insertBefore} method instead.
         * @param nodes A node or nodes to append.
         */
        Node.prototype.append = function (nodes) {
            // Passing a single parameter to an open-ended version of `append`
            // would be 30-35% slower than this.
            if (Node.isNode(nodes)) {
                nodes = [nodes];
            }
            // The function takes an array rather than having open-ended
            // arguments like `...nodes: Node[]` because the latter is
            // transpiled to a function where the `arguments` object
            // is copied to a temporary array inside a loop.
            // So an array is created either way. And if we already have
            // an array of nodes we want to add, we have to use the prohibitively
            // expensive spread operator to pass it to the function,
            // and, on top of that, the copy of the `arguments` is still made.
            var n = nodes.length;
            for (var i = 0; i < n; i++) {
                var node = nodes[i];
                if (node.parent) {
                    throw new Error(node + " already belongs to another parent: " + node.parent + ".");
                }
                if (node.scene) {
                    throw new Error(node + " already belongs a scene: " + node.scene + ".");
                }
                if (this.childSet[node.id]) {
                    // Cast to `any` to avoid `Property 'name' does not exist on type 'Function'`.
                    throw new Error("Duplicate " + node.constructor.name + " node: " + node);
                }
                this._children.push(node);
                this.childSet[node.id] = true;
                node._setParent(this);
                node._setScene(this.scene);
            }
            this.dirty = true;
        };
        Node.prototype.appendChild = function (node) {
            if (node.parent) {
                throw new Error(node + " already belongs to another parent: " + node.parent + ".");
            }
            if (node.scene) {
                throw new Error(node + " already belongs to a scene: " + node.scene + ".");
            }
            if (this.childSet[node.id]) {
                // Cast to `any` to avoid `Property 'name' does not exist on type 'Function'`.
                throw new Error("Duplicate " + node.constructor.name + " node: " + node);
            }
            this._children.push(node);
            this.childSet[node.id] = true;
            node._setParent(this);
            node._setScene(this.scene);
            this.dirty = true;
            return node;
        };
        Node.prototype.removeChild = function (node) {
            if (node.parent === this) {
                var i = this.children.indexOf(node);
                if (i >= 0) {
                    this._children.splice(i, 1);
                    delete this.childSet[node.id];
                    node._setParent();
                    node._setScene();
                    this.dirty = true;
                    return node;
                }
            }
            throw new Error("The node to be removed is not a child of this node.");
        };
        /**
         * Inserts the node `node` before the existing child node `nextNode`.
         * If `nextNode` is null, insert `node` at the end of the list of children.
         * If the `node` belongs to another parent, it is first removed.
         * Returns the `node`.
         * @param node
         * @param nextNode
         */
        Node.prototype.insertBefore = function (node, nextNode) {
            var parent = node.parent;
            if (node.parent) {
                node.parent.removeChild(node);
            }
            if (nextNode && nextNode.parent === this) {
                var i = this.children.indexOf(nextNode);
                if (i >= 0) {
                    this._children.splice(i, 0, node);
                    this.childSet[node.id] = true;
                    node._setParent(this);
                    node._setScene(this.scene);
                }
                else {
                    throw new Error(nextNode + " has " + parent + " as the parent, "
                        + "but is not in its list of children.");
                }
                this.dirty = true;
            }
            else {
                this.append(node);
            }
            return node;
        };
        Object.defineProperty(Node.prototype, "nextSibling", {
            get: function () {
                var parent = this.parent;
                if (parent) {
                    var children = parent.children;
                    var index = children.indexOf(this);
                    if (index >= 0 && index <= children.length - 1) {
                        return children[index + 1];
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Node.prototype.transformPoint = function (x, y) {
            var matrix = Matrix.flyweight(this.matrix);
            var parent = this.parent;
            while (parent) {
                matrix.preMultiplySelf(parent.matrix);
                parent = parent.parent;
            }
            return matrix.invertSelf().transformPoint(x, y);
        };
        Node.prototype.inverseTransformPoint = function (x, y) {
            var matrix = Matrix.flyweight(this.matrix);
            var parent = this.parent;
            while (parent) {
                matrix.preMultiplySelf(parent.matrix);
                parent = parent.parent;
            }
            return matrix.transformPoint(x, y);
        };
        Object.defineProperty(Node.prototype, "dirtyTransform", {
            get: function () {
                return this._dirtyTransform;
            },
            set: function (value) {
                this._dirtyTransform = value;
                if (value) {
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "scalingX", {
            get: function () {
                return this._scalingX;
            },
            set: function (value) {
                if (this._scalingX !== value) {
                    this._scalingX = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "scalingY", {
            get: function () {
                return this._scalingY;
            },
            set: function (value) {
                if (this._scalingY !== value) {
                    this._scalingY = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "scalingCenterX", {
            get: function () {
                return this._scalingCenterX;
            },
            set: function (value) {
                if (this._scalingCenterX !== value) {
                    this._scalingCenterX = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "scalingCenterY", {
            get: function () {
                return this._scalingCenterY;
            },
            set: function (value) {
                if (this._scalingCenterY !== value) {
                    this._scalingCenterY = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "rotationCenterX", {
            get: function () {
                return this._rotationCenterX;
            },
            set: function (value) {
                if (this._rotationCenterX !== value) {
                    this._rotationCenterX = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "rotationCenterY", {
            get: function () {
                return this._rotationCenterY;
            },
            set: function (value) {
                if (this._rotationCenterY !== value) {
                    this._rotationCenterY = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "rotation", {
            get: function () {
                return this._rotation;
            },
            set: function (value) {
                if (this._rotation !== value) {
                    this._rotation = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "rotationDeg", {
            get: function () {
                return this.rotation / Math.PI * 180;
            },
            /**
             * For performance reasons the rotation angle's internal representation
             * is in radians. Therefore, don't expect to get the same number you set.
             * Even with integer angles about a quarter of them from 0 to 359 cannot
             * be converted to radians and back without precision loss.
             * For example:
             *
             *     node.rotationDeg = 11;
             *     console.log(node.rotationDeg); // 10.999999999999998
             *
             * @param value Rotation angle in degrees.
             */
            set: function (value) {
                this.rotation = value / 180 * Math.PI;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "translationX", {
            get: function () {
                return this._translationX;
            },
            set: function (value) {
                if (this._translationX !== value) {
                    this._translationX = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "translationY", {
            get: function () {
                return this._translationY;
            },
            set: function (value) {
                if (this._translationY !== value) {
                    this._translationY = value;
                    this.dirtyTransform = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Node.prototype.containsPoint = function (x, y) {
            return false;
        };
        /**
         * Hit testing method.
         * Recursively checks if the given point is inside this node or any of its children.
         * Returns the first matching node or `undefined`.
         * Nodes that render later (show on top) are hit tested first.
         * @param x
         * @param y
         */
        Node.prototype.pickNode = function (x, y) {
            if (!this.visible || this.pointerEvents === PointerEvents.None || !this.containsPoint(x, y)) {
                return;
            }
            var children = this.children;
            if (children.length) {
                // Nodes added later should be hit-tested first,
                // as they are rendered on top of the previously added nodes.
                for (var i = children.length - 1; i >= 0; i--) {
                    var hit = children[i].pickNode(x, y);
                    if (hit) {
                        return hit;
                    }
                }
            }
            else if (!this.isContainerNode) { // a leaf node, but not a container leaf
                return this;
            }
        };
        Node.prototype.computeBBox = function () { return; };
        Node.prototype.computeBBoxCenter = function () {
            var bbox = this.computeBBox && this.computeBBox();
            if (bbox) {
                return [
                    bbox.x + bbox.width * 0.5,
                    bbox.y + bbox.height * 0.5
                ];
            }
            return [0, 0];
        };
        Node.prototype.computeTransformMatrix = function () {
            // TODO: transforms without center of scaling and rotation correspond directly
            //       to `setAttribute('transform', 'translate(tx, ty) rotate(rDeg) scale(sx, sy)')`
            //       in SVG. Our use cases will mostly require positioning elements (rects, circles)
            //       within a group, rotating groups at right angles (e.g. for axis) and translating
            //       groups. We shouldn't even need `scale(1, -1)` (invert vertically), since this
            //       can be done using D3-like scales already by inverting the output range.
            //       So for now, just assume that centers of scaling and rotation are at the origin.
            // const [bbcx, bbcy] = this.computeBBoxCenter();
            var _a = __read$1([0, 0], 2), bbcx = _a[0], bbcy = _a[1];
            var sx = this.scalingX;
            var sy = this.scalingY;
            var scx;
            var scy;
            if (sx === 1 && sy === 1) {
                scx = 0;
                scy = 0;
            }
            else {
                scx = this.scalingCenterX === null ? bbcx : this.scalingCenterX;
                scy = this.scalingCenterY === null ? bbcy : this.scalingCenterY;
            }
            var r = this.rotation;
            var cos = Math.cos(r);
            var sin = Math.sin(r);
            var rcx;
            var rcy;
            if (r === 0) {
                rcx = 0;
                rcy = 0;
            }
            else {
                rcx = this.rotationCenterX === null ? bbcx : this.rotationCenterX;
                rcy = this.rotationCenterY === null ? bbcy : this.rotationCenterY;
            }
            var tx = this.translationX;
            var ty = this.translationY;
            // The transform matrix `M` is a result of the following transformations:
            // 1) translate the center of scaling to the origin
            // 2) scale
            // 3) translate back
            // 4) translate the center of rotation to the origin
            // 5) rotate
            // 6) translate back
            // 7) translate
            //         (7)          (6)             (5)             (4)           (3)           (2)           (1)
            //     | 1 0 tx |   | 1 0 rcx |   | cos -sin 0 |   | 1 0 -rcx |   | 1 0 scx |   | sx 0 0 |   | 1 0 -scx |
            // M = | 0 1 ty | * | 0 1 rcy | * | sin  cos 0 | * | 0 1 -rcy | * | 0 1 scy | * | 0 sy 0 | * | 0 1 -scy |
            //     | 0 0  1 |   | 0 0  1  |   |  0    0  1 |   | 0 0  1   |   | 0 0  1  |   | 0  0 0 |   | 0 0  1   |
            // Translation after steps 1-4 above:
            var tx4 = scx * (1 - sx) - rcx;
            var ty4 = scy * (1 - sy) - rcy;
            this.dirtyTransform = false;
            this.matrix.setElements([
                cos * sx, sin * sx,
                -sin * sy, cos * sy,
                cos * tx4 - sin * ty4 + rcx + tx,
                sin * tx4 + cos * ty4 + rcy + ty
            ]).inverseTo(this.inverseMatrix);
        };
        Object.defineProperty(Node.prototype, "dirty", {
            get: function () {
                return this._dirty;
            },
            set: function (value) {
                // TODO: check if we are already dirty (e.g. if (this._dirty !== value))
                //       if we are, then all parents and the scene have been
                //       notified already, and we are doing redundant work
                //       (but test if this is indeed the case)
                this._dirty = value;
                if (value) {
                    if (this.parent) {
                        this.parent.dirty = true;
                    }
                    else if (this.scene) {
                        this.scene.dirty = true;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "visible", {
            get: function () {
                return this._visible;
            },
            set: function (value) {
                if (this._visible !== value) {
                    this._visible = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Node.prototype, "zIndex", {
            get: function () {
                return this._zIndex;
            },
            set: function (value) {
                if (this._zIndex !== value) {
                    this._zIndex = value;
                    if (this.parent) {
                        this.parent.dirtyZIndex = true;
                    }
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Node.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; // Number.MAX_SAFE_INTEGER
        return Node;
    }());

    /**
     * Creates a new object with a `parent` as its prototype
     * and copies properties from the `child` into it.
     * @param parent
     * @param child
     */
    function chainObjects(parent, child) {
        var obj = Object.create(parent);
        for (var prop in child) {
            if (child.hasOwnProperty(prop)) {
                obj[prop] = child[prop];
            }
        }
        return obj;
    }
    function getValue(object, path, defaultValue) {
        var parts = Array.isArray(path) ? path : path.split('.');
        var value = object;
        try {
            parts.forEach(function (part) {
                value = value[part];
            });
        }
        catch (e) {
            if (arguments.length === 3) {
                value = defaultValue;
            }
            else {
                throw e;
            }
        }
        return value;
    }
    function emptyTarget(value) {
        return Array.isArray(value) ? [] : {};
    }
    function cloneUnlessOtherwiseSpecified(value, options) {
        return (options.clone !== false && options.isMergeableObject(value))
            ? deepMerge(emptyTarget(value), value, options)
            : value;
    }
    function defaultArrayMerge(target, source, options) {
        return target.concat(source).map(function (element) {
            return cloneUnlessOtherwiseSpecified(element, options);
        });
    }
    function getMergeFunction(key, options) {
        if (!options.customMerge) {
            return deepMerge;
        }
        var customMerge = options.customMerge(key);
        return typeof customMerge === 'function' ? customMerge : deepMerge;
    }
    function getEnumerableOwnPropertySymbols(target) {
        return Object.getOwnPropertySymbols
            ? Object.getOwnPropertySymbols(target).filter(function (symbol) {
                return target.propertyIsEnumerable(symbol);
            })
            : [];
    }
    function getKeys(target) {
        return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
    }
    function propertyIsOnObject(object, property) {
        try {
            return property in object;
        }
        catch (_) {
            return false;
        }
    }
    // Protects from prototype poisoning and unexpected merging up the prototype chain.
    function propertyIsUnsafe(target, key) {
        return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
            && !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
                && Object.propertyIsEnumerable.call(target, key)); // and also unsafe if they're nonenumerable.
    }
    function mergeObject(target, source, options) {
        var destination = {};
        if (options.isMergeableObject(target)) {
            getKeys(target).forEach(function (key) {
                destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
            });
        }
        getKeys(source).forEach(function (key) {
            if (propertyIsUnsafe(target, key)) {
                return;
            }
            if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
                destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
            }
            else {
                destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
            }
        });
        return destination;
    }
    function defaultIsMergeableObject(value) {
        return isNonNullObject(value) && !isSpecial(value);
    }
    function isNonNullObject(value) {
        return !!value && typeof value === 'object';
    }
    function isSpecial(value) {
        var stringValue = Object.prototype.toString.call(value);
        return stringValue === '[object RegExp]' || stringValue === '[object Date]';
    }
    function deepMerge(target, source, options) {
        options = options || {};
        options.arrayMerge = options.arrayMerge || defaultArrayMerge;
        options.isMergeableObject = options.isMergeableObject || defaultIsMergeableObject;
        // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
        // implementations can use it. The caller may not replace it.
        options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
        var sourceIsArray = Array.isArray(source);
        var targetIsArray = Array.isArray(target);
        var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
        if (!sourceAndTargetTypesMatch) {
            return cloneUnlessOtherwiseSpecified(source, options);
        }
        else if (sourceIsArray) {
            return options.arrayMerge(target, source, options);
        }
        else {
            return mergeObject(target, source, options);
        }
    }
    function isObject(value) {
        return typeof value === 'object' && !Array.isArray(value);
    }

    var __extends$1 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Shape = /** @class */ (function (_super) {
        __extends$1(Shape, _super);
        function Shape() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.lastInstanceId = 0;
            _this._fillOpacity = 1;
            _this._strokeOpacity = 1;
            _this._fill = Shape.defaultStyles.fill;
            /**
             * Note that `strokeStyle = null` means invisible stroke,
             * while `lineWidth = 0` means no stroke, and sometimes this can mean different things.
             * For example, a rect shape with an invisible stroke may not align to the pixel grid
             * properly because the stroke affects the rules of alignment, and arc shapes forming
             * a pie chart will have a gap between them if they have an invisible stroke, whereas
             * there would be not gap if there was no stroke at all.
             * The preferred way of making the stroke invisible is setting the `lineWidth` to zero,
             * unless specific looks that is achieved by having an invisible stroke is desired.
             */
            _this._stroke = Shape.defaultStyles.stroke;
            _this._strokeWidth = Shape.defaultStyles.strokeWidth;
            _this._lineDash = Shape.defaultStyles.lineDash;
            _this._lineDashOffset = Shape.defaultStyles.lineDashOffset;
            _this._lineCap = Shape.defaultStyles.lineCap;
            _this._lineJoin = Shape.defaultStyles.lineJoin;
            _this._opacity = Shape.defaultStyles.opacity;
            _this.onShadowChange = function () {
                _this.dirty = true;
            };
            _this._fillShadow = Shape.defaultStyles.fillShadow;
            _this._strokeShadow = Shape.defaultStyles.strokeShadow;
            return _this;
        }
        /**
         * Creates a light-weight instance of the given shape (that serves as a template).
         * The created instance only stores the properites set on the instance itself
         * and the rest of the properties come via the prototype chain from the template.
         * This can greatly reduce memory usage in cases where one has many simular shapes,
         * for example, circles of different size, position and color. The exact memory usage
         * reduction will depend on the size of the template and the number of own properties
         * set on its lightweight instances, but will typically be around an order of magnitude
         * or more.
         *
         * Note: template shapes are not supposed to be part of the scene graph (they should not
         * have a parent).
         *
         * @param template
         */
        Shape.createInstance = function (template) {
            var shape = Object.create(template);
            shape._setParent(undefined);
            shape.id = template.id + '-Instance-' + String(++template.lastInstanceId);
            return shape;
        };
        /**
         * Restores the default styles introduced by this subclass.
         */
        Shape.prototype.restoreOwnStyles = function () {
            var styles = this.constructor.defaultStyles;
            var keys = Object.getOwnPropertyNames(styles);
            // getOwnPropertyNames is about 2.5 times faster than
            // for..in with the hasOwnProperty check and in this
            // case, where most properties are inherited, can be
            // more then an order of magnitude faster.
            for (var i = 0, n = keys.length; i < n; i++) {
                var key = keys[i];
                this[key] = styles[key];
            }
        };
        Shape.prototype.restoreAllStyles = function () {
            var styles = this.constructor.defaultStyles;
            for (var property in styles) {
                this[property] = styles[property];
            }
        };
        /**
         * Restores the base class default styles that have been overridden by this subclass.
         */
        Shape.prototype.restoreOverriddenStyles = function () {
            var styles = this.constructor.defaultStyles;
            var protoStyles = Object.getPrototypeOf(styles);
            for (var property in styles) {
                if (styles.hasOwnProperty(property) && protoStyles.hasOwnProperty(property)) {
                    this[property] = styles[property];
                }
            }
        };
        Object.defineProperty(Shape.prototype, "fillOpacity", {
            get: function () {
                return this._fillOpacity;
            },
            set: function (value) {
                if (this._fillOpacity !== value) {
                    this._fillOpacity = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "strokeOpacity", {
            get: function () {
                return this._strokeOpacity;
            },
            set: function (value) {
                if (this._strokeOpacity !== value) {
                    this._strokeOpacity = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "fill", {
            get: function () {
                return this._fill;
            },
            set: function (value) {
                if (this._fill !== value) {
                    this._fill = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "stroke", {
            get: function () {
                return this._stroke;
            },
            set: function (value) {
                if (this._stroke !== value) {
                    this._stroke = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "strokeWidth", {
            get: function () {
                return this._strokeWidth;
            },
            set: function (value) {
                if (this._strokeWidth !== value) {
                    this._strokeWidth = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "alignment", {
            // An offset value to align to the pixel grid.
            get: function () {
                return Math.floor(this.strokeWidth) % 2 / 2;
            },
            enumerable: true,
            configurable: true
        });
        // Returns the aligned `start` or `length` value.
        // For example: `start` could be `y` and `length` could be `height` of a rectangle.
        Shape.prototype.align = function (alignment, start, length) {
            if (length != undefined) {
                return Math.floor(length) + Math.floor(start % 1 + length % 1);
            }
            return Math.floor(start) + alignment;
        };
        Object.defineProperty(Shape.prototype, "lineDash", {
            get: function () {
                return this._lineDash;
            },
            set: function (value) {
                var oldValue = this._lineDash;
                if (oldValue !== value) {
                    if (oldValue && value && oldValue.length === value.length) {
                        var identical = true;
                        var n = value.length;
                        for (var i = 0; i < n; i++) {
                            if (oldValue[i] !== value[i]) {
                                identical = false;
                                break;
                            }
                        }
                        if (identical) {
                            return;
                        }
                    }
                    this._lineDash = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "lineDashOffset", {
            get: function () {
                return this._lineDashOffset;
            },
            set: function (value) {
                if (this._lineDashOffset !== value) {
                    this._lineDashOffset = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "lineCap", {
            get: function () {
                return this._lineCap;
            },
            set: function (value) {
                if (this._lineCap !== value) {
                    this._lineCap = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "lineJoin", {
            get: function () {
                return this._lineJoin;
            },
            set: function (value) {
                if (this._lineJoin !== value) {
                    this._lineJoin = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "opacity", {
            get: function () {
                return this._opacity;
            },
            set: function (value) {
                value = Math.min(1, Math.max(0, value));
                if (this._opacity !== value) {
                    this._opacity = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "fillShadow", {
            get: function () {
                return this._fillShadow;
            },
            set: function (value) {
                var oldValue = this._fillShadow;
                if (oldValue !== value) {
                    if (oldValue) {
                        oldValue.removeEventListener('change', this.onShadowChange);
                    }
                    if (value) {
                        value.addEventListener('change', this.onShadowChange);
                    }
                    this._fillShadow = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Shape.prototype, "strokeShadow", {
            get: function () {
                return this._strokeShadow;
            },
            set: function (value) {
                var oldValue = this._strokeShadow;
                if (oldValue !== value) {
                    if (oldValue) {
                        oldValue.removeEventListener('change', this.onShadowChange);
                    }
                    if (value) {
                        value.addEventListener('change', this.onShadowChange);
                    }
                    this._strokeShadow = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Shape.prototype.fillStroke = function (ctx) {
            if (!this.scene) {
                return;
            }
            var pixelRatio = this.scene.canvas.pixelRatio || 1;
            var globalAlpha = ctx.globalAlpha;
            if (this.fill) {
                ctx.fillStyle = this.fill;
                ctx.globalAlpha = globalAlpha * this.opacity * this.fillOpacity;
                // The canvas context scaling (depends on the device's pixel ratio)
                // has no effect on shadows, so we have to account for the pixel ratio
                // manually here.
                var fillShadow = this.fillShadow;
                if (fillShadow && fillShadow.enabled) {
                    ctx.shadowColor = fillShadow.color;
                    ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = fillShadow.blur * pixelRatio;
                }
                ctx.fill();
            }
            ctx.shadowColor = 'rgba(0, 0, 0, 0)';
            if (this.stroke && this.strokeWidth) {
                ctx.strokeStyle = this.stroke;
                ctx.globalAlpha = globalAlpha * this.opacity * this.strokeOpacity;
                ctx.lineWidth = this.strokeWidth;
                if (this.lineDash) {
                    ctx.setLineDash(this.lineDash);
                }
                if (this.lineDashOffset) {
                    ctx.lineDashOffset = this.lineDashOffset;
                }
                if (this.lineCap) {
                    ctx.lineCap = this.lineCap;
                }
                if (this.lineJoin) {
                    ctx.lineJoin = this.lineJoin;
                }
                var strokeShadow = this.strokeShadow;
                if (strokeShadow && strokeShadow.enabled) {
                    ctx.shadowColor = strokeShadow.color;
                    ctx.shadowOffsetX = strokeShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = strokeShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = strokeShadow.blur * pixelRatio;
                }
                ctx.stroke();
            }
        };
        Shape.prototype.containsPoint = function (x, y) {
            return this.isPointInPath(x, y);
        };
        /**
         * Defaults for style properties. Note that properties that affect the position
         * and shape of the node are not considered style properties, for example:
         * `x`, `y`, `width`, `height`, `radius`, `rotation`, etc.
         * Can be used to reset to the original styling after some custom styling
         * has been applied (using the `restoreOwnStyles` and `restoreAllStyles` methods).
         * These static defaults are meant to be inherited by subclasses.
         */
        Shape.defaultStyles = chainObjects({}, {
            fill: 'black',
            stroke: undefined,
            strokeWidth: 0,
            lineDash: undefined,
            lineDashOffset: 0,
            lineCap: undefined,
            lineJoin: undefined,
            opacity: 1,
            fillShadow: undefined,
            strokeShadow: undefined
        });
        return Shape;
    }(Node));

    /**
     * Wraps the native Canvas element and overrides its CanvasRenderingContext2D to
     * provide resolution independent rendering based on `window.devicePixelRatio`.
     */
    var HdpiCanvas = /** @class */ (function () {
        // The width/height attributes of the Canvas element default to
        // 300/150 according to w3.org.
        function HdpiCanvas(document, width, height) {
            if (document === void 0) { document = window.document; }
            if (width === void 0) { width = 600; }
            if (height === void 0) { height = 300; }
            this._container = undefined;
            // `NaN` is deliberate here, so that overrides are always applied
            // and the `resetTransform` inside the `resize` method works in IE11.
            this._pixelRatio = NaN;
            this._width = 0;
            this._height = 0;
            this.document = document;
            this.element = document.createElement('canvas');
            this.context = this.element.getContext('2d');
            this.element.style.userSelect = 'none';
            this.element.style.display = 'block';
            this.setPixelRatio();
            this.resize(width, height);
        }
        Object.defineProperty(HdpiCanvas.prototype, "container", {
            get: function () {
                return this._container;
            },
            set: function (value) {
                if (this._container !== value) {
                    this.remove();
                    if (value) {
                        value.appendChild(this.element);
                    }
                    this._container = value;
                }
            },
            enumerable: true,
            configurable: true
        });
        HdpiCanvas.prototype.remove = function () {
            var parentNode = this.element.parentNode;
            if (parentNode != null) {
                parentNode.removeChild(this.element);
            }
        };
        HdpiCanvas.prototype.destroy = function () {
            this.element.remove();
            this._canvas = undefined;
            Object.freeze(this);
        };
        HdpiCanvas.prototype.toImage = function () {
            var img = this.document.createElement('img');
            img.src = this.getDataURL();
            return img;
        };
        HdpiCanvas.prototype.getDataURL = function (type) {
            return this.element.toDataURL(type);
        };
        /**
         * @param fileName The name of the file upon save. The `.png` extension is going to be added automatically.
         */
        HdpiCanvas.prototype.download = function (fileName) {
            fileName = ((fileName || '').trim() || 'image') + '.png';
            // Chart images saved as JPEG are a few times larger at 50% quality than PNG images,
            // so we don't support saving to JPEG.
            var type = 'image/png';
            var dataUrl = this.getDataURL(type);
            var document = this.document;
            var a = document.createElement('a');
            a.href = dataUrl;
            a.download = fileName;
            a.style.display = 'none';
            document.body.appendChild(a); // required for the `click` to work in Firefox
            a.click();
            document.body.removeChild(a);
        };
        Object.defineProperty(HdpiCanvas.prototype, "pixelRatio", {
            get: function () {
                return this._pixelRatio;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Changes the pixel ratio of the Canvas element to the given value,
         * or uses the window.devicePixelRatio (default), then resizes the Canvas
         * element accordingly (default).
         */
        HdpiCanvas.prototype.setPixelRatio = function (ratio) {
            var pixelRatio = ratio || window.devicePixelRatio;
            if (pixelRatio === this.pixelRatio) {
                return;
            }
            HdpiCanvas.overrideScale(this.context, pixelRatio);
            this._pixelRatio = pixelRatio;
            this.resize(this.width, this.height);
        };
        Object.defineProperty(HdpiCanvas.prototype, "pixelated", {
            get: function () {
                return this.element.style.imageRendering === 'pixelated';
            },
            set: function (value) {
                this.element.style.imageRendering = value ? 'pixelated' : 'auto';
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HdpiCanvas.prototype, "width", {
            get: function () {
                return this._width;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HdpiCanvas.prototype, "height", {
            get: function () {
                return this._height;
            },
            enumerable: true,
            configurable: true
        });
        HdpiCanvas.prototype.resize = function (width, height) {
            if (!(width > 0 && height > 0)) {
                return;
            }
            var _a = this, element = _a.element, context = _a.context, pixelRatio = _a.pixelRatio;
            element.width = Math.round(width * pixelRatio);
            element.height = Math.round(height * pixelRatio);
            element.style.width = width + 'px';
            element.style.height = height + 'px';
            context.resetTransform();
            this._width = width;
            this._height = height;
        };
        Object.defineProperty(HdpiCanvas, "textMeasuringContext", {
            get: function () {
                if (this._textMeasuringContext) {
                    return this._textMeasuringContext;
                }
                var canvas = document.createElement('canvas');
                return this._textMeasuringContext = canvas.getContext('2d');
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HdpiCanvas, "svgText", {
            get: function () {
                if (this._svgText) {
                    return this._svgText;
                }
                var xmlns = 'http://www.w3.org/2000/svg';
                var svg = document.createElementNS(xmlns, 'svg');
                svg.setAttribute('width', '100');
                svg.setAttribute('height', '100');
                // Add a descriptive class name in case someone sees this SVG element
                // in devtools and wonders about its purpose:
                if (svg.classList) {
                    svg.classList.add('text-measuring-svg');
                }
                else {
                    svg.setAttribute('class', 'text-measuring-svg');
                }
                svg.style.position = 'absolute';
                svg.style.top = '-1000px';
                svg.style.visibility = 'hidden';
                var svgText = document.createElementNS(xmlns, 'text');
                svgText.setAttribute('x', '0');
                svgText.setAttribute('y', '30');
                svgText.setAttribute('text', 'black');
                svg.appendChild(svgText);
                document.body.appendChild(svg);
                this._svgText = svgText;
                return svgText;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HdpiCanvas, "has", {
            get: function () {
                if (this._has) {
                    return this._has;
                }
                var isChrome = navigator.userAgent.indexOf('Chrome') > -1;
                var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
                var isSafari = !isChrome && navigator.userAgent.indexOf('Safari') > -1;
                return this._has = Object.freeze({
                    textMetrics: this.textMeasuringContext.measureText('test').actualBoundingBoxDescent !== undefined
                        // Firefox implemented advanced TextMetrics object in v74:
                        // https://bugzilla.mozilla.org/show_bug.cgi?id=1102584
                        // but it's buggy, so we'll keed using the SVG for text measurement in Firefox for now.
                        && !isFirefox && !isSafari,
                    getTransform: this.textMeasuringContext.getTransform !== undefined
                });
            },
            enumerable: true,
            configurable: true
        });
        HdpiCanvas.measureText = function (text, font, textBaseline, textAlign) {
            var ctx = this.textMeasuringContext;
            ctx.font = font;
            ctx.textBaseline = textBaseline;
            ctx.textAlign = textAlign;
            return ctx.measureText(text);
        };
        /**
         * Returns the width and height of the measured text.
         * @param text The single-line text to measure.
         * @param font The font shorthand string.
         */
        HdpiCanvas.getTextSize = function (text, font) {
            if (this.has.textMetrics) {
                var ctx = this.textMeasuringContext;
                ctx.font = font;
                var metrics = ctx.measureText(text);
                return {
                    width: metrics.width,
                    height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
                };
            }
            else {
                return this.measureSvgText(text, font);
            }
        };
        HdpiCanvas.measureSvgText = function (text, font) {
            var cache = this.textSizeCache;
            var fontCache = cache[font];
            // Note: consider not caching the size of numeric strings.
            // For example: if (isNaN(+text)) { // skip
            if (fontCache) {
                var size_1 = fontCache[text];
                if (size_1) {
                    return size_1;
                }
            }
            else {
                cache[font] = {};
            }
            var svgText = this.svgText;
            svgText.style.font = font;
            svgText.textContent = text;
            // `getBBox` returns an instance of `SVGRect` with the same `width` and `height`
            // measurements as `DOMRect` instance returned by the `getBoundingClientRect`.
            // But the `SVGRect` instance has half the properties of the `DOMRect`,
            // so we use the `getBBox` method.
            var bbox = svgText.getBBox();
            var size = {
                width: bbox.width,
                height: bbox.height
            };
            cache[font][text] = size;
            return size;
        };
        HdpiCanvas.overrideScale = function (ctx, scale) {
            var depth = 0;
            var overrides = {
                save: function () {
                    this.$save();
                    depth++;
                },
                restore: function () {
                    if (depth > 0) {
                        this.$restore();
                        depth--;
                    }
                },
                setTransform: function (a, b, c, d, e, f) {
                    this.$setTransform(a * scale, b * scale, c * scale, d * scale, e * scale, f * scale);
                },
                resetTransform: function () {
                    // As of Jan 8, 2019, `resetTransform` is still an "experimental technology",
                    // and doesn't work in IE11 and Edge 44.
                    this.$setTransform(scale, 0, 0, scale, 0, 0);
                    this.save();
                    depth = 0;
                    // The scale above will be impossible to restore,
                    // because we override the `ctx.restore` above and
                    // check `depth` there.
                }
            };
            for (var name_1 in overrides) {
                if (overrides.hasOwnProperty(name_1)) {
                    // Save native methods under prefixed names,
                    // if this hasn't been done by the previous overrides already.
                    if (!ctx['$' + name_1]) {
                        ctx['$' + name_1] = ctx[name_1];
                    }
                    // Replace native methods with overrides,
                    // or previous overrides with the new ones.
                    ctx[name_1] = overrides[name_1];
                }
            }
        };
        HdpiCanvas.textSizeCache = {};
        return HdpiCanvas;
    }());

    var __extends$2 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Text = /** @class */ (function (_super) {
        __extends$2(Text, _super);
        function Text() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._x = 0;
            _this._y = 0;
            _this.lineBreakRegex = /\r?\n/g;
            _this.lines = [];
            _this._text = '';
            _this._dirtyFont = true;
            _this._fontSize = 10;
            _this._fontFamily = 'sans-serif';
            _this._textAlign = Text.defaultStyles.textAlign;
            _this._textBaseline = Text.defaultStyles.textBaseline;
            _this._lineHeight = 14;
            return _this;
        }
        Object.defineProperty(Text.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (value) {
                if (this._x !== value) {
                    this._x = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (value) {
                if (this._y !== value) {
                    this._y = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Text.prototype.splitText = function () {
            this.lines = this._text.split(this.lineBreakRegex);
        };
        Object.defineProperty(Text.prototype, "text", {
            get: function () {
                return this._text;
            },
            set: function (value) {
                var str = String(value); // `value` can be an object here
                if (this._text !== str) {
                    this._text = str;
                    this.splitText();
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "font", {
            get: function () {
                if (this.dirtyFont) {
                    this.dirtyFont = false;
                    this._font = getFont(this.fontSize, this.fontFamily, this.fontStyle, this.fontWeight);
                }
                return this._font;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "dirtyFont", {
            get: function () {
                return this._dirtyFont;
            },
            set: function (value) {
                if (this._dirtyFont !== value) {
                    this._dirtyFont = value;
                    if (value) {
                        this.dirty = true;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "fontStyle", {
            get: function () {
                return this._fontStyle;
            },
            set: function (value) {
                if (this._fontStyle !== value) {
                    this._fontStyle = value;
                    this.dirtyFont = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "fontWeight", {
            get: function () {
                return this._fontWeight;
            },
            set: function (value) {
                if (this._fontWeight !== value) {
                    this._fontWeight = value;
                    this.dirtyFont = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "fontSize", {
            get: function () {
                return this._fontSize;
            },
            set: function (value) {
                if (!isFinite(value)) {
                    value = 10;
                }
                if (this._fontSize !== value) {
                    this._fontSize = value;
                    this.dirtyFont = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "fontFamily", {
            get: function () {
                return this._fontFamily;
            },
            set: function (value) {
                if (this._fontFamily !== value) {
                    this._fontFamily = value;
                    this.dirtyFont = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "textAlign", {
            get: function () {
                return this._textAlign;
            },
            set: function (value) {
                if (this._textAlign !== value) {
                    this._textAlign = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "textBaseline", {
            get: function () {
                return this._textBaseline;
            },
            set: function (value) {
                if (this._textBaseline !== value) {
                    this._textBaseline = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Text.prototype, "lineHeight", {
            get: function () {
                return this._lineHeight;
            },
            set: function (value) {
                // Multi-line text is complicated because:
                // - Canvas does not support it natively, so we have to implement it manually
                // - need to know the height of each line -> need to parse the font shorthand ->
                //   generally impossible to do because font size may not be in pixels
                // - so, need to measure the text instead, each line individually -> expensive
                // - or make the user provide the line height manually for multi-line text
                // - computeBBox should use the lineHeight for multi-line text but ignore it otherwise
                // - textBaseline kind of loses its meaning for multi-line text
                if (this._lineHeight !== value) {
                    this._lineHeight = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Text.prototype.computeBBox = function () {
            return HdpiCanvas.has.textMetrics
                ? this.getPreciseBBox()
                : this.getApproximateBBox();
        };
        Text.prototype.getPreciseBBox = function () {
            var metrics = HdpiCanvas.measureText(this.text, this.font, this.textBaseline, this.textAlign);
            return new BBox(this.x - metrics.actualBoundingBoxLeft, this.y - metrics.actualBoundingBoxAscent, metrics.width, metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent);
        };
        Text.prototype.getApproximateBBox = function () {
            var size = HdpiCanvas.getTextSize(this.text, this.font);
            var _a = this, x = _a.x, y = _a.y;
            switch (this.textAlign) {
                case 'end':
                case 'right':
                    x -= size.width;
                    break;
                case 'center':
                    x -= size.width / 2;
            }
            switch (this.textBaseline) {
                case 'alphabetic':
                    y -= size.height * 0.7;
                    break;
                case 'middle':
                    y -= size.height * 0.45;
                    break;
                case 'ideographic':
                    y -= size.height;
                    break;
                case 'hanging':
                    y -= size.height * 0.2;
                    break;
                case 'bottom':
                    y -= size.height;
                    break;
            }
            return new BBox(x, y, size.width, size.height);
        };
        Text.prototype.isPointInPath = function (x, y) {
            var point = this.transformPoint(x, y);
            var bbox = this.computeBBox();
            return bbox ? bbox.containsPoint(point.x, point.y) : false;
        };
        Text.prototype.isPointInStroke = function (x, y) {
            return false;
        };
        Text.prototype.render = function (ctx) {
            if (!this.lines.length || !this.scene) {
                return;
            }
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            // this.matrix.transformBBox(this.computeBBox!()).render(ctx); // debug
            this.matrix.toContext(ctx);
            var _a = this, fill = _a.fill, stroke = _a.stroke, strokeWidth = _a.strokeWidth;
            ctx.font = this.font;
            ctx.textAlign = this.textAlign;
            ctx.textBaseline = this.textBaseline;
            var pixelRatio = this.scene.canvas.pixelRatio || 1;
            var globalAlpha = ctx.globalAlpha;
            if (fill) {
                ctx.fillStyle = fill;
                ctx.globalAlpha = globalAlpha * this.opacity * this.fillOpacity;
                var _b = this, fillShadow = _b.fillShadow, text = _b.text, x = _b.x, y = _b.y;
                if (fillShadow && fillShadow.enabled) {
                    ctx.shadowColor = fillShadow.color;
                    ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = fillShadow.blur * pixelRatio;
                }
                ctx.fillText(text, x, y);
            }
            if (stroke && strokeWidth) {
                ctx.strokeStyle = stroke;
                ctx.lineWidth = strokeWidth;
                ctx.globalAlpha = globalAlpha * this.opacity * this.strokeOpacity;
                var _c = this, lineDash = _c.lineDash, lineDashOffset = _c.lineDashOffset, lineCap = _c.lineCap, lineJoin = _c.lineJoin, strokeShadow = _c.strokeShadow, text = _c.text, x = _c.x, y = _c.y;
                if (lineDash) {
                    ctx.setLineDash(lineDash);
                }
                if (lineDashOffset) {
                    ctx.lineDashOffset = lineDashOffset;
                }
                if (lineCap) {
                    ctx.lineCap = lineCap;
                }
                if (lineJoin) {
                    ctx.lineJoin = lineJoin;
                }
                if (strokeShadow && strokeShadow.enabled) {
                    ctx.shadowColor = strokeShadow.color;
                    ctx.shadowOffsetX = strokeShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = strokeShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = strokeShadow.blur * pixelRatio;
                }
                ctx.strokeText(text, x, y);
            }
            this.dirty = false;
        };
        Text.className = 'Text';
        Text.defaultStyles = chainObjects(Shape.defaultStyles, {
            textAlign: 'start',
            fontStyle: undefined,
            fontWeight: undefined,
            fontSize: 10,
            fontFamily: 'sans-serif',
            textBaseline: 'alphabetic'
        });
        return Text;
    }(Shape));
    function getFont(fontSize, fontFamily, fontStyle, fontWeight) {
        return [
            fontStyle || '',
            fontWeight || '',
            fontSize + 'px',
            fontFamily
        ].join(' ').trim();
    }

    var __extends$3 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var Caption = /** @class */ (function (_super) {
        __extends$3(Caption, _super);
        function Caption() {
            var _this = _super.call(this) || this;
            _this.node = new Text();
            _this.enabled = false;
            _this.padding = new Padding(10);
            var node = _this.node;
            node.textAlign = 'center';
            node.textBaseline = 'top';
            node.pointerEvents = PointerEvents.None;
            return _this;
        }
        Object.defineProperty(Caption.prototype, "text", {
            get: function () {
                return this.node.text;
            },
            set: function (value) {
                if (this.node.text !== value) {
                    this.node.text = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Caption.prototype, "fontStyle", {
            get: function () {
                return this.node.fontStyle;
            },
            set: function (value) {
                if (this.node.fontStyle !== value) {
                    this.node.fontStyle = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Caption.prototype, "fontWeight", {
            get: function () {
                return this.node.fontWeight;
            },
            set: function (value) {
                if (this.node.fontWeight !== value) {
                    this.node.fontWeight = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Caption.prototype, "fontSize", {
            get: function () {
                return this.node.fontSize;
            },
            set: function (value) {
                if (this.node.fontSize !== value) {
                    this.node.fontSize = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Caption.prototype, "fontFamily", {
            get: function () {
                return this.node.fontFamily;
            },
            set: function (value) {
                if (this.node.fontFamily !== value) {
                    this.node.fontFamily = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Caption.prototype, "color", {
            get: function () {
                return this.node.fill;
            },
            set: function (value) {
                if (this.node.fill !== value) {
                    this.node.fill = value;
                    this.fireEvent({ type: 'change' });
                }
            },
            enumerable: true,
            configurable: true
        });
        __decorate$1([
            reactive('change')
        ], Caption.prototype, "enabled", void 0);
        __decorate$1([
            reactive('change')
        ], Caption.prototype, "padding", void 0);
        return Caption;
    }(Observable));

    var __extends$4 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    function ticks (a, b, count) {
        var step = tickStep(a, b, count);
        a = Math.ceil(a / step) * step;
        b = Math.floor(b / step) * step + step / 2;
        // Add half a step here so that the array returned by `range` includes the last tick.
        return range(a, b, step);
    }
    var e10 = Math.sqrt(50);
    var e5 = Math.sqrt(10);
    var e2 = Math.sqrt(2);
    function tickStep(a, b, count) {
        var rawStep = Math.abs(b - a) / Math.max(0, count);
        var step = Math.pow(10, Math.floor(Math.log(rawStep) / Math.LN10)); // = Math.log10(rawStep)
        var error = rawStep / step;
        if (error >= e10) {
            step *= 10;
        }
        else if (error >= e5) {
            step *= 5;
        }
        else if (error >= e2) {
            step *= 2;
        }
        return b < a ? -step : step;
    }
    function tickIncrement(a, b, count) {
        var rawStep = (b - a) / Math.max(0, count);
        var power = Math.floor(Math.log(rawStep) / Math.LN10);
        var error = rawStep / Math.pow(10, power);
        return power >= 0
            ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
            : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
    }
    var NumericTicks = /** @class */ (function (_super) {
        __extends$4(NumericTicks, _super);
        function NumericTicks(fractionDigits, elements) {
            var _this = _super.call(this) || this;
            if (elements) {
                for (var i = 0, n = elements.length; i < n; i++) {
                    _this[i] = elements[i];
                }
            }
            _this.fractionDigits = fractionDigits;
            return _this;
        }
        return NumericTicks;
    }(Array));
    function range(a, b, step) {
        if (step === void 0) { step = 1; }
        var absStep = Math.abs(step);
        var fractionDigits = (absStep > 0 && absStep < 1)
            ? Math.abs(Math.floor(Math.log(absStep) / Math.LN10))
            : 0;
        var f = Math.pow(10, fractionDigits);
        var n = Math.max(0, Math.ceil((b - a) / step)) || 0;
        var values = new NumericTicks(fractionDigits);
        for (var i = 0; i < n; i++) {
            var value = a + step * i;
            values[i] = Math.round(value * f) / f;
        }
        return values;
    }

    function calculateNiceSecondaryAxis(domain, primaryTickCount) {
        // Make secondary axis domain nice using strict tick count, matching the tick count from the primary axis.
        // This is to make the secondary axis grid lines/ tick positions align with the ones from the primary axis.
        var start = Math.floor(domain[0]);
        var stop = domain[1];
        start = calculateNiceStart(start, stop, primaryTickCount);
        var step = getTickStep(start, stop, primaryTickCount);
        var segments = primaryTickCount - 1;
        stop = start + (segments * step);
        var d = [start, stop];
        var ticks = getTicks(start, step, primaryTickCount);
        return [d, ticks];
    }
    function calculateNiceStart(a, b, count) {
        var rawStep = Math.abs(b - a) / (count - 1);
        var order = Math.floor(Math.log10(rawStep));
        var magnitude = Math.pow(10, order);
        return Math.floor(a / magnitude) * magnitude;
    }
    function getTicks(start, step, count) {
        // power of the step will be negative if the step is a fraction (between 0 and 1)
        var stepPower = Math.floor(Math.log10(step));
        var fractionDigits = (step > 0 && step < 1) ? Math.abs(stepPower) : 0;
        var f = Math.pow(10, fractionDigits);
        var ticks = new NumericTicks(fractionDigits);
        for (var i = 0; i < count; i++) {
            var tick = start + step * i;
            ticks[i] = Math.round(tick * f) / f;
        }
        return ticks;
    }
    function getTickStep(start, stop, count) {
        var segments = count - 1;
        var rawStep = (stop - start) / segments;
        return calculateNextNiceStep(rawStep);
    }
    function calculateNextNiceStep(rawStep) {
        var order = Math.floor(Math.log10(rawStep));
        var magnitude = Math.pow(10, order);
        // Make order 1
        var step = (rawStep / magnitude) * 10;
        if (step > 0 && step <= 1) {
            return magnitude / 10;
        }
        if (step > 1 && step <= 2) {
            return 2 * magnitude / 10;
        }
        if (step > 1 && step <= 5) {
            return 5 * magnitude / 10;
        }
        if (step > 5 && step <= 10) {
            return 10 * magnitude / 10;
        }
        if (step > 10 && step <= 20) {
            return 20 * magnitude / 10;
        }
        if (step > 20 && step <= 40) {
            return 40 * magnitude / 10;
        }
        if (step > 40 && step <= 50) {
            return 50 * magnitude / 10;
        }
        if (step > 50 && step <= 100) {
            return 100 * magnitude / 10;
        }
        return step;
    }

    var constant = (function (x) { return function () { return x; }; });

    function interpolateNumber (a, b) {
        a = +a;
        b = +b;
        return function (t) { return a * (1 - t) + b * t; };
    }

    function date (a, b) {
        var date = new Date;
        var msA = +a;
        var msB = +b;
        return function (t) {
            date.setTime(msA * (1 - t) + msB * t);
            return date;
        };
    }

    function array (a, b) {
        var nb = b ? b.length : 0;
        var na = a ? Math.min(nb, a.length) : 0;
        var x = new Array(na);
        var c = new Array(nb);
        var i;
        for (i = 0; i < na; ++i) {
            x[i] = interpolateValue(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;
        };
    }

    function object (a, b) {
        var i = {};
        var c = {};
        var 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] = interpolateValue(a[k], b[k]);
            }
            else {
                c[k] = b[k];
            }
        }
        return function (t) {
            for (k in i) {
                c[k] = i[k](t);
            }
            return c;
        };
    }

    var __read$2 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var Color = /** @class */ (function () {
        /**
         * Every color component should be in the [0, 1] range.
         * Some easing functions (such as elastic easing) can overshoot the target value by some amount.
         * So, when animating colors, if the source or target color components are already near
         * or at the edge of the allowed [0, 1] range, it is possible for the intermediate color
         * component value to end up outside of that range mid-animation. For this reason the constructor
         * performs range checking/constraining.
         * @param r Red component.
         * @param g Green component.
         * @param b Blue component.
         * @param a Alpha (opacity) component.
         */
        function Color(r, g, b, a) {
            if (a === void 0) { a = 1; }
            // NaN is treated as 0.
            this.r = Math.min(1, Math.max(0, r || 0));
            this.g = Math.min(1, Math.max(0, g || 0));
            this.b = Math.min(1, Math.max(0, b || 0));
            this.a = Math.min(1, Math.max(0, a || 0));
        }
        /**
         * The given string can be in one of the following formats:
         * - #rgb
         * - #rrggbb
         * - rgb(r, g, b)
         * - rgba(r, g, b, a)
         * - CSS color name such as 'white', 'orange', 'cyan', etc.
         * @param str
         */
        Color.fromString = function (str) {
            // hexadecimal notation
            if (str.indexOf('#') >= 0) { // there can be some leading whitespace
                return Color.fromHexString(str);
            }
            // color name
            var hex = Color.nameToHex[str];
            if (hex) {
                return Color.fromHexString(hex);
            }
            // rgb(a) notation
            if (str.indexOf('rgb') >= 0) {
                return Color.fromRgbaString(str);
            }
            throw new Error("Invalid color string: '" + str + "'");
        };
        // See https://drafts.csswg.org/css-color/#hex-notation
        Color.parseHex = function (input) {
            input = input.replace(/ /g, '').slice(1);
            var parts;
            switch (input.length) {
                case 6:
                case 8:
                    parts = [];
                    for (var i = 0; i < input.length; i += 2) {
                        parts.push(parseInt("" + input[i] + input[i + 1], 16));
                    }
                    break;
                case 3:
                case 4:
                    parts = input.split('').map(function (p) { return parseInt(p, 16); }).map(function (p) { return p + p * 16; });
                    break;
            }
            if (parts.length >= 3) {
                if (parts.every(function (p) { return p >= 0; })) {
                    if (parts.length === 3) {
                        parts.push(255);
                    }
                    return parts;
                }
            }
        };
        Color.fromHexString = function (str) {
            var values = Color.parseHex(str);
            if (values) {
                var _a = __read$2(values, 4), r = _a[0], g = _a[1], b = _a[2], a = _a[3];
                return new Color(r / 255, g / 255, b / 255, a / 255);
            }
            throw new Error("Malformed hexadecimal color string: '" + str + "'");
        };
        Color.stringToRgba = function (str) {
            // Find positions of opening and closing parentheses.
            var _a = __read$2([NaN, NaN], 2), po = _a[0], pc = _a[1];
            for (var i = 0; i < str.length; i++) {
                var c = str[i];
                if (!po && c === '(') {
                    po = i;
                }
                else if (c === ')') {
                    pc = i;
                    break;
                }
            }
            var contents = po && pc && str.substring(po + 1, pc);
            if (!contents) {
                return;
            }
            var parts = contents.split(',');
            var rgba = [];
            for (var i = 0; i < parts.length; i++) {
                var part = parts[i];
                var value = parseFloat(part);
                if (isNaN(value)) {
                    return;
                }
                if (part.indexOf('%') >= 0) { // percentage r, g, or b value
                    value = Math.max(0, Math.min(100, value));
                    value /= 100;
                }
                else {
                    if (i === 3) { // alpha component
                        value = Math.max(0, Math.min(1, value));
                    }
                    else { // absolute r, g, or b value
                        value = Math.max(0, Math.min(255, value));
                        value /= 255;
                    }
                }
                rgba.push(value);
            }
            return rgba;
        };
        Color.fromRgbaString = function (str) {
            var rgba = Color.stringToRgba(str);
            if (rgba) {
                if (rgba.length === 3) {
                    return new Color(rgba[0], rgba[1], rgba[2]);
                }
                else if (rgba.length === 4) {
                    return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);
                }
            }
            throw new Error("Malformed rgb/rgba color string: '" + str + "'");
        };
        Color.fromArray = function (arr) {
            if (arr.length === 4) {
                return new Color(arr[0], arr[1], arr[2], arr[3]);
            }
            if (arr.length === 3) {
                return new Color(arr[0], arr[1], arr[2]);
            }
            throw new Error('The given array should contain 3 or 4 color components (numbers).');
        };
        Color.fromHSB = function (h, s, b, alpha) {
            if (alpha === void 0) { alpha = 1; }
            var rgb = Color.HSBtoRGB(h, s, b);
            return new Color(rgb[0], rgb[1], rgb[2], alpha);
        };
        Color.padHex = function (str) {
            // Can't use `padStart(2, '0')` here because of IE.
            return str.length === 1 ? '0' + str : str;
        };
        Color.prototype.toHexString = function () {
            var hex = '#'
                + Color.padHex(Math.round(this.r * 255).toString(16))
                + Color.padHex(Math.round(this.g * 255).toString(16))
                + Color.padHex(Math.round(this.b * 255).toString(16));
            if (this.a < 1) {
                hex += Color.padHex(Math.round(this.a * 255).toString(16));
            }
            return hex;
        };
        Color.prototype.toRgbaString = function (fractionDigits) {
            if (fractionDigits === void 0) { fractionDigits = 3; }
            var components = [
                Math.round(this.r * 255),
                Math.round(this.g * 255),
                Math.round(this.b * 255)
            ];
            var k = Math.pow(10, fractionDigits);
            if (this.a !== 1) {
                components.push(Math.round(this.a * k) / k);
                return "rgba(" + components.join(', ') + ")";
            }
            return "rgb(" + components.join(', ') + ")";
        };
        Color.prototype.toString = function () {
            if (this.a === 1) {
                return this.toHexString();
            }
            return this.toRgbaString();
        };
        Color.prototype.toHSB = function () {
            return Color.RGBtoHSB(this.r, this.g, this.b);
        };
        /**
         * Converts the given RGB triple to an array of HSB (HSV) components.
         * The hue component will be `NaN` for achromatic colors.
         */
        Color.RGBtoHSB = function (r, g, b) {
            var min = Math.min(r, g, b);
            var max = Math.max(r, g, b);
            var S = max !== 0 ? (max - min) / max : 0;
            var H = NaN;
            // min == max, means all components are the same
            // and the color is a shade of gray with no hue (H is NaN)
            if (min !== max) {
                var delta = max - min;
                var rc = (max - r) / delta;
                var gc = (max - g) / delta;
                var bc = (max - b) / delta;
                if (r === max) {
                    H = bc - gc;
                }
                else if (g === max) {
                    H = 2.0 + rc - bc;
                }
                else {
                    H = 4.0 + gc - rc;
                }
                H /= 6.0;
                if (H < 0) {
                    H = H + 1.0;
                }
            }
            return [H * 360, S, max];
        };
        /**
         * Converts the given HSB (HSV) triple to an array of RGB components.
         */
        Color.HSBtoRGB = function (H, S, B) {
            if (isNaN(H)) {
                H = 0;
            }
            H = (((H % 360) + 360) % 360) / 360; // normalize hue to [0, 360] interval, then scale to [0, 1]
            var r = 0;
            var g = 0;
            var b = 0;
            if (S === 0) {
                r = g = b = B;
            }
            else {
                var h = (H - Math.floor(H)) * 6;
                var f = h - Math.floor(h);
                var p = B * (1 - S);
                var q = B * (1 - S * f);
                var t = B * (1 - (S * (1 - f)));
                switch (h >> 0) { // discard the floating point part of the number
                    case 0:
                        r = B;
                        g = t;
                        b = p;
                        break;
                    case 1:
                        r = q;
                        g = B;
                        b = p;
                        break;
                    case 2:
                        r = p;
                        g = B;
                        b = t;
                        break;
                    case 3:
                        r = p;
                        g = q;
                        b = B;
                        break;
                    case 4:
                        r = t;
                        g = p;
                        b = B;
                        break;
                    case 5:
                        r = B;
                        g = p;
                        b = q;
                        break;
                }
            }
            return [r, g, b];
        };
        Color.prototype.derive = function (hueShift, saturationFactor, brightnessFactor, opacityFactor) {
            var hsb = Color.RGBtoHSB(this.r, this.g, this.b);
            var b = hsb[2];
            if (b == 0 && brightnessFactor > 1.0) {
                b = 0.05;
            }
            var h = (((hsb[0] + hueShift) % 360) + 360) % 360;
            var s = Math.max(Math.min(hsb[1] * saturationFactor, 1.0), 0.0);
            b = Math.max(Math.min(b * brightnessFactor, 1.0), 0.0);
            var a = Math.max(Math.min(this.a * opacityFactor, 1.0), 0.0);
            var rgba = Color.HSBtoRGB(h, s, b);
            rgba.push(a);
            return Color.fromArray(rgba);
        };
        Color.prototype.brighter = function () {
            return this.derive(0, 1.0, 1.0 / 0.7, 1.0);
        };
        Color.prototype.darker = function () {
            return this.derive(0, 1.0, 0.7, 1.0);
        };
        /**
         * CSS Color Module Level 4:
         * https://drafts.csswg.org/css-color/#named-colors
         */
        Color.nameToHex = Object.freeze({
            aliceblue: '#F0F8FF',
            antiquewhite: '#FAEBD7',
            aqua: '#00FFFF',
            aquamarine: '#7FFFD4',
            azure: '#F0FFFF',
            beige: '#F5F5DC',
            bisque: '#FFE4C4',
            black: '#000000',
            blanchedalmond: '#FFEBCD',
            blue: '#0000FF',
            blueviolet: '#8A2BE2',
            brown: '#A52A2A',
            burlywood: '#DEB887',
            cadetblue: '#5F9EA0',
            chartreuse: '#7FFF00',
            chocolate: '#D2691E',
            coral: '#FF7F50',
            cornflowerblue: '#6495ED',
            cornsilk: '#FFF8DC',
            crimson: '#DC143C',
            cyan: '#00FFFF',
            darkblue: '#00008B',
            darkcyan: '#008B8B',
            darkgoldenrod: '#B8860B',
            darkgray: '#A9A9A9',
            darkgreen: '#006400',
            darkgrey: '#A9A9A9',
            darkkhaki: '#BDB76B',
            darkmagenta: '#8B008B',
            darkolivegreen: '#556B2F',
            darkorange: '#FF8C00',
            darkorchid: '#9932CC',
            darkred: '#8B0000',
            darksalmon: '#E9967A',
            darkseagreen: '#8FBC8F',
            darkslateblue: '#483D8B',
            darkslategray: '#2F4F4F',
            darkslategrey: '#2F4F4F',
            darkturquoise: '#00CED1',
            darkviolet: '#9400D3',
            deeppink: '#FF1493',
            deepskyblue: '#00BFFF',
            dimgray: '#696969',
            dimgrey: '#696969',
            dodgerblue: '#1E90FF',
            firebrick: '#B22222',
            floralwhite: '#FFFAF0',
            forestgreen: '#228B22',
            fuchsia: '#FF00FF',
            gainsboro: '#DCDCDC',
            ghostwhite: '#F8F8FF',
            gold: '#FFD700',
            goldenrod: '#DAA520',
            gray: '#808080',
            green: '#008000',
            greenyellow: '#ADFF2F',
            grey: '#808080',
            honeydew: '#F0FFF0',
            hotpink: '#FF69B4',
            indianred: '#CD5C5C',
            indigo: '#4B0082',
            ivory: '#FFFFF0',
            khaki: '#F0E68C',
            lavender: '#E6E6FA',
            lavenderblush: '#FFF0F5',
            lawngreen: '#7CFC00',
            lemonchiffon: '#FFFACD',
            lightblue: '#ADD8E6',
            lightcoral: '#F08080',
            lightcyan: '#E0FFFF',
            lightgoldenrodyellow: '#FAFAD2',
            lightgray: '#D3D3D3',
            lightgreen: '#90EE90',
            lightgrey: '#D3D3D3',
            lightpink: '#FFB6C1',
            lightsalmon: '#FFA07A',
            lightseagreen: '#20B2AA',
            lightskyblue: '#87CEFA',
            lightslategray: '#778899',
            lightslategrey: '#778899',
            lightsteelblue: '#B0C4DE',
            lightyellow: '#FFFFE0',
            lime: '#00FF00',
            limegreen: '#32CD32',
            linen: '#FAF0E6',
            magenta: '#FF00FF',
            maroon: '#800000',
            mediumaquamarine: '#66CDAA',
            mediumblue: '#0000CD',
            mediumorchid: '#BA55D3',
            mediumpurple: '#9370DB',
            mediumseagreen: '#3CB371',
            mediumslateblue: '#7B68EE',
            mediumspringgreen: '#00FA9A',
            mediumturquoise: '#48D1CC',
            mediumvioletred: '#C71585',
            midnightblue: '#191970',
            mintcream: '#F5FFFA',
            mistyrose: '#FFE4E1',
            moccasin: '#FFE4B5',
            navajowhite: '#FFDEAD',
            navy: '#000080',
            oldlace: '#FDF5E6',
            olive: '#808000',
            olivedrab: '#6B8E23',
            orange: '#FFA500',
            orangered: '#FF4500',
            orchid: '#DA70D6',
            palegoldenrod: '#EEE8AA',
            palegreen: '#98FB98',
            paleturquoise: '#AFEEEE',
            palevioletred: '#DB7093',
            papayawhip: '#FFEFD5',
            peachpuff: '#FFDAB9',
            peru: '#CD853F',
            pink: '#FFC0CB',
            plum: '#DDA0DD',
            powderblue: '#B0E0E6',
            purple: '#800080',
            rebeccapurple: '#663399',
            red: '#FF0000',
            rosybrown: '#BC8F8F',
            royalblue: '#4169E1',
            saddlebrown: '#8B4513',
            salmon: '#FA8072',
            sandybrown: '#F4A460',
            seagreen: '#2E8B57',
            seashell: '#FFF5EE',
            sienna: '#A0522D',
            silver: '#C0C0C0',
            skyblue: '#87CEEB',
            slateblue: '#6A5ACD',
            slategray: '#708090',
            slategrey: '#708090',
            snow: '#FFFAFA',
            springgreen: '#00FF7F',
            steelblue: '#4682B4',
            tan: '#D2B48C',
            teal: '#008080',
            thistle: '#D8BFD8',
            tomato: '#FF6347',
            turquoise: '#40E0D0',
            violet: '#EE82EE',
            wheat: '#F5DEB3',
            white: '#FFFFFF',
            whitesmoke: '#F5F5F5',
            yellow: '#FFFF00',
            yellowgreen: '#9ACD32'
        });
        return Color;
    }());

    function color (a, b) {
        if (typeof a === 'string') {
            try {
                a = Color.fromString(a);
            }
            catch (e) {
                a = Color.fromArray([0, 0, 0]);
            }
        }
        if (typeof b === 'string') {
            try {
                b = Color.fromString(b);
            }
            catch (e) {
                b = Color.fromArray([0, 0, 0]);
            }
        }
        var red = interpolateNumber(a.r, b.r);
        var green = interpolateNumber(a.g, b.g);
        var blue = interpolateNumber(a.b, b.b);
        var alpha = interpolateNumber(a.a, b.a);
        return function (t) {
            return Color.fromArray([red(t), green(t), blue(t), alpha(t)]).toRgbaString();
        };
    }

    function interpolateValue (a, b) {
        var t = typeof b;
        var c;
        if (b == null || t === 'boolean') {
            return constant(b);
        }
        if (t === 'number') {
            return interpolateNumber(a, b);
        }
        if (t === 'string') {
            try {
                c = Color.fromString(b);
                b = c;
                return color(a, b);
            }
            catch (e) {
                // return string(a, b);
            }
        }
        if (b instanceof Color) {
            return color(a, b);
        }
        if (b instanceof Date) {
            return date(a, b);
        }
        if (Array.isArray(b)) {
            return array(a, b);
        }
        if (typeof b.valueOf !== 'function' && typeof b.toString !== 'function' || isNaN(b)) {
            return object(a, b);
        }
        return interpolateNumber(a, b);
    }

    function ascending(a, b) {
        return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
    }

    function bisectRight(list, x, comparator, lo, hi) {
        if (lo === void 0) { lo = 0; }
        if (hi === void 0) { hi = list.length; }
        while (lo < hi) {
            var mid = (lo + hi) >>> 1;
            if (comparator(list[mid], x) > 0) { // list[mid] > x
                hi = mid;
            }
            else {
                lo = mid + 1;
            }
        }
        return lo;
    }
    function complexBisectRight(list, x, map, lo, hi) {
        if (lo === void 0) { lo = 0; }
        if (hi === void 0) { hi = list.length; }
        var comparator = ascendingComparator(map);
        while (lo < hi) {
            var mid = (lo + hi) >>> 1;
            if (comparator(list[mid], x) < 0) {
                lo = mid + 1;
            }
            else {
                hi = mid;
            }
        }
        return lo;
    }
    function ascendingComparator(map) {
        return function (item, x) {
            return ascending(map(item), x);
        };
    }

    var __read$3 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var constant$1 = function (x) { return function () { return x; }; };
    var identity = function (x) { return x; };
    function clamper(domain) {
        var _a;
        var a = domain[0];
        var b = domain[domain.length - 1];
        if (a > b) {
            _a = __read$3([b, a], 2), a = _a[0], b = _a[1];
        }
        return function (x) { return Math.max(a, Math.min(b, x)); };
    }
    var ContinuousScale = /** @class */ (function () {
        function ContinuousScale() {
            /**
             * The output value of the scale for `undefined` or `NaN` input values.
             */
            this.unknown = undefined;
            this.clamper = clamper;
            this._clamp = identity;
            this._domain = [0, 1];
            this._range = [0, 1];
            this.transform = identity; // transforms domain value
            this.untransform = identity; // untransforms domain value
            this._interpolate = interpolateValue;
            this.rescale();
        }
        Object.defineProperty(ContinuousScale.prototype, "clamp", {
            get: function () {
                return this._clamp !== identity;
            },
            set: function (value) {
                this._clamp = value ? this.clamper(this.domain) : identity;
            },
            enumerable: true,
            configurable: true
        });
        ContinuousScale.prototype.setDomain = function (values) {
            this._domain = Array.prototype.map.call(values, function (v) { return +v; });
            if (this._clamp !== identity) {
                this._clamp = this.clamper(this.domain);
            }
            this.rescale();
        };
        ContinuousScale.prototype.getDomain = function () {
            return this._domain.slice();
        };
        Object.defineProperty(ContinuousScale.prototype, "domain", {
            get: function () {
                return this.getDomain();
            },
            set: function (values) {
                this.setDomain(values);
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ContinuousScale.prototype, "range", {
            get: function () {
                return this._range.slice();
            },
            set: function (values) {
                this._range = Array.prototype.slice.call(values);
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ContinuousScale.prototype, "interpolate", {
            get: function () {
                return this._interpolate;
            },
            set: function (value) {
                this._interpolate = value;
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        ContinuousScale.prototype.rescale = function () {
            if (Math.min(this.domain.length, this.range.length) > 2) {
                this.piecewise = this.polymap;
            }
            else {
                this.piecewise = this.bimap;
            }
            this.output = undefined;
            this.input = undefined;
        };
        /**
         * Returns a function that converts `x` in `[a, b]` to `t` in `[0, 1]`. Non-clamping.
         * @param a
         * @param b
         */
        ContinuousScale.prototype.normalize = function (a, b) {
            return (b -= (a = +a))
                ? function (x) { return (x - a) / b; }
                : constant$1(isNaN(b) ? NaN : 0.5);
        };
        ContinuousScale.prototype.bimap = function (domain, range, interpolate) {
            var x0 = domain[0];
            var x1 = domain[1];
            var y0 = range[0];
            var y1 = range[1];
            var xt;
            var ty;
            if (x1 < x0) {
                xt = this.normalize(x1, x0);
                ty = interpolate(y1, y0);
            }
            else {
                xt = this.normalize(x0, x1);
                ty = interpolate(y0, y1);
            }
            return function (x) { return ty(xt(x)); }; // domain value x --> t in [0, 1] --> range value y
        };
        ContinuousScale.prototype.polymap = function (domain, range, interpolate) {
            var _this = this;
            // number of segments in the polylinear scale
            var n = Math.min(domain.length, range.length) - 1;
            if (domain[n] < domain[0]) {
                domain = domain.slice().reverse();
                range = range.slice().reverse();
            }
            // deinterpolators from domain segment value to t
            var dt = Array.from({ length: n }, function (_, i) { return _this.normalize(domain[i], domain[i + 1]); });
            // reinterpolators from t to range segment value
            var tr = Array.from({ length: n }, function (_, i) { return interpolate(range[i], range[i + 1]); });
            return function (x) {
                var i = bisectRight(domain, x, ascending, 1, n) - 1; // Find the domain segment that `x` belongs to.
                // This also tells us which deinterpolator/reinterpolator pair to use.
                return tr[i](dt[i](x));
            };
        };
        ContinuousScale.prototype.convert = function (x, clamper) {
            x = +x;
            if (isNaN(x)) {
                return this.unknown;
            }
            if (!this.output) {
                this.output = this.piecewise(this.domain.map(this.transform), this.range, this.interpolate);
            }
            var clamp = clamper ? clamper(this.domain) : this._clamp;
            return this.output(this.transform(clamp(x)));
        };
        ContinuousScale.prototype.invert = function (y) {
            if (!this.input) {
                this.input = this.piecewise(this.range, this.domain.map(this.transform), interpolateNumber);
            }
            return this._clamp(this.untransform(this.input(y)));
        };
        return ContinuousScale;
    }());

    function formatDefault(x, p) {
        var xs = x.toPrecision(p);
        out: for (var n = xs.length, i = 1, i0 = -1, i1 = 0; i < n; ++i) {
            switch (xs[i]) {
                case '.':
                    i0 = i1 = i;
                    break;
                case '0':
                    if (i0 === 0)
                        i0 = i;
                    i1 = i;
                    break;
                case 'e': break out;
                default:
                    if (i0 > 0)
                        i0 = 0;
                    break;
            }
        }
        return i0 > 0 ? xs.slice(0, i0) + xs.slice(i1 + 1) : xs;
    }
    var formatTypes = {
        '': formatDefault,
        // Multiply by 100, and then decimal notation with a percent sign.
        '%': function (x, p) { return (x * 100).toFixed(p); },
        // Binary notation, rounded to integer.
        'b': function (x) { return Math.round(x).toString(2); },
        // Converts the integer to the corresponding unicode character before printing.
        'c': function (x) { return String(x); },
        // Decimal notation, rounded to integer.
        'd': formatDecimal,
        // Exponent notation.
        'e': function (x, p) { return x.toExponential(p); },
        // Fixed point notation.
        'f': function (x, p) { return x.toFixed(p); },
        // Either decimal or exponent notation, rounded to significant digits.
        'g': function (x, p) { return x.toPrecision(p); },
        // Octal notation, rounded to integer.
        'o': function (x) { return Math.round(x).toString(8); },
        // Multiply by 100, round to significant digits, and then decimal notation with a percent sign.
        'p': function (x, p) { return formatRounded(x * 100, p); },
        // Decimal notation, rounded to significant digits.
        'r': formatRounded,
        // Decimal notation with a SI prefix, rounded to significant digits.
        's': formatPrefixAuto,
        // Hexadecimal notation, using upper-case letters, rounded to integer.
        'X': function (x) { return Math.round(x).toString(16).toUpperCase(); },
        // Hexadecimal notation, using lower-case letters, rounded to integer.
        'x': function (x) { return Math.round(x).toString(16); }
    };
    var prefixes = ['y', 'z', 'a', 'f', 'p', 'n', '\xB5', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
    /**
     * [[fill]align][sign][#][0][width][grouping_option][.precision][type]
     */
    var FormatSpecifier = /** @class */ (function () {
        function FormatSpecifier(specifier) {
            if (specifier instanceof FormatSpecifier) {
                this.fill = specifier.fill;
                this.align = specifier.align;
                this.sign = specifier.sign;
                this.symbol = specifier.symbol;
                this.zero = specifier.zero;
                this.width = specifier.width;
                this.comma = specifier.comma;
                this.precision = specifier.precision;
                this.trim = specifier.trim;
                this.type = specifier.type;
                this.string = specifier.string;
            }
            else {
                this.fill = specifier.fill === undefined ? ' ' : String(specifier.fill);
                this.align = specifier.align === undefined ? '>' : String(specifier.align);
                this.sign = specifier.sign === undefined ? '-' : String(specifier.sign);
                this.symbol = specifier.symbol === undefined ? '' : String(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 ? '' : String(specifier.type);
                this.string = specifier.string;
            }
        }
        return FormatSpecifier;
    }());
    // [[fill]align][sign][symbol][0][width][,][.precision][~][type]
    var formatRegEx = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
    var interpolateRegEx = /(#\{(.*?)\})/g;
    function makeFormatSpecifier(specifier) {
        if (specifier instanceof FormatSpecifier) {
            return new FormatSpecifier(specifier);
        }
        var found = false;
        var string = specifier.replace(interpolateRegEx, function () {
            if (!found) {
                specifier = arguments[2];
                found = true;
            }
            return '#{}';
        });
        var match = formatRegEx.exec(specifier);
        if (!match) {
            throw new Error("Invalid format: " + specifier);
        }
        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],
            string: found ? string : undefined
        });
    }
    function tickFormat(start, stop, count, specifier) {
        var step = tickStep(start, stop, count);
        var formatSpecifier = makeFormatSpecifier(specifier == undefined ? ',f' : specifier);
        var precision;
        switch (formatSpecifier.type) {
            case 's': {
                var value = Math.max(Math.abs(start), Math.abs(stop));
                if (formatSpecifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) {
                    formatSpecifier.precision = precision;
                }
                return formatPrefix(formatSpecifier, value);
            }
            case '':
            case 'e':
            case 'g':
            case 'p':
            case 'r': {
                if (formatSpecifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) {
                    formatSpecifier.precision = precision - +(formatSpecifier.type === 'e');
                }
                break;
            }
            case 'f':
            case '%': {
                if (formatSpecifier.precision == null && !isNaN(precision = precisionFixed(step))) {
                    formatSpecifier.precision = precision - +(formatSpecifier.type === '%') * 2;
                }
                break;
            }
        }
        return format(formatSpecifier);
    }
    var prefixExponent;
    function formatPrefixAuto(x, p) {
        if (p === void 0) { p = 0; }
        var d = formatDecimalParts(x, p);
        if (!d) {
            return String(x);
        }
        var coefficient = d[0];
        var exponent = d[1];
        prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3;
        var i = exponent - prefixExponent + 1;
        var n = coefficient.length;
        if (i === n) {
            return coefficient;
        }
        else {
            if (i > n) {
                return coefficient + new Array(i - n + 1).join('0');
            }
            if (i > 0) {
                return coefficient.slice(0, i) + '.' + coefficient.slice(i);
            }
            else {
                var parts = formatDecimalParts(x, Math.max(0, p + i - 1));
                return '0.' + new Array(1 - i).join('0') + parts[0]; // less than 1y!
            }
        }
    }
    function formatDecimal(x) {
        return Math.abs(x = Math.round(x)) >= 1e21
            ? x.toLocaleString('en').replace(/,/g, '')
            : x.toString(10);
    }
    function formatGroup(grouping, thousands) {
        return function (value, width) {
            var t = [];
            var i = value.length;
            var j = 0;
            var g = grouping[0];
            var 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);
        };
    }
    function formatNumerals(numerals) {
        return function (value) { return value.replace(/[0-9]/g, function (i) { return numerals[+i]; }); };
    }
    // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
    function formatTrim(s) {
        out: for (var n = s.length, i = 1, i0 = -1, i1 = 0; 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;
    }
    function formatRounded(x, p) {
        var d = formatDecimalParts(x, p);
        if (!d) {
            return String(x);
        }
        var coefficient = d[0];
        var exponent = d[1];
        if (exponent < 0) {
            return '0.' + new Array(-exponent).join('0') + coefficient;
        }
        else {
            if (coefficient.length > exponent + 1) {
                return coefficient.slice(0, exponent + 1) + '.' + coefficient.slice(exponent + 1);
            }
            else {
                return coefficient + new Array(exponent - coefficient.length + 2).join('0');
            }
        }
    }
    // 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) {
        var sx = p ? x.toExponential(p - 1) : x.toExponential();
        var i = sx.indexOf('e');
        if (i < 0) { // NaN, ±Infinity
            return undefined;
        }
        var coefficient = sx.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,
            +sx.slice(i + 1)
        ];
    }
    function identity$1(x) {
        return x;
    }
    var formatDefaultLocale;
    var format;
    var formatPrefix;
    defaultLocale({
        thousands: ',',
        grouping: [3],
        currency: ['$', '']
    });
    function defaultLocale(definition) {
        formatDefaultLocale = formatLocale(definition);
        format = formatDefaultLocale.format;
        formatPrefix = formatDefaultLocale.formatPrefix;
    }
    function exponent(x) {
        var parts = formatDecimalParts(Math.abs(x));
        if (parts) {
            return parts[1];
        }
        return NaN;
    }
    function precisionFixed(step) {
        return Math.max(0, -exponent(Math.abs(step)));
    }
    function precisionPrefix(step, value) {
        var x = Math.floor(exponent(value) / 3);
        x = Math.min(8, x);
        x = Math.max(-8, x);
        return Math.max(0, x * 3 - exponent(Math.abs(step)));
    }
    function precisionRound(step, max) {
        step = Math.abs(step);
        max = Math.abs(max) - step;
        return Math.max(0, exponent(max) - exponent(step)) + 1;
    }
    function formatLocale(locale) {
        var group = locale.grouping === undefined || locale.thousands === undefined
            ? identity$1
            : formatGroup(Array.prototype.map.call(locale.grouping, Number), String(locale.thousands));
        var currencyPrefix = locale.currency === undefined ? '' : String(locale.currency[0]);
        var currencySuffix = locale.currency === undefined ? '' : String(locale.currency[1]);
        var decimal = locale.decimal === undefined ? '.' : String(locale.decimal);
        var numerals = locale.numerals === undefined
            ? identity$1
            : formatNumerals(Array.prototype.map.call(locale.numerals, String));
        var percent = locale.percent === undefined ? '%' : String(locale.percent);
        var minus = locale.minus === undefined ? '\u2212' : String(locale.minus);
        var nan = locale.nan === undefined ? 'NaN' : String(locale.nan);
        function newFormat(specifier) {
            var formatSpecifier = makeFormatSpecifier(specifier);
            var fill = formatSpecifier.fill;
            var align = formatSpecifier.align;
            var sign = formatSpecifier.sign;
            var symbol = formatSpecifier.symbol;
            var zero = formatSpecifier.zero;
            var width = formatSpecifier.width;
            var comma = formatSpecifier.comma;
            var precision = formatSpecifier.precision;
            var trim = formatSpecifier.trim;
            var type = formatSpecifier.type;
            // The 'n' type is an alias for ',g'.
            if (type === 'n') {
                comma = true;
                type = 'g';
            }
            else if (!formatTypes[type]) { // The '' type, and any invalid type, is an alias for '.12~g'.
                if (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() : '';
            var 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];
            var 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].
            if (precision === undefined) {
                precision = 6;
            }
            else if (/[gprs]/.test(type)) {
                precision = Math.max(1, Math.min(21, precision));
            }
            else {
                precision = Math.max(0, Math.min(20, precision));
            }
            function format(x) {
                var valuePrefix = prefix;
                var valueSuffix = suffix;
                var value;
                if (type === 'c') {
                    valueSuffix = formatType(+x) + valueSuffix;
                    value = '';
                }
                else {
                    var nx = +x;
                    // Determine the sign. -0 is not less than 0, but 1 / -0 is!
                    var valueNegative = x < 0 || 1 / nx < 0;
                    // Perform the initial formatting.
                    value = isNaN(nx) ? nan : formatType(Math.abs(nx), 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.
                    var signPrefix = valueNegative
                        ? (sign === '(' ? sign : minus)
                        : (sign === '-' || sign === '(' ? '' : sign);
                    var signSuffix = valueNegative && sign === '(' ? ')' : '';
                    valuePrefix = signPrefix + valuePrefix;
                    valueSuffix = (type === 's' ? prefixes[8 + prefixExponent / 3] : '') + valueSuffix + signSuffix;
                    // Break the formatted value into the integer “value” part that can be
                    // grouped, and fractional or exponential “suffix” part that is not.
                    if (maybeSuffix) {
                        for (var i = 0, n = value.length; i < n; i++) {
                            var c = value.charCodeAt(i);
                            if (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;
                var 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;
                }
                var string = formatSpecifier.string;
                if (string) {
                    return string.replace(interpolateRegEx, function () { return numerals(value); });
                }
                return numerals(value);
            }
            return format;
        }
        function formatPrefix(specifier, value) {
            var formatSpecifier = makeFormatSpecifier(specifier);
            formatSpecifier.type = 'f';
            var f = newFormat(formatSpecifier);
            var e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3;
            var k = Math.pow(10, -e);
            var prefix = prefixes[8 + e / 3];
            return function (value) {
                return f(k * +value) + prefix;
            };
        }
        return {
            format: newFormat,
            formatPrefix: formatPrefix
        };
    }

    var __extends$5 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    /**
     * Maps continuous domain to a continuous range.
     */
    var LinearScale = /** @class */ (function (_super) {
        __extends$5(LinearScale, _super);
        function LinearScale() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.type = 'linear';
            return _this;
        }
        LinearScale.prototype.ticks = function (count) {
            if (count === void 0) { count = 10; }
            var d = this._domain;
            return ticks(d[0], d[d.length - 1], count);
        };
        /**
         * Extends the domain so that it starts and ends on nice round values.
         * @param count Tick count.
         */
        LinearScale.prototype.nice = function (count) {
            if (count === void 0) { count = 10; }
            var d = this.domain;
            var i0 = 0;
            var i1 = d.length - 1;
            var start = d[i0];
            var stop = d[i1];
            var step;
            if (stop < start) {
                step = start;
                start = stop;
                stop = step;
                step = i0;
                i0 = i1;
                i1 = step;
            }
            step = tickIncrement(start, stop, count);
            if (step > 0) {
                start = Math.floor(start / step) * step;
                stop = Math.ceil(stop / step) * step;
                step = tickIncrement(start, stop, count);
            }
            else if (step < 0) {
                start = Math.ceil(start * step) / step;
                stop = Math.floor(stop * step) / step;
                step = tickIncrement(start, stop, count);
            }
            if (step > 0) {
                d[i0] = Math.floor(start / step) * step;
                d[i1] = Math.ceil(stop / step) * step;
                this.domain = d;
            }
            else if (step < 0) {
                d[i0] = Math.ceil(start * step) / step;
                d[i1] = Math.floor(stop * step) / step;
                this.domain = d;
            }
        };
        LinearScale.prototype.tickFormat = function (count, specifier) {
            var d = this.domain;
            return tickFormat(d[0], d[d.length - 1], count == undefined ? 10 : count, specifier);
        };
        return LinearScale;
    }(ContinuousScale));

    var __values = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    // Custom `Array.find` implementation for legacy browsers.
    function find(arr, predicate) {
        for (var i = 0; i < arr.length; i++) {
            var value = arr[i];
            if (predicate(value, i, arr)) {
                return value;
            }
        }
    }
    function findIndex(arr, predicate) {
        for (var i = 0; i < arr.length; i++) {
            if (predicate(arr[i], i, arr)) {
                return i;
            }
        }
        return -1;
    }
    function identity$2(value) {
        return value;
    }
    function extent(values, predicate, map) {
        var transform = map || identity$2;
        var n = values.length;
        var i = -1;
        var value;
        var min;
        var max;
        while (++i < n) { // Find the first value.
            value = values[i];
            if (predicate(value)) {
                min = max = value;
                while (++i < n) { // Compare the remaining values.
                    value = values[i];
                    if (predicate(value)) {
                        if (min > value) {
                            min = value;
                        }
                        if (max < value) {
                            max = value;
                        }
                    }
                }
            }
        }
        return min === undefined || max === undefined ? undefined : [transform(min), transform(max)];
    }
    /**
     * finds the min and max using a process appropriate for stacked values. Ie,
     * summing up the positive and negative numbers, and returning the totals of each
     */
    function findMinMax(values) {
        var e_1, _a;
        var min = 0;
        var max = 0;
        try {
            for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {
                var value = values_1_1.value;
                if (value < 0) {
                    min += value;
                }
                else {
                    max += value;
                }
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        return { min: min, max: max };
    }
    function copy(array, start, count) {
        if (start === void 0) { start = 0; }
        if (count === void 0) { count = array.length; }
        var result = [];
        var n = array.length;
        if (n) {
            for (var i = 0; i < count; i++) {
                result.push(array[(start + i) % n]);
            }
        }
        return result;
    }

    // Simplified version of https://github.com/plotly/fast-isnumeric
    // that doesn't treat number strings with leading/trailing whitespace as numbers.
    function isNumber(value) {
        var type = typeof value;
        if (type === 'string') {
            return false;
        }
        else if (type !== 'number') {
            return false;
        }
        // value - value is going to be:
        // - zero, for any finite number
        // -  NaN, for NaN, Infinity, -Infinity
        return value - value < 1;
    }
    function isNumberObject(value) {
        return !!value && value.hasOwnProperty('valueOf') && isNumber(value.valueOf());
    }
    function isNumeric(value) {
        return isNumber(value) || isNumberObject(value);
    }
    function isDate(value) {
        return value instanceof Date && !isNaN(+value);
    }
    function isString(value) {
        return typeof value === 'string';
    }
    function isStringObject(value) {
        return !!value && value.hasOwnProperty('toString') && isString(value.toString());
    }
    function isDiscrete(value) {
        return isString(value) || isStringObject(value);
    }
    function isContinuous(value) {
        return isNumeric(value) || isDate(value);
    }

    var __extends$6 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Group = /** @class */ (function (_super) {
        __extends$6(Group, _super);
        function Group() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.isContainerNode = true;
            _this._opacity = 1;
            return _this;
        }
        Object.defineProperty(Group.prototype, "opacity", {
            get: function () {
                return this._opacity;
            },
            set: function (value) {
                value = Math.min(1, Math.max(0, value));
                if (this._opacity !== value) {
                    this._opacity = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        // We consider a group to be boundless, thus any point belongs to it.
        Group.prototype.containsPoint = function (x, y) {
            return true;
        };
        Group.prototype.computeBBox = function () {
            var left = Infinity;
            var right = -Infinity;
            var top = Infinity;
            var bottom = -Infinity;
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            this.children.forEach(function (child) {
                if (!child.visible) {
                    return;
                }
                var bbox = child.computeBBox();
                if (!bbox) {
                    return;
                }
                if (!(child instanceof Group)) {
                    if (child.dirtyTransform) {
                        child.computeTransformMatrix();
                    }
                    var matrix = Matrix.flyweight(child.matrix);
                    var parent_1 = child.parent;
                    while (parent_1) {
                        matrix.preMultiplySelf(parent_1.matrix);
                        parent_1 = parent_1.parent;
                    }
                    matrix.transformBBox(bbox, 0, bbox);
                }
                var x = bbox.x;
                var y = bbox.y;
                if (x < left) {
                    left = x;
                }
                if (y < top) {
                    top = y;
                }
                if (x + bbox.width > right) {
                    right = x + bbox.width;
                }
                if (y + bbox.height > bottom) {
                    bottom = y + bbox.height;
                }
            });
            return new BBox(left, top, right - left, bottom - top);
        };
        Group.prototype.render = function (ctx) {
            // A group can have `scaling`, `rotation`, `translation` properties
            // that are applied to the canvas context before children are rendered,
            // so all children can be transformed at once.
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            this.matrix.toContext(ctx);
            var children = this.children;
            var n = children.length;
            ctx.globalAlpha *= this.opacity;
            if (this.dirtyZIndex) {
                this.dirtyZIndex = false;
                children.sort(function (a, b) { return a.zIndex - b.zIndex; });
            }
            for (var i = 0; i < n; i++) {
                var child = children[i];
                if (child.visible) {
                    ctx.save();
                    child.render(ctx);
                    ctx.restore();
                }
            }
            // debug
            // this.computeBBox().render(ctx, {
            //     label: this.id,
            //     resetTransform: true,
            //     fillStyle: 'rgba(0, 0, 0, 0.5)'
            // });
        };
        Group.className = 'Group';
        return Group;
    }(Node));

    var EnterNode = /** @class */ (function () {
        function EnterNode(parent, datum) {
            this.next = null;
            this.scene = parent.scene;
            this.parent = parent;
            this.datum = datum;
        }
        EnterNode.prototype.appendChild = function (node) {
            // This doesn't work without the `strict: true` in the `tsconfig.json`,
            // so we must have two `if` checks below, instead of this single one.
            // if (this.next && !Node.isNode(this.next)) {
            //     throw new Error(`${this.next} is not a Node.`);
            // }
            if (this.next === null) {
                return this.parent.insertBefore(node, null);
            }
            if (!Node.isNode(this.next)) {
                throw new Error(this.next + " is not a Node.");
            }
            return this.parent.insertBefore(node, this.next);
        };
        EnterNode.prototype.insertBefore = function (node, nextNode) {
            return this.parent.insertBefore(node, nextNode);
        };
        return EnterNode;
    }());
    /**
     * G - type of the selected node(s).
     * GDatum - type of the datum of the selected node(s).
     * P - type of the parent node(s).
     * PDatum - type of the datum of the parent node(s).
     */
    var Selection = /** @class */ (function () {
        function Selection(groups, parents) {
            this.groups = groups;
            this.parents = parents;
        }
        Selection.select = function (node) {
            return new Selection([[typeof node === 'function' ? node() : node]], [undefined]);
        };
        Selection.selectAll = function (nodes) {
            return new Selection([nodes == null ? [] : nodes], [undefined]);
        };
        /**
         * Creates new nodes, appends them to the nodes of this selection and returns them
         * as a new selection. The created nodes inherit the datums and the parents of the nodes
         * they replace.
         * @param Class The constructor function to use to create the new nodes.
         */
        Selection.prototype.append = function (Class) {
            return this.select(function (node) {
                return node.appendChild(new Class());
            });
        };
        /**
         * Same as the {@link append}, but accepts a custom creator function with the
         * {@link NodeSelector} signature rather than a constructor function.
         * @param creator
         */
        Selection.prototype.appendFn = function (creator) {
            return this.select(function (node, data, index, group) {
                return node.appendChild(creator(node, data, index, group));
            });
        };
        /**
         * Runs the given selector that returns a single node for every node in each group.
         * The original nodes are then replaced by the nodes returned by the selector
         * and returned as a new selection.
         * The selected nodes inherit the datums and the parents of the original nodes.
         */
        Selection.prototype.select = function (selector) {
            var groups = this.groups;
            var numGroups = groups.length;
            var subgroups = [];
            for (var j = 0; j < numGroups; j++) {
                var group = groups[j];
                var groupSize = group.length;
                var subgroup = subgroups[j] = new Array(groupSize);
                for (var i = 0; i < groupSize; i++) {
                    var node = group[i];
                    if (node) {
                        var subnode = selector(node, node.datum, i, group);
                        if (subnode) {
                            subnode.datum = node.datum;
                        }
                        subgroup[i] = subnode;
                    }
                    // else this can be a group of the `enter` selection,
                    // for example, with no nodes at the i-th position,
                    // only nodes at the end of the group
                }
            }
            return new Selection(subgroups, this.parents);
        };
        /**
         * Same as {@link select}, but uses the given {@param Class} (constructor) as a selector.
         * @param Class The constructor function to use to find matching nodes.
         */
        Selection.prototype.selectByClass = function (Class) {
            return this.select(function (node) {
                if (Node.isNode(node)) {
                    var children = node.children;
                    var n = children.length;
                    for (var i = 0; i < n; i++) {
                        var child = children[i];
                        if (child instanceof Class) {
                            return child;
                        }
                    }
                }
            });
        };
        Selection.prototype.selectByTag = function (tag) {
            return this.select(function (node) {
                if (Node.isNode(node)) {
                    var children = node.children;
                    var n = children.length;
                    for (var i = 0; i < n; i++) {
                        var child = children[i];
                        if (child.tag === tag) {
                            return child;
                        }
                    }
                }
            });
        };
        Selection.prototype.selectAllByClass = function (Class) {
            return this.selectAll(function (node) {
                var nodes = [];
                if (Node.isNode(node)) {
                    var children = node.children;
                    var n = children.length;
                    for (var i = 0; i < n; i++) {
                        var child = children[i];
                        if (child instanceof Class) {
                            nodes.push(child);
                        }
                    }
                }
                return nodes;
            });
        };
        Selection.prototype.selectAllByTag = function (tag) {
            return this.selectAll(function (node) {
                var nodes = [];
                if (Node.isNode(node)) {
                    var children = node.children;
                    var n = children.length;
                    for (var i = 0; i < n; i++) {
                        var child = children[i];
                        if (child.tag === tag) {
                            nodes.push(child);
                        }
                    }
                }
                return nodes;
            });
        };
        Selection.prototype.selectNone = function () {
            return [];
        };
        /**
         * Runs the given selector that returns a group of nodes for every node in each group.
         * The original nodes are then replaced by the groups of nodes returned by the selector
         * and returned as a new selection. The original nodes become the parent nodes for each
         * group in the new selection. The selected nodes do not inherit the datums of the original nodes.
         * If called without any parameters, creates a new selection with an empty group for each
         * node in this selection.
         */
        Selection.prototype.selectAll = function (selectorAll) {
            if (!selectorAll) {
                selectorAll = this.selectNone;
            }
            // Each subgroup is populated with the selector (run on each group node) results.
            var subgroups = [];
            // In the new selection that we return, subgroups become groups,
            // and group nodes become parents.
            var parents = [];
            var groups = this.groups;
            var groupCount = groups.length;
            for (var j = 0; j < groupCount; j++) {
                var group = groups[j];
                var groupLength = group.length;
                for (var i = 0; i < groupLength; i++) {
                    var node = group[i];
                    if (node) {
                        subgroups.push(selectorAll(node, node.datum, i, group));
                        parents.push(node);
                    }
                }
            }
            return new Selection(subgroups, parents);
        };
        /**
         * Runs the given callback for every node in this selection and returns this selection.
         * @param cb
         */
        Selection.prototype.each = function (cb) {
            var groups = this.groups;
            var numGroups = groups.length;
            for (var j = 0; j < numGroups; j++) {
                var group = groups[j];
                var groupSize = group.length;
                for (var i = 0; i < groupSize; i++) {
                    var node = group[i];
                    if (node) {
                        cb(node, node.datum, i, group);
                    }
                }
            }
            return this;
        };
        Selection.prototype.remove = function () {
            return this.each(function (node) {
                if (Node.isNode(node)) {
                    var parent_1 = node.parent;
                    if (parent_1) {
                        parent_1.removeChild(node);
                    }
                }
            });
        };
        Selection.prototype.merge = function (other) {
            var groups0 = this.groups;
            var groups1 = other.groups;
            var m0 = groups0.length;
            var m1 = groups1.length;
            var m = Math.min(m0, m1);
            var merges = new Array(m0);
            var j = 0;
            for (; j < m; j++) {
                var group0 = groups0[j];
                var group1 = groups1[j];
                var n = group0.length;
                var merge = merges[j] = new Array(n);
                for (var i = 0; i < n; i++) {
                    var node = group0[i] || group1[i];
                    merge[i] = node || undefined;
                }
            }
            for (; j < m0; j++) {
                merges[j] = groups0[j];
            }
            return new Selection(merges, this.parents);
        };
        /**
         * Return the first non-null element in this selection.
         * If the selection is empty, returns null.
         */
        Selection.prototype.node = function () {
            var groups = this.groups;
            var numGroups = groups.length;
            for (var j = 0; j < numGroups; j++) {
                var group = groups[j];
                var groupSize = group.length;
                for (var i = 0; i < groupSize; i++) {
                    var node = group[i];
                    if (node) {
                        return node;
                    }
                }
            }
            return null;
        };
        Selection.prototype.attr = function (name, value) {
            this.each(function (node) {
                node[name] = value;
            });
            return this;
        };
        Selection.prototype.attrFn = function (name, value) {
            this.each(function (node, datum, index, group) {
                node[name] = value(node, datum, index, group);
            });
            return this;
        };
        /**
         * Invokes the given function once, passing in this selection.
         * Returns this selection. Facilitates method chaining.
         * @param cb
         */
        Selection.prototype.call = function (cb) {
            cb(this);
            return this;
        };
        Object.defineProperty(Selection.prototype, "size", {
            /**
             * Returns the total number of nodes in this selection.
             */
            get: function () {
                var size = 0;
                this.each(function () { return size++; });
                return size;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Selection.prototype, "data", {
            /**
             * Returns the array of data for the selected elements.
             */
            get: function () {
                var data = [];
                this.each(function (_, datum) { return data.push(datum); });
                return data;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Selection.prototype, "enter", {
            get: function () {
                return new Selection(this.enterGroups ? this.enterGroups : [[]], this.parents);
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Selection.prototype, "exit", {
            get: function () {
                return new Selection(this.exitGroups ? this.exitGroups : [[]], this.parents);
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Binds the given value to each selected node and returns this selection
         * with its {@link GDatum} type changed to the type of the given value.
         * This method doesn't compute a join and doesn't affect indexes or the enter and exit selections.
         * This method can also be used to clear bound data.
         * @param value
         */
        Selection.prototype.setDatum = function (value) {
            return this.each(function (node) {
                node.datum = value;
            });
        };
        Object.defineProperty(Selection.prototype, "datum", {
            /**
             * Returns the bound datum for the first non-null element in the selection.
             * This is generally useful only if you know the selection contains exactly one element.
             */
            get: function () {
                var node = this.node();
                return node ? node.datum : null;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Binds the specified array of values with the selected nodes, returning a new selection
         * that represents the _update_ selection: the nodes successfully bound to the values.
         * Also defines the {@link enter} and {@link exit} selections on the returned selection,
         * which can be used to add or remove the nodes to correspond to the new data.
         * The `values` is an array of values of a particular type, or a function that returns
         * an array of values for each group.
         * When values are assigned to the nodes, they are stored in the {@link Node.datum} property.
         * @param values
         * @param key
         */
        Selection.prototype.setData = function (values, key) {
            if (typeof values !== 'function') {
                var data_1 = values;
                values = function () { return data_1; };
            }
            var groups = this.groups;
            var parents = this.parents;
            var numGroups = groups.length;
            var updateGroups = new Array(numGroups);
            var enterGroups = new Array(numGroups);
            var exitGroups = new Array(numGroups);
            for (var j = 0; j < numGroups; j++) {
                var group = groups[j];
                var parent_2 = parents[j];
                if (!parent_2) {
                    throw new Error("Group #" + j + " has no parent: " + group);
                }
                var groupSize = group.length;
                var data = values(parent_2, parent_2.datum, j, parents);
                var dataSize = data.length;
                var enterGroup = enterGroups[j] = new Array(dataSize);
                var updateGroup = updateGroups[j] = new Array(dataSize);
                var exitGroup = exitGroups[j] = new Array(groupSize);
                if (key) {
                    this.bindKey(parent_2, group, enterGroup, updateGroup, exitGroup, data, key);
                }
                else {
                    this.bindIndex(parent_2, group, enterGroup, updateGroup, exitGroup, data);
                }
                // Now connect the enter nodes to their following update node, such that
                // appendChild can insert the materialized enter node before this node,
                // rather than at the end of the parent node.
                for (var i0 = 0, i1 = 0; i0 < dataSize; i0++) {
                    var previous = enterGroup[i0];
                    if (previous) {
                        if (i0 >= i1) {
                            i1 = i0 + 1;
                        }
                        var next = void 0;
                        while (!(next = updateGroup[i1]) && i1 < dataSize) {
                            i1++;
                        }
                        previous.next = next || null;
                    }
                }
            }
            var result = new Selection(updateGroups, parents);
            result.enterGroups = enterGroups;
            result.exitGroups = exitGroups;
            return result;
        };
        Selection.prototype.bindIndex = function (parent, group, enter, update, exit, data) {
            var groupSize = group.length;
            var dataSize = data.length;
            var i = 0;
            for (; i < dataSize; i++) {
                var node = group[i];
                if (node) {
                    node.datum = data[i];
                    update[i] = node;
                }
                else { // more datums than group nodes
                    enter[i] = new EnterNode(parent, data[i]);
                }
            }
            // more group nodes than datums
            for (; i < groupSize; i++) {
                var node = group[i];
                if (node) {
                    exit[i] = node;
                }
            }
        };
        Selection.prototype.bindKey = function (parent, group, enter, update, exit, data, key) {
            var groupSize = group.length;
            var dataSize = data.length;
            var keyValues = new Array(groupSize);
            var nodeByKeyValue = {};
            // Compute the key for each node.
            // If multiple nodes have the same key, the duplicates are added to exit.
            for (var i = 0; i < groupSize; i++) {
                var node = group[i];
                if (node) {
                    var keyValue = keyValues[i] = Selection.keyPrefix + key(node, node.datum, i, group);
                    if (keyValue in nodeByKeyValue) {
                        exit[i] = node;
                    }
                    else {
                        nodeByKeyValue[keyValue] = node;
                    }
                }
            }
            // Compute the key for each datum.
            // If there is a node associated with this key, join and add it to update.
            // If there is not (or the key is a duplicate), add it to enter.
            for (var i = 0; i < dataSize; i++) {
                var keyValue = Selection.keyPrefix + key(parent, data[i], i, data);
                var node = nodeByKeyValue[keyValue];
                if (node) {
                    update[i] = node;
                    node.datum = data[i];
                    nodeByKeyValue[keyValue] = undefined;
                }
                else {
                    enter[i] = new EnterNode(parent, data[i]);
                }
            }
            // Add any remaining nodes that were not bound to data to exit.
            for (var i = 0; i < groupSize; i++) {
                var node = group[i];
                if (node && (nodeByKeyValue[keyValues[i]] === node)) {
                    exit[i] = node;
                }
            }
        };
        Selection.keyPrefix = '$'; // Protect against keys like '__proto__'.
        return Selection;
    }());

    var __extends$7 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Line = /** @class */ (function (_super) {
        __extends$7(Line, _super);
        function Line() {
            var _this = _super.call(this) || this;
            _this._x1 = 0;
            _this._y1 = 0;
            _this._x2 = 0;
            _this._y2 = 0;
            _this.restoreOwnStyles();
            return _this;
        }
        Object.defineProperty(Line.prototype, "x1", {
            get: function () {
                // TODO: Investigate getter performance further in the context
                //       of the scene graph.
                //       In isolated benchmarks using a getter has the same
                //       performance as a direct property access in Firefox 64.
                //       But in Chrome 71 the getter is 60% slower than direct access.
                //       Direct read is 4.5+ times slower in Chrome than it is in Firefox.
                //       Property access and direct read have the same performance
                //       in Safari 12, which is 2+ times faster than Firefox at this.
                // https://jsperf.com/es5-getters-setters-versus-getter-setter-methods/18
                // This is a know Chrome issue. They say it's not a regression, since
                // the behavior is observed since M60, but jsperf.com history shows the
                // 10x slowdown happened between Chrome 48 and Chrome 57.
                // https://bugs.chromium.org/p/chromium/issues/detail?id=908743
                return this._x1;
            },
            set: function (value) {
                if (this._x1 !== value) {
                    this._x1 = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Line.prototype, "y1", {
            get: function () {
                return this._y1;
            },
            set: function (value) {
                if (this._y1 !== value) {
                    this._y1 = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Line.prototype, "x2", {
            get: function () {
                return this._x2;
            },
            set: function (value) {
                if (this._x2 !== value) {
                    this._x2 = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Line.prototype, "y2", {
            get: function () {
                return this._y2;
            },
            set: function (value) {
                if (this._y2 !== value) {
                    this._y2 = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Line.prototype.computeBBox = function () {
            return new BBox(this.x1, this.y1, this.x2 - this.x1, this.y2 - this.y1);
        };
        Line.prototype.isPointInPath = function (x, y) {
            return false;
        };
        Line.prototype.isPointInStroke = function (x, y) {
            return false;
        };
        Line.prototype.render = function (ctx) {
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            this.matrix.toContext(ctx);
            var x1 = this.x1;
            var y1 = this.y1;
            var x2 = this.x2;
            var y2 = this.y2;
            // Align to the pixel grid if the line is strictly vertical
            // or horizontal (but not both, i.e. a dot).
            if (x1 === x2) {
                var x = Math.round(x1) + Math.floor(this.strokeWidth) % 2 / 2;
                x1 = x;
                x2 = x;
            }
            else if (y1 === y2) {
                var y = Math.round(y1) + Math.floor(this.strokeWidth) % 2 / 2;
                y1 = y;
                y2 = y;
            }
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            this.fillStroke(ctx);
            this.dirty = false;
        };
        Line.className = 'Line';
        Line.defaultStyles = chainObjects(Shape.defaultStyles, {
            fill: undefined,
            strokeWidth: 1
        });
        return Line;
    }(Shape));

    // @ts-ignore Suppress tsc error: Property 'sign' does not exist on type 'Math'
    var sign = Math.sign ? Math.sign : function (x) {
        x = +x;
        if (x === 0 || isNaN(x)) {
            return x;
        }
        return x > 0 ? 1 : -1;
    };
    /**
     * Finds the roots of a parametric linear equation in `t`,
     * where `t` lies in the interval of `[0,1]`.
     */
    function linearRoot(a, b) {
        var t = -b / a;
        return (a !== 0 && t >= 0 && t <= 1) ? [t] : [];
    }
    /**
     * Finds the roots of a parametric quadratic equation in `t`,
     * where `t` lies in the interval of `[0,1]`.
     */
    function quadraticRoots(a, b, c) {
        if (a === 0) {
            return linearRoot(b, c);
        }
        var D = b * b - 4 * a * c; // The polynomial's discriminant.
        var roots = [];
        if (D === 0) { // A single real root.
            var t = -b / (2 * a);
            if (t >= 0 && t <= 1) {
                roots.push(t);
            }
        }
        else if (D > 0) { // A pair of distinct real roots.
            var rD = Math.sqrt(D);
            var t1 = (-b - rD) / (2 * a);
            var t2 = (-b + rD) / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots.push(t1);
            }
            if (t2 >= 0 && t2 <= 1) {
                roots.push(t2);
            }
        }
        // else -> Complex roots.
        return roots;
    }
    /**
     * Finds the roots of a parametric cubic equation in `t`,
     * where `t` lies in the interval of `[0,1]`.
     * Returns an array of parametric intersection locations along the cubic,
     * excluding out-of-bounds intersections (before or after the end point
     * or in the imaginary plane).
     * An adaptation of http://www.particleincell.com/blog/2013/cubic-line-intersection/
     */
    function cubicRoots(a, b, c, d) {
        if (a === 0) {
            return quadraticRoots(b, c, d);
        }
        var A = b / a;
        var B = c / a;
        var C = d / a;
        var Q = (3 * B - A * A) / 9;
        var R = (9 * A * B - 27 * C - 2 * A * A * A) / 54;
        var D = Q * Q * Q + R * R; // The polynomial's discriminant.
        var third = 1 / 3;
        var roots = [];
        if (D >= 0) { // Complex or duplicate roots.
            var rD = Math.sqrt(D);
            var S = sign(R + rD) * Math.pow(Math.abs(R + rD), third);
            var T = sign(R - rD) * Math.pow(Math.abs(R - rD), third);
            var Im = Math.abs(Math.sqrt(3) * (S - T) / 2); // Complex part of the root pair.
            var t = -third * A + (S + T); // A real root.
            if (t >= 0 && t <= 1) {
                roots.push(t);
            }
            if (Im === 0) {
                var t_1 = -third * A - (S + T) / 2; // The real part of a complex root.
                if (t_1 >= 0 && t_1 <= 1) {
                    roots.push(t_1);
                }
            }
        }
        else { // Distinct real roots.
            var theta = Math.acos(R / Math.sqrt(-Q * Q * Q));
            var thirdA = third * A;
            var twoSqrtQ = 2 * Math.sqrt(-Q);
            var t1 = twoSqrtQ * Math.cos(third * theta) - thirdA;
            var t2 = twoSqrtQ * Math.cos(third * (theta + 2 * Math.PI)) - thirdA;
            var t3 = twoSqrtQ * Math.cos(third * (theta + 4 * Math.PI)) - thirdA;
            if (t1 >= 0 && t1 <= 1) {
                roots.push(t1);
            }
            if (t2 >= 0 && t2 <= 1) {
                roots.push(t2);
            }
            if (t3 >= 0 && t3 <= 1) {
                roots.push(t3);
            }
        }
        return roots;
    }

    /**
     * Returns the intersection point for the given pair of line segments, or null,
     * if the segments are parallel or don't intersect.
     * Based on http://paulbourke.net/geometry/pointlineplane/
     */
    function segmentIntersection(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {
        var d = (ax2 - ax1) * (by2 - by1) - (ay2 - ay1) * (bx2 - bx1);
        if (d === 0) { // The lines are parallel.
            return null;
        }
        var ua = ((bx2 - bx1) * (ay1 - by1) - (ax1 - bx1) * (by2 - by1)) / d;
        var ub = ((ax2 - ax1) * (ay1 - by1) - (ay2 - ay1) * (ax1 - bx1)) / d;
        if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
            return {
                x: ax1 + ua * (ax2 - ax1),
                y: ay1 + ua * (ay2 - ay1)
            };
        }
        return null; // The intersection point is outside either or both segments.
    }
    /**
     * Returns intersection points of the given cubic curve and the line segment.
     * Takes in x/y components of cubic control points and line segment start/end points
     * as parameters.
     */
    function cubicSegmentIntersections(px1, py1, px2, py2, px3, py3, px4, py4, x1, y1, x2, y2) {
        var intersections = [];
        // Find line equation coefficients.
        var A = y1 - y2;
        var B = x2 - x1;
        var C = x1 * (y2 - y1) - y1 * (x2 - x1);
        // Find cubic Bezier curve equation coefficients from control points.
        var bx = bezierCoefficients(px1, px2, px3, px4);
        var by = bezierCoefficients(py1, py2, py3, py4);
        var a = A * bx[0] + B * by[0]; // t^3
        var b = A * bx[1] + B * by[1]; // t^2
        var c = A * bx[2] + B * by[2]; // t
        var d = A * bx[3] + B * by[3] + C; // 1
        var roots = cubicRoots(a, b, c, d);
        // Verify that the roots are within bounds of the linear segment.
        for (var i = 0; i < roots.length; i++) {
            var t = roots[i];
            var tt = t * t;
            var ttt = t * tt;
            // Find the cartesian plane coordinates for the parametric root `t`.
            var x = bx[0] * ttt + bx[1] * tt + bx[2] * t + bx[3];
            var y = by[0] * ttt + by[1] * tt + by[2] * t + by[3];
            // The parametric cubic roots we found are intersection points
            // with an infinite line, and so the x/y coordinates above are as well.
            // Make sure the x/y is also within the bounds of the given segment.
            var s = void 0;
            if (x1 !== x2) {
                s = (x - x1) / (x2 - x1);
            }
            else { // the line is vertical
                s = (y - y1) / (y2 - y1);
            }
            if (s >= 0 && s <= 1) {
                intersections.push({ x: x, y: y });
            }
        }
        return intersections;
    }
    /**
     * Returns the given coordinates vector multiplied by the coefficient matrix
     * of the parametric cubic Bézier equation.
     */
    function bezierCoefficients(P1, P2, P3, P4) {
        return [
            -P1 + 3 * P2 - 3 * P3 + P4,
            3 * P1 - 6 * P2 + 3 * P3,
            -3 * P1 + 3 * P2,
            P1 //                 | 1  0  0  0| |P4|
        ];
    }

    var Path2D = /** @class */ (function () {
        function Path2D() {
            // The methods of this class will likely be called many times per animation frame,
            // and any allocation can trigger a GC cycle during animation, so we attempt
            // to minimize the number of allocations.
            this.commands = [];
            this.params = [];
            this._closedPath = false;
        }
        Path2D.prototype.draw = function (ctx) {
            var commands = this.commands;
            var params = this.params;
            var n = commands.length;
            var j = 0;
            ctx.beginPath();
            for (var i = 0; i < n; i++) {
                switch (commands[i]) {
                    case 'M':
                        ctx.moveTo(params[j++], params[j++]);
                        break;
                    case 'L':
                        ctx.lineTo(params[j++], params[j++]);
                        break;
                    case 'C':
                        ctx.bezierCurveTo(params[j++], params[j++], params[j++], params[j++], params[j++], params[j++]);
                        break;
                    case 'Z':
                        ctx.closePath();
                        break;
                }
            }
        };
        Path2D.prototype.moveTo = function (x, y) {
            if (this.xy) {
                this.xy[0] = x;
                this.xy[1] = y;
            }
            else {
                this.xy = [x, y];
            }
            this.commands.push('M');
            this.params.push(x, y);
        };
        Path2D.prototype.lineTo = function (x, y) {
            if (this.xy) {
                this.commands.push('L');
                this.params.push(x, y);
                this.xy[0] = x;
                this.xy[1] = y;
            }
            else {
                this.moveTo(x, y);
            }
        };
        Path2D.prototype.rect = function (x, y, width, height) {
            this.moveTo(x, y);
            this.lineTo(x + width, y);
            this.lineTo(x + width, y + height);
            this.lineTo(x, y + height);
            this.closePath();
        };
        /**
         * Adds an arc segment to the path definition.
         * https://www.w3.org/TR/SVG11/paths.html#PathDataEllipticalArcCommands
         * @param rx The major-axis radius.
         * @param ry The minor-axis radius.
         * @param rotation The x-axis rotation, expressed in radians.
         * @param fA The large arc flag. `1` to use angle > π.
         * @param fS The sweep flag. `1` for the arc that goes to `x`/`y` clockwise.
         * @param x2 The x coordinate to arc to.
         * @param y2 The y coordinate to arc to.
         */
        Path2D.prototype.arcTo = function (rx, ry, rotation, fA, fS, x2, y2) {
            // Convert from endpoint to center parametrization:
            // https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
            var xy = this.xy;
            if (!xy) {
                return;
            }
            if (rx < 0) {
                rx = -rx;
            }
            if (ry < 0) {
                ry = -ry;
            }
            var x1 = xy[0];
            var y1 = xy[1];
            var hdx = (x1 - x2) / 2;
            var hdy = (y1 - y2) / 2;
            var sinPhi = Math.sin(rotation);
            var cosPhi = Math.cos(rotation);
            var xp = cosPhi * hdx + sinPhi * hdy;
            var yp = -sinPhi * hdx + cosPhi * hdy;
            var ratX = xp / rx;
            var ratY = yp / ry;
            var lambda = ratX * ratX + ratY * ratY;
            var cx = (x1 + x2) / 2;
            var cy = (y1 + y2) / 2;
            var cpx = 0;
            var cpy = 0;
            if (lambda >= 1) {
                lambda = Math.sqrt(lambda);
                rx *= lambda;
                ry *= lambda;
                // me gives lambda == cpx == cpy == 0;
            }
            else {
                lambda = Math.sqrt(1 / lambda - 1);
                if (fA === fS) {
                    lambda = -lambda;
                }
                cpx = lambda * rx * ratY;
                cpy = -lambda * ry * ratX;
                cx += cosPhi * cpx - sinPhi * cpy;
                cy += sinPhi * cpx + cosPhi * cpy;
            }
            var theta1 = Math.atan2((yp - cpy) / ry, (xp - cpx) / rx);
            var deltaTheta = Math.atan2((-yp - cpy) / ry, (-xp - cpx) / rx) - theta1;
            // if (fS) {
            //     if (deltaTheta <= 0) {
            //         deltaTheta += Math.PI * 2;
            //     }
            // }
            // else {
            //     if (deltaTheta >= 0) {
            //         deltaTheta -= Math.PI * 2;
            //     }
            // }
            this.cubicArc(cx, cy, rx, ry, rotation, theta1, theta1 + deltaTheta, 1 - fS);
        };
        /**
         * Approximates an elliptical arc with up to four cubic Bézier curves.
         * @param commands The string array to write SVG command letters to.
         * @param params The number array to write SVG command parameters (cubic control points) to.
         * @param cx The x-axis coordinate for the ellipse's center.
         * @param cy The y-axis coordinate for the ellipse's center.
         * @param rx The ellipse's major-axis radius.
         * @param ry The ellipse's minor-axis radius.
         * @param phi The rotation for this ellipse, expressed in radians.
         * @param theta1 The starting angle, measured clockwise from the positive x-axis and expressed in radians.
         * @param theta2 The ending angle, measured clockwise from the positive x-axis and expressed in radians.
         * @param anticlockwise The arc control points are always placed clockwise from `theta1` to `theta2`,
         * even when `theta1 > theta2`, unless this flag is set to `1`.
         */
        Path2D.cubicArc = function (commands, params, cx, cy, rx, ry, phi, theta1, theta2, anticlockwise) {
            if (anticlockwise) {
                var temp = theta1;
                theta1 = theta2;
                theta2 = temp;
            }
            var start = params.length;
            // See https://pomax.github.io/bezierinfo/#circles_cubic
            // Arc of unit circle (start angle = 0, end angle <= π/2) in cubic Bézier coordinates:
            // S = [1, 0]
            // C1 = [1, f]
            // C2 = [cos(θ) + f * sin(θ), sin(θ) - f * cos(θ)]
            // E = [cos(θ), sin(θ)]
            // f = 4/3 * tan(θ/4)
            var f90 = 0.5522847498307935; // f for θ = π/2 is 4/3 * (Math.sqrt(2) - 1)
            var sinTheta1 = Math.sin(theta1);
            var cosTheta1 = Math.cos(theta1);
            var sinPhi = Math.sin(phi);
            var cosPhi = Math.cos(phi);
            var rightAngle = Math.PI / 2;
            // Since we know how to draw an arc of a unit circle with a cubic Bézier,
            // to draw an elliptical arc with arbitrary rotation and radii we:
            // 1) rotate the Bézier coordinates that represent a circular arc by θ
            // 2) scale the circular arc separately along the x/y axes, making it elliptical
            // 3) rotate elliptical arc by φ
            // |cos(φ) -sin(φ)| |sx  0| |cos(θ) -sin(θ)| -> |xx xy|
            // |sin(φ)  cos(φ)| | 0 sy| |sin(θ)  cos(θ)| -> |yx yy|
            var xx = cosPhi * cosTheta1 * rx - sinPhi * sinTheta1 * ry;
            var yx = sinPhi * cosTheta1 * rx + cosPhi * sinTheta1 * ry;
            var xy = -cosPhi * sinTheta1 * rx - sinPhi * cosTheta1 * ry;
            var yy = -sinPhi * sinTheta1 * rx + cosPhi * cosTheta1 * ry;
            // TODO: what if delta between θ1 and θ2 is greater than 2π?
            // Always draw clockwise from θ1 to θ2.
            theta2 -= theta1;
            if (theta2 < 0) {
                theta2 += Math.PI * 2;
            }
            // Multiplying each point [x, y] by:
            // |xx xy cx| |x|
            // |yx yy cy| |y|
            // | 0  0  1| |1|
            // TODO: This move command may be redundant, if we are already at this point.
            // The coordinates of the point calculated here may differ ever so slightly
            // because of precision error.
            commands.push('M');
            params.push(xx + cx, yx + cy);
            while (theta2 >= rightAngle) {
                theta2 -= rightAngle;
                commands.push('C');
                // Temp workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=993330
                // Revert this commit when fixed ^^.
                var lastX = xy + cx;
                params.push(xx + xy * f90 + cx, yx + yy * f90 + cy, xx * f90 + xy + cx, yx * f90 + yy + cy, Math.abs(lastX) < 1e-8 ? 0 : lastX, yy + cy);
                // Prepend π/2 rotation matrix.
                // |xx xy| | 0 1| -> | xy -xx|
                // |yx yy| |-1 0| -> | yy -yx|
                // [xx, yx, xy, yy] = [xy, yy, -xx, -yx];
                // Compared to swapping with a temp variable, destructuring is:
                // - 10% faster in Chrome 70
                // - 99% slower in Firefox 63
                // Temp variable solution is 45% faster in FF than Chrome.
                // https://jsperf.com/multi-swap
                // https://bugzilla.mozilla.org/show_bug.cgi?id=1165569
                var temp = xx;
                xx = xy;
                xy = -temp;
                temp = yx;
                yx = yy;
                yy = -temp;
            }
            if (theta2) {
                var f = 4 / 3 * Math.tan(theta2 / 4);
                var sinPhi2 = Math.sin(theta2);
                var cosPhi2 = Math.cos(theta2);
                var C2x = cosPhi2 + f * sinPhi2;
                var C2y = sinPhi2 - f * cosPhi2;
                commands.push('C');
                // Temp workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=993330
                // Revert this commit when fixed ^^.
                var lastX = xx * cosPhi2 + xy * sinPhi2 + cx;
                params.push(xx + xy * f + cx, yx + yy * f + cy, xx * C2x + xy * C2y + cx, yx * C2x + yy * C2y + cy, Math.abs(lastX) < 1e-8 ? 0 : lastX, yx * cosPhi2 + yy * sinPhi2 + cy);
            }
            if (anticlockwise) {
                for (var i = start, j = params.length - 2; i < j; i += 2, j -= 2) {
                    var temp = params[i];
                    params[i] = params[j];
                    params[j] = temp;
                    temp = params[i + 1];
                    params[i + 1] = params[j + 1];
                    params[j + 1] = temp;
                }
            }
        };
        Path2D.prototype.cubicArc = function (cx, cy, rx, ry, phi, theta1, theta2, anticlockwise) {
            var commands = this.commands;
            var params = this.params;
            var start = commands.length;
            Path2D.cubicArc(commands, params, cx, cy, rx, ry, phi, theta1, theta2, anticlockwise);
            var x = params[params.length - 2];
            var y = params[params.length - 1];
            if (this.xy) {
                commands[start] = 'L';
                this.xy[0] = x;
                this.xy[1] = y;
            }
            else {
                this.xy = [x, y];
            }
        };
        /**
         * Returns the `[x, y]` coordinates of the curve at `t`.
         * @param points `(n + 1) * 2` control point coordinates for a Bézier curve of n-th order.
         * @param t
         */
        Path2D.prototype.deCasteljau = function (points, t) {
            var n = points.length;
            if (n < 2 || n % 2 === 1) {
                throw new Error('Fewer than two points or not an even count.');
            }
            else if (n === 2 || t === 0) {
                return points.slice(0, 2);
            }
            else if (t === 1) {
                return points.slice(-2);
            }
            else {
                var newPoints = [];
                var last = n - 2;
                for (var i = 0; i < last; i += 2) {
                    newPoints.push((1 - t) * points[i] + t * points[i + 2], // x
                    (1 - t) * points[i + 1] + t * points[i + 3] // y
                    );
                }
                return this.deCasteljau(newPoints, t);
            }
        };
        /**
         * Approximates the given curve using `n` line segments.
         * @param points `(n + 1) * 2` control point coordinates for a Bézier curve of n-th order.
         * @param n
         */
        Path2D.prototype.approximateCurve = function (points, n) {
            var xy = this.deCasteljau(points, 0);
            this.moveTo(xy[0], xy[1]);
            var step = 1 / n;
            for (var t = step; t <= 1; t += step) {
                var xy_1 = this.deCasteljau(points, t);
                this.lineTo(xy_1[0], xy_1[1]);
            }
        };
        /**
         * Adds a quadratic curve segment to the path definition.
         * Note: the given quadratic segment is converted and stored as a cubic one.
         * @param cx x-component of the curve's control point
         * @param cy y-component of the curve's control point
         * @param x x-component of the end point
         * @param y y-component of the end point
         */
        Path2D.prototype.quadraticCurveTo = function (cx, cy, x, y) {
            if (!this.xy) {
                this.moveTo(cx, cy);
            }
            // See https://pomax.github.io/bezierinfo/#reordering
            this.cubicCurveTo((this.xy[0] + 2 * cx) / 3, (this.xy[1] + 2 * cy) / 3, // 1/3 start + 2/3 control
            (2 * cx + x) / 3, (2 * cy + y) / 3, // 2/3 control + 1/3 end
            x, y);
        };
        Path2D.prototype.cubicCurveTo = function (cx1, cy1, cx2, cy2, x, y) {
            if (!this.xy) {
                this.moveTo(cx1, cy1);
            }
            this.commands.push('C');
            this.params.push(cx1, cy1, cx2, cy2, x, y);
            this.xy[0] = x;
            this.xy[1] = y;
        };
        Object.defineProperty(Path2D.prototype, "closedPath", {
            get: function () {
                return this._closedPath;
            },
            enumerable: true,
            configurable: true
        });
        Path2D.prototype.closePath = function () {
            if (this.xy) {
                this.xy = undefined;
                this.commands.push('Z');
                this._closedPath = true;
            }
        };
        Path2D.prototype.clear = function () {
            this.commands.length = 0;
            this.params.length = 0;
            this.xy = undefined;
            this._closedPath = false;
        };
        Path2D.prototype.isPointInPath = function (x, y) {
            var commands = this.commands;
            var params = this.params;
            var cn = commands.length;
            // Hit testing using ray casting method, where the ray's origin is some point
            // outside the path. In this case, an offscreen point that is remote enough, so that
            // even if the path itself is large and is partially offscreen, the ray's origin
            // will likely be outside the path anyway. To test if the given point is inside the
            // path or not, we cast a ray from the origin to the given point and check the number
            // of intersections of this segment with the path. If the number of intersections is
            // even, then the ray both entered and exited the path an equal number of times,
            // therefore the point is outside the path, and inside the path, if the number of
            // intersections is odd. Since the path is compound, we check if the ray segment
            // intersects with each of the path's segments, which can be either a line segment
            // (one or no intersection points) or a Bézier curve segment (up to 3 intersection
            // points).
            var ox = -10000;
            var oy = -10000;
            // the starting point of the  current path
            var sx = NaN;
            var sy = NaN;
            // the previous point of the current path
            var px = 0;
            var py = 0;
            var intersectionCount = 0;
            for (var ci = 0, pi = 0; ci < cn; ci++) {
                switch (commands[ci]) {
                    case 'M':
                        if (!isNaN(sx)) {
                            if (segmentIntersection(sx, sy, px, py, ox, oy, x, y)) {
                                intersectionCount++;
                            }
                        }
                        sx = px = params[pi++];
                        sy = py = params[pi++];
                        break;
                    case 'L':
                        if (segmentIntersection(px, py, px = params[pi++], py = params[pi++], ox, oy, x, y)) {
                            intersectionCount++;
                        }
                        break;
                    case 'C':
                        intersectionCount += cubicSegmentIntersections(px, py, params[pi++], params[pi++], params[pi++], params[pi++], px = params[pi++], py = params[pi++], ox, oy, x, y).length;
                        break;
                    case 'Z':
                        if (!isNaN(sx)) {
                            if (segmentIntersection(sx, sy, px, py, ox, oy, x, y)) {
                                intersectionCount++;
                            }
                        }
                        break;
                }
            }
            return intersectionCount % 2 === 1;
        };
        Path2D.fromString = function (value) {
            var path = new Path2D();
            path.setFromString(value);
            return path;
        };
        /**
         * Split the SVG path at command letters,
         * then extract the command letter and parameters from each substring.
         * @param value
         */
        Path2D.parseSvgPath = function (value) {
            return value.trim().split(Path2D.splitCommandsRe).map(function (part) {
                var strParams = part.match(Path2D.matchParamsRe);
                return {
                    command: part.substr(0, 1),
                    params: strParams ? strParams.map(parseFloat) : []
                };
            });
        };
        Path2D.prettifySvgPath = function (value) {
            return Path2D.parseSvgPath(value).map(function (d) { return d.command + d.params.join(','); }).join('\n');
        };
        /**
         * See https://www.w3.org/TR/SVG11/paths.html
         * @param value
         */
        Path2D.prototype.setFromString = function (value) {
            var _this = this;
            this.clear();
            var parts = Path2D.parseSvgPath(value);
            // Current point.
            var x;
            var y;
            // Last control point. Used to calculate the reflection point
            // for `S`, `s`, `T`, `t` commands.
            var cpx;
            var cpy;
            var lastCommand;
            function checkQuadraticCP() {
                if (!lastCommand.match(Path2D.quadraticCommandRe)) {
                    cpx = x;
                    cpy = y;
                }
            }
            function checkCubicCP() {
                if (!lastCommand.match(Path2D.cubicCommandRe)) {
                    cpx = x;
                    cpy = y;
                }
            }
            // But that will make compiler complain about x/y, cpx/cpy
            // being used without being set first.
            parts.forEach(function (part) {
                var p = part.params;
                var n = p.length;
                var i = 0;
                switch (part.command) {
                    case 'M':
                        _this.moveTo(x = p[i++], y = p[i++]);
                        while (i < n) {
                            _this.lineTo(x = p[i++], y = p[i++]);
                        }
                        break;
                    case 'm':
                        _this.moveTo(x += p[i++], y += p[i++]);
                        while (i < n) {
                            _this.lineTo(x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'L':
                        while (i < n) {
                            _this.lineTo(x = p[i++], y = p[i++]);
                        }
                        break;
                    case 'l':
                        while (i < n) {
                            _this.lineTo(x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'C':
                        while (i < n) {
                            _this.cubicCurveTo(p[i++], p[i++], cpx = p[i++], cpy = p[i++], x = p[i++], y = p[i++]);
                        }
                        break;
                    case 'c':
                        while (i < n) {
                            _this.cubicCurveTo(x + p[i++], y + p[i++], cpx = x + p[i++], cpy = y + p[i++], x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'S':
                        checkCubicCP();
                        while (i < n) {
                            _this.cubicCurveTo(x + x - cpx, y + y - cpy, cpx = p[i++], cpy = p[i++], x = p[i++], y = p[i++]);
                        }
                        break;
                    case 's':
                        checkCubicCP();
                        while (i < n) {
                            _this.cubicCurveTo(x + x - cpx, y + y - cpy, cpx = x + p[i++], cpy = y + p[i++], x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'Q':
                        while (i < n) {
                            _this.quadraticCurveTo(cpx = p[i++], cpy = p[i++], x = p[i++], y = p[i++]);
                        }
                        break;
                    case 'q':
                        while (i < n) {
                            _this.quadraticCurveTo(cpx = x + p[i++], cpy = y + p[i++], x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'T':
                        checkQuadraticCP();
                        while (i < n) {
                            _this.quadraticCurveTo(cpx = x + x - cpx, cpy = y + y - cpy, x = p[i++], y = p[i++]);
                        }
                        break;
                    case 't':
                        checkQuadraticCP();
                        while (i < n) {
                            _this.quadraticCurveTo(cpx = x + x - cpx, cpy = y + y - cpy, x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'A':
                        while (i < n) {
                            _this.arcTo(p[i++], p[i++], p[i++] * Math.PI / 180, p[i++], p[i++], x = p[i++], y = p[i++]);
                        }
                        break;
                    case 'a':
                        while (i < n) {
                            _this.arcTo(p[i++], p[i++], p[i++] * Math.PI / 180, p[i++], p[i++], x += p[i++], y += p[i++]);
                        }
                        break;
                    case 'Z':
                    case 'z':
                        _this.closePath();
                        break;
                    case 'H':
                        while (i < n) {
                            _this.lineTo(x = p[i++], y);
                        }
                        break;
                    case 'h':
                        while (i < n) {
                            _this.lineTo(x += p[i++], y);
                        }
                        break;
                    case 'V':
                        while (i < n) {
                            _this.lineTo(x, y = p[i++]);
                        }
                        break;
                    case 'v':
                        while (i < n) {
                            _this.lineTo(x, y += p[i++]);
                        }
                        break;
                }
                lastCommand = part.command;
            });
        };
        Path2D.prototype.toString = function () {
            var c = this.commands;
            var p = this.params;
            var cn = c.length;
            var out = [];
            for (var ci = 0, pi = 0; ci < cn; ci++) {
                switch (c[ci]) {
                    case 'M':
                        out.push('M' + p[pi++] + ',' + p[pi++]);
                        break;
                    case 'L':
                        out.push('L' + p[pi++] + ',' + p[pi++]);
                        break;
                    case 'C':
                        out.push('C' + p[pi++] + ',' + p[pi++] + ' ' +
                            p[pi++] + ',' + p[pi++] + ' ' +
                            p[pi++] + ',' + p[pi++]);
                        break;
                    case 'Z':
                        out.push('Z');
                        break;
                }
            }
            return out.join('');
        };
        Path2D.prototype.toPrettyString = function () {
            return Path2D.prettifySvgPath(this.toString());
        };
        Path2D.prototype.toSvg = function () {
            return Path2D.xmlDeclaration + "\n<svg width=\"100%\" height=\"100%\" viewBox=\"0 0 50 50\" version=\"1.1\" xmlns=\"" + Path2D.xmlns + "\">\n    <path d=\"" + this.toString() + "\" style=\"fill:none;stroke:#000;stroke-width:0.5;\"/>\n</svg>";
        };
        Path2D.prototype.toDebugSvg = function () {
            var d = Path2D.prettifySvgPath(this.toString());
            return Path2D.xmlDeclaration + "\n<svg width=\"100%\" height=\"100%\" viewBox=\"0 0 100 100\" version=\"1.1\" xmlns=\"" + Path2D.xmlns + "\">\n    <path d=\"" + d + "\" style=\"fill:none;stroke:#000;stroke-width:0.5;\"/>\n</svg>";
        };
        /**
         * Returns an array of sub-paths of this Path,
         * where each sub-path is represented exclusively by cubic segments.
         */
        Path2D.prototype.toCubicPaths = function () {
            // Each sub-path is an array of `(n * 3 + 1) * 2` numbers,
            // where `n` is the number of segments.
            var paths = [];
            var params = this.params;
            // current path
            var path;
            // the starting point of the  current path
            var sx;
            var sy;
            // the previous point of the current path
            var px;
            var py;
            var i = 0; // current parameter
            this.commands.forEach(function (command) {
                switch (command) {
                    case 'M':
                        path = [
                            sx = px = params[i++],
                            sy = py = params[i++]
                        ];
                        paths.push(path);
                        break;
                    case 'L':
                        var x = params[i++];
                        var y = params[i++];
                        // Place control points along the line `a + (b - a) * t`
                        // at t = 1/3 and 2/3:
                        path.push((px + px + x) / 3, (py + py + y) / 3, (px + x + x) / 3, (py + y + y) / 3, px = x, py = y);
                        break;
                    case 'C':
                        path.push(params[i++], params[i++], params[i++], params[i++], px = params[i++], py = params[i++]);
                        break;
                    case 'Z':
                        path.push((px + px + sx) / 3, (py + py + sy) / 3, (px + sx + sx) / 3, (py + sy + sy) / 3, px = sx, py = sy);
                        break;
                }
            });
            return paths;
        };
        Path2D.cubicPathToString = function (path) {
            var n = path.length;
            if (!(n % 2 === 0 && (n / 2 - 1) / 2 >= 1)) {
                throw new Error('Invalid path.');
            }
            return 'M' + path.slice(0, 2).join(',') + 'C' + path.slice(2).join(',');
        };
        Path2D.splitCommandsRe = /(?=[AaCcHhLlMmQqSsTtVvZz])/g;
        Path2D.matchParamsRe = /-?[0-9]*\.?\d+/g;
        Path2D.quadraticCommandRe = /[QqTt]/;
        Path2D.cubicCommandRe = /[CcSs]/;
        Path2D.xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?>';
        Path2D.xmlns = 'http://www.w3.org/2000/svg';
        return Path2D;
    }());

    var __extends$8 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Path = /** @class */ (function (_super) {
        __extends$8(Path, _super);
        function Path() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            /**
             * Declare a path to retain for later rendering and hit testing
             * using custom Path2D class. Think of it as a TypeScript version
             * of the native Path2D (with some differences) that works in all browsers.
             */
            _this.path = new Path2D();
            /**
            * The path only has to be updated when certain attributes change.
            * For example, if transform attributes (such as `translationX`)
            * are changed, we don't have to update the path. The `dirtyPath` flag
            * is how we keep track if the path has to be updated or not.
            */
            _this._dirtyPath = true;
            /**
             * Path definition in SVG path syntax:
             * https://www.w3.org/TR/SVG11/paths.html#DAttribute
             */
            _this._svgPath = '';
            return _this;
        }
        Object.defineProperty(Path.prototype, "dirtyPath", {
            get: function () {
                return this._dirtyPath;
            },
            set: function (value) {
                if (this._dirtyPath !== value) {
                    this._dirtyPath = value;
                    if (value) {
                        this.dirty = true;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Path.prototype, "svgPath", {
            get: function () {
                return this._svgPath;
            },
            set: function (value) {
                if (this._svgPath !== value) {
                    this._svgPath = value;
                    this.path.setFromString(value);
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Path.prototype.isPointInPath = function (x, y) {
            var point = this.transformPoint(x, y);
            return this.path.closedPath && this.path.isPointInPath(point.x, point.y);
        };
        Path.prototype.isPointInStroke = function (x, y) {
            return false;
        };
        Path.prototype.updatePath = function () { };
        Path.prototype.render = function (ctx) {
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            // if (scene.debug.renderBoundingBoxes) {
            //     const bbox = this.computeBBox();
            //     if (bbox) {
            //         this.matrix.transformBBox(bbox).render(ctx);
            //     }
            // }
            this.matrix.toContext(ctx);
            if (this.dirtyPath) {
                this.updatePath();
                this.dirtyPath = false;
            }
            this.path.draw(ctx);
            this.fillStroke(ctx);
            this.dirty = false;
        };
        Path.className = 'Path';
        return Path;
    }(Shape));

    var twoPi = Math.PI * 2;
    /**
     * Normalize the given angle to be in the [0, 2π) interval.
     * @param radians Angle in radians.
     */
    function normalizeAngle360(radians) {
        radians %= twoPi;
        radians += twoPi;
        radians %= twoPi;
        return radians;
    }
    function normalizeAngle360Inclusive(radians) {
        radians %= twoPi;
        radians += twoPi;
        if (radians !== twoPi) {
            radians %= twoPi;
        }
        return radians;
    }
    /**
     * Normalize the given angle to be in the [-π, π) interval.
     * @param radians Angle in radians.
     */
    function normalizeAngle180(radians) {
        radians %= twoPi;
        if (radians < -Math.PI) {
            radians += twoPi;
        }
        else if (radians >= Math.PI) {
            radians -= twoPi;
        }
        return radians;
    }
    function toRadians(degrees) {
        return degrees / 180 * Math.PI;
    }
    function toDegrees(radians) {
        return radians / Math.PI * 180;
    }

    function isEqual(a, b, epsilon) {
        if (epsilon === void 0) { epsilon = 1e-10; }
        return Math.abs(a - b) < epsilon;
    }
    /**
     * `Number.toFixed(n)` always formats a number so that it has `n` digits after the decimal point.
     * For example, `Number(0.00003427).toFixed(2)` returns `0.00`.
     * That's not very helpful, because all the meaningful information is lost.
     * In this case we would want the formatted value to have at least two significant digits: `0.000034`,
     * not two fraction digits.
     * @param value
     * @param fractionOrSignificantDigits
     */
    function toFixed(value, fractionOrSignificantDigits) {
        if (fractionOrSignificantDigits === void 0) { fractionOrSignificantDigits = 2; }
        var power = Math.floor(Math.log(Math.abs(value)) / Math.LN10);
        if (power >= 0 || !isFinite(power)) {
            return value.toFixed(fractionOrSignificantDigits); // fraction digits
        }
        return value.toFixed(Math.abs(power) - 1 + fractionOrSignificantDigits); // significant digits
    }

    var __extends$9 = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    (function (ArcType) {
        ArcType[ArcType["Open"] = 0] = "Open";
        ArcType[ArcType["Chord"] = 1] = "Chord";
        ArcType[ArcType["Round"] = 2] = "Round";
    })(exports.ArcType || (exports.ArcType = {}));
    /**
     * Elliptical arc node.
     */
    var Arc = /** @class */ (function (_super) {
        __extends$9(Arc, _super);
        function Arc() {
            var _this = _super.call(this) || this;
            _this._centerX = 0;
            _this._centerY = 0;
            _this._radiusX = 10;
            _this._radiusY = 10;
            _this._startAngle = 0;
            _this._endAngle = Math.PI * 2;
            _this._counterClockwise = false;
            /**
             * The type of arc to render:
             * - {@link ArcType.Open} - end points of the arc segment are not connected (default)
             * - {@link ArcType.Chord} - end points of the arc segment are connected by a line segment
             * - {@link ArcType.Round} - each of the end points of the arc segment are connected
             *                           to the center of the arc
             * Arcs with {@link ArcType.Open} do not support hit testing, even if they have their
             * {@link Shape.fillStyle} set, because they are not closed paths. Hit testing support
             * would require using two paths - one for rendering, another for hit testing - and there
             * doesn't seem to be a compelling reason to do that, when one can just use {@link ArcType.Chord}
             * to create a closed path.
             */
            _this._type = exports.ArcType.Open;
            _this.restoreOwnStyles();
            return _this;
        }
        Object.defineProperty(Arc.prototype, "centerX", {
            get: function () {
                return this._centerX;
            },
            set: function (value) {
                if (this._centerX !== value) {
                    this._centerX = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "centerY", {
            get: function () {
                return this._centerY;
            },
            set: function (value) {
                if (this._centerY !== value) {
                    this._centerY = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "radiusX", {
            get: function () {
                return this._radiusX;
            },
            set: function (value) {
                if (this._radiusX !== value) {
                    this._radiusX = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "radiusY", {
            get: function () {
                return this._radiusY;
            },
            set: function (value) {
                if (this._radiusY !== value) {
                    this._radiusY = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "startAngle", {
            get: function () {
                return this._startAngle;
            },
            set: function (value) {
                if (this._startAngle !== value) {
                    this._startAngle = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "endAngle", {
            get: function () {
                return this._endAngle;
            },
            set: function (value) {
                if (this._endAngle !== value) {
                    this._endAngle = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "fullPie", {
            get: function () {
                return isEqual(normalizeAngle360(this.startAngle), normalizeAngle360(this.endAngle));
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "counterClockwise", {
            get: function () {
                return this._counterClockwise;
            },
            set: function (value) {
                if (this._counterClockwise !== value) {
                    this._counterClockwise = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Arc.prototype, "type", {
            get: function () {
                return this._type;
            },
            set: function (value) {
                if (this._type !== value) {
                    this._type = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Arc.prototype.updatePath = function () {
            var path = this.path;
            path.clear(); // No need to recreate the Path, can simply clear the existing one.
            // This is much faster than the native Path2D implementation even though this `cubicArc`
            // method is pure TypeScript and actually produces the definition of an elliptical arc,
            // where you can specify two radii and rotation, while Path2D's `arc` method simply produces
            // a circular arc. Maybe it's due to the experimental nature of the Path2D class,
            // maybe it's because we have to create a new instance of it on each render, who knows...
            path.cubicArc(this.centerX, this.centerY, this.radiusX, this.radiusY, 0, this.startAngle, this.endAngle, this.counterClockwise ? 1 : 0);
            if (this.type === exports.ArcType.Chord) {
                path.closePath();
            }
            else if (this.type === exports.ArcType.Round && !this.fullPie) {
                path.lineTo(this.centerX, this.centerY);
                path.closePath();
            }
        };
        Arc.prototype.computeBBox = function () {
            // Only works with full arcs (circles) and untransformed ellipses.
            return new BBox(this.centerX - this.radiusX, this.centerY - this.radiusY, this.radiusX * 2, this.radiusY * 2);
        };
        Arc.prototype.isPointInPath = function (x, y) {
            var point = this.transformPoint(x, y);
            var bbox = this.computeBBox();
            return this.type !== exports.ArcType.Open
                && bbox.containsPoint(point.x, point.y)
                && this.path.isPointInPath(point.x, point.y);
        };
        Arc.className = 'Arc';
        Arc.defaultStyles = chainObjects(Shape.defaultStyles, {
            lineWidth: 1,
            fillStyle: null
        });
        return Arc;
    }(Path));

    var __read$4 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    // import { Rect } from "./scene/shape/rect"; // debug (bbox)
    var Tags;
    (function (Tags) {
        Tags[Tags["Tick"] = 0] = "Tick";
        Tags[Tags["GridLine"] = 1] = "GridLine";
    })(Tags || (Tags = {}));
    var AxisTick = /** @class */ (function () {
        function AxisTick() {
            /**
             * The line width to be used by axis ticks.
             */
            this.width = 1;
            /**
             * The line length to be used by axis ticks.
             */
            this.size = 6;
            /**
             * The color of the axis ticks.
             * Use `undefined` rather than `rgba(0, 0, 0, 0)` to make the ticks invisible.
             */
            this.color = 'rgba(195, 195, 195, 1)';
            /**
             * A hint of how many ticks to use (the exact number of ticks might differ),
             * a `TimeInterval` or a `CountableTimeInterval`.
             * For example:
             *
             *     axis.tick.count = 5;
             *     axis.tick.count = year;
             *     axis.tick.count = month.every(6);
             */
            this.count = 10;
        }
        return AxisTick;
    }());
    var AxisLabel = /** @class */ (function () {
        function AxisLabel() {
            this.fontStyle = undefined;
            this.fontWeight = undefined;
            this.fontSize = 12;
            this.fontFamily = 'Verdana, sans-serif';
            /**
             * The padding between the labels and the ticks.
             */
            this.padding = 5;
            /**
             * The color of the labels.
             * Use `undefined` rather than `rgba(0, 0, 0, 0)` to make labels invisible.
             */
            this.color = 'rgba(87, 87, 87, 1)';
            /**
             * Custom label rotation in degrees.
             * Labels are rendered perpendicular to the axis line by default.
             * Or parallel to the axis line, if the {@link parallel} is set to `true`.
             * The value of this config is used as the angular offset/deflection
             * from the default rotation.
             */
            this.rotation = 0;
            /**
             * By default labels and ticks are positioned to the left of the axis line.
             * `true` positions the labels to the right of the axis line.
             * However, if the axis is rotated, its easier to think in terms
             * of this side or the opposite side, rather than left and right.
             * We use the term `mirror` for conciseness, although it's not
             * true mirroring - for example, when a label is rotated, so that
             * it is inclined at the 45 degree angle, text flowing from north-west
             * to south-east, ending at the tick to the left of the axis line,
             * and then we set this config to `true`, the text will still be flowing
             * from north-west to south-east, _starting_ at the tick to the right
             * of the axis line.
             */
            this.mirrored = false;
            /**
             * Labels are rendered perpendicular to the axis line by default.
             * Setting this config to `true` makes labels render parallel to the axis line
             * and center aligns labels' text at the ticks.
             */
            this.parallel = false;
            /**
             * In case {@param value} is a number, the {@param fractionDigits} parameter will
             * be provided as well. The `fractionDigits` corresponds to the number of fraction
             * digits used by the tick step. For example, if the tick step is `0.0005`,
             * the `fractionDigits` is 4.
             */
            this.formatter = undefined;
            this.onFormatChange = undefined;
        }
        Object.defineProperty(AxisLabel.prototype, "format", {
            get: function () {
                return this._format;
            },
            set: function (value) {
                // See `TimeLocaleObject` docs for the list of supported format directives.
                if (this._format !== value) {
                    this._format = value;
                    if (this.onFormatChange) {
                        this.onFormatChange(value);
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        return AxisLabel;
    }());
    /**
     * A general purpose linear axis with no notion of orientation.
     * The axis is always rendered vertically, with horizontal labels positioned to the left
     * of the axis line by default. The axis can be {@link rotation | rotated} by an arbitrary angle,
     * so that it can be used as a top, right, bottom, left, radial or any other kind
     * of linear axis.
     * The generic `D` parameter is the type of the domain of the axis' scale.
     * The output range of the axis' scale is always numeric (screen coordinates).
     */
    var Axis = /** @class */ (function () {
        function Axis(scale) {
            // debug (bbox)
            // private bboxRect = (() => {
            //     const rect = new Rect();
            //     rect.fill = undefined;
            //     rect.stroke = 'red';
            //     rect.strokeWidth = 1;
            //     rect.strokeOpacity = 0.2;
            //     return rect;
            // })();
            this.id = createId(this);
            this.lineNode = new Line();
            this.group = new Group();
            this.line = {
                width: 1,
                color: 'rgba(195, 195, 195, 1)'
            };
            this.tick = new AxisTick();
            this.label = new AxisLabel();
            this.translation = { x: 0, y: 0 };
            this.rotation = 0; // axis rotation angle in degrees
            this.requestedRange = [0, 1];
            this._visibleRange = [0, 1];
            this._title = undefined;
            /**
             * The length of the grid. The grid is only visible in case of a non-zero value.
             * In case {@link radialGrid} is `true`, the value is interpreted as an angle
             * (in degrees).
             */
            this._gridLength = 0;
            /**
             * The array of styles to cycle through when rendering grid lines.
             * For example, use two {@link GridStyle} objects for alternating styles.
             * Contains only one {@link GridStyle} object by default, meaning all grid lines
             * have the same style.
             */
            this.gridStyle = [{
                    stroke: 'rgba(219, 219, 219, 1)',
                    lineDash: [4, 2]
                }];
            /**
             * `false` - render grid as lines of {@link gridLength} that extend the ticks
             *           on the opposite side of the axis
             * `true` - render grid as concentric circles that go through the ticks
             */
            this._radialGrid = false;
            this.fractionDigits = 0;
            this.thickness = 0;
            this.scale = scale;
            this.groupSelection = Selection.select(this.group).selectAll();
            this.label.onFormatChange = this.onLabelFormatChange.bind(this);
            this.group.append(this.lineNode);
            // this.group.append(this.bboxRect); // debug (bbox)
        }
        Object.defineProperty(Axis.prototype, "scale", {
            get: function () {
                return this._scale;
            },
            set: function (value) {
                this._scale = value;
                this.requestedRange = value.range.slice();
                this.onLabelFormatChange();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Axis.prototype, "ticks", {
            get: function () {
                return this._ticks;
            },
            set: function (values) {
                this._ticks = values;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Meant to be overridden in subclasses to provide extra context the the label formatter.
         * The return value of this function will be passed to the laber.formatter as the `axis` parameter.
         */
        Axis.prototype.getMeta = function () { };
        Axis.prototype.updateRange = function () {
            var _a = this, rr = _a.requestedRange, vr = _a.visibleRange, scale = _a.scale;
            var span = (rr[1] - rr[0]) / (vr[1] - vr[0]);
            var shift = span * vr[0];
            var start = rr[0] - shift;
            scale.range = [start, start + span];
        };
        /**
         * Checks if a point or an object is in range.
         * @param x A point (or object's starting point).
         * @param width Object's width.
         * @param tolerance Expands the range on both ends by this amount.
         */
        Axis.prototype.inRange = function (x, width, tolerance) {
            if (width === void 0) { width = 0; }
            if (tolerance === void 0) { tolerance = 0; }
            return this.inRangeEx(x, width, tolerance) === 0;
        };
        Axis.prototype.inRangeEx = function (x, width, tolerance) {
            if (width === void 0) { width = 0; }
            if (tolerance === void 0) { tolerance = 0; }
            var range = this.range;
            // Account for inverted ranges, for example [500, 100] as well as [100, 500]
            var min = Math.min(range[0], range[1]);
            var max = Math.max(range[0], range[1]);
            if ((x + width) < (min - tolerance)) {
                return -1; // left of range
            }
            if (x > (max + tolerance)) {
                return 1; // right of range
            }
            return 0; // in range
        };
        Object.defineProperty(Axis.prototype, "range", {
            get: function () {
                return this.requestedRange.slice();
            },
            set: function (value) {
                this.requestedRange = value.slice();
                this.updateRange();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Axis.prototype, "visibleRange", {
            get: function () {
                return this._visibleRange.slice();
            },
            set: function (value) {
                if (value && value.length === 2) {
                    var _a = __read$4(value, 2), min = _a[0], max = _a[1];
                    min = Math.max(0, min);
                    max = Math.min(1, max);
                    min = Math.min(min, max);
                    max = Math.max(min, max);
                    this._visibleRange = [min, max];
                    this.updateRange();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Axis.prototype, "domain", {
            get: function () {
                return this.scale.domain.slice();
            },
            set: function (value) {
                this.scale.domain = value.slice();
                this.onLabelFormatChange(this.label.format);
            },
            enumerable: true,
            configurable: true
        });
        Axis.prototype.onLabelFormatChange = function (format) {
            if (format && this.scale && this.scale.tickFormat) {
                try {
                    this.labelFormatter = this.scale.tickFormat(this.tick.count, format);
                }
                catch (e) {
                    this.labelFormatter = undefined;
                    console.error(e);
                }
            }
            else {
                this.labelFormatter = undefined;
            }
        };
        Object.defineProperty(Axis.prototype, "title", {
            get: function () {
                return this._title;
            },
            set: function (value) {
                var oldTitle = this._title;
                if (oldTitle !== value) {
                    if (oldTitle) {
                        this.group.removeChild(oldTitle.node);
                    }
                    if (value) {
                        value.node.rotation = -Math.PI / 2;
                        this.group.appendChild(value.node);
                    }
                    this._title = value;
                    // position title so that it doesn't briefly get rendered in the top left hand corner of the canvas before update is called.
                    this.positionTitle();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Axis.prototype, "gridLength", {
            get: function () {
                return this._gridLength;
            },
            set: function (value) {
                // Was visible and now invisible, or was invisible and now visible.
                if (this._gridLength && !value || !this._gridLength && value) {
                    this.groupSelection = this.groupSelection.remove().setData([]);
                }
                this._gridLength = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Axis.prototype, "radialGrid", {
            get: function () {
                return this._radialGrid;
            },
            set: function (value) {
                if (this._radialGrid !== value) {
                    this._radialGrid = value;
                    this.groupSelection = this.groupSelection.remove().setData([]);
                }
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Creates/removes/updates the scene graph nodes that constitute the axis.
         * Supposed to be called _manually_ after changing _any_ of the axis properties.
         * This allows to bulk set axis properties before updating the nodes.
         * The node changes made by this method are rendered on the next animation frame.
         * We could schedule this method call automatically on the next animation frame
         * when any of the axis properties change (the way we do when properties of scene graph's
         * nodes change), but this will mean that we first wait for the next animation
         * frame to make changes to the nodes of the axis, then wait for another animation
         * frame to render those changes. It's nice to have everything update automatically,
         * but this extra level of async indirection will not just introduce an unwanted delay,
         * it will also make it harder to reason about the program.
         */
        Axis.prototype.update = function () {
            var _this = this;
            var _a = this, group = _a.group, scale = _a.scale, tick = _a.tick, label = _a.label, gridStyle = _a.gridStyle, requestedRange = _a.requestedRange;
            var requestedRangeMin = Math.min(requestedRange[0], requestedRange[1]);
            var requestedRangeMax = Math.max(requestedRange[0], requestedRange[1]);
            var rotation = toRadians(this.rotation);
            var parallelLabels = label.parallel;
            var labelRotation = normalizeAngle360(toRadians(label.rotation));
            group.translationX = this.translation.x;
            group.translationY = this.translation.y;
            group.rotation = rotation;
            var halfBandwidth = (scale.bandwidth || 0) / 2;
            // The side of the axis line to position the labels on.
            // -1 = left (default)
            //  1 = right
            var sideFlag = label.mirrored ? 1 : -1;
            // When labels are parallel to the axis line, the `parallelFlipFlag` is used to
            // flip the labels to avoid upside-down text, when the axis is rotated
            // such that it is in the right hemisphere, i.e. the angle of rotation
            // is in the [0, π] interval.
            // The rotation angle is normalized, so that we have an easier time checking
            // if it's in the said interval. Since the axis is always rendered vertically
            // and then rotated, zero rotation means 12 (not 3) o-clock.
            // -1 = flip
            //  1 = don't flip (default)
            var parallelFlipRotation = normalizeAngle360(rotation);
            var parallelFlipFlag = !labelRotation && parallelFlipRotation >= 0 && parallelFlipRotation <= Math.PI ? -1 : 1;
            var regularFlipRotation = normalizeAngle360(rotation - Math.PI / 2);
            // Flip if the axis rotation angle is in the top hemisphere.
            var regularFlipFlag = !labelRotation && regularFlipRotation >= 0 && regularFlipRotation <= Math.PI ? -1 : 1;
            var alignFlag = labelRotation >= 0 && labelRotation <= Math.PI ? -1 : 1;
            var ticks = this.ticks || scale.ticks(this.tick.count);
            var update = this.groupSelection.setData(ticks);
            update.exit.remove();
            var enter = update.enter.append(Group);
            // Line auto-snaps to pixel grid if vertical or horizontal.
            enter.append(Line).each(function (node) { return node.tag = Tags.Tick; });
            if (this.gridLength) {
                if (this.radialGrid) {
                    enter.append(Arc).each(function (node) { return node.tag = Tags.GridLine; });
                }
                else {
                    enter.append(Line).each(function (node) { return node.tag = Tags.GridLine; });
                }
            }
            enter.append(Text);
            var groupSelection = update.merge(enter);
            groupSelection
                .attrFn('translationY', function (_, datum) {
                return Math.round(scale.convert(datum) + halfBandwidth);
            })
                .attrFn('visible', function (node) {
                var min = Math.floor(requestedRangeMin);
                var max = Math.ceil(requestedRangeMax);
                return node.translationY >= min && node.translationY <= max;
            });
            groupSelection.selectByTag(Tags.Tick)
                .each(function (line) {
                line.strokeWidth = tick.width;
                line.stroke = tick.color;
            })
                .attr('x1', sideFlag * tick.size)
                .attr('x2', 0)
                .attr('y1', 0)
                .attr('y2', 0);
            if (this.gridLength && gridStyle.length) {
                var styleCount_1 = gridStyle.length;
                var gridLines = void 0;
                if (this.radialGrid) {
                    var angularGridLength_1 = normalizeAngle360Inclusive(toRadians(this.gridLength));
                    gridLines = groupSelection.selectByTag(Tags.GridLine)
                        .each(function (arc, datum) {
                        var radius = Math.round(scale.convert(datum) + halfBandwidth);
                        arc.centerX = 0;
                        arc.centerY = scale.range[0] - radius;
                        arc.endAngle = angularGridLength_1;
                        arc.radiusX = radius;
                        arc.radiusY = radius;
                    });
                }
                else {
                    gridLines = groupSelection.selectByTag(Tags.GridLine)
                        .each(function (line) {
                        line.x1 = 0;
                        line.x2 = -sideFlag * _this.gridLength;
                        line.y1 = 0;
                        line.y2 = 0;
                        line.visible = Math.abs(line.parent.translationY - scale.range[0]) > 1;
                    });
                }
                gridLines.each(function (gridLine, _, index) {
                    var style = gridStyle[index % styleCount_1];
                    gridLine.stroke = style.stroke;
                    gridLine.strokeWidth = tick.width;
                    gridLine.lineDash = style.lineDash;
                    gridLine.fill = undefined;
                });
            }
            // `ticks instanceof NumericTicks` doesn't work here, so we feature detect.
            this.fractionDigits = ticks.fractionDigits >= 0 ? ticks.fractionDigits : 0;
            var labelSelection = groupSelection.selectByClass(Text)
                .each(function (node, datum, index) {
                node.fontStyle = label.fontStyle;
                node.fontWeight = label.fontWeight;
                node.fontSize = label.fontSize;
                node.fontFamily = label.fontFamily;
                node.fill = label.color;
                node.textBaseline = parallelLabels && !labelRotation
                    ? (sideFlag * parallelFlipFlag === -1 ? 'hanging' : 'bottom')
                    : 'middle';
                node.text = _this.formatTickDatum(datum, index);
                node.textAlign = parallelLabels
                    ? labelRotation ? (sideFlag * alignFlag === -1 ? 'end' : 'start') : 'center'
                    : sideFlag * regularFlipFlag === -1 ? 'end' : 'start';
            });
            var labelX = sideFlag * (tick.size + label.padding);
            var autoRotation = parallelLabels
                ? parallelFlipFlag * Math.PI / 2
                : (regularFlipFlag === -1 ? Math.PI : 0);
            labelSelection.each(function (label) {
                label.x = labelX;
                label.rotationCenterX = labelX;
                label.rotation = autoRotation + labelRotation;
            });
            this.groupSelection = groupSelection;
            // Render axis line.
            var lineNode = this.lineNode;
            lineNode.x1 = 0;
            lineNode.x2 = 0;
            lineNode.y1 = requestedRange[0];
            lineNode.y2 = requestedRange[1];
            lineNode.strokeWidth = this.line.width;
            lineNode.stroke = this.line.color;
            lineNode.visible = ticks.length > 0;
            this.positionTitle();
            // debug (bbox)
            // const bbox = this.computeBBox();
            // const bboxRect = this.bboxRect;
            // bboxRect.x = bbox.x;
            // bboxRect.y = bbox.y;
            // bboxRect.width = bbox.width;
            // bboxRect.height = bbox.height;
        };
        Axis.prototype.positionTitle = function () {
            var _a = this, title = _a.title, lineNode = _a.lineNode;
            if (!title) {
                return;
            }
            var titleVisible = false;
            if (title.enabled && lineNode.visible) {
                titleVisible = true;
                var _b = this, label = _b.label, rotation = _b.rotation, requestedRange = _b.requestedRange;
                var sideFlag = label.mirrored ? 1 : -1;
                var parallelFlipRotation = normalizeAngle360(rotation);
                var padding = title.padding.bottom;
                var titleNode = title.node;
                var bbox = this.computeBBox({ excludeTitle: true });
                var titleRotationFlag = sideFlag === -1 && parallelFlipRotation > Math.PI && parallelFlipRotation < Math.PI * 2 ? -1 : 1;
                titleNode.rotation = titleRotationFlag * sideFlag * Math.PI / 2;
                // titleNode.x = titleRotationFlag * sideFlag * (lineNode.y1 + lineNode.y2) / 2; // TODO: remove?
                titleNode.x = titleRotationFlag * sideFlag * (requestedRange[0] + requestedRange[1]) / 2;
                if (sideFlag === -1) {
                    titleNode.y = titleRotationFlag * (-padding - bbox.width + Math.max(bbox.x + bbox.width, 0));
                }
                else {
                    titleNode.y = -padding - bbox.width - Math.min(bbox.x, 0);
                }
                titleNode.textBaseline = titleRotationFlag === 1 ? 'bottom' : 'top';
            }
            title.node.visible = titleVisible;
        };
        // For formatting (nice rounded) tick values.
        Axis.prototype.formatTickDatum = function (datum, index) {
            var _a = this, label = _a.label, labelFormatter = _a.labelFormatter, fractionDigits = _a.fractionDigits;
            var meta = this.getMeta();
            return label.formatter
                ? label.formatter({
                    value: fractionDigits >= 0 ? datum : String(datum),
                    index: index,
                    fractionDigits: fractionDigits,
                    formatter: labelFormatter,
                    axis: meta
                })
                : labelFormatter
                    ? labelFormatter(datum)
                    : typeof datum === 'number' && fractionDigits >= 0
                        // the `datum` is a floating point number
                        ? datum.toFixed(fractionDigits)
                        // the`datum` is an integer, a string or an object
                        : String(datum);
        };
        // For formatting arbitrary values between the ticks.
        Axis.prototype.formatDatum = function (datum) {
            return String(datum);
        };
        Axis.prototype.computeBBox = function (options) {
            var _a = this, title = _a.title, lineNode = _a.lineNode;
            var labels = this.groupSelection.selectByClass(Text);
            var left = Infinity;
            var right = -Infinity;
            var top = Infinity;
            var bottom = -Infinity;
            labels.each(function (label) {
                // The label itself is rotated, but not translated, the group that
                // contains it is. So to capture the group transform in the label bbox
                // calculation we combine the transform matrices of the label and the group.
                // Depending on the timing of the `axis.computeBBox()` method call, we may
                // not have the group's and the label's transform matrices updated yet (because
                // the transform matrix is not recalculated whenever a node's transform attributes
                // change, instead it's marked for recalculation on the next frame by setting
                // the node's `dirtyTransform` flag to `true`), so we force them to update
                // right here by calling `computeTransformMatrix`.
                label.computeTransformMatrix();
                var matrix = Matrix.flyweight(label.matrix);
                var group = label.parent;
                group.computeTransformMatrix();
                matrix.preMultiplySelf(group.matrix);
                var labelBBox = label.computeBBox();
                if (labelBBox) {
                    var bbox = matrix.transformBBox(labelBBox);
                    left = Math.min(left, bbox.x);
                    right = Math.max(right, bbox.x + bbox.width);
                    top = Math.min(top, bbox.y);
                    bottom = Math.max(bottom, bbox.y + bbox.height);
                }
            });
            if (title && title.enabled && lineNode.visible && (!options || !options.excludeTitle)) {
                var label = title.node;
                label.computeTransformMatrix();
                var matrix = Matrix.flyweight(label.matrix);
                var labelBBox = label.computeBBox();
                if (labelBBox) {
                    var bbox = matrix.transformBBox(labelBBox);
                    left = Math.min(left, bbox.x);
                    right = Math.max(right, bbox.x + bbox.width);
                    top = Math.min(top, bbox.y);
                    bottom = Math.max(bottom, bbox.y + bbox.height);
                }
            }
            left = Math.min(left, 0);
            right = Math.max(right, 0);
            top = Math.min(top, lineNode.y1, lineNode.y2);
            bottom = Math.max(bottom, lineNode.y1, lineNode.y2);
            return new BBox(left, top, right - left, bottom - top);
        };
        return Axis;
    }());

    var __extends$a = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    (function (ChartAxisDirection) {
        ChartAxisDirection["X"] = "x";
        ChartAxisDirection["Y"] = "y"; // means 'radius' in polar charts
    })(exports.ChartAxisDirection || (exports.ChartAxisDirection = {}));
    function flipChartAxisDirection(direction) {
        if (direction === exports.ChartAxisDirection.X) {
            return exports.ChartAxisDirection.Y;
        }
        else {
            return exports.ChartAxisDirection.X;
        }
    }
    (function (ChartAxisPosition) {
        ChartAxisPosition["Top"] = "top";
        ChartAxisPosition["Right"] = "right";
        ChartAxisPosition["Bottom"] = "bottom";
        ChartAxisPosition["Left"] = "left";
        ChartAxisPosition["Angle"] = "angle";
        ChartAxisPosition["Radius"] = "radius";
    })(exports.ChartAxisPosition || (exports.ChartAxisPosition = {}));
    var ChartAxis = /** @class */ (function (_super) {
        __extends$a(ChartAxis, _super);
        function ChartAxis() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.keys = [];
            _this.direction = exports.ChartAxisDirection.Y;
            _this.boundSeries = [];
            _this._position = exports.ChartAxisPosition.Left;
            return _this;
        }
        Object.defineProperty(ChartAxis.prototype, "type", {
            get: function () {
                return this.constructor.type || '';
            },
            enumerable: true,
            configurable: true
        });
        ChartAxis.prototype.getMeta = function () {
            return {
                id: this.id,
                direction: this.direction,
                boundSeries: this.boundSeries,
            };
        };
        Object.defineProperty(ChartAxis.prototype, "position", {
            get: function () {
                return this._position;
            },
            set: function (value) {
                if (this._position !== value) {
                    this._position = value;
                    switch (value) {
                        case exports.ChartAxisPosition.Top:
                            this.direction = exports.ChartAxisDirection.X;
                            this.rotation = -90;
                            this.label.mirrored = true;
                            this.label.parallel = true;
                            break;
                        case exports.ChartAxisPosition.Right:
                            this.direction = exports.ChartAxisDirection.Y;
                            this.rotation = 0;
                            this.label.mirrored = true;
                            this.label.parallel = false;
                            break;
                        case exports.ChartAxisPosition.Bottom:
                            this.direction = exports.ChartAxisDirection.X;
                            this.rotation = -90;
                            this.label.mirrored = false;
                            this.label.parallel = true;
                            break;
                        case exports.ChartAxisPosition.Left:
                            this.direction = exports.ChartAxisDirection.Y;
                            this.rotation = 0;
                            this.label.mirrored = false;
                            this.label.parallel = false;
                            break;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        return ChartAxis;
    }(Axis));

    var __extends$b = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __read$5 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    // Instead of clamping the values outside of domain to the range,
    // return NaNs to indicate invalid input.
    function clamper$1(domain) {
        var _a;
        var a = domain[0];
        var b = domain[domain.length - 1];
        if (a > b) {
            _a = __read$5([b, a], 2), a = _a[0], b = _a[1];
        }
        return function (x) { return x >= a && x <= b ? x : NaN; };
    }
    var NumberAxis = /** @class */ (function (_super) {
        __extends$b(NumberAxis, _super);
        function NumberAxis() {
            var _this = _super.call(this, new LinearScale()) || this;
            _this._nice = true;
            _this._min = NaN;
            _this._max = NaN;
            _this.scale.clamper = clamper$1;
            return _this;
        }
        Object.defineProperty(NumberAxis.prototype, "nice", {
            get: function () {
                return this._nice;
            },
            set: function (value) {
                if (this._nice !== value) {
                    this._nice = value;
                    if (value && this.scale.nice) {
                        this.scale.nice(this.tick.count);
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        NumberAxis.prototype.setDomain = function (domain, primaryTickCount) {
            var _a = this, scale = _a.scale, min = _a.min, max = _a.max;
            if (domain.length > 2) {
                domain = extent(domain, isContinuous, Number) || [0, 1];
            }
            domain = [
                isNaN(min) ? domain[0] : min,
                isNaN(max) ? domain[1] : max
            ];
            if (primaryTickCount) {
                // when `primaryTickCount` is supplied the current axis is a secondary axis which needs to be aligned to
                // the primary by constraining the tick count to the primary axis tick count
                var _b = __read$5(calculateNiceSecondaryAxis(domain, primaryTickCount), 2), d = _b[0], ticks = _b[1];
                scale.domain = d;
                this.ticks = ticks;
                return;
            }
            else {
                scale.domain = domain;
                this.onLabelFormatChange(this.label.format); // not sure why this is required?
                this.scale.clamp = true;
                if (this.nice && this.scale.nice) {
                    this.scale.nice(this.tick.count);
                }
            }
        };
        Object.defineProperty(NumberAxis.prototype, "domain", {
            get: function () {
                return this.scale.domain;
            },
            set: function (domain) {
                this.setDomain(domain);
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NumberAxis.prototype, "min", {
            get: function () {
                return this._min;
            },
            set: function (value) {
                if (this._min !== value) {
                    this._min = value;
                    if (!isNaN(value)) {
                        this.scale.domain = [value, this.scale.domain[1]];
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NumberAxis.prototype, "max", {
            get: function () {
                return this._max;
            },
            set: function (value) {
                if (this._max !== value) {
                    this._max = value;
                    if (!isNaN(value)) {
                        this.scale.domain = [this.scale.domain[0], value];
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        NumberAxis.prototype.formatDatum = function (datum) {
            return datum.toFixed(2);
        };
        NumberAxis.className = 'NumberAxis';
        NumberAxis.type = 'number';
        return NumberAxis;
    }(ChartAxis));

    var __read$6 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    /**
     * Maps a discrete domain to a continuous numeric range.
     * See https://github.com/d3/d3-scale#band-scales for more info.
     */
    var BandScale = /** @class */ (function () {
        function BandScale() {
            this.type = 'band';
            /**
             * Maps datum to its index in the {@link domain} array.
             * Used to check for duplicate datums (not allowed).
             */
            this.index = new Map();
            /**
             * The output range values for datum at each index.
             */
            this.ordinalRange = [];
            /**
             * Contains unique datums only. Since `{}` is used in place of `Map`
             * for IE11 compatibility, the datums are converted `toString` before
             * the uniqueness check.
             */
            this._domain = [];
            this._range = [0, 1];
            this._bandwidth = 1;
            /**
             * The ratio of the range that is reserved for space between bands.
             */
            this._paddingInner = 0;
            /**
             * The ratio of the range that is reserved for space before the first
             * and after the last band.
             */
            this._paddingOuter = 0;
            this._round = false;
            /**
             * How the leftover range is distributed.
             * `0.5` - equal distribution of space before the first and after the last band,
             * with bands effectively centered within the range.
             */
            this._align = 0.5;
        }
        Object.defineProperty(BandScale.prototype, "domain", {
            get: function () {
                return this._domain;
            },
            set: function (values) {
                var domain = this._domain;
                domain.length = 0;
                this.index = new Map();
                var index = this.index;
                // In case one wants to have duplicate domain values, for example, two 'Italy' categories,
                // one should use objects rather than strings for domain values like so:
                // { toString: () => 'Italy' }
                // { toString: () => 'Italy' }
                values.forEach(function (value) {
                    if (index.get(value) === undefined) {
                        index.set(value, domain.push(value) - 1);
                    }
                });
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "range", {
            get: function () {
                return this._range;
            },
            set: function (values) {
                this._range[0] = values[0];
                this._range[1] = values[1];
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        BandScale.prototype.ticks = function () {
            return this._domain;
        };
        BandScale.prototype.convert = function (d) {
            var i = this.index.get(d);
            if (i === undefined) {
                return NaN;
            }
            var r = this.ordinalRange[i];
            if (r === undefined) {
                return NaN;
            }
            return r;
        };
        Object.defineProperty(BandScale.prototype, "bandwidth", {
            get: function () {
                return this._bandwidth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "padding", {
            get: function () {
                return this._paddingInner;
            },
            set: function (value) {
                value = Math.max(0, Math.min(1, value));
                this._paddingInner = value;
                this._paddingOuter = value;
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "paddingInner", {
            get: function () {
                return this._paddingInner;
            },
            set: function (value) {
                this._paddingInner = Math.max(0, Math.min(1, value)); // [0, 1]
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "paddingOuter", {
            get: function () {
                return this._paddingOuter;
            },
            set: function (value) {
                this._paddingOuter = Math.max(0, Math.min(1, value)); // [0, 1]
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "round", {
            get: function () {
                return this._round;
            },
            set: function (value) {
                this._round = value;
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BandScale.prototype, "align", {
            get: function () {
                return this._align;
            },
            set: function (value) {
                this._align = Math.max(0, Math.min(1, value)); // [0, 1]
                this.rescale();
            },
            enumerable: true,
            configurable: true
        });
        BandScale.prototype.rescale = function () {
            var _a;
            var n = this._domain.length;
            if (!n) {
                return;
            }
            var _b = __read$6(this._range, 2), a = _b[0], b = _b[1];
            var reversed = b < a;
            if (reversed) {
                _a = __read$6([b, a], 2), a = _a[0], b = _a[1];
            }
            var step = (b - a) / Math.max(1, n - this._paddingInner + this._paddingOuter * 2);
            if (this._round) {
                step = Math.floor(step);
            }
            a += (b - a - step * (n - this._paddingInner)) * this._align;
            this._bandwidth = step * (1 - this._paddingInner);
            if (this._round) {
                a = Math.round(a);
                this._bandwidth = Math.round(this._bandwidth);
            }
            var values = [];
            for (var i = 0; i < n; i++) {
                values.push(a + step * i);
            }
            this.ordinalRange = reversed ? values.reverse() : values;
        };
        return BandScale;
    }());

    var __extends$c = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var CategoryAxis = /** @class */ (function (_super) {
        __extends$c(CategoryAxis, _super);
        function CategoryAxis() {
            var _this = _super.call(this, new BandScale()) || this;
            _this.scale.paddingInner = 0.2;
            _this.scale.paddingOuter = 0.3;
            return _this;
        }
        Object.defineProperty(CategoryAxis.prototype, "paddingInner", {
            get: function () {
                return this.scale.paddingInner;
            },
            set: function (value) {
                this.scale.paddingInner = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(CategoryAxis.prototype, "paddingOuter", {
            get: function () {
                return this.scale.paddingOuter;
            },
            set: function (value) {
                this.scale.paddingOuter = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(CategoryAxis.prototype, "domain", {
            get: function () {
                return this.scale.domain.slice();
            },
            set: function (values) {
                // Prevent duplicate categories.
                this.scale.domain = values
                    .filter(function (s, i, arr) { return arr.indexOf(s) === i; });
            },
            enumerable: true,
            configurable: true
        });
        CategoryAxis.className = 'CategoryAxis';
        CategoryAxis.type = 'category';
        return CategoryAxis;
    }(ChartAxis));

    /**
     * The tree layout is calculated in abstract x/y coordinates, where the root is at (0, 0)
     * and the tree grows downward from the root.
     */
    var TreeNode = /** @class */ (function () {
        function TreeNode(label, parent, number) {
            if (label === void 0) { label = ''; }
            if (number === void 0) { number = 0; }
            this.x = 0;
            this.y = 0;
            this.subtreeLeft = NaN;
            this.subtreeRight = NaN;
            this.screenX = 0;
            this.screenY = 0;
            this.children = [];
            this.leafCount = 0;
            this.prelim = 0;
            this.mod = 0;
            this.ancestor = this;
            this.change = 0;
            this.shift = 0;
            this.label = label;
            // screenX and screenY are meant to be recomputed from (layout) x and y
            // when the tree is resized (without performing another layout)
            this.parent = parent;
            this.depth = parent ? parent.depth + 1 : 0;
            this.number = number;
        }
        TreeNode.prototype.getLeftSibling = function () {
            return this.number > 0 && this.parent ? this.parent.children[this.number - 1] : undefined;
        };
        TreeNode.prototype.getLeftmostSibling = function () {
            return this.number > 0 && this.parent ? this.parent.children[0] : undefined;
        };
        // traverse the left contour of a subtree, return the successor of v on this contour
        TreeNode.prototype.nextLeft = function () {
            return this.children ? this.children[0] : this.thread;
        };
        // traverse the right contour of a subtree, return the successor of v on this contour
        TreeNode.prototype.nextRight = function () {
            return this.children ? this.children[this.children.length - 1] : this.thread;
        };
        TreeNode.prototype.getSiblings = function () {
            var _this = this;
            return this.parent ? this.parent.children.filter(function (_, i) { return i !== _this.number; }) : [];
        };
        return TreeNode;
    }());
    /**
     * Converts an array of ticks, where each tick has an array of labels, to a label tree.
     * If `pad` is `true`, will ensure that every branch matches the depth of the tree by
     * creating empty labels.
     */
    function ticksToTree(ticks, pad) {
        if (pad === void 0) { pad = true; }
        var root = new TreeNode();
        var depth = 0;
        if (pad) {
            ticks.forEach(function (tick) { return depth = Math.max(depth, tick.labels.length); });
        }
        ticks.forEach(function (tick) {
            if (pad) {
                while (tick.labels.length < depth) {
                    tick.labels.unshift('');
                }
            }
            insertTick(root, tick);
        });
        return root;
    }
    function insertTick(root, tick) {
        var pathParts = tick.labels.slice().reverse(); // path elements from root to leaf label
        var lastPartIndex = pathParts.length - 1;
        pathParts.forEach(function (pathPart, partIndex) {
            var children = root.children;
            var existingNode = find(children, function (child) { return child.label === pathPart; });
            var isNotLeaf = partIndex !== lastPartIndex;
            if (existingNode && isNotLeaf) { // the isNotLeaf check is to allow duplicate leafs
                root = existingNode;
            }
            else {
                var node = new TreeNode(pathPart, root);
                node.number = children.length;
                children.push(node);
                if (isNotLeaf) {
                    root = node;
                }
            }
        });
    }
    // Shift the subtree.
    function moveSubtree(wm, wp, shift) {
        var subtrees = wp.number - wm.number;
        var ratio = shift / subtrees;
        wp.change -= ratio;
        wp.shift += shift;
        wm.change += ratio;
        wp.prelim += shift;
        wp.mod += shift;
    }
    function ancestor(vim, v, defaultAncestor) {
        return v.getSiblings().indexOf(vim.ancestor) >= 0 ? vim.ancestor : defaultAncestor;
    }
    // Spaces out the children.
    function executeShifts(v) {
        var children = v.children;
        if (children) {
            var shift = 0;
            var change = 0;
            for (var i = children.length - 1; i >= 0; i--) {
                var w = children[i];
                w.prelim += shift;
                w.mod += shift;
                change += w.change;
                shift += w.shift + change;
            }
        }
    }
    // Moves current subtree with v as the root if some nodes are conflicting in space.
    function apportion(v, defaultAncestor, distance) {
        var w = v.getLeftSibling();
        if (w) {
            var vop = v;
            var vip = v;
            var vim = w;
            var vom = vip.getLeftmostSibling();
            var sip = vip.mod;
            var sop = vop.mod;
            var sim = vim.mod;
            var som = vom.mod;
            while (vim.nextRight() && vip.nextLeft()) {
                vim = vim.nextRight();
                vip = vip.nextLeft();
                vom = vom.nextLeft();
                vop = vop.nextRight();
                vop.ancestor = v;
                var shift = (vim.prelim + sim) - (vip.prelim + sip) + distance;
                if (shift > 0) {
                    moveSubtree(ancestor(vim, v, defaultAncestor), v, shift);
                    sip += shift;
                    sop += shift;
                }
                sim += vim.mod;
                sip += vip.mod;
                som += vom.mod;
                sop += vop.mod;
            }
            if (vim.nextRight() && !vop.nextRight()) {
                vop.thread = vim.nextRight();
                vop.mod += sim - sop;
            }
            else {
                if (vip.nextLeft() && !vom.nextLeft()) {
                    vom.thread = vip.nextLeft();
                    vom.mod += sip - som;
                }
                defaultAncestor = v;
            }
        }
        return defaultAncestor;
    }
    // Compute the preliminary x-coordinate of node and its children (recursively).
    function firstWalk(node, distance) {
        var children = node.children;
        if (children.length) {
            var defaultAncestor_1 = children[0];
            children.forEach(function (child) {
                firstWalk(child, distance);
                defaultAncestor_1 = apportion(child, defaultAncestor_1, distance);
            });
            executeShifts(node);
            var midpoint = (children[0].prelim + children[children.length - 1].prelim) / 2;
            var leftSibling = node.getLeftSibling();
            if (leftSibling) {
                node.prelim = leftSibling.prelim + distance;
                node.mod = node.prelim - midpoint;
            }
            else {
                node.prelim = midpoint;
            }
        }
        else {
            var leftSibling = node.getLeftSibling();
            node.prelim = leftSibling ? leftSibling.prelim + distance : 0;
        }
    }
    var Dimensions = /** @class */ (function () {
        function Dimensions() {
            this.top = Infinity;
            this.right = -Infinity;
            this.bottom = -Infinity;
            this.left = Infinity;
        }
        Dimensions.prototype.update = function (node, xy) {
            var _a = xy(node), x = _a.x, y = _a.y;
            if (x > this.right) {
                this.right = x;
            }
            if (x < this.left) {
                this.left = x;
            }
            if (y > this.bottom) {
                this.bottom = y;
            }
            if (y < this.top) {
                this.top = y;
            }
        };
        return Dimensions;
    }());
    function secondWalk(v, m, layout) {
        v.x = v.prelim + m;
        v.y = v.depth;
        layout.update(v);
        v.children.forEach(function (w) { return secondWalk(w, m + v.mod, layout); });
    }
    // After the second walk the parent nodes are positioned at the center of their immediate children.
    // If we want the parent nodes to be positioned at the center of the subtree for which they are roots,
    // we need a third walk to adjust the positions.
    function thirdWalk(v) {
        var children = v.children;
        var leafCount = 0;
        children.forEach(function (w) {
            thirdWalk(w);
            if (w.children.length) {
                leafCount += w.leafCount;
            }
            else {
                leafCount++;
            }
        });
        v.leafCount = leafCount;
        if (children.length) {
            v.subtreeLeft = children[0].subtreeLeft;
            v.subtreeRight = children[v.children.length - 1].subtreeRight;
            v.x = (v.subtreeLeft + v.subtreeRight) / 2;
        }
        else {
            v.subtreeLeft = v.x;
            v.subtreeRight = v.x;
        }
    }
    function treeLayout(root) {
        var layout = new TreeLayout;
        firstWalk(root, 1);
        secondWalk(root, -root.prelim, layout);
        thirdWalk(root);
        return layout;
    }
    var TreeLayout = /** @class */ (function () {
        function TreeLayout() {
            this.dimensions = new Dimensions;
            this.leafCount = 0;
            this.nodes = [];
            // One might want to process leaf nodes separately from the rest of the tree.
            // For example, position labels corresponding to leafs vertically, rather than horizontally.
            this.leafNodes = [];
            this.nonLeafNodes = [];
            this.depth = 0;
        }
        TreeLayout.prototype.update = function (node) {
            this.dimensions.update(node, function (node) { return ({ x: node.x, y: node.y }); });
            if (!node.children.length) {
                this.leafCount++;
                this.leafNodes.push(node);
            }
            else {
                this.nonLeafNodes.push(node);
            }
            if (node.depth > this.depth) {
                this.depth = node.depth;
            }
            this.nodes.push(node);
        };
        TreeLayout.prototype.resize = function (width, height, shiftX, shiftY, flipX) {
            if (shiftX === void 0) { shiftX = 0; }
            if (shiftY === void 0) { shiftY = 0; }
            if (flipX === void 0) { flipX = false; }
            var xSteps = this.leafCount - 1;
            var ySteps = this.depth;
            var dimensions = this.dimensions;
            var scalingX = 1;
            var scalingY = 1;
            if (width > 0 && xSteps) {
                var existingSpacingX = (dimensions.right - dimensions.left) / xSteps;
                var desiredSpacingX = width / xSteps;
                scalingX = desiredSpacingX / existingSpacingX;
                if (flipX) {
                    scalingX = -scalingX;
                }
            }
            if (height > 0 && ySteps) {
                var existingSpacingY = (dimensions.bottom - dimensions.top) / ySteps;
                var desiredSpacingY = height / ySteps;
                scalingY = desiredSpacingY / existingSpacingY;
            }
            var screenDimensions = new Dimensions();
            this.nodes.forEach(function (node) {
                node.screenX = node.x * scalingX;
                node.screenY = node.y * scalingY;
                screenDimensions.update(node, function (node) { return ({ x: node.screenX, y: node.screenY }); });
            });
            // Normalize so that root top and leftmost leaf left start at zero.
            var offsetX = -screenDimensions.left;
            var offsetY = -screenDimensions.top;
            this.nodes.forEach(function (node) {
                node.screenX += offsetX + shiftX;
                node.screenY += offsetY + shiftY;
            });
        };
        return TreeLayout;
    }());

    var __extends$d = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var GroupedCategoryAxisLabel = /** @class */ (function (_super) {
        __extends$d(GroupedCategoryAxisLabel, _super);
        function GroupedCategoryAxisLabel() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.grid = false;
            return _this;
        }
        return GroupedCategoryAxisLabel;
    }(AxisLabel));
    var GroupedCategoryAxis = /** @class */ (function (_super) {
        __extends$d(GroupedCategoryAxis, _super);
        function GroupedCategoryAxis() {
            var _this = _super.call(this, new BandScale()) || this;
            // Label scale (labels are positionsed between ticks, tick count = label count + 1).
            // We don't call is `labelScale` for consistency with other axes.
            _this.tickScale = new BandScale();
            _this.longestSeparatorLength = 0;
            _this.translation = {
                x: 0,
                y: 0
            };
            /**
             * Axis rotation angle in degrees.
             */
            _this.rotation = 0;
            _this.line = {
                width: 1,
                color: 'rgba(195, 195, 195, 1)'
            };
            // readonly tick = new AxisTick();
            _this.label = new GroupedCategoryAxisLabel();
            /**
             * The color of the labels.
             * Use `undefined` rather than `rgba(0, 0, 0, 0)` to make labels invisible.
             */
            _this.labelColor = 'rgba(87, 87, 87, 1)';
            var _a = _this, group = _a.group, tickScale = _a.tickScale, scale = _a.scale;
            scale.paddingOuter = 0.1;
            scale.paddingInner = scale.paddingOuter * 2;
            _this.requestedRange = scale.range.slice();
            _this.scale = scale;
            tickScale.paddingInner = 1;
            tickScale.paddingOuter = 0;
            _this.gridLineSelection = Selection.select(group).selectAll();
            _this.axisLineSelection = Selection.select(group).selectAll();
            _this.separatorSelection = Selection.select(group).selectAll();
            _this.labelSelection = Selection.select(group).selectAll();
            return _this;
            // this.group.append(this.bboxRect); // debug (bbox)
        }
        Object.defineProperty(GroupedCategoryAxis.prototype, "domain", {
            get: function () {
                return this.scale.domain;
            },
            set: function (domainValues) {
                // Prevent duplicate categories.
                var values = domainValues.filter(function (s, i, arr) { return arr.indexOf(s) === i; });
                this.scale.domain = values;
                var tickTree = ticksToTree(values);
                this.tickTreeLayout = treeLayout(tickTree);
                var domain = values.slice();
                domain.push('');
                this.tickScale.domain = domain;
                this.resizeTickTree();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(GroupedCategoryAxis.prototype, "range", {
            get: function () {
                return this.requestedRange.slice();
            },
            set: function (value) {
                this.requestedRange = value.slice();
                this.updateRange();
            },
            enumerable: true,
            configurable: true
        });
        GroupedCategoryAxis.prototype.updateRange = function () {
            var _a = this, rr = _a.requestedRange, vr = _a.visibleRange, scale = _a.scale;
            var span = (rr[1] - rr[0]) / (vr[1] - vr[0]);
            var shift = span * vr[0];
            var start = rr[0] - shift;
            this.tickScale.range = scale.range = [start, start + span];
            this.resizeTickTree();
        };
        GroupedCategoryAxis.prototype.resizeTickTree = function () {
            var s = this.scale;
            var range = s.domain.length ? [s.convert(s.domain[0]), s.convert(s.domain[s.domain.length - 1])] : s.range;
            var layout = this.tickTreeLayout;
            var lineHeight = this.lineHeight;
            if (layout) {
                layout.resize(Math.abs(range[1] - range[0]), layout.depth * lineHeight, (Math.min(range[0], range[1]) || 0) + (s.bandwidth || 0) / 2, -layout.depth * lineHeight, (range[1] - range[0]) < 0);
            }
        };
        Object.defineProperty(GroupedCategoryAxis.prototype, "lineHeight", {
            get: function () {
                return this.label.fontSize * 1.5;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(GroupedCategoryAxis.prototype, "gridLength", {
            get: function () {
                return this._gridLength;
            },
            /**
             * The length of the grid. The grid is only visible in case of a non-zero value.
             */
            set: function (value) {
                // Was visible and now invisible, or was invisible and now visible.
                if (this._gridLength && !value || !this._gridLength && value) {
                    this.gridLineSelection = this.gridLineSelection.remove().setData([]);
                    this.labelSelection = this.labelSelection.remove().setData([]);
                }
                this._gridLength = value;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * Creates/removes/updates the scene graph nodes that constitute the axis.
         * Supposed to be called _manually_ after changing _any_ of the axis properties.
         * This allows to bulk set axis properties before updating the nodes.
         * The node changes made by this method are rendered on the next animation frame.
         * We could schedule this method call automatically on the next animation frame
         * when any of the axis properties change (the way we do when properties of scene graph's
         * nodes change), but this will mean that we first wait for the next animation
         * frame to make changes to the nodes of the axis, then wait for another animation
         * frame to render those changes. It's nice to have everything update automatically,
         * but this extra level of async indirection will not just introduce an unwanted delay,
         * it will also make it harder to reason about the program.
         */
        GroupedCategoryAxis.prototype.update = function () {
            var _this = this;
            var _a = this, group = _a.group, scale = _a.scale, label = _a.label, tickScale = _a.tickScale, requestedRange = _a.requestedRange;
            var rangeStart = scale.range[0];
            var rangeEnd = scale.range[1];
            var rangeLength = Math.abs(rangeEnd - rangeStart);
            var bandwidth = (rangeLength / scale.domain.length) || 0;
            var parallelLabels = label.parallel;
            var rotation = toRadians(this.rotation);
            var isHorizontal = Math.abs(Math.cos(rotation)) < 1e-8;
            var labelRotation = normalizeAngle360(toRadians(this.label.rotation));
            group.translationX = this.translation.x;
            group.translationY = this.translation.y;
            group.rotation = rotation;
            var title = this.title;
            // The Text `node` of the Caption is not used to render the title of the grouped category axis.
            // The phantom root of the tree layout is used instead.
            if (title) {
                title.node.visible = false;
            }
            var lineHeight = this.lineHeight;
            // Render ticks and labels.
            var tickTreeLayout = this.tickTreeLayout;
            var labels = scale.ticks();
            var treeLabels = tickTreeLayout ? tickTreeLayout.nodes : [];
            var isLabelTree = tickTreeLayout ? tickTreeLayout.depth > 1 : false;
            var ticks = tickScale.ticks();
            // The side of the axis line to position the labels on.
            // -1 = left (default)
            //  1 = right
            var sideFlag = label.mirrored ? 1 : -1;
            // When labels are parallel to the axis line, the `parallelFlipFlag` is used to
            // flip the labels to avoid upside-down text, when the axis is rotated
            // such that it is in the right hemisphere, i.e. the angle of rotation
            // is in the [0, π] interval.
            // The rotation angle is normalized, so that we have an easier time checking
            // if it's in the said interval. Since the axis is always rendered vertically
            // and then rotated, zero rotation means 12 (not 3) o-clock.
            // -1 = flip
            //  1 = don't flip (default)
            var parallelFlipRotation = normalizeAngle360(rotation);
            var parallelFlipFlag = (!labelRotation && parallelFlipRotation >= 0 && parallelFlipRotation <= Math.PI) ? -1 : 1;
            var regularFlipRotation = normalizeAngle360(rotation - Math.PI / 2);
            // Flip if the axis rotation angle is in the top hemisphere.
            var regularFlipFlag = (!labelRotation && regularFlipRotation >= 0 && regularFlipRotation <= Math.PI) ? -1 : 1;
            var updateGridLines = this.gridLineSelection.setData(this.gridLength ? ticks : []);
            updateGridLines.exit.remove();
            var enterGridLines = updateGridLines.enter.append(Line);
            var gridLineSelection = updateGridLines.merge(enterGridLines);
            var updateLabels = this.labelSelection.setData(treeLabels);
            updateLabels.exit.remove();
            var enterLabels = updateLabels.enter.append(Text);
            var labelSelection = updateLabels.merge(enterLabels);
            var labelFormatter = label.formatter;
            var maxLeafLabelWidth = 0;
            labelSelection
                .each(function (node, datum, index) {
                node.fontStyle = label.fontStyle;
                node.fontWeight = label.fontWeight;
                node.fontSize = label.fontSize;
                node.fontFamily = label.fontFamily;
                node.fill = label.color;
                node.textBaseline = parallelFlipFlag === -1 ? 'bottom' : 'hanging';
                // label.textBaseline = parallelLabels && !labelRotation
                //     ? (sideFlag * parallelFlipFlag === -1 ? 'hanging' : 'bottom')
                //     : 'middle';
                node.textAlign = 'center';
                node.translationX = datum.screenY - label.fontSize * 0.25;
                node.translationY = datum.screenX;
                if (index === 0) { // use the phantom root as the axis title
                    if (title && title.enabled && labels.length > 0) {
                        node.visible = true;
                        node.text = title.text;
                        node.fontSize = title.fontSize;
                        node.fontStyle = title.fontStyle;
                        node.fontWeight = title.fontWeight;
                        node.fontFamily = title.fontFamily;
                        node.textBaseline = 'hanging';
                    }
                    else {
                        node.visible = false;
                    }
                }
                else {
                    node.text = labelFormatter
                        ? labelFormatter({
                            value: String(datum.label),
                            index: index
                        })
                        : String(datum.label);
                    node.visible =
                        datum.screenX >= requestedRange[0] &&
                            datum.screenX <= requestedRange[1];
                }
                var bbox = node.computeBBox();
                if (bbox && bbox.width > maxLeafLabelWidth) {
                    maxLeafLabelWidth = bbox.width;
                }
            });
            var labelX = sideFlag * label.padding;
            var autoRotation = parallelLabels
                ? parallelFlipFlag * Math.PI / 2
                : (regularFlipFlag === -1 ? Math.PI : 0);
            var labelGrid = this.label.grid;
            var separatorData = [];
            labelSelection.each(function (label, datum, index) {
                label.x = labelX;
                label.rotationCenterX = labelX;
                if (!datum.children.length) {
                    label.rotation = labelRotation;
                    label.textAlign = 'end';
                    label.textBaseline = 'middle';
                }
                else {
                    label.translationX -= maxLeafLabelWidth - lineHeight + _this.label.padding;
                    if (isHorizontal) {
                        label.rotation = autoRotation;
                    }
                    else {
                        label.rotation = -Math.PI / 2;
                    }
                }
                // Calculate positions of label separators for all nodes except the root.
                // Each separator is placed to the top of the current label.
                if (datum.parent && isLabelTree) {
                    var y = !datum.children.length
                        ? datum.screenX - bandwidth / 2
                        : datum.screenX - datum.leafCount * bandwidth / 2;
                    if (!datum.children.length) {
                        if ((datum.number !== datum.children.length - 1) || labelGrid) {
                            separatorData.push({
                                y: y,
                                x1: 0,
                                x2: -maxLeafLabelWidth - _this.label.padding * 2,
                                toString: function () { return String(index); }
                            });
                        }
                    }
                    else {
                        var x = -maxLeafLabelWidth - _this.label.padding * 2 + datum.screenY;
                        separatorData.push({
                            y: y,
                            x1: x + lineHeight,
                            x2: x,
                            toString: function () { return String(index); }
                        });
                    }
                }
            });
            // Calculate the position of the long separator on the far bottom of the axis.
            var minX = 0;
            separatorData.forEach(function (d) { return minX = Math.min(minX, d.x2); });
            this.longestSeparatorLength = Math.abs(minX);
            separatorData.push({
                y: Math.max(rangeStart, rangeEnd),
                x1: 0,
                x2: minX,
                toString: function () { return String(separatorData.length); }
            });
            var updateSeparators = this.separatorSelection.setData(separatorData);
            updateSeparators.exit.remove();
            var enterSeparators = updateSeparators.enter.append(Line);
            var separatorSelection = updateSeparators.merge(enterSeparators);
            this.separatorSelection = separatorSelection;
            var epsilon = 0.0000001;
            separatorSelection.each(function (line, datum, i) {
                line.x1 = datum.x1;
                line.x2 = datum.x2;
                line.y1 = datum.y;
                line.y2 = datum.y;
                line.visible = datum.y >= requestedRange[0] - epsilon && datum.y <= requestedRange[1] + epsilon;
                line.stroke = _this.tick.color;
                line.fill = undefined;
                line.strokeWidth = 1;
            });
            this.gridLineSelection = gridLineSelection;
            this.labelSelection = labelSelection;
            // Render axis lines.
            var lineCount = tickTreeLayout ? tickTreeLayout.depth + 1 : 1;
            var lines = [];
            for (var i = 0; i < lineCount; i++) {
                lines.push(i);
            }
            var updateAxisLines = this.axisLineSelection.setData(lines);
            updateAxisLines.exit.remove();
            var enterAxisLines = updateAxisLines.enter.append(Line);
            var axisLineSelection = updateAxisLines.merge(enterAxisLines);
            this.axisLineSelection = axisLineSelection;
            axisLineSelection.each(function (line, _, index) {
                var x = index > 0 ? -maxLeafLabelWidth - _this.label.padding * 2 - (index - 1) * lineHeight : 0;
                line.x1 = x;
                line.x2 = x;
                line.y1 = requestedRange[0];
                line.y2 = requestedRange[1];
                line.strokeWidth = _this.line.width;
                line.stroke = _this.line.color;
                line.visible = labels.length > 0 && (index === 0 || (labelGrid && isLabelTree));
            });
            if (this.gridLength) {
                var styles_1 = this.gridStyle;
                var styleCount_1 = styles_1.length;
                gridLineSelection
                    .each(function (line, datum, index) {
                    var y = Math.round(tickScale.convert(datum));
                    line.x1 = 0;
                    line.x2 = -sideFlag * _this.gridLength;
                    line.y1 = y;
                    line.y2 = y;
                    line.visible = y >= requestedRange[0] && y <= requestedRange[1] &&
                        Math.abs(line.parent.translationY - rangeStart) > 1;
                    var style = styles_1[index % styleCount_1];
                    line.stroke = style.stroke;
                    line.strokeWidth = _this.tick.width;
                    line.lineDash = style.lineDash;
                    line.fill = undefined;
                });
            }
            // debug (bbox)
            // const bbox = this.computeBBox();
            // const bboxRect = this.bboxRect;
            // bboxRect.x = bbox.x;
            // bboxRect.y = bbox.y;
            // bboxRect.width = bbox.width;
            // bboxRect.height = bbox.height;
        };
        GroupedCategoryAxis.prototype.computeBBox = function (options) {
            var includeTitle = !options || !options.excludeTitle;
            var left = Infinity;
            var right = -Infinity;
            var top = Infinity;
            var bottom = -Infinity;
            this.labelSelection.each(function (label, _, index) {
                // The label itself is rotated, but not translated, the group that
                // contains it is. So to capture the group transform in the label bbox
                // calculation we combine the transform matrices of the label and the group.
                // Depending on the timing of the `axis.computeBBox()` method call, we may
                // not have the group's and the label's transform matrices updated yet (because
                // the transform matrix is not recalculated whenever a node's transform attributes
                // change, instead it's marked for recalculation on the next frame by setting
                // the node's `dirtyTransform` flag to `true`), so we force them to update
                // right here by calling `computeTransformMatrix`.
                if (index > 0 || includeTitle) { // first node is the root (title)
                    label.computeTransformMatrix();
                    var matrix = Matrix.flyweight(label.matrix);
                    var labelBBox = label.computeBBox();
                    if (labelBBox) {
                        var bbox = matrix.transformBBox(labelBBox);
                        left = Math.min(left, bbox.x);
                        right = Math.max(right, bbox.x + bbox.width);
                        top = Math.min(top, bbox.y);
                        bottom = Math.max(bottom, bbox.y + bbox.height);
                    }
                }
            });
            return new BBox(left, top, Math.max(right - left, this.longestSeparatorLength), bottom - top);
        };
        // debug (bbox)
        // private bboxRect = (() => {
        //     const rect = new Rect();
        //     rect.fill = undefined;
        //     rect.stroke = 'red';
        //     rect.strokeWidth = 1;
        //     rect.strokeOpacity = 0.2;
        //     return rect;
        // })();
        GroupedCategoryAxis.className = 'GroupedCategoryAxis';
        GroupedCategoryAxis.type = 'groupedCategory';
        return GroupedCategoryAxis;
    }(ChartAxis));

    var __extends$e = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var t0 = new Date;
    var t1 = new Date;
    /**
     * The interval methods don't mutate Date parameters.
     */
    var TimeInterval = /** @class */ (function () {
        function TimeInterval(floor, offset) {
            this._floor = floor;
            this._offset = offset;
        }
        /**
         * Returns a new date representing the latest interval boundary date before or equal to date.
         * For example, `day.floor(date)` typically returns 12:00 AM local time on the given date.
         * @param date
         */
        TimeInterval.prototype.floor = function (date) {
            date = new Date(+date);
            this._floor(date);
            return date;
        };
        /**
         * Returns a new date representing the earliest interval boundary date after or equal to date.
         * @param date
         */
        TimeInterval.prototype.ceil = function (date) {
            date = new Date(+date - 1);
            this._floor(date);
            this._offset(date, 1);
            this._floor(date);
            return date;
        };
        /**
         * Returns a new date representing the closest interval boundary date to date.
         * @param date
         */
        TimeInterval.prototype.round = function (date) {
            var d0 = this.floor(date);
            var d1 = this.ceil(date);
            var ms = +date;
            return ms - d0.getTime() < d1.getTime() - ms ? d0 : d1;
        };
        /**
         * Returns a new date equal to date plus step intervals.
         * @param date
         * @param step
         */
        TimeInterval.prototype.offset = function (date, step) {
            if (step === void 0) { step = 1; }
            date = new Date(+date);
            this._offset(date, Math.floor(step));
            return date;
        };
        /**
         * Returns an array of dates representing every interval boundary after or equal to start (inclusive) and before stop (exclusive).
         * @param start
         * @param stop
         * @param step
         */
        TimeInterval.prototype.range = function (start, stop, step) {
            if (step === void 0) { step = 1; }
            var range = [];
            start = this.ceil(start);
            step = Math.floor(step);
            if (start > stop || step <= 0) {
                return range;
            }
            var previous;
            do {
                previous = new Date(+start);
                range.push(previous);
                this._offset(start, step);
                this._floor(start);
            } while (previous < start && start < stop);
            return range;
        };
        // Returns an interval that is a subset of this interval.
        // For example, to create an interval that return 1st, 11th, 21st and 31st of each month:
        // day.filter(date => (date.getDate() - 1) % 10 === 0)
        TimeInterval.prototype.filter = function (test) {
            var _this = this;
            var floor = function (date) {
                if (date >= date) {
                    while (_this._floor(date), !test(date)) {
                        date.setTime(date.getTime() - 1);
                    }
                }
                return date;
            };
            var offset = function (date, step) {
                if (date >= date) {
                    if (step < 0) {
                        while (++step <= 0) {
                            do {
                                _this._offset(date, -1);
                            } while (!test(date));
                        }
                    }
                    else {
                        while (--step >= 0) {
                            do {
                                _this._offset(date, 1);
                            } while (!test(date));
                        }
                    }
                }
                return date;
            };
            return new TimeInterval(floor, offset);
        };
        return TimeInterval;
    }());
    var CountableTimeInterval = /** @class */ (function (_super) {
        __extends$e(CountableTimeInterval, _super);
        function CountableTimeInterval(floor, offset, count, field) {
            var _this = _super.call(this, floor, offset) || this;
            _this._count = count;
            _this._field = field;
            return _this;
        }
        /**
         * Returns the number of interval boundaries after start (exclusive) and before or equal to end (inclusive).
         * @param start
         * @param end
         */
        CountableTimeInterval.prototype.count = function (start, end) {
            t0.setTime(+start);
            t1.setTime(+end);
            this._floor(t0);
            this._floor(t1);
            return Math.floor(this._count(t0, t1));
        };
        /**
         * Returns a filtered view of this interval representing every step'th date.
         * The meaning of step is dependent on this interval’s parent interval as defined by the `field` function.
         * @param step
         */
        CountableTimeInterval.prototype.every = function (step) {
            var _this = this;
            var result;
            step = Math.floor(step);
            if (isFinite(step) && step > 0) {
                if (step > 1) {
                    var field_1 = this._field;
                    if (field_1) {
                        result = this.filter(function (d) { return field_1(d) % step === 0; });
                    }
                    else {
                        result = this.filter(function (d) { return _this.count(0, d) % step === 0; });
                    }
                }
                else {
                    result = this;
                }
            }
            return result;
        };
        return CountableTimeInterval;
    }(TimeInterval));

    function floor(date) {
        return date;
    }
    function offset(date, milliseconds) {
        date.setTime(date.getTime() + milliseconds);
    }
    function count(start, end) {
        return end.getTime() - start.getTime();
    }
    var millisecond = new CountableTimeInterval(floor, offset, count);

    // Common time unit sizes in milliseconds.
    var durationSecond = 1000;
    var durationMinute = durationSecond * 60;
    var durationHour = durationMinute * 60;
    var durationDay = durationHour * 24;
    var durationWeek = durationDay * 7;
    var durationMonth = durationDay * 30;
    var durationYear = durationDay * 365;

    function floor$1(date) {
        date.setTime(date.getTime() - date.getMilliseconds());
    }
    function offset$1(date, seconds) {
        date.setTime(date.getTime() + seconds * durationSecond);
    }
    function count$1(start, end) {
        return (end.getTime() - start.getTime()) / durationSecond;
    }
    var second = new CountableTimeInterval(floor$1, offset$1, count$1);

    function floor$2(date) {
        date.setTime(date.getTime() - date.getMilliseconds() - date.getSeconds() * durationSecond);
    }
    function offset$2(date, minutes) {
        date.setTime(date.getTime() + minutes * durationMinute);
    }
    function count$2(start, end) {
        return (end.getTime() - start.getTime()) / durationMinute;
    }
    function field(date) {
        return date.getMinutes();
    }
    var minute = new CountableTimeInterval(floor$2, offset$2, count$2, field);

    function floor$3(date) {
        date.setTime(date.getTime() - date.getMilliseconds() - date.getSeconds() * durationSecond - date.getMinutes() * durationMinute);
    }
    function offset$3(date, hours) {
        date.setTime(date.getTime() + hours * durationHour);
    }
    function count$3(start, end) {
        return (end.getTime() - start.getTime()) / durationHour;
    }
    function field$1(date) {
        return date.getHours();
    }
    var hour = new CountableTimeInterval(floor$3, offset$3, count$3, field$1);

    function floor$4(date) {
        date.setHours(0, 0, 0, 0);
    }
    function offset$4(date, days) {
        date.setDate(date.getDate() + days);
    }
    function count$4(start, end) {
        var tzMinuteDelta = end.getTimezoneOffset() - start.getTimezoneOffset();
        return (end.getTime() - start.getTime() - tzMinuteDelta * durationMinute) / durationDay;
    }
    function field$2(date) {
        return date.getDate() - 1;
    }
    var day = new CountableTimeInterval(floor$4, offset$4, count$4, field$2);

    // Set date to n-th day of the week.
    function weekday(n) {
        // Sets the `date` to the start of the `n`-th day of the current week.
        // n == 0 is Sunday.
        function floor(date) {
            //                  1..31            1..7
            date.setDate(date.getDate() - (date.getDay() + 7 - n) % 7);
            date.setHours(0, 0, 0, 0); // h, m, s, ms
        }
        // Offset the date by the given number of weeks.
        function offset(date, weeks) {
            date.setDate(date.getDate() + weeks * 7);
        }
        // Count the number of weeks between the start and end dates.
        function count(start, end) {
            var msDelta = end.getTime() - start.getTime();
            var tzMinuteDelta = end.getTimezoneOffset() - start.getTimezoneOffset();
            return (msDelta - tzMinuteDelta * durationMinute) / durationWeek;
        }
        return new CountableTimeInterval(floor, offset, count);
    }
    var sunday = weekday(0);
    var monday = weekday(1);
    var tuesday = weekday(2);
    var wednesday = weekday(3);
    var thursday = weekday(4);
    var friday = weekday(5);
    var saturday = weekday(6);

    function floor$5(date) {
        date.setDate(1);
        date.setHours(0, 0, 0, 0);
    }
    function offset$5(date, months) {
        date.setMonth(date.getMonth() + months);
    }
    function count$5(start, end) {
        return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
    }
    function field$3(date) {
        return date.getMonth();
    }
    var month = new CountableTimeInterval(floor$5, offset$5, count$5, field$3);

    function floor$6(date) {
        date.setMonth(0, 1);
        date.setHours(0, 0, 0, 0);
    }
    function offset$6(date, years) {
        date.setFullYear(date.getFullYear() + years);
    }
    function count$6(start, end) {
        return end.getFullYear() - start.getFullYear();
    }
    function field$4(date) {
        return date.getFullYear();
    }
    var year = new CountableTimeInterval(floor$6, offset$6, count$6, field$4);

    function floor$7(date) {
        date.setUTCHours(0, 0, 0, 0);
    }
    function offset$7(date, days) {
        date.setUTCDate(date.getUTCDate() + days);
    }
    function count$7(start, end) {
        return (end.getTime() - start.getTime()) / durationDay;
    }
    function field$5(date) {
        return date.getUTCDate() - 1;
    }
    var utcDay = new CountableTimeInterval(floor$7, offset$7, count$7, field$5);

    function floor$8(date) {
        date.setUTCMonth(0, 1);
        date.setUTCHours(0, 0, 0, 0);
    }
    function offset$8(date, years) {
        date.setUTCFullYear(date.getUTCFullYear() + years);
    }
    function count$8(start, end) {
        return end.getUTCFullYear() - start.getUTCFullYear();
    }
    function field$6(date) {
        return date.getUTCFullYear();
    }
    var utcYear = new CountableTimeInterval(floor$8, offset$8, count$8, field$6);

    // Set date to n-th day of the week.
    function weekday$1(n) {
        // Sets the `date` to the start of the `n`-th day of the current week.
        // n == 0 is Sunday.
        function floor(date) {
            date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - n) % 7);
            date.setHours(0, 0, 0, 0); // h, m, s, ms
        }
        // Offset the date by the given number of weeks.
        function offset(date, weeks) {
            date.setUTCDate(date.getUTCDate() + weeks * 7);
        }
        // Count the number of weeks between the start and end dates.
        function count(start, end) {
            return (end.getTime() - start.getTime()) / durationWeek;
        }
        return new CountableTimeInterval(floor, offset, count);
    }
    var utcSunday = weekday$1(0);
    var utcMonday = weekday$1(1);
    var utcTuesday = weekday$1(2);
    var utcWednesday = weekday$1(3);
    var utcThursday = weekday$1(4);
    var utcFriday = weekday$1(5);
    var utcSaturday = weekday$1(6);

    function localDate(d) {
        // For JS Dates the [0, 100) interval is a time warp, a fast forward to the 20th century.
        // For example, -1 is -0001 BC, 0 is already 1900 AD.
        if (d.y >= 0 && 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 utcDate(d) {
        if (d.y >= 0 && 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));
    }
    /**
     * Creates a lookup map for array of names to go from a name to index.
     * @param names
     */
    function formatLookup(names) {
        var map = {};
        for (var i = 0, n = names.length; i < n; i++) {
            map[names[i].toLowerCase()] = i;
        }
        return map;
    }
    function newYear(y) {
        return {
            y: y,
            m: 0,
            d: 1,
            H: 0,
            M: 0,
            S: 0,
            L: 0
        };
    }
    var percentCharCode = 37;
    var numberRe = /^\s*\d+/; // ignores next directive
    var percentRe = /^%/;
    var requoteRe = /[\\^$*+?|[\]().{}]/g;
    /**
     * Prepends any character in the `requoteRe` set with a backslash.
     * @param s
     */
    var requote = function (s) { return s.replace(requoteRe, '\\$&'); }; // $& - matched substring
    /**
     * Returns a RegExp that matches any string that starts with any of the given names (case insensitive).
     * @param names
     */
    var formatRe = function (names) { return new RegExp('^(?:' + names.map(requote).join('|') + ')', 'i'); };
    // A map of padding modifiers to padding strings. Default is `0`.
    var pads = {
        '-': '',
        '_': ' ',
        '0': '0'
    };
    function pad(value, fill, width) {
        var sign = value < 0 ? '-' : '';
        var string = String(sign ? -value : value);
        var length = string.length;
        return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
    }
    /**
     * Create a new time-locale-based object which exposes time-formatting
     * methods for the specified locale definition.
     *
     * @param timeLocale A time locale definition.
     */
    function formatLocale$1(timeLocale) {
        var lDateTime = timeLocale.dateTime;
        var lDate = timeLocale.date;
        var lTime = timeLocale.time;
        var lPeriods = timeLocale.periods;
        var lWeekdays = timeLocale.days;
        var lShortWeekdays = timeLocale.shortDays;
        var lMonths = timeLocale.months;
        var lShortMonths = timeLocale.shortMonths;
        var periodRe = formatRe(lPeriods);
        var periodLookup = formatLookup(lPeriods);
        var weekdayRe = formatRe(lWeekdays);
        var weekdayLookup = formatLookup(lWeekdays);
        var shortWeekdayRe = formatRe(lShortWeekdays);
        var shortWeekdayLookup = formatLookup(lShortWeekdays);
        var monthRe = formatRe(lMonths);
        var monthLookup = formatLookup(lMonths);
        var shortMonthRe = formatRe(lShortMonths);
        var shortMonthLookup = formatLookup(lShortMonths);
        var formats = {
            'a': formatShortWeekday,
            'A': formatWeekday,
            'b': formatShortMonth,
            'B': formatMonth,
            'c': undefined,
            'd': formatDayOfMonth,
            'e': formatDayOfMonth,
            'f': formatMicroseconds,
            'H': formatHour24,
            'I': formatHour12,
            'j': formatDayOfYear,
            'L': formatMilliseconds,
            'm': formatMonthNumber,
            'M': formatMinutes,
            'p': formatPeriod,
            'Q': formatUnixTimestamp,
            's': formatUnixTimestampSeconds,
            'S': formatSeconds,
            'u': formatWeekdayNumberMonday,
            'U': formatWeekNumberSunday,
            'V': formatWeekNumberISO,
            'w': formatWeekdayNumberSunday,
            'W': formatWeekNumberMonday,
            'x': undefined,
            'X': undefined,
            'y': formatYear,
            'Y': formatFullYear,
            'Z': formatZone,
            '%': formatLiteralPercent
        };
        var utcFormats = {
            'a': formatUTCShortWeekday,
            'A': formatUTCWeekday,
            'b': formatUTCShortMonth,
            'B': formatUTCMonth,
            'c': undefined,
            'd': formatUTCDayOfMonth,
            'e': formatUTCDayOfMonth,
            'f': formatUTCMicroseconds,
            'H': formatUTCHour24,
            'I': formatUTCHour12,
            'j': formatUTCDayOfYear,
            'L': formatUTCMilliseconds,
            'm': formatUTCMonthNumber,
            'M': formatUTCMinutes,
            'p': formatUTCPeriod,
            'Q': formatUnixTimestamp,
            's': formatUnixTimestampSeconds,
            'S': formatUTCSeconds,
            'u': formatUTCWeekdayNumberMonday,
            'U': formatUTCWeekNumberSunday,
            'V': formatUTCWeekNumberISO,
            'w': formatUTCWeekdayNumberSunday,
            'W': formatUTCWeekNumberMonday,
            'x': undefined,
            'X': undefined,
            '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,
            'H': parseHour24,
            'I': parseHour24,
            'j': parseDayOfYear,
            'L': parseMilliseconds,
            'm': parseMonthNumber,
            'M': parseMinutes,
            'p': parsePeriod,
            '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
        };
        // Recursive definitions.
        formats.x = newFormat(lDate, formats);
        formats.X = newFormat(lTime, formats);
        formats.c = newFormat(lDateTime, formats);
        utcFormats.x = newFormat(lDate, utcFormats);
        utcFormats.X = newFormat(lTime, utcFormats);
        utcFormats.c = newFormat(lDateTime, utcFormats);
        function newParse(specifier, newDate) {
            return function (str) {
                var d = newYear(1900);
                var i = parseSpecifier(d, specifier, str += '', 0);
                if (i != str.length) {
                    return undefined;
                }
                // If a UNIX timestamp is specified, return it.
                if ('Q' in d) {
                    return new Date(d.Q);
                }
                // The am-pm flag is 0 for AM, and 1 for PM.
                if ('p' in d) {
                    d.H = d.H % 12 + d.p * 12;
                }
                // Convert day-of-week and week-of-year to day-of-year.
                if ('V' in d) {
                    if (d.V < 1 || d.V > 53) {
                        return undefined;
                    }
                    if (!('w' in d)) {
                        d.w = 1;
                    }
                    if ('Z' in d) {
                        var week = utcDate(newYear(d.y));
                        var day$1 = week.getUTCDay();
                        week = day$1 > 4 || day$1 === 0 ? utcMonday.ceil(week) : utcMonday.floor(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 {
                        var week = newDate(newYear(d.y));
                        var day$1 = week.getDay();
                        week = day$1 > 4 || day$1 === 0 ? monday.ceil(week) : monday.floor(week);
                        week = day.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;
                    }
                    var day$1 = 'Z' in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
                    d.m = 0;
                    d.d = 'W' in d ? (d.w + 6) % 7 + d.W * 7 - (day$1 + 5) % 7 : d.w + d.U * 7 - (day$1 + 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 utcDate(d);
                }
                // Otherwise, all fields are in local time.
                return newDate(d);
            };
        }
        /**
         * Creates a new function that formats the given Date or timestamp according to specifier.
         * @param specifier
         * @param formats
         */
        function newFormat(specifier, formats) {
            return function (date) {
                var string = [];
                var n = specifier.length;
                var i = -1;
                var j = 0;
                if (!(date instanceof Date)) {
                    date = new Date(+date);
                }
                while (++i < n) {
                    if (specifier.charCodeAt(i) === percentCharCode) {
                        string.push(specifier.slice(j, i)); // copy the chunks of specifier with no directives as is
                        var c = specifier.charAt(++i);
                        var pad_1 = pads[c];
                        if (pad_1 != undefined) { // if format directive has a padding modifier in front of it
                            c = specifier.charAt(++i); // fetch the directive itself
                        }
                        else {
                            pad_1 = c === 'e' ? ' ' : '0'; // use the default padding modifier
                        }
                        var format = formats[c];
                        if (format) { // if the directive has a corresponding formatting function
                            c = format(date, pad_1); // replace the directive with the formatted date
                        }
                        string.push(c);
                        j = i + 1;
                    }
                }
                string.push(specifier.slice(j, i));
                return string.join('');
            };
        }
        // Simultaneously walks over the specifier and the parsed string, populating the `d` map with parsed values.
        // The returned number is expected to equal the length of the parsed `string`, if parsing succeeded.
        function parseSpecifier(d, specifier, string, j) {
            // i - `specifier` string index
            // j - parsed `string` index
            var i = 0;
            var n = specifier.length;
            var m = string.length;
            while (i < n) {
                if (j >= m) {
                    return -1;
                }
                var code = specifier.charCodeAt(i++);
                if (code === percentCharCode) {
                    var char = specifier.charAt(i++);
                    var parse = parses[(char in pads ? specifier.charAt(i++) : char)];
                    if (!parse || ((j = parse(d, string, j)) < 0)) {
                        return -1;
                    }
                }
                else if (code != string.charCodeAt(j++)) {
                    return -1;
                }
            }
            return j;
        }
        // ----------------------------- formats ----------------------------------
        function formatMicroseconds(date, fill) {
            return formatMilliseconds(date, fill) + '000';
        }
        function formatMilliseconds(date, fill) {
            return pad(date.getMilliseconds(), fill, 3);
        }
        function formatSeconds(date, fill) {
            return pad(date.getSeconds(), fill, 2);
        }
        function formatMinutes(date, fill) {
            return pad(date.getMinutes(), fill, 2);
        }
        function formatHour12(date, fill) {
            return pad(date.getHours() % 12 || 12, fill, 2);
        }
        function formatHour24(date, fill) {
            return pad(date.getHours(), fill, 2);
        }
        function formatPeriod(date) {
            return lPeriods[date.getHours() >= 12 ? 1 : 0];
        }
        function formatShortWeekday(date) {
            return lShortWeekdays[date.getDay()];
        }
        function formatWeekday(date) {
            return lWeekdays[date.getDay()];
        }
        function formatWeekdayNumberMonday(date) {
            var dayOfWeek = date.getDay();
            return dayOfWeek === 0 ? 7 : dayOfWeek;
        }
        function formatWeekNumberSunday(date, fill) {
            return pad(sunday.count(year.floor(date), date), fill, 2);
        }
        function formatWeekNumberISO(date, fill) {
            var day = date.getDay();
            date = (day >= 4 || day === 0) ? thursday.floor(date) : thursday.ceil(date);
            var yearStart = year.floor(date);
            return pad(thursday.count(yearStart, date) + (yearStart.getDay() === 4 ? 1 : 0), fill, 2);
        }
        function formatWeekdayNumberSunday(date) {
            return date.getDay();
        }
        function formatWeekNumberMonday(date, fill) {
            return pad(monday.count(year.floor(date), date), fill, 2);
        }
        function formatDayOfMonth(date, fill) {
            return pad(date.getDate(), fill, 2);
        }
        function formatDayOfYear(date, fill) {
            return pad(1 + day.count(year.floor(date), date), fill, 3);
        }
        function formatShortMonth(date) {
            return lShortMonths[date.getMonth()];
        }
        function formatMonth(date) {
            return lMonths[date.getMonth()];
        }
        function formatMonthNumber(date, fill) {
            return pad(date.getMonth() + 1, fill, 2);
        }
        function formatYear(date, fill) {
            return pad(date.getFullYear() % 100, fill, 2);
        }
        function formatFullYear(date, fill) {
            return pad(date.getFullYear() % 10000, fill, 4);
        }
        function formatZone(date) {
            var z = date.getTimezoneOffset();
            return (z > 0 ? '-' : (z *= -1, '+')) + pad(Math.floor(z / 60), '0', 2) + pad(z % 60, '0', 2);
        }
        // -------------------------- UTC formats -----------------------------------
        function formatUTCMicroseconds(date, fill) {
            return formatUTCMilliseconds(date, fill) + '000';
        }
        function formatUTCMilliseconds(date, fill) {
            return pad(date.getUTCMilliseconds(), fill, 3);
        }
        function formatUTCSeconds(date, fill) {
            return pad(date.getUTCSeconds(), fill, 2);
        }
        function formatUTCMinutes(date, fill) {
            return pad(date.getUTCMinutes(), fill, 2);
        }
        function formatUTCHour12(date, fill) {
            return pad(date.getUTCHours() % 12 || 12, fill, 2);
        }
        function formatUTCHour24(date, fill) {
            return pad(date.getUTCHours(), fill, 2);
        }
        function formatUTCPeriod(date) {
            return lPeriods[date.getUTCHours() >= 12 ? 1 : 0];
        }
        function formatUTCDayOfMonth(date, fill) {
            return pad(date.getUTCDate(), fill, 2);
        }
        function formatUTCDayOfYear(date, fill) {
            return pad(1 + utcDay.count(utcYear.floor(date), date), fill, 3);
        }
        function formatUTCMonthNumber(date, fill) {
            return pad(date.getUTCMonth() + 1, fill, 2);
        }
        function formatUTCShortMonth(date) {
            return lShortMonths[date.getUTCMonth()];
        }
        function formatUTCMonth(date) {
            return lMonths[date.getUTCMonth()];
        }
        function formatUTCShortWeekday(date) {
            return lShortWeekdays[date.getUTCDay()];
        }
        function formatUTCWeekday(date) {
            return lWeekdays[date.getUTCDay()];
        }
        function formatUTCWeekdayNumberMonday(date) {
            var dayOfWeek = date.getUTCDay();
            return dayOfWeek === 0 ? 7 : dayOfWeek;
        }
        function formatUTCWeekNumberSunday(date, fill) {
            return pad(utcSunday.count(utcYear.floor(date), date), fill, 2);
        }
        function formatUTCWeekNumberISO(date, fill) {
            var day = date.getUTCDay();
            date = (day >= 4 || day === 0) ? utcThursday.floor(date) : utcThursday.ceil(date);
            var yearStart = utcYear.floor(date);
            return pad(utcThursday.count(yearStart, date) + (yearStart.getUTCDay() === 4 ? 1 : 0), fill, 4);
        }
        function formatUTCWeekdayNumberSunday(date) {
            return date.getUTCDay();
        }
        function formatUTCWeekNumberMonday(date, fill) {
            return pad(utcMonday.count(utcYear.floor(date), date), fill, 2);
        }
        function formatUTCYear(date, fill) {
            return pad(date.getUTCFullYear() % 100, fill, 2);
        }
        function formatUTCFullYear(date, fill) {
            return pad(date.getUTCFullYear() % 10000, fill, 4);
        }
        function formatUTCZone() {
            return '+0000';
        }
        function formatLiteralPercent(date) {
            return '%';
        }
        function formatUnixTimestamp(date) {
            return date.getTime();
        }
        function formatUnixTimestampSeconds(date) {
            return Math.floor(date.getTime() / 1000);
        }
        // ------------------------------- parsers ------------------------------------
        function parseMicroseconds(d, string, i) {
            var n = numberRe.exec(string.slice(i, i + 6));
            return n ? (d.L = Math.floor(parseFloat(n[0]) / 1000), 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 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 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 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 parsePeriod(d, string, i) {
            var n = periodRe.exec(string.slice(i));
            return n ? (d.p = periodLookup[n[0].toLowerCase()], 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 parseShortWeekday(d, string, i) {
            var n = shortWeekdayRe.exec(string.slice(i));
            return n ? (d.w = shortWeekdayLookup[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[n[0].toLowerCase()], 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 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 parseShortMonth(d, string, i) {
            var n = shortMonthRe.exec(string.slice(i));
            return n ? (d.m = shortMonthLookup[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[n[0].toLowerCase()], i + n[0].length) : -1;
        }
        function parseMonthNumber(d, string, i) {
            var n = numberRe.exec(string.slice(i, i + 2));
            return n ? (d.m = parseFloat(n[0]) - 1, i + n[0].length) : -1;
        }
        function parseLocaleDateTime(d, string, i) {
            return parseSpecifier(d, lDateTime, string, i);
        }
        function parseLocaleDate(d, string, i) {
            return parseSpecifier(d, lDate, string, i);
        }
        function parseLocaleTime(d, string, i) {
            return parseSpecifier(d, lTime, string, i);
        }
        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.Q = (+n[0]) * 1000, 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 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 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 parseLiteralPercent(d, string, i) {
            var n = percentRe.exec(string.slice(i, i + 1));
            return n ? i + n[0].length : -1;
        }
        return {
            format: function (specifier) {
                var f = newFormat(specifier, formats);
                f.toString = function () { return specifier; };
                return f;
            },
            parse: function (specifier) {
                var p = newParse(specifier, localDate);
                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, utcDate);
                p.toString = function () { return specifier; };
                return p;
            }
        };
    }

    var locale;
    setDefaultLocale({
        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 setDefaultLocale(definition) {
        return locale = formatLocale$1(definition);
    }

    var __extends$f = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __read$7 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var TimeScale = /** @class */ (function (_super) {
        __extends$f(TimeScale, _super);
        function TimeScale() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.type = 'time';
            _this.year = year;
            _this.month = month;
            _this.week = sunday;
            _this.day = day;
            _this.hour = hour;
            _this.minute = minute;
            _this.second = second;
            _this.millisecond = millisecond;
            _this.format = locale.format;
            /**
             * Array of default tick intervals in the following format:
             *
             *     [
             *         interval (unit of time),
             *         number of units (step),
             *         the length of that number of units in milliseconds
             *     ]
             */
            _this.tickIntervals = [
                [_this.second, 1, durationSecond],
                [_this.second, 5, 5 * durationSecond],
                [_this.second, 15, 15 * durationSecond],
                [_this.second, 30, 30 * durationSecond],
                [_this.minute, 1, durationMinute],
                [_this.minute, 5, 5 * durationMinute],
                [_this.minute, 15, 15 * durationMinute],
                [_this.minute, 30, 30 * durationMinute],
                [_this.hour, 1, durationHour],
                [_this.hour, 3, 3 * durationHour],
                [_this.hour, 6, 6 * durationHour],
                [_this.hour, 12, 12 * durationHour],
                [_this.day, 1, durationDay],
                [_this.day, 2, 2 * durationDay],
                [_this.week, 1, durationWeek],
                [_this.month, 1, durationMonth],
                [_this.month, 3, 3 * durationMonth],
                [_this.year, 1, durationYear]
            ];
            _this.formatMillisecond = _this.format('.%L');
            _this.formatSecond = _this.format(':%S');
            _this.formatMinute = _this.format('%I:%M');
            _this.formatHour = _this.format('%I %p');
            _this.formatDay = _this.format('%a %d');
            _this.formatWeek = _this.format('%b %d');
            _this.formatMonth = _this.format('%B');
            _this.formatYear = _this.format('%Y');
            _this._domain = [new Date(2000, 0, 1), new Date(2000, 0, 2)];
            return _this;
        }
        TimeScale.prototype.defaultTickFormat = function (date) {
            return (this.second.floor(date) < date
                ? this.formatMillisecond
                : this.minute.floor(date) < date
                    ? this.formatSecond
                    : this.hour.floor(date) < date
                        ? this.formatMinute
                        : this.day.floor(date) < date
                            ? this.formatHour
                            : this.month.floor(date) < date
                                ? (this.week.floor(date) < date ? this.formatDay : this.formatWeek)
                                : this.year.floor(date) < date
                                    ? this.formatMonth
                                    : this.formatYear)(date);
        };
        /**
         *
         * @param interval If the `interval` is a number, it's interpreted as the desired tick count
         * and the method tries to pick an appropriate interval automatically, based on the extent of the domain.
         * If the `interval` is `undefined`, it defaults to `10`.
         * If the `interval` is a time interval, simply use it.
         * @param start The start time (timestamp).
         * @param stop The end time (timestamp).
         * @param step Number of intervals between ticks.
         */
        TimeScale.prototype.tickInterval = function (interval, start, stop, step) {
            var _a;
            if (typeof interval === 'number') {
                var tickCount = interval;
                var tickIntervals = this.tickIntervals;
                var target = Math.abs(stop - start) / tickCount;
                var i = complexBisectRight(tickIntervals, target, function (interval) { return interval[2]; });
                if (i === tickIntervals.length) {
                    step = tickStep(start / durationYear, stop / durationYear, tickCount);
                    interval = this.year;
                }
                else if (i) {
                    _a = __read$7(tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i], 2), interval = _a[0], step = _a[1];
                }
                else {
                    step = Math.max(tickStep(start, stop, interval), 1);
                    interval = this.millisecond;
                }
            }
            return step == undefined ? interval : interval.every(step);
        };
        Object.defineProperty(TimeScale.prototype, "domain", {
            get: function () {
                return _super.prototype.getDomain.call(this).map(function (t) { return new Date(t); });
            },
            set: function (values) {
                _super.prototype.setDomain.call(this, Array.prototype.map.call(values, function (t) { return t instanceof Date ? +t : +new Date(+t); }));
            },
            enumerable: true,
            configurable: true
        });
        TimeScale.prototype.invert = function (y) {
            return new Date(_super.prototype.invert.call(this, y));
        };
        /**
         * Returns uniformly-spaced dates that represent the scale's domain.
         * @param interval The desired tick count or a time interval object.
         */
        TimeScale.prototype.ticks = function (interval) {
            if (interval === void 0) { interval = 10; }
            var d = _super.prototype.getDomain.call(this);
            var t0 = d[0];
            var t1 = d[d.length - 1];
            var reverse = t1 < t0;
            if (reverse) {
                var _ = t0;
                t0 = t1;
                t1 = _;
            }
            var t = this.tickInterval(interval, t0, t1);
            var i = t ? t.range(t0, t1 + 1) : []; // inclusive stop
            return reverse ? i.reverse() : i;
        };
        /**
         * Returns a time format function suitable for displaying tick values.
         * @param count Ignored. Used only to satisfy the {@link Scale} interface.
         * @param specifier If the specifier string is provided, this method is equivalent to
         * the {@link TimeLocaleObject.format} method.
         * If no specifier is provided, this method returns the default time format function.
         */
        TimeScale.prototype.tickFormat = function (count, specifier) {
            return specifier == undefined ? this.defaultTickFormat.bind(this) : this.format(specifier);
        };
        /**
         * Extends the domain so that it starts and ends on nice round values.
         * This method typically modifies the scale’s domain, and may only extend the bounds to the nearest round value.
         * @param interval
         */
        TimeScale.prototype.nice = function (interval) {
            if (interval === void 0) { interval = 10; }
            var d = _super.prototype.getDomain.call(this);
            var i = this.tickInterval(interval, d[0], d[d.length - 1]);
            if (i) {
                this.domain = this._nice(d, i);
            }
        };
        TimeScale.prototype._nice = function (domain, interval) {
            var _a, _b;
            domain = domain.slice();
            var i0 = 0;
            var i1 = domain.length - 1;
            var x0 = domain[i0];
            var x1 = domain[i1];
            if (x1 < x0) {
                _a = __read$7([i1, i0], 2), i0 = _a[0], i1 = _a[1];
                _b = __read$7([x1, x0], 2), x0 = _b[0], x1 = _b[1];
            }
            domain[i0] = interval.floor(x0);
            domain[i1] = interval.ceil(x1);
            return domain;
        };
        return TimeScale;
    }(ContinuousScale));

    var __extends$g = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var TimeAxis = /** @class */ (function (_super) {
        __extends$g(TimeAxis, _super);
        function TimeAxis() {
            var _this = _super.call(this, new TimeScale()) || this;
            _this.datumFormat = '%m/%d/%y, %H:%M:%S';
            _this._nice = true;
            var scale = _this.scale;
            scale.clamp = true;
            _this.scale = scale;
            _this.datumFormatter = scale.tickFormat(_this.tick.count, _this.datumFormat);
            return _this;
        }
        Object.defineProperty(TimeAxis.prototype, "nice", {
            get: function () {
                return this._nice;
            },
            set: function (value) {
                if (this._nice !== value) {
                    this._nice = value;
                    if (value && this.scale.nice) {
                        this.scale.nice(10);
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(TimeAxis.prototype, "domain", {
            get: function () {
                return this.scale.domain;
            },
            set: function (domain) {
                if (domain.length > 2) {
                    domain = (extent(domain, isContinuous, Number) || [0, 1000]).map(function (x) { return new Date(x); });
                }
                this.scale.domain = domain;
                if (this.nice && this.scale.nice) {
                    this.scale.nice(10);
                }
            },
            enumerable: true,
            configurable: true
        });
        TimeAxis.prototype.onLabelFormatChange = function (format) {
            if (format) {
                _super.prototype.onLabelFormatChange.call(this, format);
            }
            else {
                // For time axis labels to look nice, even if date format wasn't set.
                this.labelFormatter = this.scale.tickFormat(this.tick.count, undefined);
            }
        };
        TimeAxis.prototype.formatDatum = function (datum) {
            return this.datumFormatter(datum);
        };
        TimeAxis.className = 'TimeAxis';
        TimeAxis.type = 'time';
        return TimeAxis;
    }(ChartAxis));

    var __read$8 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$8(arguments[i]));
        return ar;
    };
    var Scene = /** @class */ (function () {
        // As a rule of thumb, constructors with no parameters are preferred.
        // A few exceptions are:
        // - we absolutely need to know something at construction time (document)
        // - knowing something at construction time meaningfully improves performance (width, height)
        function Scene(document, width, height) {
            var _this = this;
            if (document === void 0) { document = window.document; }
            this.id = createId(this);
            this._dirty = false;
            this.animationFrameId = 0;
            this._root = null;
            this.debug = {
                renderFrameIndex: false,
                renderBoundingBoxes: false
            };
            this._frameIndex = 0;
            this.render = function () {
                var _a;
                var _b = _this, ctx = _b.ctx, root = _b.root, pendingSize = _b.pendingSize;
                _this.animationFrameId = 0;
                if (pendingSize) {
                    (_a = _this.canvas).resize.apply(_a, __spread(pendingSize));
                    _this.pendingSize = undefined;
                }
                if (root && !root.visible) {
                    _this.dirty = false;
                    return;
                }
                // start with a blank canvas, clear previous drawing
                ctx.clearRect(0, 0, _this.width, _this.height);
                if (root) {
                    ctx.save();
                    if (root.visible) {
                        root.render(ctx);
                    }
                    ctx.restore();
                }
                _this._frameIndex++;
                if (_this.debug.renderFrameIndex) {
                    ctx.fillStyle = 'white';
                    ctx.fillRect(0, 0, 40, 15);
                    ctx.fillStyle = 'black';
                    ctx.fillText(_this.frameIndex.toString(), 2, 10);
                }
                _this.dirty = false;
            };
            this.canvas = new HdpiCanvas(document, width, height);
            this.ctx = this.canvas.context;
        }
        Object.defineProperty(Scene.prototype, "container", {
            get: function () {
                return this.canvas.container;
            },
            set: function (value) {
                this.canvas.container = value;
            },
            enumerable: true,
            configurable: true
        });
        Scene.prototype.download = function (fileName) {
            this.canvas.download(fileName);
        };
        Scene.prototype.getDataURL = function (type) {
            return this.canvas.getDataURL(type);
        };
        Object.defineProperty(Scene.prototype, "width", {
            get: function () {
                return this.pendingSize ? this.pendingSize[0] : this.canvas.width;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Scene.prototype, "height", {
            get: function () {
                return this.pendingSize ? this.pendingSize[1] : this.canvas.height;
            },
            enumerable: true,
            configurable: true
        });
        Scene.prototype.resize = function (width, height) {
            width = Math.round(width);
            height = Math.round(height);
            if (width === this.width && height === this.height) {
                return;
            }
            this.pendingSize = [width, height];
            this.dirty = true;
        };
        Object.defineProperty(Scene.prototype, "dirty", {
            get: function () {
                return this._dirty;
            },
            set: function (dirty) {
                if (dirty) {
                    if (!this._dirty) {
                        this.animationFrameId = requestAnimationFrame(this.render);
                    }
                }
                else if (this.animationFrameId) {
                    cancelAnimationFrame(this.animationFrameId);
                    this.animationFrameId = 0;
                }
                this._dirty = dirty;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Scene.prototype, "root", {
            get: function () {
                return this._root;
            },
            set: function (node) {
                if (node === this._root) {
                    return;
                }
                if (this._root) {
                    this._root._setScene();
                }
                this._root = node;
                if (node) {
                    // If `node` is the root node of another scene ...
                    if (node.parent === null && node.scene && node.scene !== this) {
                        node.scene.root = null;
                    }
                    node._setScene(this);
                }
                this.dirty = true;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Scene.prototype, "frameIndex", {
            get: function () {
                return this._frameIndex;
            },
            enumerable: true,
            configurable: true
        });
        Scene.className = 'Scene';
        return Scene;
    }());

    var Gradient = /** @class */ (function () {
        function Gradient() {
            this.stops = [];
        }
        return Gradient;
    }());

    var __extends$h = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var LinearGradient = /** @class */ (function (_super) {
        __extends$h(LinearGradient, _super);
        function LinearGradient() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.angle = 0;
            return _this;
        }
        LinearGradient.prototype.createGradient = function (ctx, bbox) {
            var stops = this.stops;
            var radians = (this.angle % 360) * Math.PI / 180;
            var cos = Math.cos(radians);
            var sin = Math.sin(radians);
            var w = bbox.width;
            var h = bbox.height;
            var cx = bbox.x + w * 0.5;
            var cy = bbox.y + h * 0.5;
            if (w > 0 && h > 0) {
                var l = (Math.sqrt(h * h + w * w) * Math.abs(Math.cos(radians - Math.atan(h / w)))) / 2;
                var gradient_1 = ctx.createLinearGradient(cx + cos * l, cy + sin * l, cx - cos * l, cy - sin * l);
                stops.forEach(function (stop) {
                    gradient_1.addColorStop(stop.offset, stop.color);
                });
                return gradient_1;
            }
            return 'black';
        };
        return LinearGradient;
    }(Gradient));

    var __extends$i = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    (function (RectSizing) {
        RectSizing[RectSizing["Content"] = 0] = "Content";
        RectSizing[RectSizing["Border"] = 1] = "Border";
    })(exports.RectSizing || (exports.RectSizing = {}));
    var Rect = /** @class */ (function (_super) {
        __extends$i(Rect, _super);
        function Rect() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._x = 0;
            _this._y = 0;
            _this._width = 10;
            _this._height = 10;
            _this._radius = 0;
            /**
             * If `true`, the rect is aligned to the pixel grid for crisp looking lines.
             * Animated rects may not look nice with this option enabled, for example
             * when a rect is translated by a sub-pixel value on each frame.
             */
            _this._crisp = false;
            _this._gradient = false;
            _this.effectiveStrokeWidth = Shape.defaultStyles.strokeWidth;
            /**
             * Similar to https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
             */
            _this._sizing = exports.RectSizing.Content;
            return _this;
        }
        Object.defineProperty(Rect.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (value) {
                if (this._x !== value) {
                    this._x = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (value) {
                if (this._y !== value) {
                    this._y = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "width", {
            get: function () {
                return this._width;
            },
            set: function (value) {
                if (this._width !== value) {
                    this._width = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "height", {
            get: function () {
                return this._height;
            },
            set: function (value) {
                if (this._height !== value) {
                    this._height = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "radius", {
            get: function () {
                return this._radius;
            },
            set: function (value) {
                if (this._radius !== value) {
                    this._radius = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "crisp", {
            get: function () {
                return this._crisp;
            },
            set: function (value) {
                if (this._crisp !== value) {
                    this._crisp = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "gradient", {
            get: function () {
                return this._gradient;
            },
            set: function (value) {
                if (this._gradient !== value) {
                    this._gradient = value;
                    this.updateGradientInstance();
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Rect.prototype.updateGradientInstance = function () {
            if (this.gradient) {
                var fill = this.fill;
                if (fill) {
                    var gradient = new LinearGradient();
                    gradient.angle = 270;
                    gradient.stops = [{
                            offset: 0,
                            color: Color.fromString(fill).brighter().toString()
                        }, {
                            offset: 1,
                            color: Color.fromString(fill).darker().toString()
                        }];
                    this.gradientInstance = gradient;
                }
            }
            else {
                this.gradientInstance = undefined;
            }
        };
        Object.defineProperty(Rect.prototype, "fill", {
            get: function () {
                return this._fill;
            },
            set: function (value) {
                if (this._fill !== value) {
                    this._fill = value;
                    this.updateGradientInstance();
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "strokeWidth", {
            get: function () {
                return this._strokeWidth;
            },
            set: function (value) {
                if (this._strokeWidth !== value) {
                    this._strokeWidth = value;
                    // Normally, when the `lineWidth` changes, we only need to repaint the rect
                    // without updating the path. If the `isCrisp` is set to `true` however,
                    // we need to update the path to make sure the new stroke aligns to
                    // the pixel grid. This is the reason we override the `lineWidth` setter
                    // and getter here.
                    if (this.crisp || this.sizing === exports.RectSizing.Border) {
                        this.dirtyPath = true;
                    }
                    else {
                        this.effectiveStrokeWidth = value;
                        this.dirty = true;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Rect.prototype, "sizing", {
            get: function () {
                return this._sizing;
            },
            set: function (value) {
                if (this._sizing !== value) {
                    this._sizing = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Rect.prototype.updatePath = function () {
            var borderSizing = this.sizing === exports.RectSizing.Border;
            var path = this.path;
            path.clear();
            var x = this.x;
            var y = this.y;
            var width = this.width;
            var height = this.height;
            var strokeWidth;
            if (borderSizing) {
                var halfWidth = width / 2;
                var halfHeight = height / 2;
                strokeWidth = Math.min(this.strokeWidth, halfWidth, halfHeight);
                x = Math.min(x + strokeWidth / 2, x + halfWidth);
                y = Math.min(y + strokeWidth / 2, y + halfHeight);
                width = Math.max(width - strokeWidth, 0);
                height = Math.max(height - strokeWidth, 0);
            }
            else {
                strokeWidth = this.strokeWidth;
            }
            this.effectiveStrokeWidth = strokeWidth;
            if (this.crisp && !borderSizing) {
                var _a = this, a = _a.alignment, al = _a.align;
                path.rect(al(a, x), al(a, y), al(a, x, width), al(a, y, height));
            }
            else {
                path.rect(x, y, width, height);
            }
        };
        Rect.prototype.computeBBox = function () {
            var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
            return new BBox(x, y, width, height);
        };
        Rect.prototype.isPointInPath = function (x, y) {
            var point = this.transformPoint(x, y);
            var bbox = this.computeBBox();
            return bbox.containsPoint(point.x, point.y);
        };
        Rect.prototype.isPointInStroke = function (x, y) {
            return false;
        };
        Rect.prototype.fillStroke = function (ctx) {
            if (!this.scene) {
                return;
            }
            var pixelRatio = this.scene.canvas.pixelRatio || 1;
            if (this.fill) {
                if (this.gradientInstance) {
                    ctx.fillStyle = this.gradientInstance.createGradient(ctx, this.computeBBox());
                }
                else {
                    ctx.fillStyle = this.fill;
                }
                ctx.globalAlpha = this.opacity * this.fillOpacity;
                // The canvas context scaling (depends on the device's pixel ratio)
                // has no effect on shadows, so we have to account for the pixel ratio
                // manually here.
                var fillShadow = this.fillShadow;
                if (fillShadow && fillShadow.enabled) {
                    ctx.shadowColor = fillShadow.color;
                    ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = fillShadow.blur * pixelRatio;
                }
                ctx.fill();
            }
            ctx.shadowColor = 'rgba(0, 0, 0, 0)';
            if (this.stroke && this.effectiveStrokeWidth) {
                ctx.strokeStyle = this.stroke;
                ctx.globalAlpha = this.opacity * this.strokeOpacity;
                ctx.lineWidth = this.effectiveStrokeWidth;
                if (this.lineDash) {
                    ctx.setLineDash(this.lineDash);
                }
                if (this.lineDashOffset) {
                    ctx.lineDashOffset = this.lineDashOffset;
                }
                if (this.lineCap) {
                    ctx.lineCap = this.lineCap;
                }
                if (this.lineJoin) {
                    ctx.lineJoin = this.lineJoin;
                }
                var strokeShadow = this.strokeShadow;
                if (strokeShadow && strokeShadow.enabled) {
                    ctx.shadowColor = strokeShadow.color;
                    ctx.shadowOffsetX = strokeShadow.xOffset * pixelRatio;
                    ctx.shadowOffsetY = strokeShadow.yOffset * pixelRatio;
                    ctx.shadowBlur = strokeShadow.blur * pixelRatio;
                }
                ctx.stroke();
            }
        };
        Rect.className = 'Rect';
        return Rect;
    }(Path));

    var __extends$j = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Marker = /** @class */ (function (_super) {
        __extends$j(Marker, _super);
        function Marker() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._x = 0;
            _this._y = 0;
            _this._size = 12;
            return _this;
        }
        Object.defineProperty(Marker.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (value) {
                if (this._x !== value) {
                    this._x = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Marker.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (value) {
                if (this._y !== value) {
                    this._y = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Marker.prototype, "size", {
            get: function () {
                return this._size;
            },
            set: function (value) {
                if (this._size !== value) {
                    this._size = Math.abs(value);
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Marker.prototype.computeBBox = function () {
            var _a = this, x = _a.x, y = _a.y, size = _a.size;
            var half = size / 2;
            return new BBox(x - half, y - half, size, size);
        };
        return Marker;
    }(Path));

    var __extends$k = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Square = /** @class */ (function (_super) {
        __extends$k(Square, _super);
        function Square() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Square.prototype.updatePath = function () {
            var _a = this, path = _a.path, x = _a.x, y = _a.y;
            var hs = this.size / 2;
            var _b = this, a = _b.alignment, al = _b.align;
            path.clear();
            path.moveTo(al(a, x - hs), al(a, y - hs));
            path.lineTo(al(a, x + hs), al(a, y - hs));
            path.lineTo(al(a, x + hs), al(a, y + hs));
            path.lineTo(al(a, x - hs), al(a, y + hs));
            path.closePath();
        };
        Square.className = 'Square';
        return Square;
    }(Marker));

    var __extends$l = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var MarkerLabel = /** @class */ (function (_super) {
        __extends$l(MarkerLabel, _super);
        function MarkerLabel() {
            var _this = _super.call(this) || this;
            _this.label = new Text();
            _this._marker = new Square();
            _this._markerSize = 15;
            _this._spacing = 8;
            var label = _this.label;
            label.textBaseline = 'middle';
            label.fontSize = 12;
            label.fontFamily = 'Verdana, sans-serif';
            label.fill = 'black';
            // For better looking vertical alignment of labels to markers.
            label.y = HdpiCanvas.has.textMetrics ? 1 : 0;
            _this.append([_this.marker, label]);
            _this.update();
            return _this;
        }
        Object.defineProperty(MarkerLabel.prototype, "text", {
            get: function () {
                return this.label.text;
            },
            set: function (value) {
                this.label.text = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "fontStyle", {
            get: function () {
                return this.label.fontStyle;
            },
            set: function (value) {
                this.label.fontStyle = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "fontWeight", {
            get: function () {
                return this.label.fontWeight;
            },
            set: function (value) {
                this.label.fontWeight = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "fontSize", {
            get: function () {
                return this.label.fontSize;
            },
            set: function (value) {
                this.label.fontSize = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "fontFamily", {
            get: function () {
                return this.label.fontFamily;
            },
            set: function (value) {
                this.label.fontFamily = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "color", {
            get: function () {
                return this.label.fill;
            },
            set: function (value) {
                this.label.fill = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "marker", {
            get: function () {
                return this._marker;
            },
            set: function (value) {
                if (this._marker !== value) {
                    this.removeChild(this._marker);
                    this._marker = value;
                    this.appendChild(value);
                    this.update();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerSize", {
            get: function () {
                return this._markerSize;
            },
            set: function (value) {
                if (this._markerSize !== value) {
                    this._markerSize = value;
                    this.update();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerFill", {
            get: function () {
                return this.marker.fill;
            },
            set: function (value) {
                this.marker.fill = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerStroke", {
            get: function () {
                return this.marker.stroke;
            },
            set: function (value) {
                this.marker.stroke = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerStrokeWidth", {
            get: function () {
                return this.marker.strokeWidth;
            },
            set: function (value) {
                this.marker.strokeWidth = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerFillOpacity", {
            get: function () {
                return this.marker.fillOpacity;
            },
            set: function (value) {
                this.marker.fillOpacity = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "markerStrokeOpacity", {
            get: function () {
                return this.marker.strokeOpacity;
            },
            set: function (value) {
                this.marker.strokeOpacity = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "opacity", {
            get: function () {
                return this.marker.opacity;
            },
            set: function (value) {
                this.marker.opacity = value;
                this.label.opacity = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(MarkerLabel.prototype, "spacing", {
            get: function () {
                return this._spacing;
            },
            set: function (value) {
                if (this._spacing !== value) {
                    this._spacing = value;
                    this.update();
                }
            },
            enumerable: true,
            configurable: true
        });
        MarkerLabel.prototype.update = function () {
            var marker = this.marker;
            var markerSize = this.markerSize;
            marker.size = markerSize;
            this.label.x = markerSize / 2 + this.spacing;
        };
        MarkerLabel.className = 'MarkerLabel';
        return MarkerLabel;
    }(Group));

    var __extends$m = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Circle = /** @class */ (function (_super) {
        __extends$m(Circle, _super);
        function Circle() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Circle.prototype.updatePath = function () {
            var _a = this, x = _a.x, y = _a.y, path = _a.path, size = _a.size;
            var r = size / 2;
            path.clear();
            path.cubicArc(x, y, r, r, 0, 0, Math.PI * 2, 0);
            path.closePath();
        };
        Circle.className = 'Circle';
        return Circle;
    }(Marker));

    var __extends$n = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Cross = /** @class */ (function (_super) {
        __extends$n(Cross, _super);
        function Cross() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Cross.prototype.updatePath = function () {
            var _a = this, x = _a.x, y = _a.y;
            var _b = this, path = _b.path, size = _b.size;
            var s = size / 4.2;
            path.clear();
            path.moveTo(x -= s, y);
            path.lineTo(x -= s, y -= s);
            path.lineTo(x += s, y -= s);
            path.lineTo(x += s, y += s);
            path.lineTo(x += s, y -= s);
            path.lineTo(x += s, y += s);
            path.lineTo(x -= s, y += s);
            path.lineTo(x += s, y += s);
            path.lineTo(x -= s, y += s);
            path.lineTo(x -= s, y -= s);
            path.lineTo(x -= s, y += s);
            path.lineTo(x -= s, y -= s);
            path.closePath();
        };
        Cross.className = 'Cross';
        return Cross;
    }(Marker));

    var __extends$o = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Diamond = /** @class */ (function (_super) {
        __extends$o(Diamond, _super);
        function Diamond() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Diamond.prototype.updatePath = function () {
            var _a = this, x = _a.x, y = _a.y;
            var _b = this, path = _b.path, size = _b.size;
            var s = size / 2;
            path.clear();
            path.moveTo(x, y -= s);
            path.lineTo(x += s, y += s);
            path.lineTo(x -= s, y += s);
            path.lineTo(x -= s, y -= s);
            path.lineTo(x += s, y -= s);
            path.closePath();
        };
        Diamond.className = 'Diamond';
        return Diamond;
    }(Marker));

    var __extends$p = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Heart = /** @class */ (function (_super) {
        __extends$p(Heart, _super);
        function Heart() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Heart.prototype.rad = function (degree) {
            return degree / 180 * Math.PI;
        };
        Heart.prototype.updatePath = function () {
            var _a = this, x = _a.x, path = _a.path, size = _a.size, rad = _a.rad;
            var r = size / 4;
            var y = this.y + r / 2;
            path.clear();
            path.cubicArc(x - r, y - r, r, r, 0, rad(130), rad(330), 0);
            path.cubicArc(x + r, y - r, r, r, 0, rad(220), rad(50), 0);
            path.lineTo(x, y + r);
            path.closePath();
        };
        Heart.className = 'Heart';
        return Heart;
    }(Marker));

    var __extends$q = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Plus = /** @class */ (function (_super) {
        __extends$q(Plus, _super);
        function Plus() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Plus.prototype.updatePath = function () {
            var _a = this, x = _a.x, y = _a.y;
            var _b = this, path = _b.path, size = _b.size;
            var s = size / 3;
            var hs = s / 2;
            path.clear();
            path.moveTo(x -= hs, y -= hs);
            path.lineTo(x, y -= s);
            path.lineTo(x += s, y);
            path.lineTo(x, y += s);
            path.lineTo(x += s, y);
            path.lineTo(x, y += s);
            path.lineTo(x -= s, y);
            path.lineTo(x, y += s);
            path.lineTo(x -= s, y);
            path.lineTo(x, y -= s);
            path.lineTo(x -= s, y);
            path.lineTo(x, y -= s);
            path.closePath();
        };
        Plus.className = 'Plus';
        return Plus;
    }(Marker));

    var __extends$r = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Triangle = /** @class */ (function (_super) {
        __extends$r(Triangle, _super);
        function Triangle() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Triangle.prototype.updatePath = function () {
            var _a = this, x = _a.x, y = _a.y;
            var _b = this, path = _b.path, size = _b.size;
            var s = size * 1.1;
            path.clear();
            path.moveTo(x, y -= s * 0.48);
            path.lineTo(x += s * 0.5, y += s * 0.87);
            path.lineTo(x -= s, y);
            path.closePath();
        };
        Triangle.className = 'Triangle';
        return Triangle;
    }(Marker));

    // This function is in its own file because putting it into SeriesMarker makes the Legend
    // suddenly aware of the series (it's an agnostic component), and putting it into Marker
    // introduces circular dependencies.
    function getMarker(shape) {
        if (shape === void 0) { shape = Square; }
        if (typeof shape === 'string') {
            switch (shape) {
                case 'circle':
                    return Circle;
                case 'cross':
                    return Cross;
                case 'diamond':
                    return Diamond;
                case 'heart':
                    return Heart;
                case 'plus':
                    return Plus;
                case 'triangle':
                    return Triangle;
                default:
                    return Square;
            }
        }
        if (typeof shape === 'function') {
            return shape;
        }
        return Square;
    }

    var __extends$s = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    (function (LegendOrientation) {
        LegendOrientation[LegendOrientation["Vertical"] = 0] = "Vertical";
        LegendOrientation[LegendOrientation["Horizontal"] = 1] = "Horizontal";
    })(exports.LegendOrientation || (exports.LegendOrientation = {}));
    (function (LegendPosition) {
        LegendPosition["Top"] = "top";
        LegendPosition["Right"] = "right";
        LegendPosition["Bottom"] = "bottom";
        LegendPosition["Left"] = "left";
    })(exports.LegendPosition || (exports.LegendPosition = {}));
    var LegendLabel = /** @class */ (function (_super) {
        __extends$s(LegendLabel, _super);
        function LegendLabel() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.color = 'black';
            _this.fontSize = 12;
            _this.fontFamily = 'Verdana, sans-serif';
            return _this;
        }
        __decorate$2([
            reactive('change')
        ], LegendLabel.prototype, "color", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendLabel.prototype, "fontStyle", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendLabel.prototype, "fontWeight", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendLabel.prototype, "fontSize", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendLabel.prototype, "fontFamily", void 0);
        __decorate$2([
            reactive()
        ], LegendLabel.prototype, "formatter", void 0);
        return LegendLabel;
    }(Observable));
    var LegendMarker = /** @class */ (function (_super) {
        __extends$s(LegendMarker, _super);
        function LegendMarker() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.size = 15;
            /**
             * Padding between the marker and the label within each legend item.
             */
            _this.padding = 8;
            _this.strokeWidth = 1;
            return _this;
        }
        __decorate$2([
            reactive('layoutChange')
        ], LegendMarker.prototype, "size", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendMarker.prototype, "shape", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendMarker.prototype, "padding", void 0);
        __decorate$2([
            reactive('change')
        ], LegendMarker.prototype, "strokeWidth", void 0);
        return LegendMarker;
    }(Observable));
    var LegendItem = /** @class */ (function (_super) {
        __extends$s(LegendItem, _super);
        function LegendItem() {
            var _this = _super.call(this) || this;
            _this.marker = new LegendMarker();
            _this.label = new LegendLabel();
            /**
             * The legend uses grid layout for its items, occupying as few columns as possible when positioned to left or right,
             * and as few rows as possible when positioned to top or bottom. This config specifies the amount of horizontal
             * padding between legend items.
             */
            _this.paddingX = 16;
            /**
             * The legend uses grid layout for its items, occupying as few columns as possible when positioned to left or right,
             * and as few rows as possible when positioned to top or bottom. This config specifies the amount of vertical
             * padding between legend items.
             */
            _this.paddingY = 8;
            var changeListener = function () { return _this.fireEvent({ type: 'change' }); };
            _this.marker.addEventListener('change', changeListener);
            _this.label.addEventListener('change', changeListener);
            var layoutChangeListener = function () { return _this.fireEvent({ type: 'layoutChange' }); };
            _this.marker.addEventListener('layoutChange', layoutChangeListener);
            _this.label.addEventListener('layoutChange', layoutChangeListener);
            return _this;
        }
        __decorate$2([
            reactive('layoutChange')
        ], LegendItem.prototype, "paddingX", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], LegendItem.prototype, "paddingY", void 0);
        return LegendItem;
    }(Observable));
    var Legend = /** @class */ (function (_super) {
        __extends$s(Legend, _super);
        function Legend() {
            var _this = _super.call(this) || this;
            _this.id = createId(_this);
            _this.group = new Group();
            _this.itemSelection = Selection.select(_this.group).selectAll();
            _this.oldSize = [0, 0];
            _this.item = new LegendItem();
            _this.data = [];
            _this.enabled = true;
            _this.orientation = exports.LegendOrientation.Vertical;
            _this.position = exports.LegendPosition.Right;
            /**
             * Spacing between the legend and the edge of the chart's element.
             */
            _this.spacing = 20;
            _this._size = [0, 0];
            _this.addPropertyListener('data', _this.onDataChange);
            _this.addPropertyListener('enabled', _this.onEnabledChange);
            _this.addPropertyListener('position', _this.onPositionChange);
            _this.item.marker.addPropertyListener('shape', _this.onMarkerShapeChange, _this);
            _this.addEventListener('change', _this.update);
            _this.item.addEventListener('change', function () { return _this.fireEvent({ type: 'change' }); });
            _this.item.addEventListener('layoutChange', function () { return _this.fireEvent({ type: 'layoutChange' }); });
            return _this;
        }
        Object.defineProperty(Legend.prototype, "size", {
            get: function () {
                return this._size;
            },
            enumerable: true,
            configurable: true
        });
        Legend.prototype.onDataChange = function (event) {
            this.group.visible = event.value.length > 0 && this.enabled;
        };
        Legend.prototype.onEnabledChange = function (event) {
            this.group.visible = event.value && this.data.length > 0;
        };
        Legend.prototype.onPositionChange = function (event) {
            switch (event.value) {
                case 'right':
                case 'left':
                    this.orientation = exports.LegendOrientation.Vertical;
                    break;
                case 'bottom':
                case 'top':
                    this.orientation = exports.LegendOrientation.Horizontal;
                    break;
            }
        };
        Legend.prototype.onMarkerShapeChange = function () {
            this.itemSelection = this.itemSelection.setData([]);
            this.itemSelection.exit.remove();
            if (this.group.scene) {
                this.group.scene.dirty = false;
            }
        };
        /**
         * The method is given the desired size of the legend, which only serves as a hint.
         * The vertically oriented legend will take as much horizontal space as needed, but will
         * respect the height constraints, and the horizontal legend will take as much vertical
         * space as needed in an attempt not to exceed the given width.
         * After the layout is done, the {@link size} will contain the actual size of the legend.
         * If the actual size is not the same as the previous actual size, the legend will fire
         * the 'layoutChange' event to communicate that another layout is needed, and the above
         * process should be repeated.
         * @param width
         * @param height
         */
        Legend.prototype.performLayout = function (width, height) {
            var item = this.item;
            var marker = item.marker, paddingX = item.paddingX, paddingY = item.paddingY;
            var updateSelection = this.itemSelection.setData(this.data, function (_, datum) {
                var MarkerShape = getMarker(marker.shape || datum.marker.shape);
                return datum.id + '-' + datum.itemId + '-' + MarkerShape.name;
            });
            updateSelection.exit.remove();
            var enterSelection = updateSelection.enter.append(MarkerLabel).each(function (node, datum) {
                var MarkerShape = getMarker(marker.shape || datum.marker.shape);
                node.marker = new MarkerShape();
            });
            var itemSelection = this.itemSelection = updateSelection.merge(enterSelection);
            var itemCount = itemSelection.size;
            // Update properties that affect the size of the legend items and measure them.
            var bboxes = [];
            var itemMarker = this.item.marker;
            var itemLabel = this.item.label;
            var maxCharCount = 25;
            var ellipsis = "...";
            itemSelection.each(function (markerLabel, datum) {
                // TODO: measure only when one of these properties or data change (in a separate routine)
                markerLabel.markerSize = itemMarker.size;
                markerLabel.spacing = itemMarker.padding;
                markerLabel.fontStyle = itemLabel.fontStyle;
                markerLabel.fontWeight = itemLabel.fontWeight;
                markerLabel.fontSize = itemLabel.fontSize;
                markerLabel.fontFamily = itemLabel.fontFamily;
                var text = datum.label.text;
                if (text.length > maxCharCount) {
                    text = "" + text.substring(0, maxCharCount - ellipsis.length) + ellipsis;
                }
                markerLabel.text = text;
                bboxes.push(markerLabel.computeBBox());
            });
            var itemHeight = bboxes.length && bboxes[0].height;
            var rowCount = 0;
            var columnWidth = 0;
            var paddedItemsWidth = 0;
            var paddedItemsHeight = 0;
            width = Math.max(1, width);
            height = Math.max(1, height);
            switch (this.orientation) {
                case exports.LegendOrientation.Horizontal:
                    if (!(isFinite(width) && width > 0)) {
                        return false;
                    }
                    rowCount = 0;
                    var columnCount = 0;
                    // Split legend items into columns until the width is suitable.
                    do {
                        var itemsWidth = 0;
                        columnCount = 0;
                        columnWidth = 0;
                        rowCount++;
                        var i = 0;
                        while (i < itemCount) {
                            var bbox = bboxes[i];
                            if (bbox.width > columnWidth) {
                                columnWidth = bbox.width;
                            }
                            i++;
                            if (i % rowCount === 0) {
                                itemsWidth += columnWidth;
                                columnWidth = 0;
                                columnCount++;
                            }
                        }
                        if (i % rowCount !== 0) {
                            itemsWidth += columnWidth;
                            columnCount++;
                        }
                        paddedItemsWidth = itemsWidth + (columnCount - 1) * paddingX;
                    } while (paddedItemsWidth > width && columnCount > 1);
                    paddedItemsHeight = itemHeight * rowCount + (rowCount - 1) * paddingY;
                    break;
                case exports.LegendOrientation.Vertical:
                    if (!(isFinite(height) && height > 0)) {
                        return false;
                    }
                    rowCount = itemCount * 2;
                    // Split legend items into columns until the height is suitable.
                    do {
                        rowCount = (rowCount >> 1) + (rowCount % 2);
                        columnWidth = 0;
                        var itemsWidth = 0;
                        var itemsHeight = 0;
                        var columnCount_1 = 0;
                        var i = 0;
                        while (i < itemCount) {
                            var bbox = bboxes[i];
                            if (!columnCount_1) {
                                itemsHeight += bbox.height;
                            }
                            if (bbox.width > columnWidth) {
                                columnWidth = bbox.width;
                            }
                            i++;
                            if (i % rowCount === 0) {
                                itemsWidth += columnWidth;
                                columnWidth = 0;
                                columnCount_1++;
                            }
                        }
                        if (i % rowCount !== 0) {
                            itemsWidth += columnWidth;
                            columnCount_1++;
                        }
                        paddedItemsWidth = itemsWidth + (columnCount_1 - 1) * paddingX;
                        paddedItemsHeight = itemsHeight + (rowCount - 1) * paddingY;
                    } while (paddedItemsHeight > height && rowCount > 1);
                    break;
            }
            // Top-left corner of the first legend item.
            var startX = (width - paddedItemsWidth) / 2;
            var startY = (height - paddedItemsHeight) / 2;
            var x = 0;
            var y = 0;
            columnWidth = 0;
            // Position legend items using the layout computed above.
            itemSelection.each(function (markerLabel, datum, i) {
                // Round off for pixel grid alignment to work properly.
                markerLabel.translationX = Math.floor(startX + x);
                markerLabel.translationY = Math.floor(startY + y);
                var bbox = bboxes[i];
                if (bbox.width > columnWidth) {
                    columnWidth = bbox.width;
                }
                if ((i + 1) % rowCount === 0) {
                    x += columnWidth + paddingX;
                    y = 0;
                    columnWidth = 0;
                }
                else {
                    y += bbox.height + paddingY;
                }
            });
            // Update legend item properties that don't affect the layout.
            this.update();
            var size = this._size;
            var oldSize = this.oldSize;
            size[0] = paddedItemsWidth;
            size[1] = paddedItemsHeight;
            if (size[0] !== oldSize[0] || size[1] !== oldSize[1]) {
                oldSize[0] = size[0];
                oldSize[1] = size[1];
            }
        };
        Legend.prototype.update = function () {
            var _this = this;
            this.itemSelection.each(function (markerLabel, datum) {
                var marker = datum.marker;
                markerLabel.markerFill = marker.fill;
                markerLabel.markerStroke = marker.stroke;
                markerLabel.markerStrokeWidth = _this.item.marker.strokeWidth;
                markerLabel.markerFillOpacity = marker.fillOpacity;
                markerLabel.markerStrokeOpacity = marker.strokeOpacity;
                markerLabel.opacity = datum.enabled ? 1 : 0.5;
                markerLabel.color = _this.item.label.color;
            });
        };
        Legend.prototype.getDatumForPoint = function (x, y) {
            var node = this.group.pickNode(x, y);
            if (node && node.parent) {
                return node.parent.datum;
            }
        };
        Legend.className = 'Legend';
        __decorate$2([
            reactive('layoutChange')
        ], Legend.prototype, "data", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], Legend.prototype, "enabled", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], Legend.prototype, "orientation", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], Legend.prototype, "position", void 0);
        __decorate$2([
            reactive('layoutChange')
        ], Legend.prototype, "spacing", void 0);
        return Legend;
    }(Observable));

    var __values$1 = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var SizeMonitor = /** @class */ (function () {
        function SizeMonitor() {
        }
        SizeMonitor.init = function () {
            var _this = this;
            var NativeResizeObserver = window.ResizeObserver;
            if (NativeResizeObserver) {
                this.resizeObserver = new NativeResizeObserver(function (entries) {
                    var e_1, _a;
                    try {
                        for (var entries_1 = __values$1(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) {
                            var entry = entries_1_1.value;
                            var _b = entry.contentRect, width = _b.width, height = _b.height;
                            _this.checkSize(_this.elements.get(entry.target), entry.target, width, height);
                        }
                    }
                    catch (e_1_1) { e_1 = { error: e_1_1 }; }
                    finally {
                        try {
                            if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1);
                        }
                        finally { if (e_1) throw e_1.error; }
                    }
                });
            }
            else { // polyfill (more reliable even in browsers that support ResizeObserver)
                var step = function () {
                    _this.elements.forEach(function (entry, element) {
                        var width = element.clientWidth ? element.clientWidth : 0;
                        var height = element.clientHeight ? element.clientHeight : 0;
                        _this.checkSize(entry, element, width, height);
                    });
                };
                window.setInterval(step, 100);
            }
            this.ready = true;
        };
        SizeMonitor.checkSize = function (entry, element, width, height) {
            if (entry) {
                if (!entry.size || width !== entry.size.width || height !== entry.size.height) {
                    entry.size = { width: width, height: height };
                    entry.cb(entry.size, element);
                }
            }
        };
        // Only a single callback is supported.
        SizeMonitor.observe = function (element, cb) {
            if (!this.ready) {
                this.init();
            }
            this.unobserve(element);
            if (this.resizeObserver) {
                this.resizeObserver.observe(element);
            }
            this.elements.set(element, { cb: cb });
        };
        SizeMonitor.unobserve = function (element) {
            if (this.resizeObserver) {
                this.resizeObserver.unobserve(element);
            }
            this.elements.delete(element);
        };
        SizeMonitor.elements = new Map();
        SizeMonitor.ready = false;
        return SizeMonitor;
    }());

    function circleRectOverlap(cx, cy, r, x, y, w, h) {
        // Find closest horizontal and vertical edges.
        var edgeX = cx < x ? x : cx > x + w ? x + w : cx;
        var edgeY = cy < y ? y : cy > y + h ? y + h : cy;
        // Find distance to closest edges.
        var dx = cx - edgeX;
        var dy = cy - edgeY;
        var d = Math.sqrt((dx * dx) + (dy * dy));
        return d <= r;
    }
    function rectRectOverlap(x1, y1, w1, h1, x2, y2, w2, h2) {
        var xOverlap = (x1 + w1) > x2 && x1 < (x2 + w2);
        var yOverlap = (y1 + h1) > y2 && y1 < (y2 + h2);
        return xOverlap && yOverlap;
    }
    function rectContainsRect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) {
        return (r2x + r2w) < (r1x + r1w) && (r2x) > (r1x) && (r2y) > (r1y) && (r2y + r2h) < (r1y + r1h);
    }
    /**
     * @param data Points and labels for one or more series. The order of series determines label placement precedence.
     * @param bounds Bounds to fit the labels into. If a label can't be fully contained, it doesn't fit.
     * @returns Placed labels for the given series (in the given order).
     */
    function placeLabels(data, bounds, padding) {
        if (padding === void 0) { padding = 5; }
        var result = [];
        data = data.map(function (d) { return d.slice().sort(function (a, b) { return b.size - a.size; }); });
        for (var j = 0; j < data.length; j++) {
            var labels = result[j] = [];
            var datum = data[j];
            if (!(datum && datum.length && datum[0].label)) {
                continue;
            }
            var _loop_1 = function (i, ln) {
                var d = datum[i];
                var l = d.label;
                var r = d.size * 0.5;
                var x = d.point.x - l.width * 0.5;
                var y = d.point.y - r - l.height - padding;
                var width = l.width, height = l.height;
                var withinBounds = !bounds || rectContainsRect(bounds.x, bounds.y, bounds.width, bounds.height, x, y, width, height);
                if (!withinBounds) {
                    return "continue";
                }
                var overlapPoints = data.some(function (datum) { return datum.some(function (d) { return circleRectOverlap(d.point.x, d.point.y, d.size * 0.5, x, y, width, height); }); });
                if (overlapPoints) {
                    return "continue";
                }
                var overlapLabels = result.some(function (labels) { return labels.some(function (l) { return rectRectOverlap(l.x, l.y, l.width, l.height, x, y, width, height); }); });
                if (overlapLabels) {
                    return "continue";
                }
                labels.push({
                    index: i,
                    text: l.text,
                    x: x,
                    y: y,
                    width: width,
                    height: height
                });
            };
            for (var i = 0, ln = datum.length; i < ln; i++) {
                _loop_1(i, ln);
            }
        }
        return result;
    }

    var __extends$t = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __assign$1 = (undefined && undefined.__assign) || function () {
        __assign$1 = Object.assign || function(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$1.apply(this, arguments);
    };
    var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __values$2 = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var defaultTooltipCss = "\n.ag-chart-tooltip {\n    display: table;\n    position: absolute;\n    user-select: none;\n    pointer-events: none;\n    white-space: nowrap;\n    z-index: 99999;\n    font: 12px Verdana, sans-serif;\n    color: black;\n    background: rgb(244, 244, 244);\n    border-radius: 5px;\n    box-shadow: 0 0 1px rgba(3, 3, 3, 0.7), 0.5vh 0.5vh 1vh rgba(3, 3, 3, 0.25);\n}\n\n.ag-chart-tooltip-hidden {\n    top: -10000px !important;\n}\n\n.ag-chart-tooltip-title {\n    font-weight: bold;\n    padding: 7px;\n    border-top-left-radius: 5px;\n    border-top-right-radius: 5px;\n    color: white;\n    background-color: #888888;\n    border-top-left-radius: 5px;\n    border-top-right-radius: 5px;\n}\n\n.ag-chart-tooltip-content {\n    padding: 7px;\n    line-height: 1.7em;\n    border-bottom-left-radius: 5px;\n    border-bottom-right-radius: 5px;\n    overflow: hidden;\n}\n\n.ag-chart-tooltip-content:empty {\n    padding: 0;\n    height: 7px;\n}\n\n.ag-chart-tooltip-arrow::before {\n    content: \"\";\n\n    position: absolute;\n    top: 100%;\n    left: 50%;\n    transform: translateX(-50%);\n\n    border: 6px solid #989898;\n\n    border-left-color: transparent;\n    border-right-color: transparent;\n    border-top-color: #989898;\n    border-bottom-color: transparent;\n\n    width: 0;\n    height: 0;\n\n    margin: 0 auto;\n}\n\n.ag-chart-tooltip-arrow::after {\n    content: \"\";\n\n    position: absolute;\n    top: 100%;\n    left: 50%;\n    transform: translateX(-50%);\n\n    border: 5px solid black;\n\n    border-left-color: transparent;\n    border-right-color: transparent;\n    border-top-color: rgb(244, 244, 244);\n    border-bottom-color: transparent;\n\n    width: 0;\n    height: 0;\n\n    margin: 0 auto;\n}\n\n.ag-chart-wrapper {\n    box-sizing: border-box;\n    overflow: hidden;\n}\n";
    function toTooltipHtml(input, defaults) {
        if (typeof input === 'string') {
            return input;
        }
        defaults = defaults || {};
        var _a = input.content, content = _a === void 0 ? defaults.content || '' : _a, _b = input.title, title = _b === void 0 ? defaults.title || undefined : _b, _c = input.color, color = _c === void 0 ? defaults.color || 'white' : _c, _d = input.backgroundColor, backgroundColor = _d === void 0 ? defaults.backgroundColor || '#888' : _d;
        var titleHtml = title ? "<div class=\"" + Chart.defaultTooltipClass + "-title\"\n        style=\"color: " + color + "; background-color: " + backgroundColor + "\">" + title + "</div>" : '';
        return titleHtml + "<div class=\"" + Chart.defaultTooltipClass + "-content\">" + content + "</div>";
    }
    var ChartTooltip = /** @class */ (function (_super) {
        __extends$t(ChartTooltip, _super);
        function ChartTooltip(chart, document) {
            var _this = _super.call(this) || this;
            _this.enabled = true;
            _this.class = Chart.defaultTooltipClass;
            _this.delay = 0;
            /**
             * If `true`, the tooltip will be shown for the marker closest to the mouse cursor.
             * Only has effect on series with markers.
             */
            _this.tracking = true;
            _this.showTimeout = 0;
            _this.constrained = false;
            _this.chart = chart;
            _this.class = '';
            var tooltipRoot = document.body;
            var element = document.createElement('div');
            _this.element = tooltipRoot.appendChild(element);
            // Detect when the chart becomes invisible and hide the tooltip as well.
            if (window.IntersectionObserver) {
                var target_1 = _this.chart.scene.canvas.element;
                var observer = new IntersectionObserver(function (entries) {
                    var e_1, _a;
                    try {
                        for (var entries_1 = __values$2(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) {
                            var entry = entries_1_1.value;
                            if (entry.target === target_1 && entry.intersectionRatio === 0) {
                                _this.toggle(false);
                            }
                        }
                    }
                    catch (e_1_1) { e_1 = { error: e_1_1 }; }
                    finally {
                        try {
                            if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1);
                        }
                        finally { if (e_1) throw e_1.error; }
                    }
                }, { root: tooltipRoot });
                observer.observe(target_1);
                _this.observer = observer;
            }
            return _this;
        }
        ChartTooltip.prototype.destroy = function () {
            var parentNode = this.element.parentNode;
            if (parentNode) {
                parentNode.removeChild(this.element);
            }
            if (this.observer) {
                this.observer.unobserve(this.chart.scene.canvas.element);
            }
        };
        ChartTooltip.prototype.isVisible = function () {
            var element = this.element;
            if (element.classList) { // if not IE11
                return !element.classList.contains(Chart.defaultTooltipClass + '-hidden');
            }
            // IE11 part.
            var classes = element.getAttribute('class');
            if (classes) {
                return classes.split(' ').indexOf(Chart.defaultTooltipClass + '-hidden') < 0;
            }
            return false;
        };
        ChartTooltip.prototype.updateClass = function (visible, constrained) {
            var classList = [Chart.defaultTooltipClass, this.class];
            if (visible !== true) {
                classList.push(Chart.defaultTooltipClass + "-hidden");
            }
            if (constrained !== true) {
                classList.push(Chart.defaultTooltipClass + "-arrow");
            }
            this.element.setAttribute('class', classList.join(' '));
        };
        /**
         * Shows tooltip at the given event's coordinates.
         * If the `html` parameter is missing, moves the existing tooltip to the new position.
         */
        ChartTooltip.prototype.show = function (meta, html, instantly) {
            var _this = this;
            if (instantly === void 0) { instantly = false; }
            var el = this.element;
            if (html !== undefined) {
                el.innerHTML = html;
            }
            else if (!el.innerHTML) {
                return;
            }
            var left = meta.pageX - el.clientWidth / 2;
            var top = meta.pageY - el.clientHeight - 8;
            this.constrained = false;
            if (this.chart.container) {
                var tooltipRect = el.getBoundingClientRect();
                var minLeft = 0;
                var maxLeft = window.innerWidth - tooltipRect.width - 1;
                if (left < minLeft) {
                    left = minLeft;
                    this.updateClass(true, this.constrained = true);
                }
                else if (left > maxLeft) {
                    left = maxLeft;
                    this.updateClass(true, this.constrained = true);
                }
                if (top < window.pageYOffset) {
                    top = meta.pageY + 20;
                    this.updateClass(true, this.constrained = true);
                }
            }
            el.style.left = Math.round(left) + "px";
            el.style.top = Math.round(top) + "px";
            if (this.delay > 0 && !instantly) {
                this.toggle(false);
                this.showTimeout = window.setTimeout(function () {
                    _this.toggle(true);
                }, this.delay);
                return;
            }
            this.toggle(true);
        };
        ChartTooltip.prototype.toggle = function (visible) {
            if (!visible) {
                window.clearTimeout(this.showTimeout);
                if (this.chart.lastPick && !this.delay) {
                    this.chart.dehighlightDatum();
                    this.chart.lastPick = undefined;
                }
            }
            this.updateClass(visible, this.constrained);
        };
        __decorate$3([
            reactive()
        ], ChartTooltip.prototype, "enabled", void 0);
        __decorate$3([
            reactive()
        ], ChartTooltip.prototype, "class", void 0);
        __decorate$3([
            reactive()
        ], ChartTooltip.prototype, "delay", void 0);
        __decorate$3([
            reactive()
        ], ChartTooltip.prototype, "tracking", void 0);
        return ChartTooltip;
    }(Observable));
    var Chart = /** @class */ (function (_super) {
        __extends$t(Chart, _super);
        function Chart(document) {
            if (document === void 0) { document = window.document; }
            var _this = _super.call(this) || this;
            _this.id = createId(_this);
            _this.background = new Rect();
            _this.legend = new Legend();
            _this.legendAutoPadding = new Padding();
            _this.captionAutoPadding = 0; // top padding only
            _this._container = undefined;
            _this._data = [];
            _this._autoSize = false;
            _this.padding = new Padding(20);
            _this._axes = [];
            _this._series = [];
            _this._axesChanged = false;
            _this._seriesChanged = false;
            _this.layoutCallbackId = 0;
            _this._performLayout = function () {
                _this.layoutCallbackId = 0;
                _this.background.width = _this.width;
                _this.background.height = _this.height;
                _this.performLayout();
                if (!_this.layoutPending) {
                    _this.fireEvent({ type: 'layoutDone' });
                }
            };
            _this.dataCallbackId = 0;
            _this.nodeData = new Map();
            _this.updateCallbackId = 0;
            _this.legendBBox = new BBox(0, 0, 0, 0);
            _this._onMouseDown = _this.onMouseDown.bind(_this);
            _this._onMouseMove = _this.onMouseMove.bind(_this);
            _this._onMouseUp = _this.onMouseUp.bind(_this);
            _this._onMouseOut = _this.onMouseOut.bind(_this);
            _this._onClick = _this.onClick.bind(_this);
            _this.pointerInsideLegend = false;
            var root = new Group();
            var background = _this.background;
            background.fill = 'white';
            root.appendChild(background);
            var element = _this._element = document.createElement('div');
            element.setAttribute('class', 'ag-chart-wrapper');
            var scene = new Scene(document);
            _this.scene = scene;
            scene.root = root;
            scene.container = element;
            _this.autoSize = true;
            _this.padding.addEventListener('layoutChange', _this.scheduleLayout, _this);
            var legend = _this.legend;
            legend.addEventListener('layoutChange', _this.scheduleLayout, _this);
            legend.item.label.addPropertyListener('formatter', _this.updateLegend, _this);
            legend.addPropertyListener('position', _this.onLegendPositionChange, _this);
            _this.tooltip = new ChartTooltip(_this, document);
            _this.tooltip.addPropertyListener('class', function () { return _this.tooltip.toggle(); });
            if (Chart.tooltipDocuments.indexOf(document) < 0) {
                var styleElement = document.createElement('style');
                styleElement.innerHTML = defaultTooltipCss;
                // Make sure the default tooltip style goes before other styles so it can be overridden.
                document.head.insertBefore(styleElement, document.head.querySelector('style'));
                Chart.tooltipDocuments.push(document);
            }
            _this.setupDomListeners(scene.canvas.element);
            _this.addPropertyListener('title', _this.onCaptionChange);
            _this.addPropertyListener('subtitle', _this.onCaptionChange);
            _this.addEventListener('layoutChange', _this.scheduleLayout);
            return _this;
        }
        Object.defineProperty(Chart.prototype, "container", {
            get: function () {
                return this._container;
            },
            set: function (value) {
                if (this._container !== value) {
                    var parentNode = this.element.parentNode;
                    if (parentNode != null) {
                        parentNode.removeChild(this.element);
                    }
                    if (value) {
                        value.appendChild(this.element);
                    }
                    this._container = value;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "data", {
            get: function () {
                return this._data;
            },
            set: function (data) {
                this._data = data;
                this.series.forEach(function (series) { return series.data = data; });
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "width", {
            get: function () {
                return this.scene.width;
            },
            set: function (value) {
                this.autoSize = false;
                if (this.width !== value) {
                    this.scene.resize(value, this.height);
                    this.fireEvent({ type: 'layoutChange' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "height", {
            get: function () {
                return this.scene.height;
            },
            set: function (value) {
                this.autoSize = false;
                if (this.height !== value) {
                    this.scene.resize(this.width, value);
                    this.fireEvent({ type: 'layoutChange' });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "autoSize", {
            get: function () {
                return this._autoSize;
            },
            set: function (value) {
                if (this._autoSize !== value) {
                    this._autoSize = value;
                    var style = this.element.style;
                    if (value) {
                        var chart_1 = this; // capture `this` for IE11
                        SizeMonitor.observe(this.element, function (size) {
                            if (size.width !== chart_1.width || size.height !== chart_1.height) {
                                chart_1.scene.resize(size.width, size.height);
                                chart_1.fireEvent({ type: 'layoutChange' });
                            }
                        });
                        style.display = 'block';
                        style.width = '100%';
                        style.height = '100%';
                    }
                    else {
                        SizeMonitor.unobserve(this.element);
                        style.display = 'inline-block';
                        style.width = 'auto';
                        style.height = 'auto';
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Chart.prototype.download = function (fileName) {
            this.scene.download(fileName);
        };
        Chart.prototype.destroy = function () {
            this.tooltip.destroy();
            SizeMonitor.unobserve(this.element);
            this.container = undefined;
            this.cleanupDomListeners(this.scene.canvas.element);
            this.scene.container = undefined;
        };
        Chart.prototype.onLegendPositionChange = function () {
            this.legendAutoPadding.clear();
            this.layoutPending = true;
        };
        Chart.prototype.onCaptionChange = function (event) {
            var value = event.value, oldValue = event.oldValue;
            if (oldValue) {
                oldValue.removeEventListener('change', this.scheduleLayout, this);
                this.scene.root.removeChild(oldValue.node);
            }
            if (value) {
                value.addEventListener('change', this.scheduleLayout, this);
                this.scene.root.appendChild(value.node);
            }
        };
        Object.defineProperty(Chart.prototype, "element", {
            get: function () {
                return this._element;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "axes", {
            get: function () {
                return this._axes;
            },
            set: function (values) {
                var _this = this;
                this._axes.forEach(function (axis) { return _this.detachAxis(axis); });
                // make linked axes go after the regular ones (simulates stable sort by `linkedTo` property)
                this._axes = values.filter(function (a) { return !a.linkedTo; }).concat(values.filter(function (a) { return a.linkedTo; }));
                this._axes.forEach(function (axis) { return _this.attachAxis(axis); });
                this.axesChanged = true;
            },
            enumerable: true,
            configurable: true
        });
        Chart.prototype.attachAxis = function (axis) {
            this.scene.root.insertBefore(axis.group, this.seriesRoot);
        };
        Chart.prototype.detachAxis = function (axis) {
            this.scene.root.removeChild(axis.group);
        };
        Object.defineProperty(Chart.prototype, "series", {
            get: function () {
                return this._series;
            },
            set: function (values) {
                var _this = this;
                this.removeAllSeries();
                values.forEach(function (series) { return _this.addSeries(series); });
            },
            enumerable: true,
            configurable: true
        });
        Chart.prototype.scheduleLayout = function () {
            this.layoutPending = true;
        };
        Chart.prototype.scheduleData = function () {
            // To prevent the chart from thinking the cursor is over the same node
            // after a change to data (the nodes are reused on data changes).
            this.dehighlightDatum();
            this.dataPending = true;
        };
        Chart.prototype.addSeries = function (series, before) {
            var _a = this, allSeries = _a.series, seriesRoot = _a.seriesRoot;
            var canAdd = allSeries.indexOf(series) < 0;
            if (canAdd) {
                var beforeIndex = before ? allSeries.indexOf(before) : -1;
                if (beforeIndex >= 0) {
                    allSeries.splice(beforeIndex, 0, series);
                    seriesRoot.insertBefore(series.group, before.group);
                }
                else {
                    allSeries.push(series);
                    seriesRoot.append(series.group);
                }
                this.initSeries(series);
                this.seriesChanged = true;
                this.axesChanged = true;
                return true;
            }
            return false;
        };
        Chart.prototype.initSeries = function (series) {
            series.chart = this;
            if (!series.data) {
                series.data = this.data;
            }
            series.addEventListener('layoutChange', this.scheduleLayout, this);
            series.addEventListener('dataChange', this.scheduleData, this);
            series.addEventListener('legendChange', this.updateLegend, this);
            series.addEventListener('nodeClick', this.onSeriesNodeClick, this);
        };
        Chart.prototype.freeSeries = function (series) {
            series.chart = undefined;
            series.removeEventListener('layoutChange', this.scheduleLayout, this);
            series.removeEventListener('dataChange', this.scheduleData, this);
            series.removeEventListener('legendChange', this.updateLegend, this);
            series.removeEventListener('nodeClick', this.onSeriesNodeClick, this);
        };
        Chart.prototype.addSeriesAfter = function (series, after) {
            var _a = this, allSeries = _a.series, seriesRoot = _a.seriesRoot;
            var canAdd = allSeries.indexOf(series) < 0;
            if (canAdd) {
                var afterIndex = after ? this.series.indexOf(after) : -1;
                if (afterIndex >= 0) {
                    if (afterIndex + 1 < allSeries.length) {
                        seriesRoot.insertBefore(series.group, allSeries[afterIndex + 1].group);
                    }
                    else {
                        seriesRoot.append(series.group);
                    }
                    this.initSeries(series);
                    allSeries.splice(afterIndex + 1, 0, series);
                }
                else {
                    if (allSeries.length > 0) {
                        seriesRoot.insertBefore(series.group, allSeries[0].group);
                    }
                    else {
                        seriesRoot.append(series.group);
                    }
                    this.initSeries(series);
                    allSeries.unshift(series);
                }
                this.seriesChanged = true;
                this.axesChanged = true;
            }
            return false;
        };
        Chart.prototype.removeSeries = function (series) {
            var index = this.series.indexOf(series);
            if (index >= 0) {
                this.series.splice(index, 1);
                this.freeSeries(series);
                this.seriesRoot.removeChild(series.group);
                this.seriesChanged = true;
                return true;
            }
            return false;
        };
        Chart.prototype.removeAllSeries = function () {
            var _this = this;
            this.series.forEach(function (series) {
                _this.freeSeries(series);
                _this.seriesRoot.removeChild(series.group);
            });
            this._series = []; // using `_series` instead of `series` to prevent infinite recursion
            this.seriesChanged = true;
        };
        Chart.prototype.assignSeriesToAxes = function () {
            var _this = this;
            this.axes.forEach(function (axis) {
                var axisName = axis.direction + 'Axis';
                var boundSeries = [];
                _this.series.forEach(function (series) {
                    if (series[axisName] === axis) {
                        boundSeries.push(series);
                    }
                });
                axis.boundSeries = boundSeries;
            });
            this.seriesChanged = false;
        };
        Chart.prototype.assignAxesToSeries = function (force) {
            var _this = this;
            if (force === void 0) { force = false; }
            // This method has to run before `assignSeriesToAxes`.
            var directionToAxesMap = {};
            this.axes.forEach(function (axis) {
                var direction = axis.direction;
                var directionAxes = directionToAxesMap[direction] || (directionToAxesMap[direction] = []);
                directionAxes.push(axis);
            });
            this.series.forEach(function (series) {
                series.directions.forEach(function (direction) {
                    var axisName = direction + 'Axis';
                    if (!series[axisName] || force) {
                        var directionAxes = directionToAxesMap[direction];
                        if (directionAxes) {
                            var axis = _this.findMatchingAxis(directionAxes, series.getKeys(direction));
                            if (axis) {
                                series[axisName] = axis;
                            }
                        }
                    }
                });
            });
            this.axesChanged = false;
        };
        Chart.prototype.findMatchingAxis = function (directionAxes, directionKeys) {
            for (var i = 0; i < directionAxes.length; i++) {
                var axis = directionAxes[i];
                var axisKeys = axis.keys;
                if (!axisKeys.length) {
                    return axis;
                }
                else if (directionKeys) {
                    for (var j = 0; j < directionKeys.length; j++) {
                        if (axisKeys.indexOf(directionKeys[j]) >= 0) {
                            return axis;
                        }
                    }
                }
            }
        };
        Object.defineProperty(Chart.prototype, "axesChanged", {
            get: function () {
                return this._axesChanged;
            },
            set: function (value) {
                this._axesChanged = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "seriesChanged", {
            get: function () {
                return this._seriesChanged;
            },
            set: function (value) {
                this._seriesChanged = value;
                if (value) {
                    this.dataPending = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "layoutPending", {
            /**
             * Only `true` while we are waiting for the layout to start.
             * This will be `false` if the layout has already started and is ongoing.
             */
            get: function () {
                return !!this.layoutCallbackId;
            },
            set: function (value) {
                if (value) {
                    if (!(this.layoutCallbackId || this.dataPending)) {
                        this.layoutCallbackId = requestAnimationFrame(this._performLayout);
                        this.series.forEach(function (s) { return s.nodeDataPending = true; });
                    }
                }
                else if (this.layoutCallbackId) {
                    cancelAnimationFrame(this.layoutCallbackId);
                    this.layoutCallbackId = 0;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Chart.prototype, "dataPending", {
            get: function () {
                return !!this.dataCallbackId;
            },
            set: function (value) {
                var _this = this;
                if (this.dataCallbackId) {
                    clearTimeout(this.dataCallbackId);
                    this.dataCallbackId = 0;
                }
                if (value) {
                    this.dataCallbackId = window.setTimeout(function () {
                        _this.dataPending = false;
                        _this.processData();
                    }, 0);
                }
            },
            enumerable: true,
            configurable: true
        });
        Chart.prototype.processData = function () {
            this.layoutPending = false;
            if (this.axesChanged) {
                this.assignAxesToSeries(true);
                this.assignSeriesToAxes();
            }
            if (this.seriesChanged) {
                this.assignSeriesToAxes();
            }
            this.series.forEach(function (s) { return s.processData(); });
            this.updateLegend(); // sets legend data which schedules a layout
            this.layoutPending = true;
        };
        Chart.prototype.createNodeData = function () {
            var _this = this;
            this.nodeData.clear();
            this.series.forEach(function (s) {
                var data = s.visible ? s.createNodeData() : [];
                _this.nodeData.set(s, data);
            });
        };
        Chart.prototype.placeLabels = function () {
            var series = [];
            var data = [];
            this.nodeData.forEach(function (d, s) {
                if (s.visible && s.label.enabled) {
                    series.push(s);
                    data.push(s.getLabelData());
                }
            });
            var seriesRect = this.seriesRect;
            var labels = seriesRect
                ? placeLabels(data, { x: 0, y: 0, width: seriesRect.width, height: seriesRect.height })
                : [];
            return new Map(labels.map(function (l, i) { return [series[i], l]; }));
        };
        Chart.prototype.updateLegend = function () {
            var legendData = [];
            this.series.filter(function (s) { return s.showInLegend; }).forEach(function (series) { return series.listSeriesItems(legendData); });
            var formatter = this.legend.item.label.formatter;
            if (formatter) {
                legendData.forEach(function (datum) { return datum.label.text = formatter({
                    id: datum.id,
                    itemId: datum.itemId,
                    value: datum.label.text
                }); });
            }
            this.legend.data = legendData;
        };
        Object.defineProperty(Chart.prototype, "updatePending", {
            get: function () {
                return !!this.updateCallbackId;
            },
            set: function (value) {
                var _this = this;
                if (this.updateCallbackId) {
                    clearTimeout(this.updateCallbackId);
                    this.updateCallbackId = 0;
                }
                if (value && !this.layoutPending) {
                    this.updateCallbackId = window.setTimeout(function () {
                        _this.update();
                    }, 0);
                }
            },
            enumerable: true,
            configurable: true
        });
        Chart.prototype.update = function () {
            this.updatePending = false;
            this.series.forEach(function (series) {
                if (series.updatePending) {
                    series.update();
                }
            });
        };
        Chart.prototype.positionCaptions = function () {
            var _a = this, title = _a.title, subtitle = _a.subtitle;
            var titleVisible = false;
            var subtitleVisible = false;
            var spacing = 10;
            var paddingTop = spacing;
            if (title && title.enabled) {
                title.node.x = this.width / 2;
                title.node.y = paddingTop;
                titleVisible = true;
                var titleBBox = title.node.computeBBox(); // make sure to set node's x/y, then computeBBox
                if (titleBBox) {
                    paddingTop = titleBBox.y + titleBBox.height;
                }
                if (subtitle && subtitle.enabled) {
                    subtitle.node.x = this.width / 2;
                    subtitle.node.y = paddingTop + spacing;
                    subtitleVisible = true;
                    var subtitleBBox = subtitle.node.computeBBox();
                    if (subtitleBBox) {
                        paddingTop = subtitleBBox.y + subtitleBBox.height;
                    }
                }
            }
            if (title) {
                title.node.visible = titleVisible;
            }
            if (subtitle) {
                subtitle.node.visible = subtitleVisible;
            }
            this.captionAutoPadding = Math.floor(paddingTop);
        };
        Chart.prototype.positionLegend = function () {
            if (!this.legend.enabled || !this.legend.data.length) {
                return;
            }
            var _a = this, legend = _a.legend, captionAutoPadding = _a.captionAutoPadding, legendAutoPadding = _a.legendAutoPadding;
            var width = this.width;
            var height = this.height - captionAutoPadding;
            var legendGroup = legend.group;
            var legendSpacing = legend.spacing;
            var translationX = 0;
            var translationY = 0;
            var legendBBox;
            switch (legend.position) {
                case 'bottom':
                    legend.performLayout(width - legendSpacing * 2, 0);
                    legendBBox = legendGroup.computeBBox();
                    legendGroup.visible = legendBBox.height < Math.floor((height * 0.5)); // Remove legend if it takes up more than 50% of the chart height.
                    if (legendGroup.visible) {
                        translationX = (width - legendBBox.width) / 2 - legendBBox.x;
                        translationY = captionAutoPadding + height - legendBBox.height - legendBBox.y - legendSpacing;
                        legendAutoPadding.bottom = legendBBox.height;
                    }
                    else {
                        legendAutoPadding.bottom = 0;
                    }
                    break;
                case 'top':
                    legend.performLayout(width - legendSpacing * 2, 0);
                    legendBBox = legendGroup.computeBBox();
                    legendGroup.visible = legendBBox.height < Math.floor((height * 0.5));
                    if (legendGroup.visible) {
                        translationX = (width - legendBBox.width) / 2 - legendBBox.x;
                        translationY = captionAutoPadding + legendSpacing - legendBBox.y;
                        legendAutoPadding.top = legendBBox.height;
                    }
                    else {
                        legendAutoPadding.top = 0;
                    }
                    break;
                case 'left':
                    legend.performLayout(0, height - legendSpacing * 2);
                    legendBBox = legendGroup.computeBBox();
                    legendGroup.visible = legendBBox.width < Math.floor((width * 0.5)); // Remove legend if it takes up more than 50% of the chart width.
                    if (legendGroup.visible) {
                        translationX = legendSpacing - legendBBox.x;
                        translationY = captionAutoPadding + (height - legendBBox.height) / 2 - legendBBox.y;
                        legendAutoPadding.left = legendBBox.width;
                    }
                    else {
                        legendAutoPadding.left = 0;
                    }
                    break;
                default: // case 'right':
                    legend.performLayout(0, height - legendSpacing * 2);
                    legendBBox = legendGroup.computeBBox();
                    legendGroup.visible = legendBBox.width < Math.floor((width * 0.5));
                    if (legendGroup.visible) {
                        translationX = width - legendBBox.width - legendBBox.x - legendSpacing;
                        translationY = captionAutoPadding + (height - legendBBox.height) / 2 - legendBBox.y;
                        legendAutoPadding.right = legendBBox.width;
                    }
                    else {
                        legendAutoPadding.right = 0;
                    }
                    break;
            }
            if (legendGroup.visible) {
                // Round off for pixel grid alignment to work properly.
                legendGroup.translationX = Math.floor(translationX + legendGroup.translationX);
                legendGroup.translationY = Math.floor(translationY + legendGroup.translationY);
                this.legendBBox = legendGroup.computeBBox();
            }
        };
        Chart.prototype.setupDomListeners = function (chartElement) {
            chartElement.addEventListener('mousedown', this._onMouseDown);
            chartElement.addEventListener('mousemove', this._onMouseMove);
            chartElement.addEventListener('mouseup', this._onMouseUp);
            chartElement.addEventListener('mouseout', this._onMouseOut);
            chartElement.addEventListener('click', this._onClick);
        };
        Chart.prototype.cleanupDomListeners = function (chartElement) {
            chartElement.removeEventListener('mousedown', this._onMouseDown);
            chartElement.removeEventListener('mousemove', this._onMouseMove);
            chartElement.removeEventListener('mouseup', this._onMouseUp);
            chartElement.removeEventListener('mouseout', this._onMouseOut);
            chartElement.removeEventListener('click', this._onClick);
        };
        Chart.prototype.getSeriesRect = function () {
            return this.seriesRect;
        };
        // x/y are local canvas coordinates in CSS pixels, not actual pixels
        Chart.prototype.pickSeriesNode = function (x, y) {
            if (!(this.seriesRect && this.seriesRect.containsPoint(x, y))) {
                return undefined;
            }
            var allSeries = this.series;
            var node = undefined;
            for (var i = allSeries.length - 1; i >= 0; i--) {
                var series = allSeries[i];
                if (!series.visible) {
                    continue;
                }
                node = series.pickGroup.pickNode(x, y);
                if (node) {
                    return {
                        series: series,
                        node: node
                    };
                }
            }
        };
        // Provided x/y are in canvas coordinates.
        Chart.prototype.pickClosestSeriesNodeDatum = function (x, y) {
            if (!this.seriesRect || !this.seriesRect.containsPoint(x, y)) {
                return undefined;
            }
            var allSeries = this.series;
            function getDistance(p1, p2) {
                return Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
            }
            var minDistance = Infinity;
            var closestDatum;
            var _loop_1 = function (i) {
                var series = allSeries[i];
                if (!series.visible) {
                    return "continue";
                }
                var hitPoint = series.group.transformPoint(x, y);
                series.getNodeData().forEach(function (datum) {
                    if (!datum.point) {
                        return;
                    }
                    var distance = getDistance(hitPoint, datum.point);
                    if (distance < minDistance) {
                        minDistance = distance;
                        closestDatum = datum;
                    }
                });
            };
            for (var i = allSeries.length - 1; i >= 0; i--) {
                _loop_1(i);
            }
            return closestDatum;
        };
        Chart.prototype.onMouseMove = function (event) {
            this.handleLegendMouseMove(event);
            if (this.tooltip.enabled) {
                if (this.tooltip.delay > 0) {
                    this.tooltip.toggle(false);
                }
                this.handleTooltip(event);
            }
        };
        Chart.prototype.handleTooltip = function (event) {
            var _a = this, lastPick = _a.lastPick, tooltipTracking = _a.tooltip.tracking;
            var offsetX = event.offsetX, offsetY = event.offsetY;
            var pick = this.pickSeriesNode(offsetX, offsetY);
            var nodeDatum;
            if (pick && pick.node instanceof Shape) {
                var node = pick.node;
                nodeDatum = node.datum;
                if (lastPick && lastPick.datum === nodeDatum) {
                    lastPick.node = node;
                    lastPick.event = event;
                }
                // Marker nodes will have the `point` info in their datums.
                // Highlight if not a marker node or, if not in the tracking mode, highlight markers too.
                if ((!node.datum.point || !tooltipTracking)) {
                    if (!lastPick // cursor moved from empty space to a node
                        || lastPick.node !== node) { // cursor moved from one node to another
                        this.onSeriesDatumPick(event, node.datum, node, event);
                    }
                    else if (pick.series.tooltip.enabled) { // cursor moved within the same node
                        this.tooltip.show(event);
                    }
                    // A non-marker node (takes precedence over marker nodes) was highlighted.
                    // Or we are not in the tracking mode.
                    // Either way, we are done at this point.
                    return;
                }
            }
            var hideTooltip = false;
            // In tracking mode a tooltip is shown for the closest rendered datum.
            // This makes it easier to show tooltips when markers are small and/or plentiful
            // and also gives the ability to show tooltips even when the series were configured
            // to not render markers.
            if (tooltipTracking) {
                var closestDatum = this.pickClosestSeriesNodeDatum(offsetX, offsetY);
                if (closestDatum && closestDatum.point) {
                    var _b = closestDatum.point, x = _b.x, y = _b.y;
                    var canvas = this.scene.canvas;
                    var point = closestDatum.series.group.inverseTransformPoint(x, y);
                    var canvasRect = canvas.element.getBoundingClientRect();
                    this.onSeriesDatumPick({
                        pageX: Math.round(canvasRect.left + window.pageXOffset + point.x),
                        pageY: Math.round(canvasRect.top + window.pageYOffset + point.y)
                    }, closestDatum, nodeDatum === closestDatum && pick ? pick.node : undefined, event);
                }
                else {
                    hideTooltip = true;
                }
            }
            if (lastPick && (hideTooltip || !tooltipTracking)) {
                // Cursor moved from a non-marker node to empty space.
                this.dehighlightDatum();
                this.tooltip.toggle(false);
                this.lastPick = undefined;
            }
        };
        Chart.prototype.onMouseDown = function (event) { };
        Chart.prototype.onMouseUp = function (event) { };
        Chart.prototype.onMouseOut = function (event) {
            this.tooltip.toggle(false);
        };
        Chart.prototype.onClick = function (event) {
            if (this.checkSeriesNodeClick()) {
                return;
            }
            if (this.checkLegendClick(event)) {
                return;
            }
            this.fireEvent({
                type: 'click',
                event: event
            });
        };
        Chart.prototype.checkSeriesNodeClick = function () {
            var lastPick = this.lastPick;
            if (lastPick && lastPick.event && lastPick.node) {
                var event_1 = lastPick.event, datum = lastPick.datum;
                datum.series.fireNodeClickEvent(event_1, datum);
                return true;
            }
            return false;
        };
        Chart.prototype.onSeriesNodeClick = function (event) {
            this.fireEvent(__assign$1(__assign$1({}, event), { type: 'seriesNodeClick' }));
        };
        Chart.prototype.checkLegendClick = function (event) {
            var datum = this.legend.getDatumForPoint(event.offsetX, event.offsetY);
            if (datum) {
                var id_1 = datum.id, itemId = datum.itemId, enabled = datum.enabled;
                var series = find(this.series, function (series) { return series.id === id_1; });
                if (series) {
                    series.toggleSeriesItem(itemId, !enabled);
                    if (enabled) {
                        this.tooltip.toggle(false);
                    }
                    this.legend.fireEvent({
                        type: 'click',
                        event: event,
                        itemId: itemId,
                        enabled: !enabled
                    });
                    return true;
                }
            }
            return false;
        };
        Chart.prototype.handleLegendMouseMove = function (event) {
            if (!this.legend.enabled) {
                return;
            }
            var offsetX = event.offsetX, offsetY = event.offsetY;
            var datum = this.legend.getDatumForPoint(offsetX, offsetY);
            var pointerInsideLegend = this.legendBBox.containsPoint(offsetX, offsetY);
            if (pointerInsideLegend) {
                if (!this.pointerInsideLegend) {
                    this.pointerInsideLegend = true;
                }
            }
            else if (this.pointerInsideLegend) {
                this.pointerInsideLegend = false;
                // Dehighlight if the pointer was inside the legend and is now leaving it.
                if (this.highlightedDatum) {
                    this.highlightedDatum = undefined;
                    this.series.forEach(function (s) { return s.updatePending = true; });
                }
                return;
            }
            var oldHighlightedDatum = this.highlightedDatum;
            if (datum) {
                var id_2 = datum.id, itemId = datum.itemId, enabled = datum.enabled;
                if (enabled) {
                    var series = find(this.series, function (series) { return series.id === id_2; });
                    if (series) {
                        this.highlightedDatum = {
                            series: series,
                            itemId: itemId,
                            datum: undefined
                        };
                    }
                }
            }
            // Careful to only schedule updates when necessary.
            if ((this.highlightedDatum && !oldHighlightedDatum) ||
                (this.highlightedDatum && oldHighlightedDatum &&
                    (this.highlightedDatum.series !== oldHighlightedDatum.series ||
                        this.highlightedDatum.itemId !== oldHighlightedDatum.itemId))) {
                this.series.forEach(function (s) { return s.updatePending = true; });
            }
        };
        Chart.prototype.onSeriesDatumPick = function (meta, datum, node, event) {
            var lastPick = this.lastPick;
            if (lastPick) {
                if (lastPick.datum === datum) {
                    return;
                }
                this.dehighlightDatum();
            }
            this.lastPick = {
                datum: datum,
                node: node,
                event: event
            };
            this.highlightDatum(datum);
            var html = datum.series.tooltip.enabled && datum.series.getTooltipHtml(datum);
            if (html) {
                this.tooltip.show(meta, html);
            }
        };
        Chart.prototype.highlightDatum = function (datum) {
            this.scene.canvas.element.style.cursor = datum.series.cursor;
            this.highlightedDatum = datum;
            this.series.forEach(function (s) { return s.updatePending = true; });
        };
        Chart.prototype.dehighlightDatum = function () {
            this.scene.canvas.element.style.cursor = 'default';
            this.highlightedDatum = undefined;
            this.series.forEach(function (s) { return s.updatePending = true; });
        };
        Chart.defaultTooltipClass = 'ag-chart-tooltip';
        Chart.tooltipDocuments = [];
        __decorate$3([
            reactive('layoutChange')
        ], Chart.prototype, "title", void 0);
        __decorate$3([
            reactive('layoutChange')
        ], Chart.prototype, "subtitle", void 0);
        return Chart;
    }(Observable));

    var __extends$u = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    /**
     * Acts as `Group` node but with specified bounds that form a rectangle.
     * Any parts of the child nodes outside that rectangle will not be visible.
     * Unlike the `Group` node, the `ClipRect` node cannot be transformed.
     */
    var ClipRect = /** @class */ (function (_super) {
        __extends$u(ClipRect, _super);
        function ClipRect() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.isContainerNode = true;
            _this.path = new Path2D();
            _this._enabled = true;
            _this._dirtyPath = true;
            _this._x = 0;
            _this._y = 0;
            _this._width = 10;
            _this._height = 10;
            return _this;
        }
        ClipRect.prototype.containsPoint = function (x, y) {
            var point = this.transformPoint(x, y);
            return point.x >= this.x && point.x <= this.x + this.width
                && point.y >= this.y && point.y <= this.y + this.height;
        };
        Object.defineProperty(ClipRect.prototype, "enabled", {
            get: function () {
                return this._enabled;
            },
            set: function (value) {
                if (this._enabled !== value) {
                    this._enabled = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ClipRect.prototype, "dirtyPath", {
            get: function () {
                return this._dirtyPath;
            },
            set: function (value) {
                if (this._dirtyPath !== value) {
                    this._dirtyPath = value;
                    if (value) {
                        this.dirty = true;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ClipRect.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (value) {
                if (this._x !== value) {
                    this._x = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ClipRect.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (value) {
                if (this._y !== value) {
                    this._y = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ClipRect.prototype, "width", {
            get: function () {
                return this._width;
            },
            set: function (value) {
                if (this._width !== value) {
                    this._width = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ClipRect.prototype, "height", {
            get: function () {
                return this._height;
            },
            set: function (value) {
                if (this._height !== value) {
                    this._height = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        ClipRect.prototype.updatePath = function () {
            var path = this.path;
            path.clear();
            path.rect(this.x, this.y, this.width, this.height);
            this.dirtyPath = false;
        };
        ClipRect.prototype.computeBBox = function () {
            var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
            return new BBox(x, y, width, height);
        };
        ClipRect.prototype.render = function (ctx) {
            if (this.enabled) {
                if (this.dirtyPath) {
                    this.updatePath();
                }
                this.path.draw(ctx);
                ctx.clip();
            }
            var children = this.children;
            var n = children.length;
            for (var i = 0; i < n; i++) {
                ctx.save();
                var child = children[i];
                if (child.visible) {
                    child.render(ctx);
                }
                ctx.restore();
            }
            // debug
            // this.computeBBox().render(ctx, {
            //     label: this.id,
            //     resetTransform: true,
            //     fillStyle: 'rgba(0, 0, 0, 0.5)'
            // });
        };
        ClipRect.className = 'ClipRect';
        return ClipRect;
    }(Node));

    var __extends$v = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var RangeHandle = /** @class */ (function (_super) {
        __extends$v(RangeHandle, _super);
        function RangeHandle() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._fill = '#f2f2f2';
            _this._stroke = '#999999';
            _this._strokeWidth = 1;
            _this._lineCap = 'square';
            _this._centerX = 0;
            _this._centerY = 0;
            // Use an even number for better looking results.
            _this._width = 8;
            // Use an even number for better looking results.
            _this._gripLineGap = 2;
            // Use an even number for better looking results.
            _this._gripLineLength = 8;
            _this._height = 16;
            return _this;
        }
        Object.defineProperty(RangeHandle.prototype, "centerX", {
            get: function () {
                return this._centerX;
            },
            set: function (value) {
                if (this._centerX !== value) {
                    this._centerX = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeHandle.prototype, "centerY", {
            get: function () {
                return this._centerY;
            },
            set: function (value) {
                if (this._centerY !== value) {
                    this._centerY = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeHandle.prototype, "width", {
            get: function () {
                return this._width;
            },
            set: function (value) {
                if (this._width !== value) {
                    this._width = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeHandle.prototype, "gripLineGap", {
            get: function () {
                return this._gripLineGap;
            },
            set: function (value) {
                if (this._gripLineGap !== value) {
                    this._gripLineGap = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeHandle.prototype, "gripLineLength", {
            get: function () {
                return this._gripLineLength;
            },
            set: function (value) {
                if (this._gripLineLength !== value) {
                    this._gripLineLength = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeHandle.prototype, "height", {
            get: function () {
                return this._height;
            },
            set: function (value) {
                if (this._height !== value) {
                    this._height = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        RangeHandle.prototype.computeBBox = function () {
            var _a = this, centerX = _a.centerX, centerY = _a.centerY, width = _a.width, height = _a.height;
            var x = centerX - width / 2;
            var y = centerY - height / 2;
            return new BBox(x, y, width, height);
        };
        RangeHandle.prototype.isPointInPath = function (x, y) {
            var point = this.transformPoint(x, y);
            var bbox = this.computeBBox();
            return bbox.containsPoint(point.x, point.y);
        };
        RangeHandle.prototype.updatePath = function () {
            var _a = this, path = _a.path, centerX = _a.centerX, centerY = _a.centerY, width = _a.width, height = _a.height;
            var _b = this, a = _b.alignment, al = _b.align;
            path.clear();
            var x = centerX - width / 2;
            var y = centerY - height / 2;
            var ax = al(a, x);
            var ay = al(a, y);
            var axw = ax + al(a, x, width);
            var ayh = ay + al(a, y, height);
            // Handle.
            path.moveTo(ax, ay);
            path.lineTo(axw, ay);
            path.lineTo(axw, ayh);
            path.lineTo(ax, ayh);
            path.lineTo(ax, ay);
            // Grip lines.
            var dx = this.gripLineGap / 2;
            var dy = this.gripLineLength / 2;
            path.moveTo(al(a, centerX - dx), al(a, centerY - dy));
            path.lineTo(al(a, centerX - dx), al(a, centerY + dy));
            path.moveTo(al(a, centerX + dx), al(a, centerY - dy));
            path.lineTo(al(a, centerX + dx), al(a, centerY + dy));
        };
        RangeHandle.className = 'RangeHandle';
        return RangeHandle;
    }(Path));

    var __extends$w = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var RangeMask = /** @class */ (function (_super) {
        __extends$w(RangeMask, _super);
        function RangeMask() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._stroke = '#999999';
            _this._strokeWidth = 1;
            _this._fill = '#999999';
            _this._fillOpacity = 0.2;
            _this._lineCap = 'square';
            _this._x = 0;
            _this._y = 0;
            _this._width = 200;
            _this._height = 30;
            _this.minRange = 0.05;
            _this._min = 0;
            _this._max = 1;
            return _this;
        }
        Object.defineProperty(RangeMask.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (value) {
                if (this._x !== value) {
                    this._x = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeMask.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (value) {
                if (this._y !== value) {
                    this._y = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeMask.prototype, "width", {
            get: function () {
                return this._width;
            },
            set: function (value) {
                if (this._width !== value) {
                    this._width = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeMask.prototype, "height", {
            get: function () {
                return this._height;
            },
            set: function (value) {
                if (this._height !== value) {
                    this._height = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeMask.prototype, "min", {
            get: function () {
                return this._min;
            },
            set: function (value) {
                value = Math.min(Math.max(value, 0), this.max - this.minRange);
                if (isNaN(value)) {
                    return;
                }
                if (this._min !== value) {
                    this._min = value;
                    this.dirtyPath = true;
                    this.onRangeChange && this.onRangeChange(value, this.max);
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeMask.prototype, "max", {
            get: function () {
                return this._max;
            },
            set: function (value) {
                value = Math.max(Math.min(value, 1), this.min + this.minRange);
                if (isNaN(value)) {
                    return;
                }
                if (this._max !== value) {
                    this._max = value;
                    this.dirtyPath = true;
                    this.onRangeChange && this.onRangeChange(this.min, value);
                }
            },
            enumerable: true,
            configurable: true
        });
        RangeMask.prototype.computeBBox = function () {
            var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
            return new BBox(x, y, width, height);
        };
        RangeMask.prototype.computeVisibleRangeBBox = function () {
            var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height, min = _a.min, max = _a.max;
            var minX = x + width * min;
            var maxX = x + width * max;
            return new BBox(minX, y, maxX - minX, height);
        };
        RangeMask.prototype.updatePath = function () {
            var _a = this, path = _a.path, x = _a.x, y = _a.y, width = _a.width, height = _a.height, min = _a.min, max = _a.max;
            var _b = this, a = _b.alignment, al = _b.align;
            path.clear();
            var ax = al(a, x);
            var ay = al(a, y);
            var axw = ax + al(a, x, width);
            var ayh = ay + al(a, y, height);
            // Whole range.
            path.moveTo(ax, ay);
            path.lineTo(axw, ay);
            path.lineTo(axw, ayh);
            path.lineTo(ax, ayh);
            path.lineTo(ax, ay);
            var minX = al(a, x + width * min);
            var maxX = al(a, x + width * max);
            // Visible range.
            path.moveTo(minX, ay);
            path.lineTo(minX, ayh);
            path.lineTo(maxX, ayh);
            path.lineTo(maxX, ay);
            path.lineTo(minX, ay);
        };
        RangeMask.className = 'RangeMask';
        return RangeMask;
    }(Path));

    var __extends$x = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var RangeSelector = /** @class */ (function (_super) {
        __extends$x(RangeSelector, _super);
        function RangeSelector() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.isContainerNode = true;
            _this.minHandle = new RangeHandle();
            _this.maxHandle = new RangeHandle();
            _this.mask = (function () {
                var _a = RangeSelector.defaults, x = _a.x, y = _a.y, width = _a.width, height = _a.height, min = _a.min, max = _a.max;
                var mask = new RangeMask();
                mask.x = x;
                mask.y = y;
                mask.width = width;
                mask.height = height;
                mask.min = min;
                mask.max = max;
                var _b = _this, minHandle = _b.minHandle, maxHandle = _b.maxHandle;
                minHandle.centerX = x;
                maxHandle.centerX = x + width;
                minHandle.centerY = maxHandle.centerY = y + height / 2;
                _this.append([mask, minHandle, maxHandle]);
                mask.onRangeChange = function (min, max) {
                    _this.updateHandles();
                    _this.onRangeChange && _this.onRangeChange(min, max);
                };
                return mask;
            })();
            _this._x = RangeSelector.defaults.x;
            _this._y = RangeSelector.defaults.y;
            _this._width = RangeSelector.defaults.width;
            _this._height = RangeSelector.defaults.height;
            _this._min = RangeSelector.defaults.min;
            _this._max = RangeSelector.defaults.max;
            return _this;
        }
        Object.defineProperty(RangeSelector.prototype, "x", {
            get: function () {
                return this.mask.x;
            },
            set: function (value) {
                this.mask.x = value;
                this.updateHandles();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeSelector.prototype, "y", {
            get: function () {
                return this.mask.y;
            },
            set: function (value) {
                this.mask.y = value;
                this.updateHandles();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeSelector.prototype, "width", {
            get: function () {
                return this.mask.width;
            },
            set: function (value) {
                this.mask.width = value;
                this.updateHandles();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeSelector.prototype, "height", {
            get: function () {
                return this.mask.height;
            },
            set: function (value) {
                this.mask.height = value;
                this.updateHandles();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeSelector.prototype, "min", {
            get: function () {
                return this.mask.min;
            },
            set: function (value) {
                this.mask.min = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(RangeSelector.prototype, "max", {
            get: function () {
                return this.mask.max;
            },
            set: function (value) {
                this.mask.max = value;
            },
            enumerable: true,
            configurable: true
        });
        RangeSelector.prototype.updateHandles = function () {
            var _a = this, minHandle = _a.minHandle, maxHandle = _a.maxHandle, x = _a.x, y = _a.y, width = _a.width, height = _a.height, mask = _a.mask;
            minHandle.centerX = x + width * mask.min;
            maxHandle.centerX = x + width * mask.max;
            minHandle.centerY = maxHandle.centerY = y + height / 2;
        };
        RangeSelector.prototype.computeBBox = function () {
            return this.mask.computeBBox();
        };
        RangeSelector.prototype.computeVisibleRangeBBox = function () {
            return this.mask.computeVisibleRangeBBox();
        };
        RangeSelector.prototype.render = function (ctx) {
            if (this.dirtyTransform) {
                this.computeTransformMatrix();
            }
            this.matrix.toContext(ctx);
            var _a = this, mask = _a.mask, minHandle = _a.minHandle, maxHandle = _a.maxHandle;
            [mask, minHandle, maxHandle].forEach(function (child) {
                ctx.save();
                if (child.visible) {
                    child.render(ctx);
                }
                ctx.restore();
            });
        };
        RangeSelector.className = 'Range';
        RangeSelector.defaults = {
            x: 0,
            y: 0,
            width: 200,
            height: 30,
            min: 0,
            max: 1
        };
        return RangeSelector;
    }(Group));

    var NavigatorMask = /** @class */ (function () {
        function NavigatorMask(rangeMask) {
            this.rm = rangeMask;
        }
        Object.defineProperty(NavigatorMask.prototype, "fill", {
            get: function () {
                return this.rm.fill;
            },
            set: function (value) {
                this.rm.fill = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorMask.prototype, "stroke", {
            get: function () {
                return this.rm.stroke;
            },
            set: function (value) {
                this.rm.stroke = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorMask.prototype, "strokeWidth", {
            get: function () {
                return this.rm.strokeWidth;
            },
            set: function (value) {
                this.rm.strokeWidth = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorMask.prototype, "fillOpacity", {
            get: function () {
                return this.rm.fillOpacity;
            },
            set: function (value) {
                this.rm.fillOpacity = value;
            },
            enumerable: true,
            configurable: true
        });
        return NavigatorMask;
    }());

    var NavigatorHandle = /** @class */ (function () {
        function NavigatorHandle(rangeHandle) {
            this.rh = rangeHandle;
        }
        Object.defineProperty(NavigatorHandle.prototype, "fill", {
            get: function () {
                return this.rh.fill;
            },
            set: function (value) {
                this.rh.fill = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "stroke", {
            get: function () {
                return this.rh.stroke;
            },
            set: function (value) {
                this.rh.stroke = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "strokeWidth", {
            get: function () {
                return this.rh.strokeWidth;
            },
            set: function (value) {
                this.rh.strokeWidth = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "width", {
            get: function () {
                return this.rh.width;
            },
            set: function (value) {
                this.rh.width = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "height", {
            get: function () {
                return this.rh.height;
            },
            set: function (value) {
                this.rh.height = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "gripLineGap", {
            get: function () {
                return this.rh.gripLineGap;
            },
            set: function (value) {
                this.rh.gripLineGap = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NavigatorHandle.prototype, "gripLineLength", {
            get: function () {
                return this.rh.gripLineLength;
            },
            set: function (value) {
                this.rh.gripLineLength = value;
            },
            enumerable: true,
            configurable: true
        });
        return NavigatorHandle;
    }());

    var Navigator = /** @class */ (function () {
        function Navigator(chart) {
            var _this = this;
            this.rs = new RangeSelector();
            this.mask = new NavigatorMask(this.rs.mask);
            this.minHandle = new NavigatorHandle(this.rs.minHandle);
            this.maxHandle = new NavigatorHandle(this.rs.maxHandle);
            this.minHandleDragging = false;
            this.maxHandleDragging = false;
            this.panHandleOffset = NaN;
            this._margin = 10;
            this.chart = chart;
            chart.scene.root.append(this.rs);
            this.rs.onRangeChange = function (min, max) { return _this.updateAxes(min, max); };
        }
        Object.defineProperty(Navigator.prototype, "enabled", {
            get: function () {
                return this.rs.visible;
            },
            set: function (value) {
                this.rs.visible = value;
                this.chart.layoutPending = true;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "x", {
            get: function () {
                return this.rs.x;
            },
            set: function (value) {
                this.rs.x = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "y", {
            get: function () {
                return this.rs.y;
            },
            set: function (value) {
                this.rs.y = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "width", {
            get: function () {
                return this.rs.width;
            },
            set: function (value) {
                this.rs.width = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "height", {
            get: function () {
                return this.rs.height;
            },
            set: function (value) {
                this.rs.height = value;
                this.chart.layoutPending = true;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "margin", {
            get: function () {
                return this._margin;
            },
            set: function (value) {
                this._margin = value;
                this.chart.layoutPending = true;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "min", {
            get: function () {
                return this.rs.min;
            },
            set: function (value) {
                this.rs.min = value;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Navigator.prototype, "max", {
            get: function () {
                return this.rs.max;
            },
            set: function (value) {
                this.rs.max = value;
            },
            enumerable: true,
            configurable: true
        });
        Navigator.prototype.updateAxes = function (min, max) {
            var chart = this.chart;
            var clipSeries = false;
            chart.axes.forEach(function (axis) {
                if (axis.direction === exports.ChartAxisDirection.X) {
                    if (!clipSeries && (min > 0 || max < 1)) {
                        clipSeries = true;
                    }
                    axis.visibleRange = [min, max];
                    axis.update();
                }
            });
            chart.seriesRoot.enabled = clipSeries;
            chart.series.forEach(function (s) { return s.nodeDataPending = true; });
        };
        Navigator.prototype.onDragStart = function (offset) {
            if (!this.enabled) {
                return;
            }
            var offsetX = offset.offsetX, offsetY = offset.offsetY;
            var rs = this.rs;
            var minHandle = rs.minHandle, maxHandle = rs.maxHandle, x = rs.x, width = rs.width, min = rs.min;
            var visibleRange = rs.computeVisibleRangeBBox();
            if (!(this.minHandleDragging || this.maxHandleDragging)) {
                if (minHandle.containsPoint(offsetX, offsetY)) {
                    this.minHandleDragging = true;
                }
                else if (maxHandle.containsPoint(offsetX, offsetY)) {
                    this.maxHandleDragging = true;
                }
                else if (visibleRange.containsPoint(offsetX, offsetY)) {
                    this.panHandleOffset = (offsetX - x) / width - min;
                }
            }
        };
        Navigator.prototype.onDrag = function (offset) {
            if (!this.enabled) {
                return;
            }
            var _a = this, rs = _a.rs, panHandleOffset = _a.panHandleOffset;
            var x = rs.x, y = rs.y, width = rs.width, height = rs.height, minHandle = rs.minHandle, maxHandle = rs.maxHandle;
            var style = this.chart.element.style;
            var offsetX = offset.offsetX, offsetY = offset.offsetY;
            var minX = x + width * rs.min;
            var maxX = x + width * rs.max;
            var visibleRange = new BBox(minX, y, maxX - minX, height);
            function getRatio() {
                return Math.min(Math.max((offsetX - x) / width, 0), 1);
            }
            if (minHandle.containsPoint(offsetX, offsetY)) {
                style.cursor = 'ew-resize';
            }
            else if (maxHandle.containsPoint(offsetX, offsetY)) {
                style.cursor = 'ew-resize';
            }
            else if (visibleRange.containsPoint(offsetX, offsetY)) {
                style.cursor = 'grab';
            }
            else {
                style.cursor = 'default';
            }
            if (this.minHandleDragging) {
                rs.min = getRatio();
            }
            else if (this.maxHandleDragging) {
                rs.max = getRatio();
            }
            else if (!isNaN(panHandleOffset)) {
                var span = rs.max - rs.min;
                var min = Math.min(getRatio() - panHandleOffset, 1 - span);
                if (min <= rs.min) { // pan left
                    rs.min = min;
                    rs.max = rs.min + span;
                }
                else { // pan right
                    rs.max = min + span;
                    rs.min = rs.max - span;
                }
            }
        };
        Navigator.prototype.onDragStop = function () {
            this.stopHandleDragging();
        };
        Navigator.prototype.stopHandleDragging = function () {
            this.minHandleDragging = this.maxHandleDragging = false;
            this.panHandleOffset = NaN;
        };
        return Navigator;
    }());

    var __extends$y = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __read$9 = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$1 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$9(arguments[i]));
        return ar;
    };
    var CartesianChart = /** @class */ (function (_super) {
        __extends$y(CartesianChart, _super);
        function CartesianChart(document) {
            if (document === void 0) { document = window.document; }
            var _this = _super.call(this, document) || this;
            _this._seriesRoot = new ClipRect();
            _this.navigator = new Navigator(_this);
            // Prevent the scene from rendering chart components in an invalid state
            // (before first layout is performed).
            _this.scene.root.visible = false;
            var root = _this.scene.root;
            root.append(_this.seriesRoot);
            root.append(_this.legend.group);
            _this.navigator.enabled = false;
            return _this;
        }
        Object.defineProperty(CartesianChart.prototype, "seriesRoot", {
            get: function () {
                return this._seriesRoot;
            },
            enumerable: true,
            configurable: true
        });
        CartesianChart.prototype.performLayout = function () {
            if (this.dataPending) {
                return;
            }
            this.scene.root.visible = true;
            var _a = this, width = _a.width, height = _a.height, axes = _a.axes, legend = _a.legend, navigator = _a.navigator;
            var shrinkRect = new BBox(0, 0, width, height);
            this.positionCaptions();
            this.positionLegend();
            if (legend.enabled && legend.data.length) {
                var legendAutoPadding = this.legendAutoPadding;
                var legendPadding = this.legend.spacing;
                shrinkRect.x += legendAutoPadding.left;
                shrinkRect.y += legendAutoPadding.top;
                shrinkRect.width -= legendAutoPadding.left + legendAutoPadding.right;
                shrinkRect.height -= legendAutoPadding.top + legendAutoPadding.bottom;
                switch (this.legend.position) {
                    case 'right':
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'bottom':
                        shrinkRect.height -= legendPadding;
                        break;
                    case 'left':
                        shrinkRect.x += legendPadding;
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'top':
                        shrinkRect.y += legendPadding;
                        shrinkRect.height -= legendPadding;
                        break;
                }
            }
            var _b = this, captionAutoPadding = _b.captionAutoPadding, padding = _b.padding;
            this.updateAxes();
            shrinkRect.x += padding.left;
            shrinkRect.width -= padding.left + padding.right;
            shrinkRect.y += padding.top + captionAutoPadding;
            shrinkRect.height -= padding.top + captionAutoPadding + padding.bottom;
            if (navigator.enabled) {
                shrinkRect.height -= navigator.height + navigator.margin;
            }
            var bottomAxesHeight = 0;
            var axisPositionVisited = {
                top: false,
                right: false,
                bottom: false,
                left: false,
                angle: false,
                radius: false
            };
            axes.forEach(function (axis) {
                axis.group.visible = true;
                var axisThickness = Math.floor(axis.thickness || axis.computeBBox().width);
                // for multiple axes in the same direction and position, apply padding at the top of each inner axis (i.e. between axes).
                var axisPadding = axis.title && axis.title.padding.top || 15;
                if (axisPositionVisited[axis.position]) {
                    axisThickness += axisPadding;
                }
                switch (axis.position) {
                    case exports.ChartAxisPosition.Top:
                        axisPositionVisited[exports.ChartAxisPosition.Top] = true;
                        shrinkRect.y += axisThickness;
                        shrinkRect.height -= axisThickness;
                        axis.translation.y = Math.floor(shrinkRect.y + 1);
                        axis.label.mirrored = true;
                        break;
                    case exports.ChartAxisPosition.Right:
                        axisPositionVisited[exports.ChartAxisPosition.Right] = true;
                        shrinkRect.width -= axisThickness;
                        axis.translation.x = Math.floor(shrinkRect.x + shrinkRect.width);
                        axis.label.mirrored = true;
                        break;
                    case exports.ChartAxisPosition.Bottom:
                        axisPositionVisited[exports.ChartAxisPosition.Bottom] = true;
                        shrinkRect.height -= axisThickness;
                        bottomAxesHeight += axisThickness;
                        axis.translation.y = Math.floor(shrinkRect.y + shrinkRect.height + 1);
                        break;
                    case exports.ChartAxisPosition.Left:
                        axisPositionVisited[exports.ChartAxisPosition.Left] = true;
                        shrinkRect.x += axisThickness;
                        shrinkRect.width -= axisThickness;
                        axis.translation.x = Math.floor(shrinkRect.x);
                        break;
                }
            });
            axes.forEach(function (axis) {
                switch (axis.position) {
                    case exports.ChartAxisPosition.Top:
                    case exports.ChartAxisPosition.Bottom:
                        axis.translation.x = Math.floor(shrinkRect.x);
                        axis.range = [0, shrinkRect.width];
                        axis.gridLength = shrinkRect.height;
                        break;
                    case exports.ChartAxisPosition.Left:
                    case exports.ChartAxisPosition.Right:
                        axis.translation.y = Math.floor(shrinkRect.y);
                        if (axis instanceof CategoryAxis || axis instanceof GroupedCategoryAxis) {
                            axis.range = [0, shrinkRect.height];
                        }
                        else {
                            axis.range = [shrinkRect.height, 0];
                        }
                        axis.gridLength = shrinkRect.width;
                        break;
                }
            });
            this.createNodeData();
            this.seriesRect = shrinkRect;
            this.series.forEach(function (series) {
                series.group.translationX = Math.floor(shrinkRect.x);
                series.group.translationY = Math.floor(shrinkRect.y);
                series.update(); // this has to happen after the `updateAxes` call
            });
            var seriesRoot = this.seriesRoot;
            seriesRoot.x = shrinkRect.x;
            seriesRoot.y = shrinkRect.y;
            seriesRoot.width = shrinkRect.width;
            seriesRoot.height = shrinkRect.height;
            if (navigator.enabled) {
                navigator.x = shrinkRect.x;
                navigator.y = shrinkRect.y + shrinkRect.height + bottomAxesHeight + navigator.margin;
                navigator.width = shrinkRect.width;
            }
            this.axes.forEach(function (axis) { return axis.update(); });
        };
        CartesianChart.prototype.initSeries = function (series) {
            _super.prototype.initSeries.call(this, series);
        };
        CartesianChart.prototype.freeSeries = function (series) {
            _super.prototype.freeSeries.call(this, series);
        };
        CartesianChart.prototype.setupDomListeners = function (chartElement) {
            _super.prototype.setupDomListeners.call(this, chartElement);
            this._onTouchStart = this.onTouchStart.bind(this);
            this._onTouchMove = this.onTouchMove.bind(this);
            this._onTouchEnd = this.onTouchEnd.bind(this);
            this._onTouchCancel = this.onTouchCancel.bind(this);
            chartElement.addEventListener('touchstart', this._onTouchStart, { passive: true });
            chartElement.addEventListener('touchmove', this._onTouchMove, { passive: true });
            chartElement.addEventListener('touchend', this._onTouchEnd, { passive: true });
            chartElement.addEventListener('touchcancel', this._onTouchCancel, { passive: true });
        };
        CartesianChart.prototype.cleanupDomListeners = function (chartElement) {
            _super.prototype.cleanupDomListeners.call(this, chartElement);
            chartElement.removeEventListener('touchstart', this._onTouchStart);
            chartElement.removeEventListener('touchmove', this._onTouchMove);
            chartElement.removeEventListener('touchend', this._onTouchEnd);
            chartElement.removeEventListener('touchcancel', this._onTouchCancel);
        };
        CartesianChart.prototype.getTouchOffset = function (event) {
            var rect = this.scene.canvas.element.getBoundingClientRect();
            var touch = event.touches[0];
            return touch ? {
                offsetX: touch.clientX - rect.left,
                offsetY: touch.clientY - rect.top
            } : undefined;
        };
        CartesianChart.prototype.onTouchStart = function (event) {
            var offset = this.getTouchOffset(event);
            if (offset) {
                this.navigator.onDragStart(offset);
            }
        };
        CartesianChart.prototype.onTouchMove = function (event) {
            var offset = this.getTouchOffset(event);
            if (offset) {
                this.navigator.onDrag(offset);
            }
        };
        CartesianChart.prototype.onTouchEnd = function (event) {
            this.navigator.onDragStop();
        };
        CartesianChart.prototype.onTouchCancel = function (event) {
            this.navigator.onDragStop();
        };
        CartesianChart.prototype.onMouseDown = function (event) {
            _super.prototype.onMouseDown.call(this, event);
            this.navigator.onDragStart(event);
        };
        CartesianChart.prototype.onMouseMove = function (event) {
            _super.prototype.onMouseMove.call(this, event);
            this.navigator.onDrag(event);
        };
        CartesianChart.prototype.onMouseUp = function (event) {
            _super.prototype.onMouseUp.call(this, event);
            this.navigator.onDragStop();
        };
        CartesianChart.prototype.onMouseOut = function (event) {
            _super.prototype.onMouseOut.call(this, event);
            this.navigator.onDragStop();
        };
        CartesianChart.prototype.assignAxesToSeries = function (force) {
            if (force === void 0) { force = false; }
            _super.prototype.assignAxesToSeries.call(this, force);
            this.series.forEach(function (series) {
                if (!series.xAxis) {
                    console.warn("Could not find a matching xAxis for the " + series.id + " series.");
                }
                if (!series.yAxis) {
                    console.warn("Could not find a matching yAxis for the " + series.id + " series.");
                }
            });
        };
        CartesianChart.prototype.updateAxes = function () {
            var navigator = this.navigator;
            var clipSeries = false;
            var primaryTickCount;
            this.axes.forEach(function (axis) {
                var _a;
                var direction = axis.direction, boundSeries = axis.boundSeries;
                if (axis.linkedTo) {
                    axis.domain = axis.linkedTo.domain;
                }
                else {
                    var domains_1 = [];
                    boundSeries.filter(function (s) { return s.visible; }).forEach(function (series) {
                        domains_1.push(series.getDomain(direction));
                    });
                    var domain = (_a = new Array()).concat.apply(_a, __spread$1(domains_1));
                    var isYAxis = axis.direction === 'y';
                    if (axis instanceof NumberAxis && isYAxis) {
                        // the `primaryTickCount` is used to align the secondary axis tick count with the primary
                        axis.setDomain(domain, primaryTickCount);
                        primaryTickCount = primaryTickCount || axis.scale.ticks(axis.tick.count).length;
                    }
                    else {
                        axis.domain = domain;
                    }
                }
                if (axis.direction === exports.ChartAxisDirection.X) {
                    axis.visibleRange = [navigator.min, navigator.max];
                }
                if (!clipSeries && (axis.visibleRange[0] > 0 || axis.visibleRange[1] < 1)) {
                    clipSeries = true;
                }
                axis.update();
            });
            this.seriesRoot.enabled = clipSeries;
        };
        CartesianChart.className = 'CartesianChart';
        CartesianChart.type = 'cartesian';
        return CartesianChart;
    }(Chart));

    var __extends$z = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var HierarchyChart = /** @class */ (function (_super) {
        __extends$z(HierarchyChart, _super);
        function HierarchyChart(document) {
            if (document === void 0) { document = window.document; }
            var _this = _super.call(this, document) || this;
            _this._data = {};
            _this._seriesRoot = new ClipRect();
            // Prevent the scene from rendering chart components in an invalid state
            // (before first layout is performed).
            _this.scene.root.visible = false;
            var root = _this.scene.root;
            root.append(_this.seriesRoot);
            root.append(_this.legend.group);
            return _this;
        }
        Object.defineProperty(HierarchyChart.prototype, "seriesRoot", {
            get: function () {
                return this._seriesRoot;
            },
            enumerable: true,
            configurable: true
        });
        HierarchyChart.prototype.performLayout = function () {
            if (this.dataPending) {
                return;
            }
            this.scene.root.visible = true;
            var _a = this, width = _a.width, height = _a.height, legend = _a.legend;
            var shrinkRect = new BBox(0, 0, width, height);
            this.positionCaptions();
            this.positionLegend();
            if (legend.enabled && legend.data.length) {
                var legendAutoPadding = this.legendAutoPadding;
                var legendPadding = this.legend.spacing;
                shrinkRect.x += legendAutoPadding.left;
                shrinkRect.y += legendAutoPadding.top;
                shrinkRect.width -= legendAutoPadding.left + legendAutoPadding.right;
                shrinkRect.height -= legendAutoPadding.top + legendAutoPadding.bottom;
                switch (this.legend.position) {
                    case 'right':
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'bottom':
                        shrinkRect.height -= legendPadding;
                        break;
                    case 'left':
                        shrinkRect.x += legendPadding;
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'top':
                        shrinkRect.y += legendPadding;
                        shrinkRect.height -= legendPadding;
                        break;
                }
            }
            var _b = this, captionAutoPadding = _b.captionAutoPadding, padding = _b.padding;
            shrinkRect.x += padding.left;
            shrinkRect.width -= padding.left + padding.right;
            shrinkRect.y += padding.top + captionAutoPadding;
            shrinkRect.height -= padding.top + captionAutoPadding + padding.bottom;
            this.seriesRect = shrinkRect;
            this.series.forEach(function (series) {
                series.group.translationX = Math.floor(shrinkRect.x);
                series.group.translationY = Math.floor(shrinkRect.y);
                series.update(); // this has to happen after the `updateAxes` call
            });
            var seriesRoot = this.seriesRoot;
            seriesRoot.x = shrinkRect.x;
            seriesRoot.y = shrinkRect.y;
            seriesRoot.width = shrinkRect.width;
            seriesRoot.height = shrinkRect.height;
        };
        HierarchyChart.className = 'HierarchyChart';
        HierarchyChart.type = 'hierarchy';
        return HierarchyChart;
    }(Chart));

    var __extends$A = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __read$a = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$2 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$a(arguments[i]));
        return ar;
    };
    var GroupedCategoryChart = /** @class */ (function (_super) {
        __extends$A(GroupedCategoryChart, _super);
        function GroupedCategoryChart() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        GroupedCategoryChart.prototype.updateAxes = function () {
            this.axes.forEach(function (axis) {
                var _a;
                var direction = axis.direction, boundSeries = axis.boundSeries;
                var domains = [];
                var isNumericX = undefined;
                boundSeries.filter(function (s) { return s.visible; }).forEach(function (series) {
                    if (direction === exports.ChartAxisDirection.X) {
                        if (isNumericX === undefined) {
                            // always add first X domain
                            var domain_1 = series.getDomain(direction);
                            domains.push(domain_1);
                            isNumericX = typeof domain_1[0] === 'number';
                        }
                        else if (isNumericX) {
                            // only add further X domains if the axis is numeric
                            domains.push(series.getDomain(direction));
                        }
                    }
                    else {
                        domains.push(series.getDomain(direction));
                    }
                });
                var domain = (_a = new Array()).concat.apply(_a, __spread$2(domains));
                axis.domain = extent(domain, isContinuous) || domain;
                axis.update();
            });
        };
        GroupedCategoryChart.className = 'GroupedCategoryChart';
        GroupedCategoryChart.type = 'groupedCategory';
        return GroupedCategoryChart;
    }(CartesianChart));

    var __extends$B = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var Label = /** @class */ (function (_super) {
        __extends$B(Label, _super);
        function Label() {
            var _this = _super.call(this) || this;
            _this.enabled = true;
            _this.fontSize = 12;
            _this.fontFamily = 'Verdana, sans-serif';
            _this.color = 'rgba(70, 70, 70, 1)';
            return _this;
        }
        Label.prototype.getFont = function () {
            return getFont(this.fontSize, this.fontFamily, this.fontStyle, this.fontWeight);
        };
        __decorate$4([
            reactive('change', 'dataChange')
        ], Label.prototype, "enabled", void 0);
        __decorate$4([
            reactive('change')
        ], Label.prototype, "fontSize", void 0);
        __decorate$4([
            reactive('change')
        ], Label.prototype, "fontFamily", void 0);
        __decorate$4([
            reactive('change')
        ], Label.prototype, "fontStyle", void 0);
        __decorate$4([
            reactive('change')
        ], Label.prototype, "fontWeight", void 0);
        __decorate$4([
            reactive('change')
        ], Label.prototype, "color", void 0);
        return Label;
    }(Observable));

    var __extends$C = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$5 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __read$b = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$3 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$b(arguments[i]));
        return ar;
    };
    var SeriesItemHighlightStyle = /** @class */ (function () {
        function SeriesItemHighlightStyle() {
            this.fill = 'yellow';
            this.stroke = undefined;
            this.strokeWidth = undefined;
        }
        return SeriesItemHighlightStyle;
    }());
    var SeriesHighlightStyle = /** @class */ (function () {
        function SeriesHighlightStyle() {
            this.strokeWidth = undefined;
            this.dimOpacity = undefined;
        }
        return SeriesHighlightStyle;
    }());
    var HighlightStyle = /** @class */ (function () {
        function HighlightStyle() {
            /**
             * @deprecated Use item.fill instead.
             */
            this.fill = undefined;
            /**
             * @deprecated Use item.stroke instead.
             */
            this.stroke = undefined;
            /**
            * @deprecated Use item.strokeWidth instead.
            */
            this.strokeWidth = undefined;
            this.item = new SeriesItemHighlightStyle();
            this.series = new SeriesHighlightStyle();
        }
        return HighlightStyle;
    }());
    var SeriesTooltip = /** @class */ (function (_super) {
        __extends$C(SeriesTooltip, _super);
        function SeriesTooltip() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.enabled = true;
            return _this;
        }
        __decorate$5([
            reactive('change')
        ], SeriesTooltip.prototype, "enabled", void 0);
        return SeriesTooltip;
    }(Observable));
    var Series = /** @class */ (function (_super) {
        __extends$C(Series, _super);
        function Series() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.id = createId(_this);
            // The group node that contains all the nodes used to render this series.
            _this.group = new Group();
            // The group node that contains all the nodes that can be "picked" (react to hover, tap, click).
            _this.pickGroup = _this.group.appendChild(new Group());
            _this.directions = [exports.ChartAxisDirection.X, exports.ChartAxisDirection.Y];
            _this.directionKeys = {};
            _this.label = new Label();
            _this.data = undefined;
            _this.visible = true;
            _this.showInLegend = true;
            _this.cursor = 'default';
            _this._nodeDataPending = true;
            _this._updatePending = false;
            _this.highlightStyle = new HighlightStyle();
            _this.scheduleLayout = function () {
                _this.fireEvent({ type: 'layoutChange' });
            };
            _this.scheduleData = function () {
                _this.fireEvent({ type: 'dataChange' });
            };
            return _this;
        }
        Object.defineProperty(Series.prototype, "type", {
            get: function () {
                return this.constructor.type || '';
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Series.prototype, "grouped", {
            set: function (g) {
                if (g === true) {
                    throw new Error("AG Charts - grouped: true is unsupported for series of type: " + this.type);
                }
            },
            enumerable: true,
            configurable: true
        });
        Series.prototype.setColors = function (fills, strokes) { };
        // Returns the actual keys used (to fetch the values from `data` items) for the given direction.
        Series.prototype.getKeys = function (direction) {
            var _this = this;
            var directionKeys = this.directionKeys;
            var keys = directionKeys && directionKeys[direction];
            var values = [];
            if (keys) {
                keys.forEach(function (key) {
                    var value = _this[key];
                    if (value) {
                        if (Array.isArray(value)) {
                            values.push.apply(values, __spread$3(value));
                        }
                        else {
                            values.push(value);
                        }
                    }
                });
            }
            return values;
        };
        // Using processed data, create data that backs visible nodes.
        Series.prototype.createNodeData = function () { return []; };
        // Returns persisted node data associated with the rendered portion of the series' data.
        Series.prototype.getNodeData = function () { return []; };
        Series.prototype.getLabelData = function () { return []; };
        Object.defineProperty(Series.prototype, "nodeDataPending", {
            get: function () {
                return this._nodeDataPending;
            },
            set: function (value) {
                if (this._nodeDataPending !== value) {
                    this._nodeDataPending = value;
                    this.updatePending = true;
                    if (value && this.chart) {
                        this.chart.updatePending = value;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Series.prototype.scheduleNodeDate = function () {
            this.nodeDataPending = true;
        };
        Object.defineProperty(Series.prototype, "updatePending", {
            get: function () {
                return this._updatePending;
            },
            set: function (value) {
                if (this._updatePending !== value) {
                    this._updatePending = value;
                    if (value && this.chart) {
                        this.chart.updatePending = value;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Series.prototype.scheduleUpdate = function () {
            this.updatePending = true;
        };
        Series.prototype.getOpacity = function (datum) {
            var _a = this, chart = _a.chart, _b = _a.highlightStyle.series.dimOpacity, dimOpacity = _b === void 0 ? 1 : _b;
            return !chart || !chart.highlightedDatum ||
                chart.highlightedDatum.series === this &&
                    (!datum || chart.highlightedDatum.itemId === datum.itemId) ? 1 : dimOpacity;
        };
        Series.prototype.getStrokeWidth = function (defaultStrokeWidth, datum) {
            var _a = this, chart = _a.chart, strokeWidth = _a.highlightStyle.series.strokeWidth;
            return chart && chart.highlightedDatum &&
                chart.highlightedDatum.series === this &&
                (!datum || chart.highlightedDatum.itemId === datum.itemId) &&
                strokeWidth !== undefined ? strokeWidth : defaultStrokeWidth;
        };
        Series.prototype.fireNodeClickEvent = function (event, datum) { };
        Series.prototype.toggleSeriesItem = function (itemId, enabled) {
            this.visible = enabled;
        };
        // Each series is expected to have its own logic to efficiently update its nodes
        // on hightlight changes.
        Series.prototype.onHighlightChange = function () { };
        Series.prototype.fixNumericExtent = function (extent, type) {
            if (!extent) {
                // if (type) {
                //     console.warn(`The ${type}-domain could not be found (no valid values), using the default of [0, 1].`);
                // }
                return [0, 1];
            }
            var _a = __read$b(extent, 2), min = _a[0], max = _a[1];
            min = +min;
            max = +max;
            if (min === max) {
                var padding = Math.abs(min * 0.01);
                min -= padding;
                max += padding;
                // if (type) {
                //     console.warn(`The ${type}-domain has zero length and has been automatically expanded`
                //         + ` by 1 in each direction (from the single valid ${type}-value: ${min}).`);
                // }
            }
            if (!(isNumber(min) && isNumber(max))) {
                min = 0;
                max = 1;
                // if (type) {
                //     console.warn(`The ${type}-domain has infinite length, using the default of [0, 1].`);
                // }
            }
            return [min, max];
        };
        Series.highlightedZIndex = 1000000000000;
        __decorate$5([
            reactive('dataChange')
        ], Series.prototype, "data", void 0);
        __decorate$5([
            reactive('dataChange')
        ], Series.prototype, "visible", void 0);
        __decorate$5([
            reactive('layoutChange')
        ], Series.prototype, "showInLegend", void 0);
        return Series;
    }(Observable));

    var __extends$D = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$6 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var SeriesMarker = /** @class */ (function (_super) {
        __extends$D(SeriesMarker, _super);
        function SeriesMarker() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.enabled = true;
            /**
             * One of the predefined marker names, or a marker constructor function (for user-defined markers).
             * A series will create one marker instance per data point.
             */
            _this.shape = Circle;
            _this.size = 6;
            /**
             * In case a series has the `sizeKey` set, the `sizeKey` values along with the `size` and `maxSize` configs
             * will be used to determine the size of the marker. All values will be mapped to a marker size
             * within the `[size, maxSize]` range, where the largest values will correspond to the `maxSize`
             * and the lowest to the `size`.
             */
            _this.maxSize = 30;
            _this.strokeWidth = 1;
            return _this;
        }
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "enabled", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "shape", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "size", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "maxSize", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "domain", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "fill", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "stroke", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "strokeWidth", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "fillOpacity", void 0);
        __decorate$6([
            reactive('change')
        ], SeriesMarker.prototype, "strokeOpacity", void 0);
        return SeriesMarker;
    }(Observable));

    var __extends$E = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var PolarSeries = /** @class */ (function (_super) {
        __extends$E(PolarSeries, _super);
        function PolarSeries() {
            var _a;
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.directionKeys = (_a = {},
                _a[exports.ChartAxisDirection.X] = ['angleKey'],
                _a[exports.ChartAxisDirection.Y] = ['radiusKey'],
                _a);
            /**
             * The center of the polar series (for example, the center of a pie).
             * If the polar chart has multiple series, all of them will have their
             * center set to the same value as a result of the polar chart layout.
             * The center coordinates are not supposed to be set by the user.
             */
            _this.centerX = 0;
            _this.centerY = 0;
            /**
             * The maximum radius the series can use.
             * This value is set automatically as a result of the polar chart layout
             * and is not supposed to be set by the user.
             */
            _this.radius = 0;
            return _this;
        }
        return PolarSeries;
    }(Series));
    var PolarSeriesMarker = /** @class */ (function (_super) {
        __extends$E(PolarSeriesMarker, _super);
        function PolarSeriesMarker() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return PolarSeriesMarker;
    }(SeriesMarker));

    var __extends$F = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var PolarChart = /** @class */ (function (_super) {
        __extends$F(PolarChart, _super);
        function PolarChart(document) {
            if (document === void 0) { document = window.document; }
            var _this = _super.call(this, document) || this;
            _this.padding = new Padding(40);
            _this.scene.root.append(_this.legend.group);
            _this.padding.addEventListener('layoutChange', _this.scheduleLayout, _this);
            return _this;
        }
        Object.defineProperty(PolarChart.prototype, "seriesRoot", {
            get: function () {
                return this.scene.root;
            },
            enumerable: true,
            configurable: true
        });
        PolarChart.prototype.performLayout = function () {
            var shrinkRect = new BBox(0, 0, this.width, this.height);
            this.positionCaptions();
            this.positionLegend();
            var captionAutoPadding = this.captionAutoPadding;
            shrinkRect.y += captionAutoPadding;
            shrinkRect.height -= captionAutoPadding;
            if (this.legend.enabled && this.legend.data.length) {
                var legendAutoPadding = this.legendAutoPadding;
                shrinkRect.x += legendAutoPadding.left;
                shrinkRect.y += legendAutoPadding.top;
                shrinkRect.width -= legendAutoPadding.left + legendAutoPadding.right;
                shrinkRect.height -= legendAutoPadding.top + legendAutoPadding.bottom;
                var legendPadding = this.legend.spacing;
                switch (this.legend.position) {
                    case 'right':
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'bottom':
                        shrinkRect.height -= legendPadding;
                        break;
                    case 'left':
                        shrinkRect.x += legendPadding;
                        shrinkRect.width -= legendPadding;
                        break;
                    case 'top':
                        shrinkRect.y += legendPadding;
                        shrinkRect.height -= legendPadding;
                        break;
                }
            }
            var padding = this.padding;
            shrinkRect.x += padding.left;
            shrinkRect.y += padding.top;
            shrinkRect.width -= padding.left + padding.right;
            shrinkRect.height -= padding.top + padding.bottom;
            this.seriesRect = shrinkRect;
            var centerX = shrinkRect.x + shrinkRect.width / 2;
            var centerY = shrinkRect.y + shrinkRect.height / 2;
            var radius = Math.max(0, Math.min(shrinkRect.width, shrinkRect.height) / 2); // radius shouldn't be negative
            this.series.forEach(function (series) {
                if (series instanceof PolarSeries) {
                    series.centerX = centerX;
                    series.centerY = centerY;
                    series.radius = radius;
                    series.update();
                }
            });
        };
        PolarChart.className = 'PolarChart';
        PolarChart.type = 'polar';
        return PolarChart;
    }(Chart));

    var __extends$G = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var CartesianSeries = /** @class */ (function (_super) {
        __extends$G(CartesianSeries, _super);
        function CartesianSeries() {
            var _a;
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.directionKeys = (_a = {},
                _a[exports.ChartAxisDirection.X] = ['xKey'],
                _a[exports.ChartAxisDirection.Y] = ['yKey'],
                _a);
            return _this;
        }
        /**
         * Note: we are passing `isContinuousX` and `isContinuousY` into this method because it will
         *       typically be called inside a loop and this check only needs to happen once.
         * @param x A domain value to be plotted along the x-axis.
         * @param y A domain value to be plotted along the y-axis.
         * @param isContinuousX Typically this will be the value of `xAxis.scale instanceof ContinuousScale`.
         * @param isContinuousY Typically this will be the value of `yAxis.scale instanceof ContinuousScale`.
         * @returns `[x, y]`, if both x and y are valid domain values for their respective axes/scales, or `undefined`.
         */
        CartesianSeries.prototype.checkDomainXY = function (x, y, isContinuousX, isContinuousY) {
            var isValidDatum = (isContinuousX && isContinuous(x) || isDiscrete(x)) &&
                (isContinuousY && isContinuous(y) || isDiscrete(y));
            return isValidDatum ? [x, y] : undefined;
        };
        /**
         * Note: we are passing the xAxis and yAxis because the calling code is supposed to make sure
         *       that series has both of them defined, and also to avoid one level of indirection,
         *       e.g. `this.xAxis!.inRange(x)`, both of which are suboptimal in tight loops where this method is used.
         * @param x A range value to be plotted along the x-axis.
         * @param y A range value to be plotted along the y-axis.
         * @param xAxis The series' x-axis.
         * @param yAxis The series' y-axis.
         * @returns
         */
        CartesianSeries.prototype.checkRangeXY = function (x, y, xAxis, yAxis) {
            return !isNaN(x) && !isNaN(y) && xAxis.inRange(x) && yAxis.inRange(y);
        };
        return CartesianSeries;
    }(Series));
    var CartesianSeriesMarker = /** @class */ (function (_super) {
        __extends$G(CartesianSeriesMarker, _super);
        function CartesianSeriesMarker() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return CartesianSeriesMarker;
    }(SeriesMarker));

    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_1, i = void 0;
            if (Array.isArray(a)) {
                length_1 = a.length;
                if (length_1 != b.length)
                    return false;
                for (i = length_1; i-- !== 0;)
                    if (!equal(a[i], b[i]))
                        return false;
                return true;
            }
            // if ((a instanceof Map) && (b instanceof Map)) {
            //     if (a.size !== b.size) return false;
            //     for (i of a.entries())
            //         if (!b.has(i[0])) return false;
            //     for (i of a.entries())
            //         if (!equal(i[1], b.get(i[0]))) return false;
            //     return true;
            // }
            //
            // if ((a instanceof Set) && (b instanceof Set)) {
            //     if (a.size !== b.size) return false;
            //     for (i of a.entries())
            //         if (!b.has(i[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;
            if (a.valueOf !== Object.prototype.valueOf)
                return a.valueOf() === b.valueOf();
            if (a.toString !== Object.prototype.toString)
                return a.toString() === b.toString();
            var keys = Object.keys(a);
            length_1 = keys.length;
            if (length_1 !== Object.keys(b).length)
                return false;
            for (i = length_1; i-- !== 0;)
                if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
                    return false;
            for (i = length_1; 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;
    }

    var __read$c = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var interpolatePattern = /(#\{(.*?)\})/g;
    function interpolate(input, values, formats) {
        return input.replace(interpolatePattern, function () {
            var name = arguments[2];
            var _a = __read$c(name.split(':'), 2), valueName = _a[0], formatName = _a[1];
            var value = values[valueName];
            if (typeof value === 'number') {
                var format = formatName && formats && formats[formatName];
                if (format) {
                    var _b = format, locales = _b.locales, options = _b.options;
                    return value.toLocaleString(locales, options);
                }
                return String(value);
            }
            if (value instanceof Date) {
                var format = formatName && formats && formats[formatName];
                if (typeof format === 'string') {
                    var formatter = locale.format(format);
                    return formatter(value);
                }
                return value.toDateString();
            }
            if (typeof value === 'string' || (value && value.toString)) {
                return String(value);
            }
            return '';
        });
    }

    var element = null;
    function sanitizeHtml(text) {
        element = element || document.createElement('div');
        if (!text) {
            return '';
        }
        element.innerText = text;
        return element.innerHTML;
    }

    var __extends$H = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$7 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __values$3 = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var AreaSeriesLabel = /** @class */ (function (_super) {
        __extends$H(AreaSeriesLabel, _super);
        function AreaSeriesLabel() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$7([
            reactive('change')
        ], AreaSeriesLabel.prototype, "formatter", void 0);
        return AreaSeriesLabel;
    }(Label));
    var AreaSeriesTooltip = /** @class */ (function (_super) {
        __extends$H(AreaSeriesTooltip, _super);
        function AreaSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$7([
            reactive('change')
        ], AreaSeriesTooltip.prototype, "renderer", void 0);
        __decorate$7([
            reactive('change')
        ], AreaSeriesTooltip.prototype, "format", void 0);
        return AreaSeriesTooltip;
    }(SeriesTooltip));
    var AreaSeries = /** @class */ (function (_super) {
        __extends$H(AreaSeries, _super);
        function AreaSeries() {
            var _this = _super.call(this) || this;
            _this.tooltip = new AreaSeriesTooltip();
            _this.areaGroup = _this.group.insertBefore(new Group, _this.pickGroup);
            _this.strokeGroup = _this.group.insertBefore(new Group, _this.pickGroup);
            _this.markerGroup = _this.pickGroup.appendChild(new Group);
            _this.labelGroup = _this.group.appendChild(new Group);
            _this.fillSelection = Selection.select(_this.areaGroup).selectAll();
            _this.strokeSelection = Selection.select(_this.strokeGroup).selectAll();
            _this.markerSelection = Selection.select(_this.markerGroup).selectAll();
            _this.labelSelection = Selection.select(_this.labelGroup).selectAll();
            /**
             * The assumption is that the values will be reset (to `true`)
             * in the {@link yKeys} setter.
             */
            _this.seriesItemEnabled = new Map();
            _this.xData = [];
            _this.yData = [];
            _this.areaSelectionData = [];
            _this.markerSelectionData = [];
            _this.labelSelectionData = [];
            _this.yDomain = [];
            _this.directionKeys = {
                x: ['xKey'],
                y: ['yKeys']
            };
            _this.marker = new CartesianSeriesMarker();
            _this.label = new AreaSeriesLabel();
            _this.fills = [
                '#c16068',
                '#a2bf8a',
                '#ebcc87',
                '#80a0c3',
                '#b58dae',
                '#85c0d1'
            ];
            _this.strokes = [
                '#874349',
                '#718661',
                '#a48f5f',
                '#5a7088',
                '#7f637a',
                '#5d8692'
            ];
            _this.fillOpacity = 1;
            _this.strokeOpacity = 1;
            _this.lineDash = [0];
            _this.lineDashOffset = 0;
            _this._xKey = '';
            _this.xName = '';
            _this._yKeys = [];
            _this.yNames = [];
            _this.strokeWidth = 2;
            _this.addEventListener('update', _this.scheduleUpdate);
            var _a = _this, marker = _a.marker, label = _a.label;
            marker.enabled = false;
            marker.addPropertyListener('shape', _this.onMarkerShapeChange, _this);
            marker.addEventListener('change', _this.scheduleUpdate, _this);
            label.enabled = false;
            label.addEventListener('change', _this.scheduleUpdate, _this);
            return _this;
        }
        AreaSeries.prototype.onMarkerShapeChange = function () {
            this.markerSelection = this.markerSelection.setData([]);
            this.markerSelection.exit.remove();
            this.fireEvent({ type: 'legendChange' });
        };
        Object.defineProperty(AreaSeries.prototype, "xKey", {
            get: function () {
                return this._xKey;
            },
            set: function (value) {
                if (this._xKey !== value) {
                    this._xKey = value;
                    this.xData = [];
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(AreaSeries.prototype, "yKeys", {
            get: function () {
                return this._yKeys;
            },
            set: function (values) {
                if (!equal(this._yKeys, values)) {
                    this._yKeys = values;
                    this.yData = [];
                    var seriesItemEnabled_1 = this.seriesItemEnabled;
                    seriesItemEnabled_1.clear();
                    values.forEach(function (key) { return seriesItemEnabled_1.set(key, true); });
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        AreaSeries.prototype.setColors = function (fills, strokes) {
            this.fills = fills;
            this.strokes = strokes;
        };
        Object.defineProperty(AreaSeries.prototype, "normalizedTo", {
            get: function () {
                return this._normalizedTo;
            },
            set: function (value) {
                var absValue = value ? Math.abs(value) : undefined;
                if (this._normalizedTo !== absValue) {
                    this._normalizedTo = absValue;
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        AreaSeries.prototype.processData = function () {
            var _a = this, xKey = _a.xKey, yKeys = _a.yKeys, seriesItemEnabled = _a.seriesItemEnabled;
            var data = xKey && yKeys.length && this.data ? this.data : [];
            // If the data is an array of rows like so:
            //
            // [{
            //   xKy: 'Jan',
            //   yKey1: 5,
            //   yKey2: 7,
            //   yKey3: -9,
            // }, {
            //   xKey: 'Feb',
            //   yKey1: 10,
            //   yKey2: -15,
            //   yKey3: 20
            // }]
            //
            var keysFound = true; // only warn once
            this.xData = data.map(function (datum) {
                if (keysFound && !(xKey in datum)) {
                    keysFound = false;
                    console.warn("The key '" + xKey + "' was not found in the data: ", datum);
                }
                return datum[xKey];
            });
            this.yData = data.map(function (datum) { return yKeys.map(function (yKey) {
                if (keysFound && !(yKey in datum)) {
                    keysFound = false;
                    console.warn("The key '" + yKey + "' was not found in the data: ", datum);
                }
                var value = datum[yKey];
                return isFinite(value) && seriesItemEnabled.get(yKey) ? value : 0;
            }); });
            // xData: ['Jan', 'Feb']
            //
            // yData: [
            //   [5, 7, -9],
            //   [10, -15, 20]
            // ]
            var _b = this, yData = _b.yData, normalizedTo = _b.normalizedTo;
            var yMinMax = yData.map(function (values) { return findMinMax(values); }); // used for normalization
            var yLargestMinMax = this.findLargestMinMax(yMinMax);
            // Calculate the sum of the absolute values of all items in each stack. Used for normalization of stacked areas.
            var yAbsTotal = this.yData.map(function (values) { return values.reduce(function (acc, stack) {
                acc += Math.abs(stack);
                return acc;
            }, 0); });
            var yMin;
            var yMax;
            if (normalizedTo && isFinite(normalizedTo)) {
                yMin = yLargestMinMax.min < 0 ? -normalizedTo : 0;
                yMax = yLargestMinMax.max > 0 ? normalizedTo : 0;
                yData.forEach(function (stack, i) { return stack.forEach(function (y, j) { return stack[j] = y / yAbsTotal[i] * normalizedTo; }); });
            }
            else {
                yMin = yLargestMinMax.min;
                yMax = yLargestMinMax.max;
            }
            if (yMin === 0 && yMax === 0) {
                yMax = 1;
            }
            this.yDomain = this.fixNumericExtent([yMin, yMax], 'y');
            this.fireEvent({ type: 'dataProcessed' });
            return true;
        };
        AreaSeries.prototype.findLargestMinMax = function (totals) {
            var e_1, _a;
            var min = 0;
            var max = 0;
            try {
                for (var totals_1 = __values$3(totals), totals_1_1 = totals_1.next(); !totals_1_1.done; totals_1_1 = totals_1.next()) {
                    var total = totals_1_1.value;
                    if (total.min < min) {
                        min = total.min;
                    }
                    if (total.max > max) {
                        max = total.max;
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (totals_1_1 && !totals_1_1.done && (_a = totals_1.return)) _a.call(totals_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            return { min: min, max: max };
        };
        AreaSeries.prototype.getDomain = function (direction) {
            if (direction === exports.ChartAxisDirection.X) {
                return this.xData;
            }
            else {
                return this.yDomain;
            }
        };
        AreaSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        AreaSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            this.createSelectionData();
            this.updateFillSelection();
            this.updateStrokeSelection();
            this.updateMarkerSelection();
            this.updateLabelSelection();
        };
        AreaSeries.prototype.updateNodes = function () {
            this.group.visible = this.visible && this.xData.length > 0 && this.yData.length > 0;
            this.updateFillNodes();
            this.updateStrokeNodes();
            this.updateMarkerNodes();
            this.updateLabelNodes();
        };
        AreaSeries.prototype.createSelectionData = function () {
            var _this = this;
            var _a = this, data = _a.data, xAxis = _a.xAxis, yAxis = _a.yAxis, xData = _a.xData, yData = _a.yData, areaSelectionData = _a.areaSelectionData, markerSelectionData = _a.markerSelectionData, labelSelectionData = _a.labelSelectionData;
            if (!data || !xAxis || !yAxis || !xData.length || !yData.length) {
                return;
            }
            var _b = this, yKeys = _b.yKeys, marker = _b.marker, label = _b.label, fills = _b.fills, strokes = _b.strokes;
            var xScale = xAxis.scale;
            var yScale = yAxis.scale;
            var xOffset = (xScale.bandwidth || 0) / 2;
            var yOffset = (yScale.bandwidth || 0) / 2;
            var last = xData.length * 2 - 1;
            areaSelectionData.length = 0;
            markerSelectionData.length = 0;
            labelSelectionData.length = 0;
            xData.forEach(function (xDatum, i) {
                var yDatum = yData[i];
                var seriesDatum = data[i];
                var x = xScale.convert(xDatum) + xOffset;
                var prevMin = 0;
                var prevMax = 0;
                yDatum.forEach(function (curr, j) {
                    var prev = curr < 0 ? prevMin : prevMax;
                    var continuousY = yScale instanceof ContinuousScale;
                    var y = yScale.convert(prev + curr, continuousY ? clamper : undefined);
                    var yKey = yKeys[j];
                    var yValue = seriesDatum[yKey];
                    if (marker) {
                        markerSelectionData.push({
                            index: i,
                            series: _this,
                            itemId: yKey,
                            datum: seriesDatum,
                            yValue: yValue,
                            yKey: yKey,
                            point: { x: x, y: y },
                            fill: fills[j % fills.length],
                            stroke: strokes[j % strokes.length]
                        });
                    }
                    var labelText;
                    if (label.formatter) {
                        labelText = label.formatter({ value: yValue });
                    }
                    else {
                        labelText = isNumber(yValue) ? yValue.toFixed(2) : String(yValue);
                    }
                    if (label) {
                        labelSelectionData.push({
                            index: i,
                            itemId: yKey,
                            point: { x: x, y: y },
                            label: labelText ? {
                                text: labelText,
                                fontStyle: label.fontStyle,
                                fontWeight: label.fontWeight,
                                fontSize: label.fontSize,
                                fontFamily: label.fontFamily,
                                textAlign: 'center',
                                textBaseline: 'bottom',
                                fill: label.color
                            } : undefined
                        });
                    }
                    var areaDatum = areaSelectionData[j] || (areaSelectionData[j] = { itemId: yKey, points: [] });
                    var areaPoints = areaDatum.points;
                    areaPoints[i] = { x: x, y: y };
                    areaPoints[last - i] = { x: x, y: yScale.convert(prev) + yOffset }; // bottom y
                    if (curr < 0) {
                        prevMin += curr;
                    }
                    else {
                        prevMax += curr;
                    }
                });
            });
        };
        AreaSeries.prototype.updateFillSelection = function () {
            var updateFills = this.fillSelection.setData(this.areaSelectionData);
            updateFills.exit.remove();
            var enterFills = updateFills.enter.append(Path)
                .each(function (path) {
                path.lineJoin = 'round';
                path.stroke = undefined;
                path.pointerEvents = PointerEvents.None;
            });
            this.fillSelection = updateFills.merge(enterFills);
        };
        AreaSeries.prototype.updateFillNodes = function () {
            var _this = this;
            var _a = this, fills = _a.fills, fillOpacity = _a.fillOpacity, strokes = _a.strokes, strokeOpacity = _a.strokeOpacity, strokeWidth = _a.strokeWidth, shadow = _a.shadow, seriesItemEnabled = _a.seriesItemEnabled;
            this.fillSelection.each(function (shape, datum, index) {
                var path = shape.path;
                shape.fill = fills[index % fills.length];
                shape.fillOpacity = fillOpacity;
                shape.stroke = strokes[index % strokes.length];
                shape.strokeOpacity = strokeOpacity;
                shape.strokeWidth = strokeWidth;
                shape.lineDash = _this.lineDash;
                shape.lineDashOffset = _this.lineDashOffset;
                shape.fillShadow = shadow;
                shape.visible = !!seriesItemEnabled.get(datum.itemId);
                shape.opacity = _this.getOpacity(datum);
                path.clear();
                var points = datum.points;
                points.forEach(function (_a, i) {
                    var x = _a.x, y = _a.y;
                    if (i > 0) {
                        path.lineTo(x, y);
                    }
                    else {
                        path.moveTo(x, y);
                    }
                });
                path.closePath();
            });
        };
        AreaSeries.prototype.updateStrokeSelection = function () {
            var updateStrokes = this.strokeSelection.setData(this.areaSelectionData);
            updateStrokes.exit.remove();
            var enterStrokes = updateStrokes.enter.append(Path)
                .each(function (path) {
                path.fill = undefined;
                path.lineJoin = path.lineCap = 'round';
                path.pointerEvents = PointerEvents.None;
            });
            this.strokeSelection = updateStrokes.merge(enterStrokes);
        };
        AreaSeries.prototype.updateStrokeNodes = function () {
            var _this = this;
            if (!this.data) {
                return;
            }
            var _a = this, data = _a.data, strokes = _a.strokes, strokeOpacity = _a.strokeOpacity, seriesItemEnabled = _a.seriesItemEnabled;
            this.strokeSelection.each(function (shape, datum, index) {
                var path = shape.path;
                shape.visible = !!seriesItemEnabled.get(datum.itemId);
                shape.opacity = _this.getOpacity(datum);
                shape.stroke = strokes[index % strokes.length];
                shape.strokeWidth = _this.getStrokeWidth(_this.strokeWidth, datum);
                shape.strokeOpacity = strokeOpacity;
                shape.lineDash = _this.lineDash;
                shape.lineDashOffset = _this.lineDashOffset;
                path.clear();
                var points = datum.points;
                // The stroke doesn't go all the way around the fill, only on top,
                // that's why we iterate until `data.length` (rather than `points.length`) and stop.
                for (var i = 0; i < data.length; i++) {
                    var _a = points[i], x = _a.x, y = _a.y;
                    if (i > 0) {
                        path.lineTo(x, y);
                    }
                    else {
                        path.moveTo(x, y);
                    }
                }
            });
        };
        AreaSeries.prototype.updateMarkerSelection = function () {
            var MarkerShape = getMarker(this.marker.shape);
            var data = MarkerShape ? this.markerSelectionData : [];
            var updateMarkers = this.markerSelection.setData(data);
            updateMarkers.exit.remove();
            var enterMarkers = updateMarkers.enter.append(MarkerShape);
            this.markerSelection = updateMarkers.merge(enterMarkers);
        };
        AreaSeries.prototype.updateMarkerNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, xKey = _a.xKey, marker = _a.marker, seriesItemEnabled = _a.seriesItemEnabled, yKeys = _a.yKeys, fills = _a.fills, strokes = _a.strokes, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            var size = marker.size, formatter = marker.formatter;
            var markerStrokeWidth = marker.strokeWidth !== undefined ? marker.strokeWidth : this.strokeWidth;
            this.markerSelection.each(function (node, datum) {
                var yKeyIndex = yKeys.indexOf(datum.yKey);
                var isDatumHighlighted = datum === highlightedDatum;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : marker.fill || fills[yKeyIndex % fills.length];
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : marker.stroke || strokes[yKeyIndex % fills.length];
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : markerStrokeWidth;
                var format = undefined;
                if (formatter) {
                    format = formatter({
                        datum: datum.datum,
                        xKey: xKey,
                        yKey: datum.yKey,
                        fill: fill,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        size: size,
                        highlighted: isDatumHighlighted
                    });
                }
                node.fill = format && format.fill || fill;
                node.stroke = format && format.stroke || stroke;
                node.strokeWidth = format && format.strokeWidth !== undefined
                    ? format.strokeWidth
                    : strokeWidth;
                node.size = format && format.size !== undefined
                    ? format.size
                    : size;
                node.translationX = datum.point.x;
                node.translationY = datum.point.y;
                node.visible = marker.enabled && node.size > 0 && !!seriesItemEnabled.get(datum.yKey) && !isNaN(datum.point.x);
                node.opacity = _this.getOpacity(datum);
            });
        };
        AreaSeries.prototype.updateLabelSelection = function () {
            var updateLabels = this.labelSelection.setData(this.labelSelectionData);
            updateLabels.exit.remove();
            var enterLabels = updateLabels.enter.append(Text);
            this.labelSelection = updateLabels.merge(enterLabels);
        };
        AreaSeries.prototype.updateLabelNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this.label, labelEnabled = _a.enabled, fontStyle = _a.fontStyle, fontWeight = _a.fontWeight, fontSize = _a.fontSize, fontFamily = _a.fontFamily, color = _a.color;
            this.labelSelection.each(function (text, datum) {
                var point = datum.point, label = datum.label;
                if (label && labelEnabled) {
                    text.fontStyle = fontStyle;
                    text.fontWeight = fontWeight;
                    text.fontSize = fontSize;
                    text.fontFamily = fontFamily;
                    text.textAlign = label.textAlign;
                    text.textBaseline = label.textBaseline;
                    text.text = label.text;
                    text.x = point.x;
                    text.y = point.y - 10;
                    text.fill = color;
                    text.visible = true;
                    text.opacity = _this.getOpacity(datum);
                }
                else {
                    text.visible = false;
                }
            });
        };
        AreaSeries.prototype.getNodeData = function () {
            return this.markerSelectionData;
        };
        AreaSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                xKey: this.xKey,
                yKey: datum.yKey
            });
        };
        AreaSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var xKey = this.xKey;
            var yKey = nodeDatum.yKey;
            if (!(xKey && yKey)) {
                return '';
            }
            var datum = nodeDatum.datum;
            var xValue = datum[xKey];
            var yValue = datum[yKey];
            var _a = this, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!(xAxis && yAxis && isNumber(yValue))) {
                return '';
            }
            var x = xAxis.scale.convert(xValue);
            var y = yAxis.scale.convert(yValue);
            // Don't show the tooltip for the off-screen markers.
            // Node: some markers might still go off-screen despite virtual rendering
            //       (to connect the dots and render the area properly).
            if (!(xAxis.inRange(x) && yAxis.inRange(y))) {
                return '';
            }
            var _b = this, xName = _b.xName, yKeys = _b.yKeys, yNames = _b.yNames, yData = _b.yData, fills = _b.fills, strokes = _b.strokes, tooltip = _b.tooltip, marker = _b.marker;
            var size = marker.size, markerFormatter = marker.formatter, markerStrokeWidth = marker.strokeWidth, markerFill = marker.fill, markerStroke = marker.stroke;
            var xString = xAxis.formatDatum(xValue);
            var yString = yAxis.formatDatum(yValue);
            var yKeyIndex = yKeys.indexOf(yKey);
            var yGroup = yData[nodeDatum.index];
            var processedYValue = yGroup[yKeyIndex];
            var yName = yNames[yKeyIndex];
            var title = sanitizeHtml(yName);
            var content = sanitizeHtml(xString + ': ' + yString);
            var strokeWidth = markerStrokeWidth !== undefined ? markerStrokeWidth : this.strokeWidth;
            var fill = markerFill || fills[yKeyIndex % fills.length];
            var stroke = markerStroke || strokes[yKeyIndex % fills.length];
            var format = undefined;
            if (markerFormatter) {
                format = markerFormatter({
                    datum: datum,
                    xKey: xKey,
                    yKey: yKey,
                    fill: fill,
                    stroke: stroke,
                    strokeWidth: strokeWidth,
                    size: size,
                    highlighted: false
                });
            }
            var color = format && format.fill || markerFill;
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            var tooltipRenderer = tooltip.renderer, tooltipFormat = tooltip.format;
            if (tooltipFormat || tooltipRenderer) {
                var params = {
                    datum: datum,
                    xKey: xKey,
                    xName: xName,
                    xValue: xValue,
                    yKey: yKey,
                    yValue: yValue,
                    processedYValue: processedYValue,
                    yName: yName,
                    color: color
                };
                if (tooltipFormat) {
                    return toTooltipHtml({
                        content: interpolate(tooltipFormat, params)
                    }, defaults);
                }
                if (tooltipRenderer) {
                    return toTooltipHtml(tooltipRenderer(params), defaults);
                }
            }
            return toTooltipHtml(defaults);
        };
        AreaSeries.prototype.listSeriesItems = function (legendData) {
            var _a = this, data = _a.data, id = _a.id, xKey = _a.xKey, yKeys = _a.yKeys, yNames = _a.yNames, seriesItemEnabled = _a.seriesItemEnabled, marker = _a.marker, fills = _a.fills, strokes = _a.strokes, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity;
            if (data && data.length && xKey && yKeys.length) {
                yKeys.forEach(function (yKey, index) {
                    legendData.push({
                        id: id,
                        itemId: yKey,
                        enabled: seriesItemEnabled.get(yKey) || false,
                        label: {
                            text: yNames[index] || yKeys[index]
                        },
                        marker: {
                            shape: marker.shape,
                            fill: marker.fill || fills[index % fills.length],
                            stroke: marker.stroke || strokes[index % strokes.length],
                            fillOpacity: fillOpacity,
                            strokeOpacity: strokeOpacity
                        }
                    });
                });
            }
        };
        AreaSeries.prototype.toggleSeriesItem = function (itemId, enabled) {
            this.seriesItemEnabled.set(itemId, enabled);
            this.scheduleData();
        };
        AreaSeries.className = 'AreaSeries';
        AreaSeries.type = 'area';
        __decorate$7([
            reactive('dataChange')
        ], AreaSeries.prototype, "fills", void 0);
        __decorate$7([
            reactive('dataChange')
        ], AreaSeries.prototype, "strokes", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "fillOpacity", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "strokeOpacity", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "lineDash", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "lineDashOffset", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "xName", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "yNames", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "strokeWidth", void 0);
        __decorate$7([
            reactive('update')
        ], AreaSeries.prototype, "shadow", void 0);
        return AreaSeries;
    }(CartesianSeries));

    var __extends$I = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$8 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __values$4 = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var BarSeriesNodeTag;
    (function (BarSeriesNodeTag) {
        BarSeriesNodeTag[BarSeriesNodeTag["Bar"] = 0] = "Bar";
        BarSeriesNodeTag[BarSeriesNodeTag["Label"] = 1] = "Label";
    })(BarSeriesNodeTag || (BarSeriesNodeTag = {}));
    (function (BarLabelPlacement) {
        BarLabelPlacement["Inside"] = "inside";
        BarLabelPlacement["Outside"] = "outside";
    })(exports.BarLabelPlacement || (exports.BarLabelPlacement = {}));
    var BarSeriesLabel = /** @class */ (function (_super) {
        __extends$I(BarSeriesLabel, _super);
        function BarSeriesLabel() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.placement = exports.BarLabelPlacement.Inside;
            return _this;
        }
        __decorate$8([
            reactive('change')
        ], BarSeriesLabel.prototype, "formatter", void 0);
        __decorate$8([
            reactive('change')
        ], BarSeriesLabel.prototype, "placement", void 0);
        return BarSeriesLabel;
    }(Label));
    var BarSeriesTooltip = /** @class */ (function (_super) {
        __extends$I(BarSeriesTooltip, _super);
        function BarSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$8([
            reactive('change')
        ], BarSeriesTooltip.prototype, "renderer", void 0);
        return BarSeriesTooltip;
    }(SeriesTooltip));
    function flat(arr, target) {
        if (target === void 0) { target = []; }
        arr.forEach(function (v) {
            if (Array.isArray(v)) {
                flat(v, target);
            }
            else {
                target.push(v);
            }
        });
        return target;
    }
    function is2dArray(array) {
        return array.length > 0 && Array.isArray(array[0]);
    }
    var BarSeries = /** @class */ (function (_super) {
        __extends$I(BarSeries, _super);
        function BarSeries() {
            var _a;
            var _this = _super.call(this) || this;
            // Need to put bar and label nodes into separate groups, because even though label nodes are
            // created after the bar nodes, this only guarantees that labels will always be on top of bars
            // on the first run. If on the next run more bars are added, they might clip the labels
            // rendered during the previous run.
            _this.rectGroup = _this.pickGroup.appendChild(new Group);
            _this.labelGroup = _this.group.appendChild(new Group);
            _this.rectSelection = Selection.select(_this.rectGroup).selectAll();
            _this.labelSelection = Selection.select(_this.labelGroup).selectAll();
            _this.nodeData = [];
            _this.xData = [];
            _this.yData = [];
            _this.yDomain = [];
            _this.label = new BarSeriesLabel();
            /**
             * The assumption is that the values will be reset (to `true`)
             * in the {@link yKeys} setter.
             */
            _this.seriesItemEnabled = new Map();
            _this.tooltip = new BarSeriesTooltip();
            _this.flipXY = false;
            _this.fills = [
                '#c16068',
                '#a2bf8a',
                '#ebcc87',
                '#80a0c3',
                '#b58dae',
                '#85c0d1'
            ];
            _this.strokes = [
                '#874349',
                '#718661',
                '#a48f5f',
                '#5a7088',
                '#7f637a',
                '#5d8692'
            ];
            _this.fillOpacity = 1;
            _this.strokeOpacity = 1;
            _this.lineDash = [0];
            _this.lineDashOffset = 0;
            /**
             * Used to get the position of bars within each group.
             */
            _this.groupScale = new BandScale();
            _this.directionKeys = (_a = {},
                _a[exports.ChartAxisDirection.X] = ['xKey'],
                _a[exports.ChartAxisDirection.Y] = ['yKeys'],
                _a);
            _this._xKey = '';
            _this._xName = '';
            _this.cumYKeyCount = [];
            _this.flatYKeys = undefined; // only set when a user used a flat array for yKeys
            _this.hideInLegend = [];
            /**
             * yKeys: [['coffee']] - regular bars, each category has a single bar that shows a value for coffee
             * yKeys: [['coffee'], ['tea'], ['milk']] - each category has three bars that show values for coffee, tea and milk
             * yKeys: [['coffee', 'tea', 'milk']] - each category has a single bar with three stacks that show values for coffee, tea and milk
             * yKeys: [['coffee', 'tea', 'milk'], ['paper', 'ink']] - each category has 2 stacked bars,
             *     first showing values for coffee, tea and milk and second values for paper and ink
             */
            _this._yKeys = [];
            _this._grouped = false;
            /**
             * A map of `yKeys` to their names (used in legends and tooltips).
             * For example, if a key is `product_name` it's name can be a more presentable `Product Name`.
             */
            _this._yNames = {};
            _this._strokeWidth = 1;
            _this.addEventListener('update', _this.scheduleUpdate);
            _this.label.enabled = false;
            _this.label.addEventListener('change', _this.scheduleUpdate, _this);
            return _this;
        }
        BarSeries.prototype.getKeys = function (direction) {
            var _this = this;
            var directionKeys = this.directionKeys;
            var keys = directionKeys && directionKeys[this.flipXY ? flipChartAxisDirection(direction) : direction];
            var values = [];
            if (keys) {
                keys.forEach(function (key) {
                    var value = _this[key];
                    if (value) {
                        if (Array.isArray(value)) {
                            values = values.concat(flat(value));
                        }
                        else {
                            values.push(value);
                        }
                    }
                });
            }
            return values;
        };
        Object.defineProperty(BarSeries.prototype, "xKey", {
            get: function () {
                return this._xKey;
            },
            set: function (value) {
                if (this._xKey !== value) {
                    this._xKey = value;
                    this.xData = [];
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "xName", {
            get: function () {
                return this._xName;
            },
            set: function (value) {
                if (this._xName !== value) {
                    this._xName = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "yKeys", {
            get: function () {
                return this._yKeys;
            },
            set: function (yKeys) {
                var _this = this;
                var flatYKeys = undefined;
                // Convert from flat y-keys to grouped y-keys.
                if (!is2dArray(yKeys)) {
                    flatYKeys = yKeys;
                    yKeys = this.grouped ? flatYKeys.map(function (k) { return [k]; }) : [flatYKeys];
                }
                if (!equal(this._yKeys, yKeys)) {
                    this.flatYKeys = flatYKeys ? flatYKeys : undefined;
                    this._yKeys = yKeys;
                    var prevYKeyCount_1 = 0;
                    this.cumYKeyCount = [];
                    var visibleStacks_1 = [];
                    yKeys.forEach(function (stack, index) {
                        if (stack.length > 0) {
                            visibleStacks_1.push(String(index));
                        }
                        _this.cumYKeyCount.push(prevYKeyCount_1);
                        prevYKeyCount_1 += stack.length;
                    });
                    this.yData = [];
                    var seriesItemEnabled_1 = this.seriesItemEnabled;
                    seriesItemEnabled_1.clear();
                    yKeys.forEach(function (stack) {
                        stack.forEach(function (yKey) { return seriesItemEnabled_1.set(yKey, true); });
                    });
                    var groupScale = this.groupScale;
                    groupScale.domain = visibleStacks_1;
                    groupScale.padding = 0.1;
                    groupScale.round = true;
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "grouped", {
            get: function () {
                return this._grouped;
            },
            set: function (value) {
                if (this._grouped !== value) {
                    this._grouped = value;
                    if (this.flatYKeys) {
                        this.yKeys = this.flatYKeys;
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "yNames", {
            get: function () {
                return this._yNames;
            },
            set: function (values) {
                if (Array.isArray(values) && this.flatYKeys) {
                    var map_1 = {};
                    this.flatYKeys.forEach(function (k, i) {
                        map_1[k] = values[i];
                    });
                    values = map_1;
                }
                this._yNames = values;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        BarSeries.prototype.setColors = function (fills, strokes) {
            this.fills = fills;
            this.strokes = strokes;
        };
        Object.defineProperty(BarSeries.prototype, "normalizedTo", {
            get: function () {
                return this._normalizedTo;
            },
            set: function (value) {
                var absValue = value ? Math.abs(value) : undefined;
                if (this._normalizedTo !== absValue) {
                    this._normalizedTo = absValue;
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "strokeWidth", {
            get: function () {
                return this._strokeWidth;
            },
            set: function (value) {
                if (this._strokeWidth !== value) {
                    this._strokeWidth = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BarSeries.prototype, "shadow", {
            get: function () {
                return this._shadow;
            },
            set: function (value) {
                if (this._shadow !== value) {
                    this._shadow = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        BarSeries.prototype.onHighlightChange = function () {
            this.updateRectNodes();
        };
        BarSeries.prototype.processData = function () {
            var _a = this, xKey = _a.xKey, yKeys = _a.yKeys, seriesItemEnabled = _a.seriesItemEnabled, xAxis = _a.xAxis;
            var data = xKey && yKeys.length && this.data ? this.data : [];
            if (!xAxis) {
                return false;
            }
            var keysFound = true; // only warn once
            this.xData = data.map(function (datum) {
                if (keysFound && !(xKey in datum)) {
                    keysFound = false;
                    console.warn("The key '" + xKey + "' was not found in the data: ", datum);
                }
                return isDiscrete(datum[xKey]) ? datum[xKey] : String(datum[xKey]);
            });
            this.yData = data.map(function (datum) { return yKeys.map(function (stack) {
                return stack.map(function (yKey) {
                    if (keysFound && !(yKey in datum)) {
                        keysFound = false;
                        console.warn("The key '" + yKey + "' was not found in the data: ", datum);
                    }
                    var value = datum[yKey];
                    return isFinite(value) && seriesItemEnabled.get(yKey) ? value : 0;
                });
            }); });
            // Contains min/max values for each stack in each group,
            // where min is zero and max is a positive total of all values in the stack
            // or min is a negative total of all values in the stack and max is zero.
            var yMinMax = this.yData.map(function (group) { return group.map(function (stack) { return findMinMax(stack); }); });
            var _b = this, yData = _b.yData, normalizedTo = _b.normalizedTo;
            // Calculate the sum of the absolute values of all items in each stack in each group. Used for normalization of stacked bars.
            var yAbsTotal = this.yData.map(function (group) { return group.map(function (stack) { return stack.reduce(function (acc, stack) {
                acc += Math.abs(stack);
                return acc;
            }, 0); }); });
            var yLargestMinMax = this.findLargestMinMax(yMinMax);
            var yMin;
            var yMax;
            if (normalizedTo && isFinite(normalizedTo)) {
                yMin = yLargestMinMax.min < 0 ? -normalizedTo : 0;
                yMax = yLargestMinMax.max > 0 ? normalizedTo : 0;
                yData.forEach(function (group, i) {
                    group.forEach(function (stack, j) {
                        stack.forEach(function (y, k) {
                            stack[k] = y / yAbsTotal[i][j] * normalizedTo;
                        });
                    });
                });
            }
            else {
                yMin = yLargestMinMax.min;
                yMax = yLargestMinMax.max;
            }
            if (yMin === yMax && yMin === 0) {
                yMax = 1;
            }
            this.yDomain = this.fixNumericExtent([yMin, yMax], 'y');
            this.fireEvent({ type: 'dataProcessed' });
            return true;
        };
        BarSeries.prototype.findLargestMinMax = function (groups) {
            var e_1, _a, e_2, _b;
            var tallestStackMin = 0;
            var tallestStackMax = 0;
            try {
                for (var groups_1 = __values$4(groups), groups_1_1 = groups_1.next(); !groups_1_1.done; groups_1_1 = groups_1.next()) {
                    var group = groups_1_1.value;
                    try {
                        for (var group_1 = (e_2 = void 0, __values$4(group)), group_1_1 = group_1.next(); !group_1_1.done; group_1_1 = group_1.next()) {
                            var stack = group_1_1.value;
                            if (stack.min < tallestStackMin) {
                                tallestStackMin = stack.min;
                            }
                            if (stack.max > tallestStackMax) {
                                tallestStackMax = stack.max;
                            }
                        }
                    }
                    catch (e_2_1) { e_2 = { error: e_2_1 }; }
                    finally {
                        try {
                            if (group_1_1 && !group_1_1.done && (_b = group_1.return)) _b.call(group_1);
                        }
                        finally { if (e_2) throw e_2.error; }
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (groups_1_1 && !groups_1_1.done && (_a = groups_1.return)) _a.call(groups_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            return { min: tallestStackMin, max: tallestStackMax };
        };
        BarSeries.prototype.getDomain = function (direction) {
            if (this.flipXY) {
                direction = flipChartAxisDirection(direction);
            }
            if (direction === exports.ChartAxisDirection.X) {
                return this.xData;
            }
            else {
                return this.yDomain;
            }
        };
        BarSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                xKey: this.xKey,
                yKey: datum.yKey
            });
        };
        BarSeries.prototype.getCategoryAxis = function () {
            return this.flipXY ? this.yAxis : this.xAxis;
        };
        BarSeries.prototype.getValueAxis = function () {
            return this.flipXY ? this.xAxis : this.yAxis;
        };
        BarSeries.prototype.createNodeData = function () {
            var _this = this;
            var _a = this, chart = _a.chart, data = _a.data, visible = _a.visible;
            var xAxis = this.getCategoryAxis();
            var yAxis = this.getValueAxis();
            if (!(chart && data && visible && xAxis && yAxis) || chart.layoutPending || chart.dataPending) {
                return [];
            }
            var flipXY = this.flipXY;
            var xScale = xAxis.scale;
            var yScale = yAxis.scale;
            var _b = this, groupScale = _b.groupScale, yKeys = _b.yKeys, cumYKeyCount = _b.cumYKeyCount, fills = _b.fills, strokes = _b.strokes, strokeWidth = _b.strokeWidth, seriesItemEnabled = _b.seriesItemEnabled, xData = _b.xData, yData = _b.yData, label = _b.label;
            var labelFontStyle = label.fontStyle, labelFontWeight = label.fontWeight, labelFontSize = label.fontSize, labelFontFamily = label.fontFamily, labelColor = label.color, labelFormatter = label.formatter, labelPlacement = label.placement;
            groupScale.range = [0, xScale.bandwidth];
            var barWidth =  groupScale.bandwidth ;
            var nodeData = [];
            xData.forEach(function (group, groupIndex) {
                var seriesDatum = data[groupIndex];
                var x = xScale.convert(group);
                var groupYs = yData[groupIndex]; // y-data for groups of stacks
                for (var stackIndex = 0; stackIndex < groupYs.length; stackIndex++) {
                    var stackYs = groupYs[stackIndex]; // y-data for a stack within a group
                    var prevMinY = 0;
                    var prevMaxY = 0;
                    for (var levelIndex = 0; levelIndex < stackYs.length; levelIndex++) {
                        var currY = stackYs[levelIndex];
                        var yKey = yKeys[stackIndex][levelIndex];
                        var barX =  x + groupScale.convert(String(stackIndex)) ;
                        // Bars outside of visible range are not rendered, so we create node data
                        // only for the visible subset of user data.
                        if (!xAxis.inRange(barX, barWidth)) {
                            continue;
                        }
                        var prevY = currY < 0 ? prevMinY : prevMaxY;
                        var continuousY = yScale instanceof ContinuousScale;
                        var y = yScale.convert(prevY + currY, continuousY ? clamper : undefined);
                        var bottomY = yScale.convert(prevY, continuousY ? clamper : undefined);
                        var yValue = seriesDatum[yKey]; // unprocessed y-value
                        var labelText = void 0;
                        if (labelFormatter) {
                            labelText = labelFormatter({ value: isNumber(yValue) ? yValue : undefined });
                        }
                        else {
                            labelText = isNumber(yValue) ? yValue.toFixed(2) : '';
                        }
                        var labelX = void 0;
                        var labelY = void 0;
                        if (flipXY) {
                            labelY = barX + barWidth / 2;
                            if (labelPlacement === exports.BarLabelPlacement.Inside) {
                                labelX = y + (yValue >= 0 ? -1 : 1) * Math.abs(bottomY - y) / 2;
                            }
                            else {
                                labelX = y + (yValue >= 0 ? 1 : -1) * 4;
                            }
                        }
                        else {
                            labelX = barX + barWidth / 2;
                            if (labelPlacement === exports.BarLabelPlacement.Inside) {
                                labelY = y + (yValue >= 0 ? 1 : -1) * Math.abs(bottomY - y) / 2;
                            }
                            else {
                                labelY = y + (yValue >= 0 ? -3 : 4);
                            }
                        }
                        var labelTextAlign = void 0;
                        var labelTextBaseline = void 0;
                        if (labelPlacement === exports.BarLabelPlacement.Inside) {
                            labelTextAlign = 'center';
                            labelTextBaseline = 'middle';
                        }
                        else {
                            labelTextAlign = flipXY ? (yValue >= 0 ? 'start' : 'end') : 'center';
                            labelTextBaseline = flipXY ? 'middle' : (yValue >= 0 ? 'bottom' : 'top');
                        }
                        var colorIndex = cumYKeyCount[stackIndex] + levelIndex;
                        nodeData.push({
                            index: groupIndex,
                            series: _this,
                            itemId: yKey,
                            datum: seriesDatum,
                            yValue: yValue,
                            yKey: yKey,
                            x: flipXY ? Math.min(y, bottomY) : barX,
                            y: flipXY ? barX : Math.min(y, bottomY),
                            width: flipXY ? Math.abs(bottomY - y) : barWidth,
                            height: flipXY ? barWidth : Math.abs(bottomY - y),
                            fill: fills[colorIndex % fills.length],
                            stroke: strokes[colorIndex % strokes.length],
                            strokeWidth: strokeWidth,
                            label: seriesItemEnabled.get(yKey) && labelText ? {
                                text: labelText,
                                fontStyle: labelFontStyle,
                                fontWeight: labelFontWeight,
                                fontSize: labelFontSize,
                                fontFamily: labelFontFamily,
                                textAlign: labelTextAlign,
                                textBaseline: labelTextBaseline,
                                fill: labelColor,
                                x: labelX,
                                y: labelY
                            } : undefined
                        });
                        if (currY < 0) {
                            prevMinY += currY;
                        }
                        else {
                            prevMaxY += currY;
                        }
                    }
                }
            });
            return this.nodeData = nodeData;
        };
        BarSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        BarSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            this.createNodeData();
            this.updateRectSelection();
            this.updateLabelSelection();
        };
        BarSeries.prototype.updateNodes = function () {
            this.group.visible = this.visible;
            this.updateRectNodes();
            this.updateLabelNodes();
        };
        BarSeries.prototype.updateRectSelection = function () {
            var updateRects = this.rectSelection.setData(this.nodeData);
            updateRects.exit.remove();
            var enterRects = updateRects.enter.append(Rect).each(function (rect) {
                rect.tag = BarSeriesNodeTag.Bar;
                rect.crisp = true;
            });
            this.rectSelection = updateRects.merge(enterRects);
        };
        BarSeries.prototype.updateRectNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, fills = _a.fills, strokes = _a.strokes, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity, shadow = _a.shadow, formatter = _a.formatter, xKey = _a.xKey, flipXY = _a.flipXY, yKeys = _a.yKeys, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            this.rectSelection.each(function (rect, datum, index) {
                var colorIndex = 0;
                var i = 0;
                for (var j = 0; j < yKeys.length; j++) {
                    var stack = yKeys[j];
                    i = stack.indexOf(datum.yKey);
                    if (i >= 0) {
                        colorIndex += i;
                        break;
                    }
                    colorIndex += stack.length;
                }
                var isDatumHighlighted = datum === highlightedDatum;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : fills[colorIndex % fills.length];
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : strokes[colorIndex % fills.length];
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : _this.getStrokeWidth(_this.strokeWidth, datum);
                var format = undefined;
                if (formatter) {
                    format = formatter({
                        datum: datum.datum,
                        fill: fill,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        highlighted: isDatumHighlighted,
                        xKey: xKey,
                        yKey: datum.yKey
                    });
                }
                rect.x = datum.x;
                rect.y = datum.y;
                rect.width = datum.width;
                rect.height = datum.height;
                rect.fill = format && format.fill || fill;
                rect.stroke = format && format.stroke || stroke;
                rect.strokeWidth = format && format.strokeWidth !== undefined ? format.strokeWidth : strokeWidth;
                rect.fillOpacity = fillOpacity;
                rect.strokeOpacity = strokeOpacity;
                rect.lineDash = _this.lineDash;
                rect.lineDashOffset = _this.lineDashOffset;
                rect.fillShadow = shadow;
                // Prevent stroke from rendering for zero height columns and zero width bars.
                rect.visible = flipXY ? datum.width > 0 : datum.height > 0;
                rect.zIndex = isDatumHighlighted ? Series.highlightedZIndex : index;
                rect.opacity = _this.getOpacity(datum);
            });
        };
        BarSeries.prototype.updateLabelSelection = function () {
            var updateLabels = this.labelSelection.setData(this.nodeData);
            updateLabels.exit.remove();
            var enterLabels = updateLabels.enter.append(Text).each(function (text) {
                text.tag = BarSeriesNodeTag.Label;
                text.pointerEvents = PointerEvents.None;
            });
            this.labelSelection = updateLabels.merge(enterLabels);
        };
        BarSeries.prototype.updateLabelNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, highlightedDatum = _a.chart.highlightedDatum, _b = _a.label, labelEnabled = _b.enabled, fontStyle = _b.fontStyle, fontWeight = _b.fontWeight, fontSize = _b.fontSize, fontFamily = _b.fontFamily, color = _b.color;
            this.labelSelection.each(function (text, datum, index) {
                var label = datum.label;
                if (label && labelEnabled) {
                    text.fontStyle = fontStyle;
                    text.fontWeight = fontWeight;
                    text.fontSize = fontSize;
                    text.fontFamily = fontFamily;
                    text.textAlign = label.textAlign;
                    text.textBaseline = label.textBaseline;
                    text.text = label.text;
                    text.x = label.x;
                    text.y = label.y;
                    text.fill = color;
                    text.visible = true;
                    text.opacity = _this.getOpacity(datum);
                }
                else {
                    text.visible = false;
                }
            });
        };
        BarSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var _a = this, xKey = _a.xKey, yKeys = _a.yKeys, yData = _a.yData;
            var xAxis = this.getCategoryAxis();
            var yAxis = this.getValueAxis();
            var yKey = nodeDatum.yKey;
            if (!yData.length || !xKey || !yKey || !xAxis || !yAxis) {
                return '';
            }
            var yGroup = yData[nodeDatum.index];
            var fillIndex = 0;
            var i = 0;
            var j = 0;
            for (; j < yKeys.length; j++) {
                var stack = yKeys[j];
                i = stack.indexOf(yKey);
                if (i >= 0) {
                    fillIndex += i;
                    break;
                }
                fillIndex += stack.length;
            }
            var _b = this, xName = _b.xName, yNames = _b.yNames, fills = _b.fills, strokes = _b.strokes, tooltip = _b.tooltip, formatter = _b.formatter;
            var tooltipRenderer = tooltip.renderer;
            var datum = nodeDatum.datum;
            var yName = yNames[yKey];
            var fill = fills[fillIndex % fills.length];
            var stroke = strokes[fillIndex % fills.length];
            var strokeWidth = this.getStrokeWidth(this.strokeWidth, datum);
            var xValue = datum[xKey];
            var yValue = datum[yKey];
            var processedYValue = yGroup[j][i];
            var xString = sanitizeHtml(xAxis.formatDatum(xValue));
            var yString = sanitizeHtml(yAxis.formatDatum(yValue));
            var title = sanitizeHtml(yName);
            var content = xString + ': ' + yString;
            var format = undefined;
            if (formatter) {
                format = formatter({
                    datum: datum,
                    fill: fill,
                    stroke: stroke,
                    strokeWidth: strokeWidth,
                    highlighted: false,
                    xKey: xKey,
                    yKey: yKey
                });
            }
            var color = format && format.fill || fill;
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            if (tooltipRenderer) {
                return toTooltipHtml(tooltipRenderer({
                    datum: datum,
                    xKey: xKey,
                    xValue: xValue,
                    xName: xName,
                    yKey: yKey,
                    yValue: yValue,
                    processedYValue: processedYValue,
                    yName: yName,
                    color: color
                }), defaults);
            }
            return toTooltipHtml(defaults);
        };
        BarSeries.prototype.listSeriesItems = function (legendData) {
            var _a = this, id = _a.id, data = _a.data, xKey = _a.xKey, yKeys = _a.yKeys, yNames = _a.yNames, cumYKeyCount = _a.cumYKeyCount, seriesItemEnabled = _a.seriesItemEnabled, hideInLegend = _a.hideInLegend, fills = _a.fills, strokes = _a.strokes, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity;
            if (data && data.length && xKey && yKeys.length) {
                this.yKeys.forEach(function (stack, stackIndex) {
                    stack.forEach(function (yKey, levelIndex) {
                        if (hideInLegend.indexOf(yKey) < 0) {
                            var colorIndex = cumYKeyCount[stackIndex] + levelIndex;
                            legendData.push({
                                id: id,
                                itemId: yKey,
                                enabled: seriesItemEnabled.get(yKey) || false,
                                label: {
                                    text: yNames[yKey] || yKey
                                },
                                marker: {
                                    fill: fills[colorIndex % fills.length],
                                    stroke: strokes[colorIndex % strokes.length],
                                    fillOpacity: fillOpacity,
                                    strokeOpacity: strokeOpacity
                                }
                            });
                        }
                    });
                });
            }
        };
        BarSeries.prototype.toggleSeriesItem = function (itemId, enabled) {
            var seriesItemEnabled = this.seriesItemEnabled;
            seriesItemEnabled.set(itemId, enabled);
            var yKeys = this.yKeys.map(function (stack) { return stack.slice(); }); // deep clone
            seriesItemEnabled.forEach(function (enabled, yKey) {
                if (!enabled) {
                    yKeys.forEach(function (stack) {
                        var index = stack.indexOf(yKey);
                        if (index >= 0) {
                            stack.splice(index, 1);
                        }
                    });
                }
            });
            var visibleStacks = [];
            yKeys.forEach(function (stack, index) {
                if (stack.length > 0) {
                    visibleStacks.push(String(index));
                }
            });
            this.groupScale.domain = visibleStacks;
            this.scheduleData();
        };
        BarSeries.className = 'BarSeries';
        BarSeries.type = 'bar';
        __decorate$8([
            reactive('dataChange')
        ], BarSeries.prototype, "flipXY", void 0);
        __decorate$8([
            reactive('dataChange')
        ], BarSeries.prototype, "fills", void 0);
        __decorate$8([
            reactive('dataChange')
        ], BarSeries.prototype, "strokes", void 0);
        __decorate$8([
            reactive('update')
        ], BarSeries.prototype, "fillOpacity", void 0);
        __decorate$8([
            reactive('update')
        ], BarSeries.prototype, "strokeOpacity", void 0);
        __decorate$8([
            reactive('update')
        ], BarSeries.prototype, "lineDash", void 0);
        __decorate$8([
            reactive('update')
        ], BarSeries.prototype, "lineDashOffset", void 0);
        __decorate$8([
            reactive('update')
        ], BarSeries.prototype, "formatter", void 0);
        __decorate$8([
            reactive('layoutChange')
        ], BarSeries.prototype, "hideInLegend", void 0);
        return BarSeries;
    }(CartesianSeries));

    var __extends$J = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$9 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __read$d = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var LineSeriesLabel = /** @class */ (function (_super) {
        __extends$J(LineSeriesLabel, _super);
        function LineSeriesLabel() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$9([
            reactive('change')
        ], LineSeriesLabel.prototype, "formatter", void 0);
        return LineSeriesLabel;
    }(Label));
    var LineSeriesTooltip = /** @class */ (function (_super) {
        __extends$J(LineSeriesTooltip, _super);
        function LineSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$9([
            reactive('change')
        ], LineSeriesTooltip.prototype, "renderer", void 0);
        __decorate$9([
            reactive('change')
        ], LineSeriesTooltip.prototype, "format", void 0);
        return LineSeriesTooltip;
    }(SeriesTooltip));
    var LineSeries = /** @class */ (function (_super) {
        __extends$J(LineSeries, _super);
        function LineSeries() {
            var _this = _super.call(this) || this;
            _this.xDomain = [];
            _this.yDomain = [];
            _this.xData = [];
            _this.yData = [];
            _this.lineNode = new Path();
            // We use groups for this selection even though each group only contains a marker ATM
            // because in the future we might want to add label support as well.
            _this.nodeSelection = Selection.select(_this.pickGroup).selectAll();
            _this.nodeData = [];
            _this.marker = new CartesianSeriesMarker();
            _this.label = new LineSeriesLabel();
            _this.stroke = '#874349';
            _this.lineDash = [0];
            _this.lineDashOffset = 0;
            _this.strokeWidth = 2;
            _this.strokeOpacity = 1;
            _this.tooltip = new LineSeriesTooltip();
            _this._xKey = '';
            _this.xName = '';
            _this._yKey = '';
            _this.yName = '';
            var lineNode = _this.lineNode;
            lineNode.fill = undefined;
            lineNode.lineJoin = 'round';
            lineNode.pointerEvents = PointerEvents.None;
            // Make line render before markers in the pick group.
            _this.group.insertBefore(lineNode, _this.pickGroup);
            _this.addEventListener('update', _this.scheduleUpdate);
            var _a = _this, marker = _a.marker, label = _a.label;
            marker.fill = '#c16068';
            marker.stroke = '#874349';
            marker.addPropertyListener('shape', _this.onMarkerShapeChange, _this);
            marker.addEventListener('change', _this.scheduleUpdate, _this);
            label.enabled = false;
            label.addEventListener('change', _this.scheduleUpdate, _this);
            return _this;
        }
        LineSeries.prototype.onMarkerShapeChange = function () {
            this.nodeSelection = this.nodeSelection.setData([]);
            this.nodeSelection.exit.remove();
            this.fireEvent({ type: 'legendChange' });
        };
        LineSeries.prototype.setColors = function (fills, strokes) {
            this.stroke = fills[0];
            this.marker.stroke = strokes[0];
            this.marker.fill = fills[0];
        };
        Object.defineProperty(LineSeries.prototype, "xKey", {
            get: function () {
                return this._xKey;
            },
            set: function (value) {
                if (this._xKey !== value) {
                    this._xKey = value;
                    this.xData = [];
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(LineSeries.prototype, "yKey", {
            get: function () {
                return this._yKey;
            },
            set: function (value) {
                if (this._yKey !== value) {
                    this._yKey = value;
                    this.yData = [];
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        LineSeries.prototype.processData = function () {
            var _a = this, xAxis = _a.xAxis, yAxis = _a.yAxis, xKey = _a.xKey, yKey = _a.yKey, xData = _a.xData, yData = _a.yData;
            var data = xKey && yKey && this.data ? this.data : [];
            if (!xAxis || !yAxis) {
                return false;
            }
            var isContinuousX = xAxis.scale instanceof ContinuousScale;
            var isContinuousY = yAxis.scale instanceof ContinuousScale;
            xData.length = 0;
            yData.length = 0;
            for (var i = 0, n = data.length; i < n; i++) {
                var datum = data[i];
                var x = datum[xKey];
                var y = datum[yKey];
                if (isContinuousX) {
                    xData.push(x);
                }
                else {
                    // i.e. category axis
                    xData.push(isDiscrete(x) ? x : String(x));
                }
                if (isContinuousY) {
                    yData.push(y);
                }
                else {
                    yData.push(isDiscrete(y) ? y : String(y));
                }
            }
            this.xDomain = isContinuousX ? this.fixNumericExtent(extent(xData, isContinuous), 'x') : xData;
            this.yDomain = isContinuousY ? this.fixNumericExtent(extent(yData, isContinuous), 'y') : yData;
            return true;
        };
        LineSeries.prototype.getDomain = function (direction) {
            if (direction === exports.ChartAxisDirection.X) {
                return this.xDomain;
            }
            return this.yDomain;
        };
        LineSeries.prototype.onHighlightChange = function () {
            this.updateNodes();
        };
        LineSeries.prototype.resetHighlight = function () {
            this.lineNode.strokeWidth = this.strokeWidth;
        };
        LineSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        LineSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            this.updateLinePath(); // this will create node data too
            this.updateNodeSelection();
        };
        LineSeries.prototype.updateLinePath = function () {
            var _a = this, data = _a.data, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!data || !xAxis || !yAxis) {
                return;
            }
            var _b = this, xData = _b.xData, yData = _b.yData, lineNode = _b.lineNode, label = _b.label;
            var xScale = xAxis.scale;
            var yScale = yAxis.scale;
            var isContinuousX = xScale instanceof ContinuousScale;
            var isContinuousY = yScale instanceof ContinuousScale;
            var xOffset = (xScale.bandwidth || 0) / 2;
            var yOffset = (yScale.bandwidth || 0) / 2;
            var linePath = lineNode.path;
            var nodeData = [];
            linePath.clear();
            var moveTo = true;
            var prevXInRange = undefined;
            var nextXYDatums = undefined;
            for (var i = 0; i < xData.length; i++) {
                var xyDatums = nextXYDatums || this.checkDomainXY(xData[i], yData[i], isContinuousX, isContinuousY);
                if (!xyDatums) {
                    prevXInRange = undefined;
                    moveTo = true;
                }
                else {
                    var _c = __read$d(xyDatums, 2), xDatum = _c[0], yDatum = _c[1];
                    var x = xScale.convert(xDatum) + xOffset;
                    if (isNaN(x)) {
                        prevXInRange = undefined;
                        moveTo = true;
                        continue;
                    }
                    var tolerance = (xScale.bandwidth || (this.marker.size * 0.5 + (this.marker.strokeWidth || 0))) + 1;
                    nextXYDatums = this.checkDomainXY(xData[i + 1], yData[i + 1], isContinuousX, isContinuousY);
                    var xInRange = xAxis.inRangeEx(x, 0, tolerance);
                    var nextXInRange = nextXYDatums && xAxis.inRangeEx(xScale.convert(nextXYDatums[0]) + xOffset, 0, tolerance);
                    if (xInRange === -1 && nextXInRange === -1) {
                        moveTo = true;
                        continue;
                    }
                    if (xInRange === 1 && prevXInRange === 1) {
                        moveTo = true;
                        continue;
                    }
                    prevXInRange = xInRange;
                    var y = yScale.convert(yDatum) + yOffset;
                    if (moveTo) {
                        linePath.moveTo(x, y);
                        moveTo = false;
                    }
                    else {
                        linePath.lineTo(x, y);
                    }
                    var labelText = void 0;
                    if (label.formatter) {
                        labelText = label.formatter({ value: yDatum });
                    }
                    else {
                        labelText = typeof yDatum === 'number' && isFinite(yDatum) ? yDatum.toFixed(2) : yDatum ? String(yDatum) : '';
                    }
                    nodeData.push({
                        series: this,
                        datum: data[i],
                        point: { x: x, y: y },
                        label: labelText ? {
                            text: labelText,
                            fontStyle: label.fontStyle,
                            fontWeight: label.fontWeight,
                            fontSize: label.fontSize,
                            fontFamily: label.fontFamily,
                            textAlign: 'center',
                            textBaseline: 'bottom',
                            fill: label.color
                        } : undefined
                    });
                }
            }
            // Used by marker nodes and for hit-testing even when not using markers
            // when `chart.tooltip.tracking` is true.
            this.nodeData = nodeData;
        };
        LineSeries.prototype.updateNodeSelection = function () {
            var marker = this.marker;
            var nodeData = marker.shape ? this.nodeData : [];
            var MarkerShape = getMarker(marker.shape);
            var updateSelection = this.nodeSelection.setData(nodeData);
            updateSelection.exit.remove();
            var enterSelection = updateSelection.enter.append(Group);
            enterSelection.append(MarkerShape);
            enterSelection.append(Text);
            this.nodeSelection = updateSelection.merge(enterSelection);
        };
        LineSeries.prototype.updateNodes = function () {
            this.group.visible = this.visible;
            this.updateLineNode();
            this.updateMarkerNodes();
            this.updateTextNodes();
        };
        LineSeries.prototype.updateLineNode = function () {
            var lineNode = this.lineNode;
            lineNode.stroke = this.stroke;
            lineNode.strokeWidth = this.getStrokeWidth(this.strokeWidth);
            lineNode.strokeOpacity = this.strokeOpacity;
            lineNode.lineDash = this.lineDash;
            lineNode.lineDashOffset = this.lineDashOffset;
            lineNode.opacity = this.getOpacity();
        };
        LineSeries.prototype.updateMarkerNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, marker = _a.marker, xKey = _a.xKey, yKey = _a.yKey, lineStroke = _a.stroke, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            var size = marker.size, formatter = marker.formatter;
            var markerStrokeWidth = marker.strokeWidth !== undefined ? marker.strokeWidth : this.strokeWidth;
            var MarkerShape = getMarker(marker.shape);
            this.nodeSelection.selectByClass(MarkerShape)
                .each(function (node, datum) {
                var isDatumHighlighted = datum === highlightedDatum;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : marker.fill;
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : marker.stroke || lineStroke;
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : markerStrokeWidth;
                var format = undefined;
                if (formatter) {
                    format = formatter({
                        datum: datum.datum,
                        xKey: xKey,
                        yKey: yKey,
                        fill: fill,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        size: size,
                        highlighted: isDatumHighlighted
                    });
                }
                node.fill = format && format.fill || fill;
                node.stroke = format && format.stroke || stroke;
                node.strokeWidth = format && format.strokeWidth !== undefined
                    ? format.strokeWidth
                    : strokeWidth;
                node.size = format && format.size !== undefined
                    ? format.size
                    : size;
                node.translationX = datum.point.x;
                node.translationY = datum.point.y;
                node.opacity = _this.getOpacity(datum);
                node.visible = marker.enabled && node.size > 0;
            });
        };
        LineSeries.prototype.updateTextNodes = function () {
            var _this = this;
            this.nodeSelection.selectByClass(Text)
                .each(function (text, datum) {
                var point = datum.point, label = datum.label;
                var _a = _this.label, labelEnabled = _a.enabled, fontStyle = _a.fontStyle, fontWeight = _a.fontWeight, fontSize = _a.fontSize, fontFamily = _a.fontFamily, color = _a.color;
                if (label && labelEnabled) {
                    text.fontStyle = fontStyle;
                    text.fontWeight = fontWeight;
                    text.fontSize = fontSize;
                    text.fontFamily = fontFamily;
                    text.textAlign = label.textAlign;
                    text.textBaseline = label.textBaseline;
                    text.text = label.text;
                    text.x = point.x;
                    text.y = point.y - 10;
                    text.fill = color;
                    text.visible = true;
                }
                else {
                    text.visible = false;
                }
            });
        };
        LineSeries.prototype.getNodeData = function () {
            return this.nodeData;
        };
        LineSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                xKey: this.xKey,
                yKey: this.yKey
            });
        };
        LineSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var _a = this, xKey = _a.xKey, yKey = _a.yKey, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!xKey || !yKey || !xAxis || !yAxis) {
                return '';
            }
            var _b = this, xName = _b.xName, yName = _b.yName, tooltip = _b.tooltip, marker = _b.marker;
            var tooltipRenderer = tooltip.renderer, tooltipFormat = tooltip.format;
            var datum = nodeDatum.datum;
            var xValue = datum[xKey];
            var yValue = datum[yKey];
            var xString = xAxis.formatDatum(xValue);
            var yString = yAxis.formatDatum(yValue);
            var title = sanitizeHtml(this.title || yName);
            var content = sanitizeHtml(xString + ': ' + yString);
            var markerFormatter = marker.formatter, fill = marker.fill, stroke = marker.stroke, markerStrokeWidth = marker.strokeWidth, size = marker.size;
            var strokeWidth = markerStrokeWidth !== undefined ? markerStrokeWidth : this.strokeWidth;
            var format = undefined;
            if (markerFormatter) {
                format = markerFormatter({
                    datum: datum,
                    xKey: xKey,
                    yKey: yKey,
                    fill: fill,
                    stroke: stroke,
                    strokeWidth: strokeWidth,
                    size: size,
                    highlighted: false
                });
            }
            var color = format && format.fill || fill;
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            if (tooltipFormat || tooltipRenderer) {
                var params = {
                    datum: datum,
                    xKey: xKey,
                    xValue: xValue,
                    xName: xName,
                    yKey: yKey,
                    yValue: yValue,
                    yName: yName,
                    title: title,
                    color: color
                };
                if (tooltipFormat) {
                    return toTooltipHtml({
                        content: interpolate(tooltipFormat, params)
                    }, defaults);
                }
                if (tooltipRenderer) {
                    return toTooltipHtml(tooltipRenderer(params), defaults);
                }
            }
            return toTooltipHtml(defaults);
        };
        LineSeries.prototype.listSeriesItems = function (legendData) {
            var _a = this, id = _a.id, data = _a.data, xKey = _a.xKey, yKey = _a.yKey, yName = _a.yName, visible = _a.visible, title = _a.title, marker = _a.marker, stroke = _a.stroke, strokeOpacity = _a.strokeOpacity;
            if (data && data.length && xKey && yKey) {
                legendData.push({
                    id: id,
                    itemId: undefined,
                    enabled: visible,
                    label: {
                        text: title || yName || yKey
                    },
                    marker: {
                        shape: marker.shape,
                        fill: marker.fill || 'rgba(0, 0, 0, 0)',
                        stroke: marker.stroke || stroke || 'rgba(0, 0, 0, 0)',
                        fillOpacity: 1,
                        strokeOpacity: strokeOpacity
                    }
                });
            }
        };
        LineSeries.className = 'LineSeries';
        LineSeries.type = 'line';
        __decorate$9([
            reactive('layoutChange')
        ], LineSeries.prototype, "title", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "stroke", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "lineDash", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "lineDashOffset", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "strokeWidth", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "strokeOpacity", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "xName", void 0);
        __decorate$9([
            reactive('update')
        ], LineSeries.prototype, "yName", void 0);
        return LineSeries;
    }(CartesianSeries));

    var __extends$K = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __assign$2 = (undefined && undefined.__assign) || function () {
        __assign$2 = Object.assign || function(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$2.apply(this, arguments);
    };
    var __decorate$a = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var ScatterSeriesTooltip = /** @class */ (function (_super) {
        __extends$K(ScatterSeriesTooltip, _super);
        function ScatterSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$a([
            reactive('change')
        ], ScatterSeriesTooltip.prototype, "renderer", void 0);
        return ScatterSeriesTooltip;
    }(SeriesTooltip));
    var ScatterSeries = /** @class */ (function (_super) {
        __extends$K(ScatterSeries, _super);
        function ScatterSeries() {
            var _this = _super.call(this) || this;
            _this.xDomain = [];
            _this.yDomain = [];
            _this.xData = [];
            _this.yData = [];
            _this.sizeData = [];
            _this.sizeScale = new LinearScale();
            _this.nodeData = [];
            _this.markerSelection = Selection.select(_this.pickGroup).selectAll();
            _this.labelData = [];
            _this.labelSelection = Selection.select(_this.group).selectAll();
            _this.marker = new CartesianSeriesMarker();
            _this.label = new Label();
            _this._fill = '#c16068';
            _this._stroke = '#874349';
            _this._strokeWidth = 2;
            _this._fillOpacity = 1;
            _this._strokeOpacity = 1;
            _this.xKey = '';
            _this.yKey = '';
            _this.xName = '';
            _this.yName = '';
            _this.sizeName = 'Size';
            _this.labelName = 'Label';
            _this.tooltip = new ScatterSeriesTooltip();
            var _a = _this, marker = _a.marker, label = _a.label;
            marker.addPropertyListener('shape', _this.onMarkerShapeChange, _this);
            marker.addEventListener('change', _this.scheduleUpdate, _this);
            _this.addPropertyListener('xKey', function () { return _this.xData = []; });
            _this.addPropertyListener('yKey', function () { return _this.yData = []; });
            _this.addPropertyListener('sizeKey', function () { return _this.sizeData = []; });
            label.enabled = false;
            label.addEventListener('change', _this.scheduleUpdate, _this);
            label.addEventListener('dataChange', _this.scheduleData, _this);
            return _this;
        }
        Object.defineProperty(ScatterSeries.prototype, "fill", {
            get: function () {
                return this._fill;
            },
            /**
             * @deprecated Use {@link marker.fill} instead.
             */
            set: function (value) {
                if (this._fill !== value) {
                    this._fill = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ScatterSeries.prototype, "stroke", {
            get: function () {
                return this._stroke;
            },
            /**
             * @deprecated Use {@link marker.stroke} instead.
             */
            set: function (value) {
                if (this._stroke !== value) {
                    this._stroke = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ScatterSeries.prototype, "strokeWidth", {
            get: function () {
                return this._strokeWidth;
            },
            /**
             * @deprecated Use {@link marker.strokeWidth} instead.
             */
            set: function (value) {
                if (this._strokeWidth !== value) {
                    this._strokeWidth = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ScatterSeries.prototype, "fillOpacity", {
            get: function () {
                return this._fillOpacity;
            },
            /**
             * @deprecated Use {@link marker.fillOpacity} instead.
             */
            set: function (value) {
                if (this._fillOpacity !== value) {
                    this._fillOpacity = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(ScatterSeries.prototype, "strokeOpacity", {
            get: function () {
                return this._strokeOpacity;
            },
            /**
             * @deprecated Use {@link marker.strokeOpacity} instead.
             */
            set: function (value) {
                if (this._strokeOpacity !== value) {
                    this._strokeOpacity = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        ScatterSeries.prototype.onHighlightChange = function () {
            this.updateMarkerNodes();
        };
        ScatterSeries.prototype.onMarkerShapeChange = function () {
            this.markerSelection = this.markerSelection.setData([]);
            this.markerSelection.exit.remove();
            this.fireEvent({ type: 'legendChange' });
        };
        ScatterSeries.prototype.setColors = function (fills, strokes) {
            this.fill = fills[0];
            this.stroke = strokes[0];
            this.marker.fill = fills[0];
            this.marker.stroke = strokes[0];
        };
        ScatterSeries.prototype.processData = function () {
            var _a = this, xKey = _a.xKey, yKey = _a.yKey, sizeKey = _a.sizeKey, labelKey = _a.labelKey, xAxis = _a.xAxis, yAxis = _a.yAxis, marker = _a.marker, label = _a.label;
            if (!xAxis || !yAxis) {
                return false;
            }
            var data = xKey && yKey && this.data ? this.data : [];
            this.xData = data.map(function (d) { return d[xKey]; });
            this.yData = data.map(function (d) { return d[yKey]; });
            this.sizeData = sizeKey ? data.map(function (d) { return d[sizeKey]; }) : [];
            var font = label.getFont();
            this.labelData = labelKey ? data.map(function (d) {
                var text = String(d[labelKey]);
                var size = HdpiCanvas.getTextSize(text, font);
                return __assign$2({ text: text }, size);
            }) : [];
            this.sizeScale.domain = marker.domain ? marker.domain : extent(this.sizeData, isContinuous) || [1, 1];
            if (xAxis.scale instanceof ContinuousScale) {
                this.xDomain = this.fixNumericExtent(extent(this.xData, isContinuous), 'x');
            }
            else {
                this.xDomain = this.xData;
            }
            if (yAxis.scale instanceof ContinuousScale) {
                this.yDomain = this.fixNumericExtent(extent(this.yData, isContinuous), 'y');
            }
            else {
                this.yDomain = this.yData;
            }
            return true;
        };
        ScatterSeries.prototype.getDomain = function (direction) {
            if (direction === exports.ChartAxisDirection.X) {
                return this.xDomain;
            }
            else {
                return this.yDomain;
            }
        };
        ScatterSeries.prototype.getNodeData = function () {
            return this.nodeData;
        };
        ScatterSeries.prototype.getLabelData = function () {
            return this.nodeData;
        };
        ScatterSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                xKey: this.xKey,
                yKey: this.yKey,
                sizeKey: this.sizeKey
            });
        };
        ScatterSeries.prototype.createNodeData = function () {
            var _a = this, chart = _a.chart, data = _a.data, visible = _a.visible, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!(chart && data && visible && xAxis && yAxis) || chart.layoutPending || chart.dataPending) {
                return [];
            }
            var xScale = xAxis.scale;
            var yScale = yAxis.scale;
            var isContinuousX = xScale instanceof ContinuousScale;
            var isContinuousY = yScale instanceof ContinuousScale;
            var xOffset = (xScale.bandwidth || 0) / 2;
            var yOffset = (yScale.bandwidth || 0) / 2;
            var _b = this, xData = _b.xData, yData = _b.yData, sizeData = _b.sizeData, sizeScale = _b.sizeScale, marker = _b.marker;
            var nodeData = [];
            sizeScale.range = [marker.size, marker.maxSize];
            for (var i = 0; i < xData.length; i++) {
                var xy = this.checkDomainXY(xData[i], yData[i], isContinuousX, isContinuousY);
                if (!xy) {
                    continue;
                }
                var x = xScale.convert(xy[0]) + xOffset;
                var y = yScale.convert(xy[1]) + yOffset;
                if (!this.checkRangeXY(x, y, xAxis, yAxis)) {
                    continue;
                }
                nodeData.push({
                    series: this,
                    datum: data[i],
                    point: { x: x, y: y },
                    size: sizeData.length ? sizeScale.convert(sizeData[i]) : marker.size,
                    label: this.labelData[i]
                });
            }
            return this.nodeData = nodeData;
        };
        ScatterSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        ScatterSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            this.createNodeData();
            this.updateMarkerSelection();
            this.updateLabelSelection();
        };
        ScatterSeries.prototype.updateNodes = function () {
            this.group.visible = this.visible;
            this.updateMarkerNodes();
            this.updateLabelNodes();
        };
        ScatterSeries.prototype.updateLabelSelection = function () {
            var placedLabels = this.chart && this.chart.placeLabels().get(this) || [];
            var updateLabels = this.labelSelection.setData(placedLabels);
            updateLabels.exit.remove();
            var enterLabels = updateLabels.enter.append(Text);
            this.labelSelection = updateLabels.merge(enterLabels);
        };
        ScatterSeries.prototype.updateMarkerSelection = function () {
            var MarkerShape = getMarker(this.marker.shape);
            var updateMarkers = this.markerSelection.setData(this.nodeData);
            updateMarkers.exit.remove();
            var enterMarkers = updateMarkers.enter.append(MarkerShape);
            this.markerSelection = updateMarkers.merge(enterMarkers);
        };
        ScatterSeries.prototype.updateLabelNodes = function () {
            var label = this.label;
            this.labelSelection.each(function (text, datum) {
                text.text = datum.text;
                text.fill = label.color;
                text.x = datum.x;
                text.y = datum.y;
                text.fontStyle = label.fontStyle;
                text.fontWeight = label.fontWeight;
                text.fontSize = label.fontSize;
                text.fontFamily = label.fontFamily;
                text.textAlign = 'left';
                text.textBaseline = 'top';
            });
        };
        ScatterSeries.prototype.updateMarkerNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, marker = _a.marker, xKey = _a.xKey, yKey = _a.yKey, strokeWidth = _a.strokeWidth, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity, seriesFill = _a.fill, seriesStroke = _a.stroke, highlightedDatum = _a.chart.highlightedDatum, sizeScale = _a.sizeScale, sizeData = _a.sizeData, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            var markerStrokeWidth = marker.strokeWidth !== undefined ? marker.strokeWidth : strokeWidth;
            var formatter = marker.formatter;
            sizeScale.range = [marker.size, marker.maxSize];
            this.markerSelection.each(function (node, datum, index) {
                var isDatumHighlighted = datum === highlightedDatum;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : marker.fill || seriesFill;
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : marker.stroke || seriesStroke;
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : _this.getStrokeWidth(markerStrokeWidth, datum);
                var size = sizeData.length ? sizeScale.convert(sizeData[index]) : marker.size;
                var format = undefined;
                if (formatter) {
                    format = formatter({
                        datum: datum.datum,
                        xKey: xKey,
                        yKey: yKey,
                        fill: fill,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        size: size,
                        highlighted: isDatumHighlighted
                    });
                }
                node.fill = format && format.fill || fill;
                node.stroke = format && format.stroke || stroke;
                node.strokeWidth = format && format.strokeWidth !== undefined
                    ? format.strokeWidth
                    : strokeWidth;
                node.size = format && format.size !== undefined
                    ? format.size
                    : size;
                node.fillOpacity = marker.fillOpacity !== undefined ? marker.fillOpacity : fillOpacity;
                node.strokeOpacity = marker.strokeOpacity !== undefined ? marker.strokeOpacity : strokeOpacity;
                node.translationX = datum.point.x;
                node.translationY = datum.point.y;
                node.opacity = _this.getOpacity(datum);
                node.zIndex = isDatumHighlighted ? Series.highlightedZIndex : index;
                node.visible = marker.enabled && node.size > 0;
            });
        };
        ScatterSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var _a = this, xKey = _a.xKey, yKey = _a.yKey, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!xKey || !yKey || !xAxis || !yAxis) {
                return '';
            }
            var _b = this, seriesFill = _b.fill, seriesStroke = _b.stroke, marker = _b.marker, tooltip = _b.tooltip, xName = _b.xName, yName = _b.yName, sizeKey = _b.sizeKey, sizeName = _b.sizeName, labelKey = _b.labelKey, labelName = _b.labelName;
            var fill = marker.fill || seriesFill;
            var stroke = marker.stroke || seriesStroke;
            var strokeWidth = this.getStrokeWidth(marker.strokeWidth || this.strokeWidth, nodeDatum);
            var formatter = this.marker.formatter;
            var format = undefined;
            if (formatter) {
                format = formatter({
                    datum: nodeDatum,
                    xKey: xKey,
                    yKey: yKey,
                    fill: fill,
                    stroke: stroke,
                    strokeWidth: strokeWidth,
                    size: nodeDatum.size,
                    highlighted: false
                });
            }
            var color = format && format.fill || fill || 'gray';
            var title = this.title || yName;
            var datum = nodeDatum.datum;
            var xValue = datum[xKey];
            var yValue = datum[yKey];
            var xString = sanitizeHtml(xAxis.formatDatum(xValue));
            var yString = sanitizeHtml(yAxis.formatDatum(yValue));
            var content = "<b>" + sanitizeHtml(xName || xKey) + "</b>: " + xString + "<br>" +
                ("<b>" + sanitizeHtml(yName || yKey) + "</b>: " + yString);
            if (sizeKey) {
                content += "<br><b>" + sanitizeHtml(sizeName || sizeKey) + "</b>: " + sanitizeHtml(datum[sizeKey]);
            }
            if (labelKey) {
                content = "<b>" + sanitizeHtml(labelName || labelKey) + "</b>: " + sanitizeHtml(datum[labelKey]) + "<br>" + content;
            }
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            var tooltipRenderer = tooltip.renderer;
            if (tooltipRenderer) {
                return toTooltipHtml(tooltipRenderer({
                    datum: datum,
                    xKey: xKey,
                    xValue: xValue,
                    xName: xName,
                    yKey: yKey,
                    yValue: yValue,
                    yName: yName,
                    sizeKey: sizeKey,
                    sizeName: sizeName,
                    labelKey: labelKey,
                    labelName: labelName,
                    title: title,
                    color: color
                }), defaults);
            }
            return toTooltipHtml(defaults);
        };
        ScatterSeries.prototype.listSeriesItems = function (legendData) {
            var _a = this, id = _a.id, data = _a.data, xKey = _a.xKey, yKey = _a.yKey, yName = _a.yName, title = _a.title, visible = _a.visible, marker = _a.marker, fill = _a.fill, stroke = _a.stroke, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity;
            if (data && data.length && xKey && yKey) {
                legendData.push({
                    id: id,
                    itemId: undefined,
                    enabled: visible,
                    label: {
                        text: title || yName || yKey
                    },
                    marker: {
                        shape: marker.shape,
                        fill: marker.fill || fill || 'rgba(0, 0, 0, 0)',
                        stroke: marker.stroke || stroke || 'rgba(0, 0, 0, 0)',
                        fillOpacity: marker.fillOpacity !== undefined ? marker.fillOpacity : fillOpacity,
                        strokeOpacity: marker.strokeOpacity !== undefined ? marker.strokeOpacity : strokeOpacity
                    }
                });
            }
        };
        ScatterSeries.className = 'ScatterSeries';
        ScatterSeries.type = 'scatter';
        __decorate$a([
            reactive('layoutChange')
        ], ScatterSeries.prototype, "title", void 0);
        __decorate$a([
            reactive('dataChange')
        ], ScatterSeries.prototype, "xKey", void 0);
        __decorate$a([
            reactive('dataChange')
        ], ScatterSeries.prototype, "yKey", void 0);
        __decorate$a([
            reactive('dataChange')
        ], ScatterSeries.prototype, "sizeKey", void 0);
        __decorate$a([
            reactive('dataChange')
        ], ScatterSeries.prototype, "labelKey", void 0);
        return ScatterSeries;
    }(CartesianSeries));

    var __extends$L = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __read$e = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$4 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$e(arguments[i]));
        return ar;
    };
    var HistogramSeriesNodeTag;
    (function (HistogramSeriesNodeTag) {
        HistogramSeriesNodeTag[HistogramSeriesNodeTag["Bin"] = 0] = "Bin";
        HistogramSeriesNodeTag[HistogramSeriesNodeTag["Label"] = 1] = "Label";
    })(HistogramSeriesNodeTag || (HistogramSeriesNodeTag = {}));
    var HistogramSeriesLabel = /** @class */ (function (_super) {
        __extends$L(HistogramSeriesLabel, _super);
        function HistogramSeriesLabel() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$b([
            reactive('change')
        ], HistogramSeriesLabel.prototype, "formatter", void 0);
        return HistogramSeriesLabel;
    }(Label));
    var defaultBinCount = 10;
    var aggregationFunctions = {
        count: function (bin) { return bin.data.length; },
        sum: function (bin, yKey) { return bin.data.reduce(function (acc, datum) { return acc + datum[yKey]; }, 0); },
        mean: function (bin, yKey) { return aggregationFunctions.sum(bin, yKey) / aggregationFunctions.count(bin, yKey); }
    };
    var HistogramBin = /** @class */ (function () {
        function HistogramBin(_a) {
            var _b = __read$e(_a, 2), domainMin = _b[0], domainMax = _b[1];
            this.data = [];
            this.aggregatedValue = 0;
            this.frequency = 0;
            this.domain = [domainMin, domainMax];
        }
        HistogramBin.prototype.addDatum = function (datum) {
            this.data.push(datum);
            this.frequency++;
        };
        Object.defineProperty(HistogramBin.prototype, "domainWidth", {
            get: function () {
                var _a = __read$e(this.domain, 2), domainMin = _a[0], domainMax = _a[1];
                return domainMax - domainMin;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramBin.prototype, "relativeHeight", {
            get: function () {
                return this.aggregatedValue / this.domainWidth;
            },
            enumerable: true,
            configurable: true
        });
        HistogramBin.prototype.calculateAggregatedValue = function (aggregationName, yKey) {
            if (!yKey) {
                // not having a yKey forces us into a frequency plot
                aggregationName = 'count';
            }
            var aggregationFunction = aggregationFunctions[aggregationName];
            this.aggregatedValue = aggregationFunction(this, yKey);
        };
        HistogramBin.prototype.getY = function (areaPlot) {
            return areaPlot ? this.relativeHeight : this.aggregatedValue;
        };
        return HistogramBin;
    }());
    var HistogramSeriesTooltip = /** @class */ (function (_super) {
        __extends$L(HistogramSeriesTooltip, _super);
        function HistogramSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$b([
            reactive('change')
        ], HistogramSeriesTooltip.prototype, "renderer", void 0);
        return HistogramSeriesTooltip;
    }(SeriesTooltip));
    var HistogramSeries = /** @class */ (function (_super) {
        __extends$L(HistogramSeries, _super);
        function HistogramSeries() {
            var _a;
            var _this = _super.call(this) || this;
            // Need to put column and label nodes into separate groups, because even though label nodes are
            // created after the column nodes, this only guarantees that labels will always be on top of columns
            // on the first run. If on the next run more columns are added, they might clip the labels
            // rendered during the previous run.
            _this.rectGroup = _this.pickGroup.appendChild(new Group());
            _this.textGroup = _this.group.appendChild(new Group());
            _this.rectSelection = Selection.select(_this.rectGroup).selectAll();
            _this.textSelection = Selection.select(_this.textGroup).selectAll();
            _this.binnedData = [];
            _this.xDomain = [];
            _this.yDomain = [];
            _this.label = new HistogramSeriesLabel();
            _this.seriesItemEnabled = true;
            _this.tooltip = new HistogramSeriesTooltip();
            _this.fill = undefined;
            _this.stroke = undefined;
            _this.fillOpacity = 1;
            _this.strokeOpacity = 1;
            _this.lineDash = [0];
            _this.lineDashOffset = 0;
            _this.directionKeys = (_a = {},
                _a[exports.ChartAxisDirection.X] = ['xKey'],
                _a[exports.ChartAxisDirection.Y] = ['yKey'],
                _a);
            _this._xKey = '';
            _this._areaPlot = false;
            _this._bins = undefined;
            _this._aggregation = 'count';
            _this._binCount = undefined;
            _this._xName = '';
            _this._yKey = '';
            _this._yName = '';
            _this._strokeWidth = 1;
            _this.label.enabled = false;
            _this.label.addEventListener('change', _this.scheduleUpdate, _this);
            return _this;
        }
        HistogramSeries.prototype.getKeys = function (direction) {
            var _this = this;
            var directionKeys = this.directionKeys;
            var keys = directionKeys && directionKeys[direction];
            var values = [];
            if (keys) {
                keys.forEach(function (key) {
                    var value = _this[key];
                    if (value) {
                        if (Array.isArray(value)) {
                            values.push.apply(values, __spread$4(value));
                        }
                        else {
                            values.push(value);
                        }
                    }
                });
            }
            return values;
        };
        Object.defineProperty(HistogramSeries.prototype, "xKey", {
            get: function () {
                return this._xKey;
            },
            set: function (value) {
                if (this._xKey !== value) {
                    this._xKey = value;
                    this.scheduleData();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "areaPlot", {
            get: function () {
                return this._areaPlot;
            },
            set: function (c) {
                this._areaPlot = c;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "bins", {
            get: function () {
                return this._bins;
            },
            set: function (bins) {
                this._bins = bins;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "aggregation", {
            get: function () {
                return this._aggregation;
            },
            set: function (aggregation) {
                this._aggregation = aggregation;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "binCount", {
            get: function () {
                return this._binCount;
            },
            set: function (binCount) {
                this._binCount = binCount;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "xName", {
            get: function () {
                return this._xName;
            },
            set: function (value) {
                if (this._xName !== value) {
                    this._xName = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "yKey", {
            get: function () {
                return this._yKey;
            },
            set: function (yKey) {
                this._yKey = yKey;
                this.seriesItemEnabled = true;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "yName", {
            get: function () {
                return this._yName;
            },
            set: function (values) {
                this._yName = values;
                this.scheduleData();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "strokeWidth", {
            get: function () {
                return this._strokeWidth;
            },
            set: function (value) {
                if (this._strokeWidth !== value) {
                    this._strokeWidth = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(HistogramSeries.prototype, "shadow", {
            get: function () {
                return this._shadow;
            },
            set: function (value) {
                if (this._shadow !== value) {
                    this._shadow = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        HistogramSeries.prototype.onHighlightChange = function () {
            this.updateRectNodes();
        };
        HistogramSeries.prototype.setColors = function (fills, strokes) {
            this.fill = fills[0];
            this.stroke = strokes[0];
        };
        // During processData phase, used to unify different ways of the user specifying
        // the bins. Returns bins in format[[min1, max1], [min2, max2], ... ].
        HistogramSeries.prototype.deriveBins = function () {
            var _this = this;
            var _a = this, bins = _a.bins, binCount = _a.binCount;
            if (!this.data) {
                return [];
            }
            if (bins) {
                return bins;
            }
            var xData = this.data.map(function (datum) { return datum[_this.xKey]; });
            var xDomain = this.fixNumericExtent(extent(xData, isContinuous), 'x');
            var binStarts = ticks(xDomain[0], xDomain[1], this.binCount || defaultBinCount);
            var binSize = tickStep(xDomain[0], xDomain[1], this.binCount || defaultBinCount);
            var firstBinEnd = binStarts[0];
            var expandStartToBin = function (n) { return [n, n + binSize]; };
            return __spread$4([
                [firstBinEnd - binSize, firstBinEnd]
            ], binStarts.map(expandStartToBin));
        };
        HistogramSeries.prototype.placeDataInBins = function (data) {
            var _this = this;
            var xKey = this.xKey;
            var derivedBins = this.deriveBins();
            // creating a sorted copy allows binning in O(n) rather than O(n²)
            // but at the expense of more temporary memory
            var sortedData = data.slice().sort(function (a, b) {
                if (a[xKey] < b[xKey]) {
                    return -1;
                }
                if (a[xKey] > b[xKey]) {
                    return 1;
                }
                return 0;
            });
            var currentBin = 0;
            var bins = [new HistogramBin(derivedBins[0])];
            loop: for (var i = 0, ln = sortedData.length; i < ln; i++) {
                var datum = sortedData[i];
                while (datum[xKey] > derivedBins[currentBin][1]) {
                    currentBin++;
                    var bin = derivedBins[currentBin];
                    if (!bin) {
                        break loop;
                    }
                    bins.push(new HistogramBin(bin));
                }
                bins[currentBin].addDatum(datum);
            }
            bins.forEach(function (b) { return b.calculateAggregatedValue(_this._aggregation, _this.yKey); });
            return bins;
        };
        Object.defineProperty(HistogramSeries.prototype, "xMax", {
            get: function () {
                var _this = this;
                return this.data && this.data.reduce(function (acc, datum) {
                    return Math.max(acc, datum[_this.xKey]);
                }, Number.NEGATIVE_INFINITY);
            },
            enumerable: true,
            configurable: true
        });
        HistogramSeries.prototype.processData = function () {
            var _this = this;
            var _a = this, xKey = _a.xKey, data = _a.data;
            this.binnedData = this.placeDataInBins(xKey && data ? data : []);
            var yData = this.binnedData.map(function (b) { return b.getY(_this.areaPlot); });
            var yMinMax = extent(yData, isContinuous);
            this.yDomain = this.fixNumericExtent([0, yMinMax ? yMinMax[1] : 1], 'y');
            var firstBin = this.binnedData[0];
            var lastBin = this.binnedData[this.binnedData.length - 1];
            var xMin = firstBin.domain[0];
            var xMax = lastBin.domain[1];
            this.xDomain = [xMin, xMax];
            this.fireEvent({ type: 'dataProcessed' });
            return true;
        };
        HistogramSeries.prototype.getDomain = function (direction) {
            if (direction === exports.ChartAxisDirection.X) {
                return this.xDomain;
            }
            else {
                return this.yDomain;
            }
        };
        HistogramSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                xKey: this.xKey
            });
        };
        HistogramSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        HistogramSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            var nodeData = this.createNodeData();
            this.updateRectSelection(nodeData);
            this.updateTextSelection(nodeData);
        };
        HistogramSeries.prototype.updateNodes = function () {
            this.group.visible = this.visible;
            this.updateRectNodes();
            this.updateTextNodes();
        };
        HistogramSeries.prototype.createNodeData = function () {
            var _this = this;
            var _a = this, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!this.seriesItemEnabled || !xAxis || !yAxis) {
                return [];
            }
            var xScale = xAxis.scale;
            var yScale = yAxis.scale;
            var _b = this, fill = _b.fill, stroke = _b.stroke, strokeWidth = _b.strokeWidth;
            var nodeData = [];
            var defaultLabelFormatter = function (params) { return String(params.value); };
            var _c = this.label, _d = _c.formatter, labelFormatter = _d === void 0 ? defaultLabelFormatter : _d, labelFontStyle = _c.fontStyle, labelFontWeight = _c.fontWeight, labelFontSize = _c.fontSize, labelFontFamily = _c.fontFamily, labelColor = _c.color;
            this.binnedData.forEach(function (binOfData) {
                var total = binOfData.aggregatedValue, frequency = binOfData.frequency, _a = __read$e(binOfData.domain, 2), xDomainMin = _a[0], xDomainMax = _a[1], relativeHeight = binOfData.relativeHeight;
                var xMinPx = xScale.convert(xDomainMin), xMaxPx = xScale.convert(xDomainMax), 
                // note: assuming can't be negative:
                y = _this.areaPlot ? relativeHeight : (_this.yKey ? total : frequency), yZeroPx = yScale.convert(0), yMaxPx = yScale.convert(y), w = xMaxPx - xMinPx, h = Math.abs(yMaxPx - yZeroPx);
                var selectionDatumLabel = y !== 0 ? {
                    text: labelFormatter({ value: binOfData.aggregatedValue }),
                    fontStyle: labelFontStyle,
                    fontWeight: labelFontWeight,
                    fontSize: labelFontSize,
                    fontFamily: labelFontFamily,
                    fill: labelColor,
                    x: xMinPx + w / 2,
                    y: yMaxPx + h / 2
                } : undefined;
                nodeData.push({
                    series: _this,
                    datum: binOfData,
                    // since each selection is an aggregation of multiple data.
                    x: xMinPx,
                    y: yMaxPx,
                    width: w,
                    height: h,
                    fill: fill,
                    stroke: stroke,
                    strokeWidth: strokeWidth,
                    label: selectionDatumLabel,
                });
            });
            return nodeData;
        };
        HistogramSeries.prototype.updateRectSelection = function (nodeData) {
            var updateRects = this.rectSelection.setData(nodeData);
            updateRects.exit.remove();
            var enterRects = updateRects.enter.append(Rect).each(function (rect) {
                rect.tag = HistogramSeriesNodeTag.Bin;
                rect.crisp = true;
            });
            this.rectSelection = updateRects.merge(enterRects);
        };
        HistogramSeries.prototype.updateRectNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity, shadow = _a.shadow, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            this.rectSelection.each(function (rect, datum, index) {
                var isDatumHighlighted = datum === highlightedDatum;
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : _this.getStrokeWidth(datum.strokeWidth, datum);
                rect.x = datum.x;
                rect.y = datum.y;
                rect.width = datum.width;
                rect.height = datum.height;
                rect.fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : datum.fill;
                rect.stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : datum.stroke;
                rect.fillOpacity = fillOpacity;
                rect.strokeOpacity = strokeOpacity;
                rect.strokeWidth = strokeWidth;
                rect.lineDash = _this.lineDash;
                rect.lineDashOffset = _this.lineDashOffset;
                rect.fillShadow = shadow;
                rect.zIndex = isDatumHighlighted ? Series.highlightedZIndex : index;
                rect.visible = datum.height > 0; // prevent stroke from rendering for zero height columns
                rect.opacity = _this.getOpacity(datum);
            });
        };
        HistogramSeries.prototype.updateTextSelection = function (nodeData) {
            var updateTexts = this.textSelection.setData(nodeData);
            updateTexts.exit.remove();
            var enterTexts = updateTexts.enter.append(Text).each(function (text) {
                text.tag = HistogramSeriesNodeTag.Label;
                text.pointerEvents = PointerEvents.None;
                text.textAlign = 'center';
                text.textBaseline = 'middle';
            });
            this.textSelection = updateTexts.merge(enterTexts);
        };
        HistogramSeries.prototype.updateTextNodes = function () {
            var labelEnabled = this.label.enabled;
            this.textSelection.each(function (text, datum) {
                var label = datum.label;
                if (label && labelEnabled) {
                    text.text = label.text;
                    text.x = label.x;
                    text.y = label.y;
                    text.fontStyle = label.fontStyle;
                    text.fontWeight = label.fontWeight;
                    text.fontSize = label.fontSize;
                    text.fontFamily = label.fontFamily;
                    text.fill = label.fill;
                    text.visible = true;
                }
                else {
                    text.visible = false;
                }
            });
        };
        HistogramSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var _a = this, xKey = _a.xKey, yKey = _a.yKey, xAxis = _a.xAxis, yAxis = _a.yAxis;
            if (!xKey || !xAxis || !yAxis) {
                return '';
            }
            var _b = this, xName = _b.xName, yName = _b.yName, color = _b.fill, tooltip = _b.tooltip, aggregation = _b.aggregation;
            var tooltipRenderer = tooltip.renderer;
            var bin = nodeDatum.datum;
            var aggregatedValue = bin.aggregatedValue, frequency = bin.frequency, _c = __read$e(bin.domain, 2), rangeMin = _c[0], rangeMax = _c[1];
            var title = sanitizeHtml(xName || xKey) + ": " + xAxis.formatDatum(rangeMin) + " - " + xAxis.formatDatum(rangeMax);
            var content = yKey ?
                "<b>" + sanitizeHtml(yName || yKey) + " (" + aggregation + ")</b>: " + yAxis.formatDatum(aggregatedValue) + "<br>" :
                '';
            content += "<b>Frequency</b>: " + frequency;
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            if (tooltipRenderer) {
                return toTooltipHtml(tooltipRenderer({
                    datum: bin,
                    xKey: xKey,
                    xValue: bin.domain,
                    xName: xName,
                    yKey: yKey,
                    yValue: bin.aggregatedValue,
                    yName: yName,
                    color: color
                }), defaults);
            }
            return toTooltipHtml(defaults);
        };
        HistogramSeries.prototype.listSeriesItems = function (legendData) {
            var _a = this, id = _a.id, data = _a.data, yKey = _a.yKey, yName = _a.yName, seriesItemEnabled = _a.seriesItemEnabled, fill = _a.fill, stroke = _a.stroke, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity;
            if (data && data.length) {
                legendData.push({
                    id: id,
                    itemId: yKey,
                    enabled: seriesItemEnabled,
                    label: {
                        text: yName || yKey || 'Frequency'
                    },
                    marker: {
                        fill: fill || 'rgba(0, 0, 0, 0)',
                        stroke: stroke || 'rgba(0, 0, 0, 0)',
                        fillOpacity: fillOpacity,
                        strokeOpacity: strokeOpacity
                    }
                });
            }
        };
        HistogramSeries.prototype.toggleSeriesItem = function (itemId, enabled) {
            if (itemId === this.yKey) {
                this.seriesItemEnabled = enabled;
            }
            this.scheduleData();
        };
        HistogramSeries.className = 'HistogramSeries';
        HistogramSeries.type = 'histogram';
        __decorate$b([
            reactive('dataChange')
        ], HistogramSeries.prototype, "fill", void 0);
        __decorate$b([
            reactive('dataChange')
        ], HistogramSeries.prototype, "stroke", void 0);
        __decorate$b([
            reactive('layoutChange')
        ], HistogramSeries.prototype, "fillOpacity", void 0);
        __decorate$b([
            reactive('layoutChange')
        ], HistogramSeries.prototype, "strokeOpacity", void 0);
        __decorate$b([
            reactive('update')
        ], HistogramSeries.prototype, "lineDash", void 0);
        __decorate$b([
            reactive('update')
        ], HistogramSeries.prototype, "lineDashOffset", void 0);
        return HistogramSeries;
    }(CartesianSeries));

    var __extends$M = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$c = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var HierarchySeries = /** @class */ (function (_super) {
        __extends$M(HierarchySeries, _super);
        function HierarchySeries() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.data = undefined;
            return _this;
        }
        __decorate$c([
            reactive('dataChange')
        ], HierarchySeries.prototype, "data", void 0);
        return HierarchySeries;
    }(Series));

    var __extends$N = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$d = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var DropShadow = /** @class */ (function (_super) {
        __extends$N(DropShadow, _super);
        function DropShadow() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.enabled = true;
            _this.color = 'rgba(0, 0, 0, 0.5)';
            _this.xOffset = 0;
            _this.yOffset = 0;
            _this.blur = 5;
            return _this;
        }
        __decorate$d([
            reactive('change')
        ], DropShadow.prototype, "enabled", void 0);
        __decorate$d([
            reactive('change')
        ], DropShadow.prototype, "color", void 0);
        __decorate$d([
            reactive('change')
        ], DropShadow.prototype, "xOffset", void 0);
        __decorate$d([
            reactive('change')
        ], DropShadow.prototype, "yOffset", void 0);
        __decorate$d([
            reactive('change')
        ], DropShadow.prototype, "blur", void 0);
        return DropShadow;
    }(Observable));

    function slice(parent, x0, y0, x1, y1) {
        var nodes = parent.children;
        var k = parent.value && (y1 - y0) / parent.value;
        nodes.forEach(function (node) {
            node.x0 = x0;
            node.x1 = x1;
            node.y0 = y0;
            node.y1 = y0 += node.value * k;
        });
    }
    function dice(parent, x0, y0, x1, y1) {
        var nodes = parent.children;
        var k = parent.value && (x1 - x0) / parent.value;
        nodes.forEach(function (node) {
            node.x0 = x0;
            node.x1 = x0 += node.value * k;
            node.y0 = y0;
            node.y1 = y1;
        });
    }
    function roundNode(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);
    }
    function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
        var rows = [];
        var nodes = parent.children;
        var n = nodes.length;
        var value = parent.value;
        var i0 = 0;
        var i1 = 0;
        var dx;
        var dy;
        var nodeValue;
        var sumValue;
        var minValue;
        var maxValue;
        var newRatio;
        var minRatio;
        var alpha;
        var 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) {
                nodeValue = nodes[i1].value;
                sumValue += nodeValue;
                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.
            var row = {
                value: sumValue,
                dice: dx < dy,
                children: nodes.slice(i0, i1)
            };
            rows.push(row);
            if (row.dice) {
                dice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
            }
            else {
                slice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
            }
            value -= sumValue;
            i0 = i1;
        }
        return rows;
    }
    var phi = (1 + Math.sqrt(5)) / 2;
    var 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);
    var Treemap = /** @class */ (function () {
        function Treemap() {
            this.paddingStack = [0];
            this.dx = 1;
            this.dy = 1;
            this.round = true;
            this.tile = squarify;
            this.paddingInner = function (_) { return 0; };
            this.paddingTop = function (_) { return 0; };
            this.paddingRight = function (_) { return 0; };
            this.paddingBottom = function (_) { return 0; };
            this.paddingLeft = function (_) { return 0; };
        }
        Object.defineProperty(Treemap.prototype, "size", {
            get: function () {
                return [this.dx, this.dy];
            },
            set: function (size) {
                this.dx = size[0];
                this.dy = size[1];
            },
            enumerable: true,
            configurable: true
        });
        Treemap.prototype.processData = function (root) {
            root.x0 = 0;
            root.y0 = 0;
            root.x1 = this.dx;
            root.y1 = this.dy;
            root.eachBefore(this.positionNode.bind(this));
            this.paddingStack = [0];
            if (this.round) {
                root.eachBefore(roundNode);
            }
            return root;
        };
        Treemap.prototype.positionNode = function (node) {
            var p = this.paddingStack[node.depth];
            var x0 = node.x0 + p;
            var y0 = node.y0 + p;
            var x1 = node.x1 - p;
            var 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 = this.paddingStack[node.depth + 1] = this.paddingInner(node) / 2;
                x0 += this.paddingLeft(node) - p;
                y0 += this.paddingTop(node) - p;
                x1 -= this.paddingRight(node) - p;
                y1 -= this.paddingBottom(node) - p;
                if (x1 < x0) {
                    x0 = x1 = (x0 + x1) / 2;
                }
                if (y1 < y0) {
                    y0 = y1 = (y0 + y1) / 2;
                }
                this.tile(node, x0, y0, x1, y1);
            }
        };
        return Treemap;
    }());

    var HierarchyNode = /** @class */ (function () {
        function HierarchyNode(datum) {
            this.value = 0;
            this.depth = 0;
            this.height = 0;
            this.parent = undefined;
            this.children = undefined;
            this.datum = datum;
        }
        HierarchyNode.prototype.countFn = function (node) {
            var sum = 0, children = node.children;
            if (!children || !children.length) {
                sum = 1;
            }
            else {
                var i = children.length;
                while (--i >= 0) {
                    sum += children[i].value;
                }
            }
            node.value = sum;
        };
        HierarchyNode.prototype.count = function () {
            return this.eachAfter(this.countFn);
        };
        HierarchyNode.prototype.each = function (callback, scope) {
            var _this = this;
            var index = -1;
            this.iterator(function (node) {
                callback.call(scope, node, ++index, _this);
            });
            return this;
        };
        /**
         * Invokes the given callback for each node in post-order traversal.
         * @param callback
         * @param scope
         */
        HierarchyNode.prototype.eachAfter = function (callback, scope) {
            var node = this;
            var nodes = [node];
            var next = [];
            while (node = nodes.pop()) {
                next.push(node);
                var children = node.children;
                if (children) {
                    for (var i = 0, n = children.length; i < n; ++i) {
                        nodes.push(children[i]);
                    }
                }
            }
            var index = -1;
            while (node = next.pop()) {
                callback.call(scope, node, ++index, this);
            }
            return this;
        };
        /**
         * Invokes the given callback for each node in pre-order traversal.
         * @param callback
         * @param scope
         */
        HierarchyNode.prototype.eachBefore = function (callback, scope) {
            var node = this;
            var nodes = [node];
            var index = -1;
            while (node = nodes.pop()) {
                callback.call(scope, node, ++index, this);
                var children = node.children;
                if (children) {
                    for (var i = children.length - 1; i >= 0; --i) {
                        var child = children[i];
                        nodes.push(child);
                    }
                }
            }
            return this;
        };
        HierarchyNode.prototype.find = function (callback, scope) {
            var _this = this;
            var index = -1;
            var result;
            this.iterator(function (node) {
                if (callback.call(scope, node, ++index, _this)) {
                    result = node;
                    return false;
                }
            });
            return result;
        };
        HierarchyNode.prototype.sum = function (value) {
            return this.eachAfter(function (node) {
                var sum = +value(node.datum) || 0;
                var children = node.children;
                if (children) {
                    var i = children.length;
                    while (--i >= 0) {
                        sum += children[i].value;
                    }
                }
                node.value = sum;
            });
        };
        HierarchyNode.prototype.sort = function (compare) {
            return this.eachBefore(function (node) {
                if (node.children) {
                    node.children.sort(compare);
                }
            });
        };
        HierarchyNode.prototype.path = function (end) {
            var start = this;
            var ancestor = leastCommonAncestor(start, end);
            var 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;
            }
            // const otherBranch = [];
            // while (end !== ancestor) {
            //     otherBranch.push(end);
            //     end = end.parent;
            // }
            // nodes.concat(otherBranch.reverse());
            return nodes;
        };
        HierarchyNode.prototype.ancestors = function () {
            var node = this;
            var nodes = [node];
            while (node = node.parent) {
                nodes.push(node);
            }
            return nodes;
        };
        HierarchyNode.prototype.descendants = function () {
            var nodes = [];
            this.iterator(function (node) { return nodes.push(node); });
            return nodes;
        };
        HierarchyNode.prototype.leaves = function () {
            var leaves = [];
            this.eachBefore(function (node) {
                if (!node.children) {
                    leaves.push(node);
                }
            });
            return leaves;
        };
        HierarchyNode.prototype.links = function () {
            var root = this;
            var 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;
        };
        HierarchyNode.prototype.copy = function () {
            // TODO
        };
        HierarchyNode.prototype.iterator = function (callback) {
            var node = this;
            var next = [node];
            var current;
            doLoop: do {
                current = next.reverse();
                next = [];
                while (node = current.pop()) {
                    if (callback(node) === false) {
                        break doLoop;
                    }
                    var children = node.children;
                    if (children) {
                        for (var i = 0, n = children.length; i < n; ++i) {
                            next.push(children[i]);
                        }
                    }
                }
            } while (next.length);
        };
        return HierarchyNode;
    }());
    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 HierarchyNode(data);
        var nodes = [root];
        var node;
        var child, childs, i, n;
        while (node = nodes.pop()) {
            if ((childs = children(node.datum)) && (n = (childs = Array.from(childs)).length)) {
                node.children = childs;
                for (i = n - 1; i >= 0; --i) {
                    nodes.push(child = childs[i] = new HierarchyNode(childs[i]));
                    child.parent = node;
                    child.depth = node.depth + 1;
                }
            }
        }
        return root.eachBefore(computeHeight);
    }
    function computeHeight(node) {
        var height = 0;
        do {
            node.height = height;
        } while ((node = node.parent) && (node.height < ++height));
    }
    function mapChildren(d) {
        return Array.isArray(d) ? d[1] : undefined;
    }
    function objectChildren(d) {
        return d.children;
    }
    function leastCommonAncestor(a, b) {
        if (!(a && b)) {
            return undefined;
        }
        if (a === b) {
            return a;
        }
        var aNodes = a.ancestors();
        var bNodes = b.ancestors();
        var c = undefined;
        a = aNodes.pop();
        b = bNodes.pop();
        while (a === b) {
            c = a;
            a = aNodes.pop();
            b = bNodes.pop();
        }
        return c;
    }

    var __extends$O = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$e = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var TreemapSeriesTooltip = /** @class */ (function (_super) {
        __extends$O(TreemapSeriesTooltip, _super);
        function TreemapSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$e([
            reactive('change')
        ], TreemapSeriesTooltip.prototype, "renderer", void 0);
        return TreemapSeriesTooltip;
    }(SeriesTooltip));
    var TreemapSeriesLabel = /** @class */ (function (_super) {
        __extends$O(TreemapSeriesLabel, _super);
        function TreemapSeriesLabel() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.padding = 10;
            return _this;
        }
        __decorate$e([
            reactive('change')
        ], TreemapSeriesLabel.prototype, "padding", void 0);
        return TreemapSeriesLabel;
    }(Label));
    var TextNodeTag;
    (function (TextNodeTag) {
        TextNodeTag[TextNodeTag["Name"] = 0] = "Name";
        TextNodeTag[TextNodeTag["Value"] = 1] = "Value";
    })(TextNodeTag || (TextNodeTag = {}));
    var TreemapSeries = /** @class */ (function (_super) {
        __extends$O(TreemapSeries, _super);
        function TreemapSeries() {
            var _this = _super.call(this) || this;
            _this.groupSelection = Selection.select(_this.pickGroup).selectAll();
            _this.labelMap = new Map();
            _this.layout = new Treemap();
            _this.title = (function () {
                var label = new TreemapSeriesLabel();
                label.color = 'white';
                label.fontWeight = 'bold';
                label.fontSize = 12;
                label.fontFamily = 'Verdana, sans-serif';
                label.padding = 15;
                return label;
            })();
            _this.subtitle = (function () {
                var label = new TreemapSeriesLabel();
                label.color = 'white';
                label.fontSize = 9;
                label.fontFamily = 'Verdana, sans-serif';
                label.padding = 13;
                return label;
            })();
            _this.labels = {
                large: (function () {
                    var label = new Label();
                    label.color = 'white';
                    label.fontWeight = 'bold';
                    label.fontSize = 18;
                    return label;
                })(),
                medium: (function () {
                    var label = new Label();
                    label.color = 'white';
                    label.fontWeight = 'bold';
                    label.fontSize = 14;
                    return label;
                })(),
                small: (function () {
                    var label = new Label();
                    label.color = 'white';
                    label.fontWeight = 'bold';
                    label.fontSize = 10;
                    return label;
                })(),
                color: (function () {
                    var label = new Label();
                    label.color = 'white';
                    return label;
                })()
            };
            _this._nodePadding = 2;
            _this.labelKey = 'label';
            _this.sizeKey = 'size';
            _this.colorKey = 'color';
            _this.colorDomain = [-5, 5];
            _this.colorRange = ['#cb4b3f', '#6acb64'];
            _this.colorParents = false;
            _this.gradient = true;
            _this.colorName = 'Change';
            _this.rootName = 'Root';
            _this._shadow = (function () {
                var shadow = new DropShadow();
                shadow.color = 'rgba(0, 0, 0, 0.4)';
                shadow.xOffset = 1.5;
                shadow.yOffset = 1.5;
                return shadow;
            })();
            _this.tooltip = new TreemapSeriesTooltip();
            _this.shadow.addEventListener('change', _this.scheduleUpdate, _this);
            _this.title.addEventListener('change', _this.scheduleUpdate, _this);
            _this.subtitle.addEventListener('change', _this.scheduleUpdate, _this);
            _this.labels.small.addEventListener('change', _this.scheduleUpdate, _this);
            _this.labels.medium.addEventListener('change', _this.scheduleUpdate, _this);
            _this.labels.large.addEventListener('change', _this.scheduleUpdate, _this);
            _this.labels.color.addEventListener('change', _this.scheduleUpdate, _this);
            return _this;
        }
        Object.defineProperty(TreemapSeries.prototype, "nodePadding", {
            get: function () {
                return this._nodePadding;
            },
            set: function (value) {
                if (this._nodePadding !== value) {
                    this._nodePadding = value;
                    this.updateLayoutPadding();
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(TreemapSeries.prototype, "shadow", {
            get: function () {
                return this._shadow;
            },
            set: function (value) {
                if (this._shadow !== value) {
                    this._shadow = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        TreemapSeries.prototype.onHighlightChange = function () {
            this.updateNodes();
        };
        TreemapSeries.prototype.updateLayoutPadding = function () {
            var _a = this, title = _a.title, subtitle = _a.subtitle, nodePadding = _a.nodePadding, labelKey = _a.labelKey;
            this.layout.paddingRight = function (_) { return nodePadding; };
            this.layout.paddingBottom = function (_) { return nodePadding; };
            this.layout.paddingLeft = function (_) { return nodePadding; };
            this.layout.paddingTop = function (node) {
                var name = node.datum[labelKey] || '';
                if (node.children) {
                    name = name.toUpperCase();
                }
                var font = node.depth > 1 ? subtitle : title;
                var textSize = HdpiCanvas.getTextSize(name, [font.fontWeight, font.fontSize + 'px', font.fontFamily].join(' ').trim());
                var innerNodeWidth = node.x1 - node.x0 - nodePadding * 2;
                var hasTitle = node.depth > 0 && node.children && textSize.width <= innerNodeWidth;
                node.hasTitle = !!hasTitle;
                return hasTitle ? textSize.height + nodePadding * 2 : nodePadding;
            };
        };
        TreemapSeries.prototype.processData = function () {
            if (!this.data) {
                return false;
            }
            var _a = this, data = _a.data, sizeKey = _a.sizeKey, labelKey = _a.labelKey, colorKey = _a.colorKey, colorDomain = _a.colorDomain, colorRange = _a.colorRange, colorParents = _a.colorParents;
            var dataRoot;
            if (sizeKey) {
                dataRoot = hierarchy(data).sum(function (datum) { return datum.children ? 1 : datum[sizeKey]; });
            }
            else {
                dataRoot = hierarchy(data).sum(function (datum) { return datum.children ? 0 : 1; });
            }
            this.dataRoot = dataRoot;
            var colorScale = new LinearScale();
            colorScale.domain = colorDomain;
            colorScale.range = colorRange;
            var series = this;
            function traverse(root, depth) {
                if (depth === void 0) { depth = 0; }
                var children = root.children, datum = root.datum;
                var label = datum[labelKey];
                var colorValue = colorKey ? datum[colorKey] : depth;
                root.series = series;
                root.fill = !children || colorParents ? colorScale.convert(colorValue) : '#272931';
                root.colorValue = colorValue;
                if (label) {
                    root.label = children ? label.toUpperCase() : label;
                }
                else {
                    root.label = '';
                }
                if (children) {
                    children.forEach(function (child) { return traverse(child, depth + 1); });
                }
            }
            traverse(this.dataRoot);
            return true;
        };
        TreemapSeries.prototype.getLabelCenterX = function (datum) {
            return (datum.x0 + datum.x1) / 2;
        };
        TreemapSeries.prototype.getLabelCenterY = function (datum) {
            return (datum.y0 + datum.y1) / 2 + 2;
        };
        TreemapSeries.prototype.update = function () {
            this.updatePending = false;
            this.updateSelections();
            this.updateNodes();
        };
        TreemapSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            var _a = this, chart = _a.chart, dataRoot = _a.dataRoot;
            if (!chart || !dataRoot) {
                return;
            }
            var seriesRect = chart.getSeriesRect();
            if (!seriesRect) {
                return;
            }
            this.layout.size = [seriesRect.width, seriesRect.height];
            this.updateLayoutPadding();
            var descendants = this.layout.processData(dataRoot).descendants();
            var updateGroups = this.groupSelection.setData(descendants);
            updateGroups.exit.remove();
            var enterGroups = updateGroups.enter.append(Group);
            enterGroups.append(Rect);
            enterGroups.append(Text).each(function (node) { return node.tag = TextNodeTag.Name; });
            enterGroups.append(Text).each(function (node) { return node.tag = TextNodeTag.Value; });
            this.groupSelection = updateGroups.merge(enterGroups);
        };
        TreemapSeries.prototype.updateNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            var _a = this, colorKey = _a.colorKey, labelMap = _a.labelMap, nodePadding = _a.nodePadding, title = _a.title, subtitle = _a.subtitle, labels = _a.labels, shadow = _a.shadow, gradient = _a.gradient, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
            this.groupSelection.selectByClass(Rect).each(function (rect, datum) {
                var isDatumHighlighted = datum === highlightedDatum;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : datum.fill;
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : datum.depth < 2 ? undefined : 'black';
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : _this.getStrokeWidth(1, datum);
                rect.fill = fill;
                rect.stroke = stroke;
                rect.strokeWidth = strokeWidth;
                rect.crisp = true;
                rect.gradient = gradient;
                rect.x = datum.x0;
                rect.y = datum.y0;
                rect.width = datum.x1 - datum.x0;
                rect.height = datum.y1 - datum.y0;
            });
            this.groupSelection.selectByTag(TextNodeTag.Name).each(function (text, datum, index) {
                var isLeaf = !datum.children;
                var innerNodeWidth = datum.x1 - datum.x0 - nodePadding * 2;
                var innerNodeHeight = datum.y1 - datum.y0 - nodePadding * 2;
                var hasTitle = datum.hasTitle;
                var highlighted = datum === highlightedDatum;
                var label;
                if (isLeaf) {
                    if (innerNodeWidth > 40 && innerNodeHeight > 40) {
                        label = labels.large;
                    }
                    else if (innerNodeWidth > 20 && innerNodeHeight > 20) {
                        label = labels.medium;
                    }
                    else {
                        label = labels.small;
                    }
                }
                else {
                    if (datum.depth > 1) {
                        label = subtitle;
                    }
                    else {
                        label = title;
                    }
                }
                text.fontWeight = label.fontWeight;
                text.fontSize = label.fontSize;
                text.fontFamily = label.fontFamily;
                text.textBaseline = isLeaf ? 'bottom' : (hasTitle ? 'top' : 'middle');
                text.textAlign = hasTitle ? 'left' : 'center';
                text.text = datum.label;
                var textBBox = text.computeBBox();
                var hasLabel = isLeaf && !!textBBox
                    && textBBox.width <= innerNodeWidth
                    && textBBox.height * 2 + 8 <= innerNodeHeight;
                labelMap.set(index, text);
                text.fill = highlighted ? 'black' : label.color;
                text.fillShadow = hasLabel && !highlighted ? shadow : undefined;
                text.visible = hasTitle || hasLabel;
                if (hasTitle) {
                    text.x = datum.x0 + nodePadding;
                    text.y = datum.y0 + nodePadding;
                }
                else {
                    text.x = _this.getLabelCenterX(datum);
                    text.y = _this.getLabelCenterY(datum);
                }
            });
            this.groupSelection.selectByTag(TextNodeTag.Value).each(function (text, datum, index) {
                var isLeaf = !datum.children;
                var innerNodeWidth = datum.x1 - datum.x0 - nodePadding * 2;
                var highlighted = datum === highlightedDatum;
                var value = datum.colorValue;
                var label = labels.color;
                text.fontSize = label.fontSize;
                text.fontFamily = label.fontFamily;
                text.fontStyle = label.fontStyle;
                text.fontWeight = label.fontWeight;
                text.textBaseline = 'top';
                text.textAlign = 'center';
                text.text = typeof value === 'number' && isFinite(value)
                    ? String(toFixed(datum.colorValue)) + '%'
                    : '';
                var textBBox = text.computeBBox();
                var nameNode = labelMap.get(index);
                var hasLabel = !!nameNode && nameNode.visible;
                var isVisible = isLeaf && !!colorKey && hasLabel && !!textBBox && textBBox.width < innerNodeWidth;
                text.fill = highlighted ? 'black' : label.color;
                text.fillShadow = highlighted ? undefined : shadow;
                text.visible = isVisible;
                if (isVisible) {
                    text.x = _this.getLabelCenterX(datum);
                    text.y = _this.getLabelCenterY(datum);
                }
                else {
                    if (nameNode && !(datum.children && datum.children.length)) {
                        nameNode.textBaseline = 'middle';
                        nameNode.y = _this.getLabelCenterY(datum);
                    }
                }
            });
        };
        TreemapSeries.prototype.getDomain = function (direction) {
            return [0, 1];
        };
        TreemapSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                labelKey: this.labelKey,
                sizeKey: this.sizeKey,
                colorKey: this.colorKey
            });
        };
        TreemapSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var _a = this, tooltip = _a.tooltip, sizeKey = _a.sizeKey, labelKey = _a.labelKey, colorKey = _a.colorKey, colorName = _a.colorName, rootName = _a.rootName;
            var datum = nodeDatum.datum;
            var tooltipRenderer = tooltip.renderer;
            var title = nodeDatum.depth ? datum[labelKey] : (rootName || datum[labelKey]);
            var content = undefined;
            var color = nodeDatum.fill || 'gray';
            if (colorKey && colorName) {
                var colorValue = datum[colorKey];
                if (typeof colorValue === 'number' && isFinite(colorValue)) {
                    content = "<b>" + colorName + "</b>: " + toFixed(datum[colorKey]);
                }
            }
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            if (tooltipRenderer) {
                return toTooltipHtml(tooltipRenderer({
                    datum: nodeDatum,
                    sizeKey: sizeKey,
                    labelKey: labelKey,
                    colorKey: colorKey,
                    title: title,
                    color: color
                }), defaults);
            }
            return toTooltipHtml(defaults);
        };
        TreemapSeries.prototype.listSeriesItems = function (legendData) {
        };
        TreemapSeries.className = 'TreemapSeries';
        TreemapSeries.type = 'treemap';
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "labelKey", void 0);
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "sizeKey", void 0);
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "colorKey", void 0);
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "colorDomain", void 0);
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "colorRange", void 0);
        __decorate$e([
            reactive('dataChange')
        ], TreemapSeries.prototype, "colorParents", void 0);
        __decorate$e([
            reactive('update')
        ], TreemapSeries.prototype, "gradient", void 0);
        return TreemapSeries;
    }(HierarchySeries));

    var __extends$P = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var Sector = /** @class */ (function (_super) {
        __extends$P(Sector, _super);
        function Sector() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this._centerX = 0;
            _this._centerY = 0;
            _this._centerOffset = 0;
            _this._innerRadius = 10;
            _this._outerRadius = 20;
            _this._startAngle = 0;
            _this._endAngle = Math.PI * 2;
            _this._angleOffset = 0;
            return _this;
        }
        Object.defineProperty(Sector.prototype, "centerX", {
            get: function () {
                return this._centerX;
            },
            set: function (value) {
                if (this._centerX !== value) {
                    this._centerX = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "centerY", {
            get: function () {
                return this._centerY;
            },
            set: function (value) {
                if (this._centerY !== value) {
                    this._centerY = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "centerOffset", {
            get: function () {
                return this._centerOffset;
            },
            set: function (value) {
                if (this._centerOffset !== value) {
                    this._centerOffset = Math.max(0, value);
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "innerRadius", {
            get: function () {
                return this._innerRadius;
            },
            set: function (value) {
                if (this._innerRadius !== value) {
                    this._innerRadius = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "outerRadius", {
            get: function () {
                return this._outerRadius;
            },
            set: function (value) {
                if (this._outerRadius !== value) {
                    this._outerRadius = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "startAngle", {
            get: function () {
                return this._startAngle;
            },
            set: function (value) {
                if (this._startAngle !== value) {
                    this._startAngle = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "endAngle", {
            get: function () {
                return this._endAngle;
            },
            set: function (value) {
                if (this._endAngle !== value) {
                    this._endAngle = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Sector.prototype, "angleOffset", {
            get: function () {
                return this._angleOffset;
            },
            set: function (value) {
                if (this._angleOffset !== value) {
                    this._angleOffset = value;
                    this.dirtyPath = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Sector.prototype.computeBBox = function () {
            var radius = this.outerRadius;
            return new BBox(this.centerX - radius, this.centerY - radius, radius * 2, radius * 2);
        };
        Sector.prototype.isFullPie = function () {
            return isEqual(normalizeAngle360(this.startAngle), normalizeAngle360(this.endAngle));
        };
        Sector.prototype.updatePath = function () {
            var path = this.path;
            var angleOffset = this.angleOffset;
            var startAngle = Math.min(this.startAngle, this.endAngle) + angleOffset;
            var endAngle = Math.max(this.startAngle, this.endAngle) + angleOffset;
            var midAngle = (startAngle + endAngle) * 0.5;
            var innerRadius = Math.min(this.innerRadius, this.outerRadius);
            var outerRadius = Math.max(this.innerRadius, this.outerRadius);
            var centerOffset = this.centerOffset;
            var fullPie = this.isFullPie();
            var centerX = this.centerX;
            var centerY = this.centerY;
            path.clear();
            if (centerOffset) {
                centerX += centerOffset * Math.cos(midAngle);
                centerY += centerOffset * Math.sin(midAngle);
            }
            if (!fullPie) {
                path.moveTo(centerX + innerRadius * Math.cos(startAngle), centerY + innerRadius * Math.sin(startAngle));
                // if (showTip) {
                //     path.lineTo(
                //         centerX + 0.5 * (innerRadius + outerRadius) * Math.cos(startAngle) + tipOffset * Math.cos(startAngle + Math.PI / 2),
                //         centerY + 0.5 * (innerRadius + outerRadius) * Math.sin(startAngle) + tipOffset * Math.sin(startAngle + Math.PI / 2)
                //     );
                // }
                path.lineTo(centerX + outerRadius * Math.cos(startAngle), centerY + outerRadius * Math.sin(startAngle));
            }
            path.cubicArc(centerX, centerY, outerRadius, outerRadius, 0, startAngle, endAngle, 0);
            // path[fullPie ? 'moveTo' : 'lineTo'](
            //     centerX + innerRadius * Math.cos(endAngle),
            //     centerY + innerRadius * Math.sin(endAngle)
            // );
            if (fullPie) {
                path.moveTo(centerX + innerRadius * Math.cos(endAngle), centerY + innerRadius * Math.sin(endAngle));
            }
            else {
                // if (showTip) {
                //     path.lineTo(
                //         centerX + 0.5 * (innerRadius + outerRadius) * Math.cos(endAngle) + tipOffset * Math.cos(endAngle + Math.PI / 2),
                //         centerY + 0.5 * (innerRadius + outerRadius) * Math.sin(endAngle) + tipOffset * Math.sin(endAngle + Math.PI / 2)
                //     );
                // }
                // Temp workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=993330
                // Revert this commit when fixed ^^.
                var x = centerX + innerRadius * Math.cos(endAngle);
                path.lineTo(Math.abs(x) < 1e-8 ? 0 : x, centerY + innerRadius * Math.sin(endAngle));
            }
            path.cubicArc(centerX, centerY, innerRadius, innerRadius, 0, endAngle, startAngle, 1);
            path.closePath();
            this.dirtyPath = false;
        };
        Sector.className = 'Sector';
        return Sector;
    }(Path));

    var __extends$Q = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __decorate$f = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __read$f = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$5 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$f(arguments[i]));
        return ar;
    };
    var PieHighlightStyle = /** @class */ (function (_super) {
        __extends$Q(PieHighlightStyle, _super);
        function PieHighlightStyle() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return PieHighlightStyle;
    }(HighlightStyle));
    var PieNodeTag;
    (function (PieNodeTag) {
        PieNodeTag[PieNodeTag["Sector"] = 0] = "Sector";
        PieNodeTag[PieNodeTag["Callout"] = 1] = "Callout";
        PieNodeTag[PieNodeTag["Label"] = 2] = "Label";
    })(PieNodeTag || (PieNodeTag = {}));
    var PieSeriesLabel = /** @class */ (function (_super) {
        __extends$Q(PieSeriesLabel, _super);
        function PieSeriesLabel() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.offset = 3; // from the callout line
            _this.minAngle = 20; // in degrees
            return _this;
        }
        __decorate$f([
            reactive('change')
        ], PieSeriesLabel.prototype, "offset", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeriesLabel.prototype, "minAngle", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeriesLabel.prototype, "formatter", void 0);
        return PieSeriesLabel;
    }(Label));
    var PieSeriesCallout = /** @class */ (function (_super) {
        __extends$Q(PieSeriesCallout, _super);
        function PieSeriesCallout() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.colors = [
                '#874349',
                '#718661',
                '#a48f5f',
                '#5a7088',
                '#7f637a',
                '#5d8692'
            ];
            _this.length = 10;
            _this.strokeWidth = 1;
            return _this;
        }
        __decorate$f([
            reactive('change')
        ], PieSeriesCallout.prototype, "colors", void 0);
        __decorate$f([
            reactive('change')
        ], PieSeriesCallout.prototype, "length", void 0);
        __decorate$f([
            reactive('change')
        ], PieSeriesCallout.prototype, "strokeWidth", void 0);
        return PieSeriesCallout;
    }(Observable));
    var PieSeriesTooltip = /** @class */ (function (_super) {
        __extends$Q(PieSeriesTooltip, _super);
        function PieSeriesTooltip() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        __decorate$f([
            reactive('change')
        ], PieSeriesTooltip.prototype, "renderer", void 0);
        return PieSeriesTooltip;
    }(SeriesTooltip));
    var PieTitle = /** @class */ (function (_super) {
        __extends$Q(PieTitle, _super);
        function PieTitle() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.showInLegend = false;
            return _this;
        }
        __decorate$f([
            reactive()
        ], PieTitle.prototype, "showInLegend", void 0);
        return PieTitle;
    }(Caption));
    var PieSeries = /** @class */ (function (_super) {
        __extends$Q(PieSeries, _super);
        function PieSeries() {
            var _this = _super.call(this) || this;
            _this.radiusScale = new LinearScale();
            _this.groupSelection = Selection.select(_this.pickGroup).selectAll();
            /**
             * The processed data that gets visualized.
             */
            _this.groupSelectionData = [];
            _this.angleScale = (function () {
                var scale = new LinearScale();
                // Each slice is a ratio of the whole, where all ratios add up to 1.
                scale.domain = [0, 1];
                // Add 90 deg to start the first pie at 12 o'clock.
                scale.range = [-Math.PI, Math.PI].map(function (angle) { return angle + Math.PI / 2; });
                return scale;
            })();
            // When a user toggles a series item (e.g. from the legend), its boolean state is recorded here.
            _this.seriesItemEnabled = [];
            _this.label = new PieSeriesLabel();
            _this.callout = new PieSeriesCallout();
            _this.tooltip = new PieSeriesTooltip();
            /**
             * The key of the numeric field to use to determine the angle (for example,
             * a pie slice angle).
             */
            _this.angleKey = '';
            _this.angleName = '';
            _this._fills = [
                '#c16068',
                '#a2bf8a',
                '#ebcc87',
                '#80a0c3',
                '#b58dae',
                '#85c0d1'
            ];
            _this._strokes = [
                '#874349',
                '#718661',
                '#a48f5f',
                '#5a7088',
                '#7f637a',
                '#5d8692'
            ];
            _this.fillOpacity = 1;
            _this.strokeOpacity = 1;
            _this.lineDash = [0];
            _this.lineDashOffset = 0;
            /**
             * The series rotation in degrees.
             */
            _this.rotation = 0;
            _this.outerRadiusOffset = 0;
            _this.innerRadiusOffset = 0;
            _this.strokeWidth = 1;
            _this.highlightStyle = new PieHighlightStyle();
            _this.addEventListener('update', _this.scheduleUpdate, _this);
            _this.label.addEventListener('change', _this.scheduleUpdate, _this);
            _this.label.addEventListener('dataChange', _this.scheduleData, _this);
            _this.callout.addEventListener('change', _this.scheduleLayout, _this);
            _this.addPropertyListener('data', function (event) {
                if (event.value) {
                    event.source.seriesItemEnabled = event.value.map(function () { return true; });
                }
            });
            return _this;
        }
        Object.defineProperty(PieSeries.prototype, "title", {
            get: function () {
                return this._title;
            },
            set: function (value) {
                var oldTitle = this._title;
                function updateLegend() {
                    this.fireEvent({ type: 'legendChange' });
                }
                if (oldTitle !== value) {
                    if (oldTitle) {
                        oldTitle.removeEventListener('change', this.scheduleUpdate, this);
                        oldTitle.addPropertyListener('showInLegend', updateLegend, this);
                        this.group.removeChild(oldTitle.node);
                    }
                    if (value) {
                        value.node.textBaseline = 'bottom';
                        value.addEventListener('change', this.scheduleUpdate, this);
                        value.addPropertyListener('showInLegend', updateLegend, this);
                        this.group.appendChild(value.node);
                    }
                    this._title = value;
                    this.scheduleUpdate();
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(PieSeries.prototype, "fills", {
            get: function () {
                return this._fills;
            },
            set: function (values) {
                this._fills = values;
                this.scheduleUpdate();
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(PieSeries.prototype, "strokes", {
            get: function () {
                return this._strokes;
            },
            set: function (values) {
                this._strokes = values;
                this.scheduleUpdate();
            },
            enumerable: true,
            configurable: true
        });
        PieSeries.prototype.onHighlightChange = function () {
            this.updateNodes();
        };
        PieSeries.prototype.setColors = function (fills, strokes) {
            this.fills = fills;
            this.strokes = strokes;
            this.callout.colors = strokes;
        };
        PieSeries.prototype.getDomain = function (direction) {
            if (direction === exports.ChartAxisDirection.X) {
                return this.angleScale.domain;
            }
            else {
                return this.radiusScale.domain;
            }
        };
        PieSeries.prototype.processData = function () {
            var _this = this;
            var _a = this, angleKey = _a.angleKey, radiusKey = _a.radiusKey, seriesItemEnabled = _a.seriesItemEnabled, angleScale = _a.angleScale, groupSelectionData = _a.groupSelectionData, label = _a.label;
            var data = angleKey && this.data ? this.data : [];
            var angleData = data.map(function (datum, index) { return seriesItemEnabled[index] && Math.abs(+datum[angleKey]) || 0; });
            var angleDataTotal = angleData.reduce(function (a, b) { return a + b; }, 0);
            // The ratios (in [0, 1] interval) used to calculate the end angle value for every pie slice.
            // Each slice starts where the previous one ends, so we only keep the ratios for end angles.
            var angleDataRatios = (function () {
                var sum = 0;
                return angleData.map(function (datum) { return sum += datum / angleDataTotal; });
            })();
            var labelFormatter = label.formatter;
            var labelKey = label.enabled && this.labelKey;
            var labelData = [];
            var radiusData = [];
            if (labelKey) {
                if (labelFormatter) {
                    labelData = data.map(function (datum) { return labelFormatter({ value: datum[labelKey] }); });
                }
                else {
                    labelData = data.map(function (datum) { return String(datum[labelKey]); });
                }
            }
            if (radiusKey) {
                var _b = this, radiusMin = _b.radiusMin, radiusMax = _b.radiusMax;
                var radii = data.map(function (datum) { return Math.abs(datum[radiusKey]); });
                var min_1 = radiusMin !== undefined ? radiusMin : Math.min.apply(Math, __spread$5(radii));
                var max = radiusMax !== undefined ? radiusMax : Math.max.apply(Math, __spread$5(radii));
                var delta_1 = max - min_1;
                radiusData = radii.map(function (value) { return delta_1 ? (value - min_1) / delta_1 : 1; });
            }
            groupSelectionData.length = 0;
            var rotation = toRadians(this.rotation);
            var halfPi = Math.PI / 2;
            var datumIndex = 0;
            // Simply use reduce here to pair up adjacent ratios.
            angleDataRatios.reduce(function (start, end) {
                var radius = radiusKey ? radiusData[datumIndex] : 1;
                var startAngle = angleScale.convert(start) + rotation;
                var endAngle = angleScale.convert(end) + rotation;
                var midAngle = (startAngle + endAngle) / 2;
                var span = Math.abs(endAngle - startAngle);
                var midCos = Math.cos(midAngle);
                var midSin = Math.sin(midAngle);
                var labelMinAngle = toRadians(label.minAngle);
                var labelVisible = labelKey && span > labelMinAngle;
                var midAngle180 = normalizeAngle180(midAngle);
                // Split the circle into quadrants like so: ⊗
                var quadrantStart = -3 * Math.PI / 4; // same as `normalizeAngle180(toRadians(-135))`
                var textAlign;
                var textBaseline;
                if (midAngle180 >= quadrantStart && midAngle180 < (quadrantStart += halfPi)) {
                    textAlign = 'center';
                    textBaseline = 'bottom';
                }
                else if (midAngle180 >= quadrantStart && midAngle180 < (quadrantStart += halfPi)) {
                    textAlign = 'left';
                    textBaseline = 'middle';
                }
                else if (midAngle180 >= quadrantStart && midAngle180 < (quadrantStart += halfPi)) {
                    textAlign = 'center';
                    textBaseline = 'hanging';
                }
                else {
                    textAlign = 'right';
                    textBaseline = 'middle';
                }
                groupSelectionData.push({
                    series: _this,
                    datum: data[datumIndex],
                    itemId: datumIndex,
                    index: datumIndex,
                    radius: radius,
                    startAngle: startAngle,
                    endAngle: endAngle,
                    midAngle: midAngle,
                    midCos: midCos,
                    midSin: midSin,
                    label: labelVisible ? {
                        text: labelData[datumIndex],
                        textAlign: textAlign,
                        textBaseline: textBaseline
                    } : undefined
                });
                datumIndex++;
                return end;
            }, 0);
            return true;
        };
        PieSeries.prototype.update = function () {
            this.updatePending = false;
            var _a = this, radius = _a.radius, innerRadiusOffset = _a.innerRadiusOffset, outerRadiusOffset = _a.outerRadiusOffset, title = _a.title;
            this.radiusScale.range = [
                innerRadiusOffset ? radius + innerRadiusOffset : 0,
                radius + (outerRadiusOffset || 0)
            ];
            this.group.translationX = this.centerX;
            this.group.translationY = this.centerY;
            if (title) {
                var outerRadius = Math.max(0, this.radiusScale.range[1]);
                if (outerRadius === 0) {
                    title.node.visible = false;
                }
                else {
                    title.node.translationY = -radius - outerRadiusOffset - 2;
                    title.node.visible = title.enabled;
                }
            }
            this.updateSelections();
            this.updateNodes();
        };
        PieSeries.prototype.updateSelections = function () {
            if (!this.nodeDataPending) {
                return;
            }
            this.nodeDataPending = false;
            this.updateGroupSelection();
        };
        PieSeries.prototype.updateGroupSelection = function () {
            var updateGroups = this.groupSelection.setData(this.groupSelectionData);
            updateGroups.exit.remove();
            var enterGroups = updateGroups.enter.append(Group);
            enterGroups.append(Sector).each(function (node) { return node.tag = PieNodeTag.Sector; });
            enterGroups.append(Line).each(function (node) {
                node.tag = PieNodeTag.Callout;
                node.pointerEvents = PointerEvents.None;
            });
            enterGroups.append(Text).each(function (node) {
                node.tag = PieNodeTag.Label;
                node.pointerEvents = PointerEvents.None;
            });
            this.groupSelection = updateGroups.merge(enterGroups);
        };
        PieSeries.prototype.updateNodes = function () {
            var _this = this;
            if (!this.chart) {
                return;
            }
            this.group.visible = this.visible && this.seriesItemEnabled.indexOf(true) >= 0;
            var _a = this, fills = _a.fills, strokes = _a.strokes, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity, radiusScale = _a.radiusScale, callout = _a.callout, shadow = _a.shadow, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f, angleKey = _a.angleKey, radiusKey = _a.radiusKey, formatter = _a.formatter;
            var centerOffsets = [];
            var innerRadius = radiusScale.convert(0);
            this.groupSelection.selectByTag(PieNodeTag.Sector).each(function (sector, datum, index) {
                var radius = radiusScale.convert(datum.radius);
                var isDatumHighlighted = !!highlightedDatum && highlightedDatum.series === _this && datum.itemId === highlightedDatum.itemId;
                var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : fills[index % fills.length];
                var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : strokes[index % strokes.length];
                var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
                    ? highlightedDatumStrokeWidth
                    : _this.getStrokeWidth(_this.strokeWidth);
                var format = undefined;
                if (formatter) {
                    format = formatter({
                        datum: datum.datum,
                        angleKey: angleKey,
                        radiusKey: radiusKey,
                        fill: fill,
                        stroke: stroke,
                        strokeWidth: strokeWidth,
                        highlighted: isDatumHighlighted
                    });
                }
                // Bring highlighted slice's parent group to front.
                var parent = sector.parent && sector.parent.parent;
                if (isDatumHighlighted && parent) {
                    parent.removeChild(sector.parent);
                    parent.appendChild(sector.parent);
                }
                sector.innerRadius = Math.max(0, innerRadius);
                sector.outerRadius = Math.max(0, radius);
                sector.startAngle = datum.startAngle;
                sector.endAngle = datum.endAngle;
                sector.fill = format && format.fill || fill;
                sector.stroke = format && format.stroke || stroke;
                sector.strokeWidth = format && format.strokeWidth !== undefined ? format.strokeWidth : strokeWidth;
                sector.fillOpacity = fillOpacity;
                sector.strokeOpacity = strokeOpacity;
                sector.lineDash = _this.lineDash;
                sector.lineDashOffset = _this.lineDashOffset;
                sector.fillShadow = shadow;
                sector.lineJoin = 'round';
                sector.opacity = _this.getOpacity();
                centerOffsets.push(sector.centerOffset);
            });
            var calloutColors = callout.colors, calloutLength = callout.length, calloutStrokeWidth = callout.strokeWidth;
            this.groupSelection.selectByTag(PieNodeTag.Callout).each(function (line, datum, index) {
                var radius = radiusScale.convert(datum.radius);
                var outerRadius = Math.max(0, radius);
                if (datum.label && outerRadius !== 0) {
                    line.strokeWidth = calloutStrokeWidth;
                    line.stroke = calloutColors[index % calloutColors.length];
                    line.x1 = datum.midCos * outerRadius;
                    line.y1 = datum.midSin * outerRadius;
                    line.x2 = datum.midCos * (outerRadius + calloutLength);
                    line.y2 = datum.midSin * (outerRadius + calloutLength);
                }
                else {
                    line.stroke = undefined;
                }
            });
            {
                var _g = this.label, offset_1 = _g.offset, fontStyle_1 = _g.fontStyle, fontWeight_1 = _g.fontWeight, fontSize_1 = _g.fontSize, fontFamily_1 = _g.fontFamily, color_1 = _g.color;
                this.groupSelection.selectByTag(PieNodeTag.Label).each(function (text, datum, index) {
                    var label = datum.label;
                    var radius = radiusScale.convert(datum.radius);
                    var outerRadius = Math.max(0, radius);
                    if (label && outerRadius !== 0) {
                        var labelRadius = centerOffsets[index] + outerRadius + calloutLength + offset_1;
                        text.fontStyle = fontStyle_1;
                        text.fontWeight = fontWeight_1;
                        text.fontSize = fontSize_1;
                        text.fontFamily = fontFamily_1;
                        text.text = label.text;
                        text.x = datum.midCos * labelRadius;
                        text.y = datum.midSin * labelRadius;
                        text.fill = color_1;
                        text.textAlign = label.textAlign;
                        text.textBaseline = label.textBaseline;
                    }
                    else {
                        text.fill = undefined;
                    }
                });
            }
        };
        PieSeries.prototype.fireNodeClickEvent = function (event, datum) {
            this.fireEvent({
                type: 'nodeClick',
                event: event,
                series: this,
                datum: datum.datum,
                angleKey: this.angleKey,
                labelKey: this.labelKey,
                radiusKey: this.radiusKey
            });
        };
        PieSeries.prototype.getTooltipHtml = function (nodeDatum) {
            var angleKey = this.angleKey;
            if (!angleKey) {
                return '';
            }
            var _a = this, fills = _a.fills, tooltip = _a.tooltip, angleName = _a.angleName, radiusKey = _a.radiusKey, radiusName = _a.radiusName, labelKey = _a.labelKey, labelName = _a.labelName;
            var tooltipRenderer = tooltip.renderer;
            var color = fills[nodeDatum.index % fills.length];
            var datum = nodeDatum.datum;
            var label = labelKey ? datum[labelKey] + ": " : '';
            var angleValue = datum[angleKey];
            var formattedAngleValue = typeof angleValue === 'number' ? toFixed(angleValue) : angleValue.toString();
            var title = this.title ? this.title.text : undefined;
            var content = label + formattedAngleValue;
            var defaults = {
                title: title,
                backgroundColor: color,
                content: content
            };
            if (tooltipRenderer) {
                return toTooltipHtml(tooltipRenderer({
                    datum: datum,
                    angleKey: angleKey,
                    angleValue: angleValue,
                    angleName: angleName,
                    radiusKey: radiusKey,
                    radiusValue: radiusKey ? datum[radiusKey] : undefined,
                    radiusName: radiusName,
                    labelKey: labelKey,
                    labelName: labelName,
                    title: title,
                    color: color,
                }), defaults);
            }
            return toTooltipHtml(defaults);
        };
        PieSeries.prototype.listSeriesItems = function (legendData) {
            var _this = this;
            var _a = this, labelKey = _a.labelKey, data = _a.data;
            if (data && data.length && labelKey) {
                var _b = this, fills_1 = _b.fills, strokes_1 = _b.strokes, id_1 = _b.id;
                var titleText_1 = this.title && this.title.showInLegend && this.title.text;
                data.forEach(function (datum, index) {
                    var labelParts = [];
                    titleText_1 && labelParts.push(titleText_1);
                    labelParts.push(String(datum[labelKey]));
                    legendData.push({
                        id: id_1,
                        itemId: index,
                        enabled: _this.seriesItemEnabled[index],
                        label: {
                            text: labelParts.join(' - ')
                        },
                        marker: {
                            fill: fills_1[index % fills_1.length],
                            stroke: strokes_1[index % strokes_1.length],
                            fillOpacity: _this.fillOpacity,
                            strokeOpacity: _this.strokeOpacity
                        }
                    });
                });
            }
        };
        PieSeries.prototype.toggleSeriesItem = function (itemId, enabled) {
            this.seriesItemEnabled[itemId] = enabled;
            this.scheduleData();
        };
        PieSeries.className = 'PieSeries';
        PieSeries.type = 'pie';
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "angleKey", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "angleName", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "radiusKey", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "radiusName", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "radiusMin", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "radiusMax", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "labelKey", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "labelName", void 0);
        __decorate$f([
            reactive('layoutChange')
        ], PieSeries.prototype, "fillOpacity", void 0);
        __decorate$f([
            reactive('layoutChange')
        ], PieSeries.prototype, "strokeOpacity", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "lineDash", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "lineDashOffset", void 0);
        __decorate$f([
            reactive('update')
        ], PieSeries.prototype, "formatter", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "rotation", void 0);
        __decorate$f([
            reactive('layoutChange')
        ], PieSeries.prototype, "outerRadiusOffset", void 0);
        __decorate$f([
            reactive('dataChange')
        ], PieSeries.prototype, "innerRadiusOffset", void 0);
        __decorate$f([
            reactive('layoutChange')
        ], PieSeries.prototype, "strokeWidth", void 0);
        __decorate$f([
            reactive('layoutChange')
        ], PieSeries.prototype, "shadow", void 0);
        return PieSeries;
    }(PolarSeries));

    function floor$9(date) {
        date.setUTCSeconds(0, 0);
    }
    function offset$9(date, minutes) {
        date.setTime(date.getTime() + minutes * durationMinute);
    }
    function count$9(start, end) {
        return (end.getTime() - start.getTime()) / durationMinute;
    }
    function field$7(date) {
        return date.getUTCMinutes();
    }
    var utcMinute = new CountableTimeInterval(floor$9, offset$9, count$9, field$7);

    function floor$a(date) {
        date.setUTCMinutes(0, 0, 0);
    }
    function offset$a(date, hours) {
        date.setTime(date.getTime() + hours * durationHour);
    }
    function count$a(start, end) {
        return (end.getTime() - start.getTime()) / durationHour;
    }
    function field$8(date) {
        return date.getUTCHours();
    }
    var utcHour = new CountableTimeInterval(floor$a, offset$a, count$a, field$8);

    function floor$b(date) {
        date.setUTCDate(1);
        date.setUTCHours(0, 0, 0, 0);
    }
    function offset$b(date, months) {
        date.setUTCMonth(date.getUTCMonth() + months);
    }
    function count$b(start, end) {
        return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
    }
    function field$9(date) {
        return date.getUTCMonth();
    }
    var utcMonth = new CountableTimeInterval(floor$b, offset$b, count$b, field$9);

    var __assign$3 = (undefined && undefined.__assign) || function () {
        __assign$3 = Object.assign || function(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$3.apply(this, arguments);
    };
    var palette = {
        fills: [
            '#f3622d',
            '#fba71b',
            '#57b757',
            '#41a9c9',
            '#4258c9',
            '#9a42c8',
            '#c84164',
            '#888888'
        ],
        strokes: [
            '#aa4520',
            '#b07513',
            '#3d803d',
            '#2d768d',
            '#2e3e8d',
            '#6c2e8c',
            '#8c2d46',
            '#5f5f5f'
        ]
    };
    function arrayMerge(target, source, options) {
        return source;
    }
    function isMergeableObject(value) {
        return defaultIsMergeableObject(value) && !(value instanceof TimeInterval);
    }
    var mergeOptions = { arrayMerge: arrayMerge, isMergeableObject: isMergeableObject };
    var ChartTheme = /** @class */ (function () {
        function ChartTheme(options) {
            var defaults = this.createChartConfigPerSeries(this.getDefaults());
            if (isObject(options)) {
                options = deepMerge({}, options, mergeOptions);
                var overrides_1 = options.overrides;
                if (overrides_1) {
                    if (isObject(overrides_1.common)) {
                        ChartTheme.seriesTypes.concat(['cartesian', 'polar', 'hierarchy']).forEach(function (seriesType) {
                            defaults[seriesType] = deepMerge(defaults[seriesType], overrides_1.common, mergeOptions);
                        });
                    }
                    if (overrides_1.cartesian) {
                        defaults.cartesian = deepMerge(defaults.cartesian, overrides_1.cartesian, mergeOptions);
                        ChartTheme.cartesianSeriesTypes.forEach(function (seriesType) {
                            defaults[seriesType] = deepMerge(defaults[seriesType], overrides_1.cartesian, mergeOptions);
                        });
                    }
                    if (overrides_1.polar) {
                        defaults.polar = deepMerge(defaults.polar, overrides_1.polar, mergeOptions);
                        ChartTheme.polarSeriesTypes.forEach(function (seriesType) {
                            defaults[seriesType] = deepMerge(defaults[seriesType], overrides_1.polar, mergeOptions);
                        });
                    }
                    if (overrides_1.hierarchy) {
                        defaults.hierarchy = deepMerge(defaults.hierarchy, overrides_1.hierarchy, mergeOptions);
                        ChartTheme.hierarchySeriesTypes.forEach(function (seriesType) {
                            defaults[seriesType] = deepMerge(defaults[seriesType], overrides_1.hierarchy, mergeOptions);
                        });
                    }
                    ChartTheme.seriesTypes.forEach(function (seriesType) {
                        var _a;
                        var chartConfig = overrides_1[seriesType];
                        if (chartConfig) {
                            if (chartConfig.series) {
                                chartConfig.series = (_a = {}, _a[seriesType] = chartConfig.series, _a);
                            }
                            defaults[seriesType] = deepMerge(defaults[seriesType], chartConfig, mergeOptions);
                        }
                    });
                }
            }
            this.palette = options && options.palette ? options.palette : this.getPalette();
            this.config = Object.freeze(defaults);
        }
        ChartTheme.prototype.getPalette = function () {
            return palette;
        };
        ChartTheme.getAxisDefaults = function () {
            return {
                top: {},
                right: {},
                bottom: {},
                left: {},
                thickness: 0,
                title: {
                    padding: {
                        top: 10,
                        right: 10,
                        bottom: 10,
                        left: 10
                    },
                    text: 'Axis Title',
                    fontStyle: undefined,
                    fontWeight: 'bold',
                    fontSize: 12,
                    fontFamily: this.fontFamily,
                    color: 'rgb(70, 70, 70)'
                },
                label: {
                    fontStyle: undefined,
                    fontWeight: undefined,
                    fontSize: 12,
                    fontFamily: this.fontFamily,
                    padding: 5,
                    rotation: 0,
                    color: 'rgb(87, 87, 87)',
                    formatter: undefined
                },
                line: {
                    width: 1,
                    color: 'rgb(195, 195, 195)'
                },
                tick: {
                    width: 1,
                    size: 6,
                    color: 'rgb(195, 195, 195)',
                    count: 10
                },
                gridStyle: [{
                        stroke: 'rgb(219, 219, 219)',
                        lineDash: [4, 2]
                    }]
            };
        };
        ChartTheme.getSeriesDefaults = function () {
            return {
                tooltip: {
                    enabled: true,
                    renderer: undefined
                },
                visible: true,
                showInLegend: true,
                cursor: 'default',
                highlightStyle: {
                    item: {
                        fill: 'yellow'
                    },
                    series: {
                        dimOpacity: 1
                    }
                }
            };
        };
        ChartTheme.getBarSeriesDefaults = function () {
            return __assign$3(__assign$3({}, this.getSeriesDefaults()), { flipXY: false, fillOpacity: 1, strokeOpacity: 1, xKey: '', xName: '', yKeys: [], yNames: [], grouped: false, normalizedTo: undefined, strokeWidth: 1, lineDash: [0], lineDashOffset: 0, label: {
                    enabled: false,
                    fontStyle: undefined,
                    fontWeight: undefined,
                    fontSize: 12,
                    fontFamily: this.fontFamily,
                    color: 'rgb(70, 70, 70)',
                    formatter: undefined,
                    placement: 'inside'
                }, shadow: {
                    enabled: false,
                    color: 'rgba(0, 0, 0, 0.5)',
                    xOffset: 3,
                    yOffset: 3,
                    blur: 5
                } });
        };
        ChartTheme.getCartesianSeriesMarkerDefaults = function () {
            return {
                enabled: true,
                shape: 'circle',
                size: 6,
                maxSize: 30,
                strokeWidth: 1,
                formatter: undefined
            };
        };
        ChartTheme.getChartDefaults = function () {
            return {
                width: 600,
                height: 300,
                autoSize: true,
                background: {
                    visible: true,
                    fill: 'white'
                },
                padding: {
                    top: 20,
                    right: 20,
                    bottom: 20,
                    left: 20
                },
                title: {
                    enabled: false,
                    padding: {
                        top: 10,
                        right: 10,
                        bottom: 10,
                        left: 10
                    },
                    text: 'Title',
                    fontStyle: undefined,
                    fontWeight: 'bold',
                    fontSize: 16,
                    fontFamily: this.fontFamily,
                    color: 'rgb(70, 70, 70)'
                },
                subtitle: {
                    enabled: false,
                    padding: {
                        top: 10,
                        right: 10,
                        bottom: 10,
                        left: 10
                    },
                    text: 'Subtitle',
                    fontStyle: undefined,
                    fontWeight: undefined,
                    fontSize: 12,
                    fontFamily: this.fontFamily,
                    color: 'rgb(140, 140, 140)'
                },
                legend: {
                    enabled: true,
                    position: 'right',
                    spacing: 20,
                    item: {
                        paddingX: 16,
                        paddingY: 8,
                        marker: {
                            shape: undefined,
                            size: 15,
                            strokeWidth: 1,
                            padding: 8
                        },
                        label: {
                            color: 'black',
                            fontStyle: undefined,
                            fontWeight: undefined,
                            fontSize: 12,
                            fontFamily: this.fontFamily,
                            formatter: undefined
                        }
                    }
                },
                tooltip: {
                    enabled: true,
                    tracking: true,
                    delay: 0,
                    class: Chart.defaultTooltipClass
                }
            };
        };
        ChartTheme.prototype.createChartConfigPerSeries = function (config) {
            var typeToAliases = {
                cartesian: ChartTheme.cartesianSeriesTypes,
                polar: ChartTheme.polarSeriesTypes
            };
            var _loop_1 = function (type) {
                typeToAliases[type].forEach(function (alias) {
                    if (!config[alias]) {
                        config[alias] = deepMerge({}, config[type], mergeOptions);
                    }
                });
            };
            for (var type in typeToAliases) {
                _loop_1(type);
            }
            return config;
        };
        ChartTheme.prototype.getConfig = function (path, defaultValue) {
            var value = getValue(this.config, path, defaultValue);
            if (Array.isArray(value)) {
                return deepMerge([], value, mergeOptions);
            }
            if (isObject(value)) {
                return deepMerge({}, value, mergeOptions);
            }
            return value;
        };
        /**
         * Meant to be overridden in subclasses. For example:
         * ```
         *     getDefaults() {
         *         const subclassDefaults = { ... };
         *         return this.mergeWithParentDefaults(subclassDefaults);
         *     }
         * ```
         */
        ChartTheme.prototype.getDefaults = function () {
            return deepMerge({}, ChartTheme.defaults, mergeOptions);
        };
        ChartTheme.prototype.mergeWithParentDefaults = function (defaults) {
            var proto = Object.getPrototypeOf(Object.getPrototypeOf(this));
            if (proto === Object.prototype) {
                var config = deepMerge({}, ChartTheme.defaults, mergeOptions);
                config = deepMerge(config, defaults, mergeOptions);
                return config;
            }
            var parentDefaults = proto.getDefaults();
            return deepMerge(parentDefaults, defaults, mergeOptions);
        };
        ChartTheme.prototype.setSeriesColors = function (series, seriesOptions, firstColorIndex) {
            var palette = this.palette;
            var colorCount = this.getSeriesColorCount(seriesOptions);
            if (colorCount === Infinity || colorCount === 0) {
                series.setColors(palette.fills, palette.strokes);
            }
            else {
                var fills = copy(palette.fills, firstColorIndex, colorCount);
                var strokes = copy(palette.strokes, firstColorIndex, colorCount);
                series.setColors(fills, strokes);
                firstColorIndex += colorCount;
            }
            return firstColorIndex;
        };
        ChartTheme.prototype.getYKeyCount = function (yKeys) {
            if (!Array.isArray(yKeys)) {
                return 0;
            }
            var count = 0;
            yKeys.forEach(function (key) {
                if (Array.isArray(key)) {
                    count += key.length;
                }
                else {
                    count += 1;
                }
            });
            return count;
        };
        /**
         * This would typically correspond to the number of dependent variables the series plots.
         * If the color count is not fixed, for example it's data-dependent with one color per data point,
         * return Infinity to fetch all unique colors and manage them in the series.
         */
        ChartTheme.prototype.getSeriesColorCount = function (seriesOptions) {
            var type = seriesOptions.type;
            switch (type) {
                case 'bar':
                case 'column':
                case 'area':
                    return this.getYKeyCount(seriesOptions.yKeys);
                case 'pie':
                    return Infinity;
                default:
                    return 1;
            }
        };
        ChartTheme.fontFamily = 'Verdana, sans-serif';
        ChartTheme.cartesianDefaults = __assign$3(__assign$3({}, ChartTheme.getChartDefaults()), { axes: {
                number: __assign$3({}, ChartTheme.getAxisDefaults()),
                log: __assign$3(__assign$3({}, ChartTheme.getAxisDefaults()), { base: 10 }),
                category: __assign$3({}, ChartTheme.getAxisDefaults()),
                groupedCategory: __assign$3({}, ChartTheme.getAxisDefaults()),
                time: __assign$3({}, ChartTheme.getAxisDefaults())
            }, series: {
                column: __assign$3(__assign$3({}, ChartTheme.getBarSeriesDefaults()), { flipXY: false }),
                bar: __assign$3(__assign$3({}, ChartTheme.getBarSeriesDefaults()), { flipXY: true }),
                line: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { title: undefined, xKey: '', xName: '', yKey: '', yName: '', strokeWidth: 2, strokeOpacity: 1, lineDash: [0], lineDashOffset: 0, marker: __assign$3({}, ChartTheme.getCartesianSeriesMarkerDefaults()), label: {
                        enabled: false,
                        fontStyle: undefined,
                        fontWeight: undefined,
                        fontSize: 12,
                        fontFamily: ChartTheme.fontFamily,
                        color: 'rgb(70, 70, 70)',
                        formatter: undefined
                    } }),
                scatter: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { title: undefined, xKey: '', yKey: '', sizeKey: undefined, labelKey: undefined, xName: '', yName: '', sizeName: 'Size', labelName: 'Label', strokeWidth: 2, fillOpacity: 1, strokeOpacity: 1, marker: __assign$3({}, ChartTheme.getCartesianSeriesMarkerDefaults()), label: {
                        enabled: false,
                        fontStyle: undefined,
                        fontWeight: undefined,
                        fontSize: 12,
                        fontFamily: ChartTheme.fontFamily,
                        color: 'rgb(70, 70, 70)'
                    } }),
                area: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { title: undefined, xKey: '', xName: '', yKeys: [], yNames: [], normalizedTo: undefined, fillOpacity: 0.8, strokeOpacity: 1, strokeWidth: 2, lineDash: [0], lineDashOffset: 0, shadow: {
                        enabled: false,
                        color: 'rgba(0, 0, 0, 0.5)',
                        xOffset: 3,
                        yOffset: 3,
                        blur: 5
                    }, marker: __assign$3(__assign$3({}, ChartTheme.getCartesianSeriesMarkerDefaults()), { enabled: false }), label: {
                        enabled: false,
                        fontStyle: undefined,
                        fontWeight: undefined,
                        fontSize: 12,
                        fontFamily: ChartTheme.fontFamily,
                        color: 'rgb(70, 70, 70)',
                        formatter: undefined
                    } }),
                histogram: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { title: undefined, xKey: '', yKey: '', xName: '', yName: '', strokeWidth: 1, fillOpacity: 1, strokeOpacity: 1, lineDash: [0], lineDashOffset: 0, areaPlot: false, binCount: 10, bins: undefined, aggregation: 'sum', label: {
                        enabled: false,
                        fontStyle: undefined,
                        fontWeight: undefined,
                        fontSize: 12,
                        fontFamily: ChartTheme.fontFamily,
                        color: 'rgb(70, 70, 70)',
                        formatter: undefined
                    } })
            }, navigator: {
                enabled: false,
                height: 30,
                mask: {
                    fill: '#999999',
                    stroke: '#999999',
                    strokeWidth: 1,
                    fillOpacity: 0.2
                },
                minHandle: {
                    fill: '#f2f2f2',
                    stroke: '#999999',
                    strokeWidth: 1,
                    width: 8,
                    height: 16,
                    gripLineGap: 2,
                    gripLineLength: 8
                },
                maxHandle: {
                    fill: '#f2f2f2',
                    stroke: '#999999',
                    strokeWidth: 1,
                    width: 8,
                    height: 16,
                    gripLineGap: 2,
                    gripLineLength: 8
                }
            } });
        ChartTheme.defaults = {
            cartesian: ChartTheme.cartesianDefaults,
            groupedCategory: ChartTheme.cartesianDefaults,
            polar: __assign$3(__assign$3({}, ChartTheme.getChartDefaults()), { series: {
                    pie: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { title: {
                            enabled: true,
                            showInLegend: false,
                            padding: new Padding(0),
                            text: '',
                            fontStyle: undefined,
                            fontWeight: 'bold',
                            fontSize: 14,
                            fontFamily: ChartTheme.fontFamily,
                            color: 'rgb(70, 70, 70)'
                        }, angleKey: '', angleName: '', radiusKey: undefined, radiusName: undefined, labelKey: undefined, labelName: undefined, label: {
                            enabled: true,
                            fontStyle: undefined,
                            fontWeight: undefined,
                            fontSize: 12,
                            fontFamily: ChartTheme.fontFamily,
                            color: 'rgb(70, 70, 70)',
                            offset: 3,
                            minAngle: 20
                        }, callout: {
                            length: 10,
                            strokeWidth: 2
                        }, fillOpacity: 1, strokeOpacity: 1, strokeWidth: 1, lineDash: [0], lineDashOffset: 0, rotation: 0, outerRadiusOffset: 0, innerRadiusOffset: 0, shadow: {
                            enabled: false,
                            color: 'rgba(0, 0, 0, 0.5)',
                            xOffset: 3,
                            yOffset: 3,
                            blur: 5
                        } })
                } }),
            hierarchy: __assign$3(__assign$3({}, ChartTheme.getChartDefaults()), { series: {
                    treemap: __assign$3(__assign$3({}, ChartTheme.getSeriesDefaults()), { showInLegend: false, labelKey: 'label', sizeKey: 'size', colorKey: 'color', colorDomain: [-5, 5], colorRange: ['#cb4b3f', '#6acb64'], colorParents: false, gradient: true, nodePadding: 2, title: {
                            enabled: true,
                            color: 'white',
                            fontStyle: undefined,
                            fontWeight: 'bold',
                            fontSize: 12,
                            fontFamily: 'Verdana, sans-serif',
                            padding: 15
                        }, subtitle: {
                            enabled: true,
                            color: 'white',
                            fontStyle: undefined,
                            fontWeight: undefined,
                            fontSize: 9,
                            fontFamily: 'Verdana, sans-serif',
                            padding: 13
                        }, labels: {
                            large: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 18,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            },
                            medium: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 14,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            },
                            small: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 10,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            },
                            color: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: undefined,
                                fontSize: 12,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            }
                        } })
                } })
        };
        ChartTheme.cartesianSeriesTypes = ['line', 'area', 'bar', 'column', 'scatter', 'histogram'];
        ChartTheme.polarSeriesTypes = ['pie'];
        ChartTheme.hierarchySeriesTypes = ['treemap'];
        ChartTheme.seriesTypes = ChartTheme.cartesianSeriesTypes.concat(ChartTheme.polarSeriesTypes);
        return ChartTheme;
    }());

    var __extends$R = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __assign$4 = (undefined && undefined.__assign) || function () {
        __assign$4 = Object.assign || function(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$4.apply(this, arguments);
    };
    var DarkTheme = /** @class */ (function (_super) {
        __extends$R(DarkTheme, _super);
        function DarkTheme(options) {
            return _super.call(this, options) || this;
        }
        DarkTheme.prototype.getDefaults = function () {
            var fontColor = 'rgb(200, 200, 200)';
            var mutedFontColor = 'rgb(150, 150, 150)';
            var axisDefaults = {
                title: {
                    color: fontColor
                },
                label: {
                    color: fontColor
                },
                gridStyle: [{
                        stroke: 'rgb(88, 88, 88)',
                        lineDash: [4, 2]
                    }]
            };
            var seriesLabelDefaults = {
                label: {
                    color: fontColor
                }
            };
            var chartDefaults = {
                background: {
                    fill: 'rgb(34, 38, 41)'
                },
                title: {
                    color: fontColor
                },
                subtitle: {
                    color: mutedFontColor
                },
                axes: {
                    number: __assign$4({}, axisDefaults),
                    category: __assign$4({}, axisDefaults),
                    time: __assign$4({}, axisDefaults)
                },
                legend: {
                    item: {
                        label: {
                            color: fontColor
                        }
                    }
                }
            };
            return this.mergeWithParentDefaults({
                cartesian: __assign$4(__assign$4({}, chartDefaults), { series: {
                        bar: __assign$4({}, seriesLabelDefaults),
                        column: __assign$4({}, seriesLabelDefaults),
                        histogram: __assign$4({}, seriesLabelDefaults)
                    } }),
                polar: __assign$4(__assign$4({}, chartDefaults), { series: {
                        pie: __assign$4(__assign$4({}, seriesLabelDefaults), { title: {
                                color: fontColor
                            } })
                    } })
            });
        };
        return DarkTheme;
    }(ChartTheme));

    var __extends$S = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$1 = {
        fills: [
            '#f44336',
            '#e91e63',
            '#9c27b0',
            '#673ab7',
            '#3f51b5',
            '#2196f3',
            '#03a9f4',
            '#00bcd4',
            '#009688',
            '#4caf50',
            '#8bc34a',
            '#cddc39',
            '#ffeb3b',
            '#ffc107',
            '#ff9800',
            '#ff5722'
        ],
        strokes: [
            '#ab2f26',
            '#a31545',
            '#6d1b7b',
            '#482980',
            '#2c397f',
            '#1769aa',
            '#0276ab',
            '#008494',
            '#00695f',
            '#357a38',
            '#618834',
            '#909a28',
            '#b3a429',
            '#b38705',
            '#b36a00',
            '#b33d18'
        ]
    };
    var MaterialLight = /** @class */ (function (_super) {
        __extends$S(MaterialLight, _super);
        function MaterialLight() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        MaterialLight.prototype.getPalette = function () {
            return palette$1;
        };
        return MaterialLight;
    }(ChartTheme));

    var __extends$T = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$2 = {
        fills: [
            '#f44336',
            '#e91e63',
            '#9c27b0',
            '#673ab7',
            '#3f51b5',
            '#2196f3',
            '#03a9f4',
            '#00bcd4',
            '#009688',
            '#4caf50',
            '#8bc34a',
            '#cddc39',
            '#ffeb3b',
            '#ffc107',
            '#ff9800',
            '#ff5722'
        ],
        strokes: [
            '#ab2f26',
            '#a31545',
            '#6d1b7b',
            '#482980',
            '#2c397f',
            '#1769aa',
            '#0276ab',
            '#008494',
            '#00695f',
            '#357a38',
            '#618834',
            '#909a28',
            '#b3a429',
            '#b38705',
            '#b36a00',
            '#b33d18'
        ]
    };
    var MaterialDark = /** @class */ (function (_super) {
        __extends$T(MaterialDark, _super);
        function MaterialDark() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        MaterialDark.prototype.getPalette = function () {
            return palette$2;
        };
        return MaterialDark;
    }(DarkTheme));

    var __extends$U = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$3 = {
        fills: [
            '#c16068',
            '#a2bf8a',
            '#ebcc87',
            '#80a0c3',
            '#b58dae',
            '#85c0d1'
        ],
        strokes: [
            '#874349',
            '#718661',
            '#a48f5f',
            '#5a7088',
            '#7f637a',
            '#5d8692'
        ]
    };
    var PastelLight = /** @class */ (function (_super) {
        __extends$U(PastelLight, _super);
        function PastelLight() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        PastelLight.prototype.getPalette = function () {
            return palette$3;
        };
        return PastelLight;
    }(ChartTheme));

    var __extends$V = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$4 = {
        fills: [
            '#c16068',
            '#a2bf8a',
            '#ebcc87',
            '#80a0c3',
            '#b58dae',
            '#85c0d1'
        ],
        strokes: [
            '#874349',
            '#718661',
            '#a48f5f',
            '#5a7088',
            '#7f637a',
            '#5d8692'
        ]
    };
    var PastelDark = /** @class */ (function (_super) {
        __extends$V(PastelDark, _super);
        function PastelDark() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        PastelDark.prototype.getPalette = function () {
            return palette$4;
        };
        return PastelDark;
    }(DarkTheme));

    var __extends$W = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$5 = {
        fills: [
            '#febe76',
            '#ff7979',
            '#badc58',
            '#f9ca23',
            '#f0932b',
            '#eb4c4b',
            '#6ab04c',
            '#7ed6df',
            '#e056fd',
            '#686de0'
        ],
        strokes: [
            '#b28553',
            '#b35555',
            '#829a3e',
            '#ae8d19',
            '#a8671e',
            '#a43535',
            '#4a7b35',
            '#58969c',
            '#9d3cb1',
            '#494c9d'
        ]
    };
    var SolarLight = /** @class */ (function (_super) {
        __extends$W(SolarLight, _super);
        function SolarLight() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        SolarLight.prototype.getPalette = function () {
            return palette$5;
        };
        return SolarLight;
    }(ChartTheme));

    var __extends$X = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$6 = {
        fills: [
            '#febe76',
            '#ff7979',
            '#badc58',
            '#f9ca23',
            '#f0932b',
            '#eb4c4b',
            '#6ab04c',
            '#7ed6df',
            '#e056fd',
            '#686de0'
        ],
        strokes: [
            '#b28553',
            '#b35555',
            '#829a3e',
            '#ae8d19',
            '#a8671e',
            '#a43535',
            '#4a7b35',
            '#58969c',
            '#9d3cb1',
            '#494c9d'
        ]
    };
    var SolarDark = /** @class */ (function (_super) {
        __extends$X(SolarDark, _super);
        function SolarDark() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        SolarDark.prototype.getPalette = function () {
            return palette$6;
        };
        return SolarDark;
    }(DarkTheme));

    var __extends$Y = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$7 = {
        fills: [
            '#5BC0EB',
            '#FDE74C',
            '#9BC53D',
            '#E55934',
            '#FA7921',
            '#fa3081'
        ],
        strokes: [
            '#4086a4',
            '#b1a235',
            '#6c8a2b',
            '#a03e24',
            '#af5517',
            '#af225a'
        ]
    };
    var VividLight = /** @class */ (function (_super) {
        __extends$Y(VividLight, _super);
        function VividLight() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        VividLight.prototype.getPalette = function () {
            return palette$7;
        };
        return VividLight;
    }(ChartTheme));

    var __extends$Z = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var palette$8 = {
        fills: [
            '#5BC0EB',
            '#FDE74C',
            '#9BC53D',
            '#E55934',
            '#FA7921',
            '#fa3081'
        ],
        strokes: [
            '#4086a4',
            '#b1a235',
            '#6c8a2b',
            '#a03e24',
            '#af5517',
            '#af225a'
        ]
    };
    var VividDark = /** @class */ (function (_super) {
        __extends$Z(VividDark, _super);
        function VividDark() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        VividDark.prototype.getPalette = function () {
            return palette$8;
        };
        return VividDark;
    }(DarkTheme));

    var __extends$_ = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __read$g = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var identity$3 = function (x) { return x; };
    var LogScale = /** @class */ (function (_super) {
        __extends$_(LogScale, _super);
        function LogScale() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.type = 'log';
            _this._domain = [1, 10];
            _this.baseLog = identity$3; // takes a log with base `base` of `x`
            _this.basePow = identity$3; // raises `base` to the power of `x`
            _this._base = 10;
            return _this;
        }
        LogScale.prototype.setDomain = function (values) {
            var df = values[0];
            var dl = values[values.length - 1];
            if (df === 0 || dl === 0 || df < 0 && dl > 0 || df > 0 && dl < 0) {
                console.warn('Log scale domain should not start at, end at or cross zero.');
                if (df === 0 && dl > 0) {
                    df = Number.EPSILON;
                }
                else if (dl === 0 && df < 0) {
                    dl = -Number.EPSILON;
                }
                else if (df < 0 && dl > 0) {
                    if (Math.abs(dl) >= Math.abs(df)) {
                        df = Number.EPSILON;
                    }
                    else {
                        dl = -Number.EPSILON;
                    }
                }
                else if (df > 0 && dl < 0) {
                    if (Math.abs(dl) >= Math.abs(df)) {
                        df = -Number.EPSILON;
                    }
                    else {
                        dl = Number.EPSILON;
                    }
                }
                values = values.slice();
                values[0] = df;
                values[values.length - 1] = dl;
            }
            _super.prototype.setDomain.call(this, values);
        };
        LogScale.prototype.getDomain = function () {
            return _super.prototype.getDomain.call(this);
        };
        Object.defineProperty(LogScale.prototype, "base", {
            get: function () {
                return this._base;
            },
            set: function (value) {
                if (this._base !== value) {
                    this._base = value;
                    this.rescale();
                }
            },
            enumerable: true,
            configurable: true
        });
        LogScale.prototype.rescale = function () {
            var base = this.base;
            var baseLog = LogScale.makeLogFn(base);
            var basePow = LogScale.makePowFn(base);
            if (this.domain[0] < 0) {
                baseLog = this.reflect(baseLog);
                basePow = this.reflect(basePow);
                this.transform = function (x) { return -Math.log(-x); };
                this.untransform = function (x) { return -Math.exp(-x); };
            }
            else {
                this.transform = function (x) { return Math.log(x); };
                this.untransform = function (x) { return Math.exp(x); };
            }
            this.baseLog = baseLog;
            this.basePow = basePow;
            _super.prototype.rescale.call(this);
        };
        /**
         * For example, if `f` is `Math.log10`, we have
         *
         *     f(100) == 2
         *     f(-100) == NaN
         *     rf = reflect(f)
         *     rf(-100) == -2
         *
         * @param f
         */
        LogScale.prototype.reflect = function (f) {
            return function (x) { return -f(-x); };
        };
        LogScale.prototype.nice = function () {
            var _a, _b;
            var domain = this.domain;
            var i0 = 0;
            var i1 = domain.length - 1;
            var x0 = domain[i0];
            var x1 = domain[i1];
            if (x1 < x0) {
                _a = __read$g([i1, i0], 2), i0 = _a[0], i1 = _a[1];
                _b = __read$g([x1, x0], 2), x0 = _b[0], x1 = _b[1];
            }
            // For example, for base == 10:
            // [ 50, 900] becomes [ 10, 1000 ]
            domain[i0] = this.basePow(Math.floor(this.baseLog(x0)));
            domain[i1] = this.basePow(Math.ceil(this.baseLog(x1)));
            this.domain = domain;
        };
        LogScale.pow10 = function (x) {
            return isFinite(x)
                ? +('1e' + x) // to avoid precision issues, e.g. Math.pow(10, -4) is not 0.0001
                : x < 0
                    ? 0
                    : x;
        };
        LogScale.makePowFn = function (base) {
            if (base === 10) {
                return LogScale.pow10;
            }
            if (base === Math.E) {
                return Math.exp;
            }
            return function (x) { return Math.pow(base, x); };
        };
        // Make a log function witn an arbitrary base or return a native function if exists.
        LogScale.makeLogFn = function (base) {
            if (base === Math.E) {
                return Math.log;
            }
            if (base === 10) {
                return Math.log10;
            }
            if (base === 2) {
                return Math.log2;
            }
            var logBase = Math.log(base);
            return function (x) { return Math.log(x) / logBase; };
        };
        LogScale.prototype.ticks = function (count) {
            var _a;
            if (count === void 0) { count = 10; }
            var n = count == null ? 10 : +count;
            var base = this.base;
            var domain = this.domain;
            var d0 = domain[0];
            var d1 = domain[domain.length - 1];
            var isReversed = d1 < d0;
            if (isReversed) {
                _a = __read$g([d1, d0], 2), d0 = _a[0], d1 = _a[1];
            }
            var p0 = this.baseLog(d0);
            var p1 = this.baseLog(d1);
            var z = [];
            // if `base` is an integer and delta in order of magnitudes is less than n
            if (!(base % 1) && p1 - p0 < n) {
                // For example, if n == 10, base == 10 and domain == [10^2, 10^6]
                // then p1 - p0 < n == true.
                p0 = Math.round(p0) - 1;
                p1 = Math.round(p1) + 1;
                if (d0 > 0) {
                    for (; p0 < p1; ++p0) {
                        for (var k = 1, p = this.basePow(p0); k < base; ++k) {
                            var t = p * k;
                            // The `t` checks are needed because we expanded the [p0, p1] by 1 in each direction.
                            if (t < d0)
                                continue;
                            if (t > d1)
                                break;
                            z.push(t);
                        }
                    }
                }
                else {
                    for (; p0 < p1; ++p0) {
                        for (var k = base - 1, p = this.basePow(p0); k >= 1; --k) {
                            var t = p * k;
                            if (t < d0)
                                continue;
                            if (t > d1)
                                break;
                            z.push(t);
                        }
                    }
                }
                if (z.length * 2 < n) {
                    z = ticks(d0, d1, n);
                }
            }
            else {
                // For example, if n == 4, base == 10 and domain == [10^2, 10^6]
                // then p1 - p0 < n == false.
                // `ticks` return [2, 3, 4, 5, 6], then mapped to [10^2, 10^3, 10^4, 10^5, 10^6].
                z = ticks(p0, p1, Math.min(p1 - p0, n)).map(this.basePow);
            }
            return isReversed ? z.reverse() : z;
        };
        LogScale.prototype.tickFormat = function (count, specifier) {
            var _this = this;
            var base = this.base;
            if (specifier == null) {
                specifier = (base === 10 ? '.0e' : ',');
            }
            if (typeof specifier !== 'function') {
                specifier = format(specifier);
            }
            if (count === Infinity) {
                return specifier;
            }
            if (count == null) {
                count = 10;
            }
            var k = Math.max(1, base * count / this.ticks().length);
            return function (d) {
                var i = d / _this.basePow(Math.round(_this.baseLog(d)));
                if (i * base < base - 0.5) {
                    i *= base;
                }
                return i <= k ? specifier(d) : '';
            };
        };
        return LogScale;
    }(ContinuousScale));

    var __extends$$ = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var LogAxis = /** @class */ (function (_super) {
        __extends$$(LogAxis, _super);
        function LogAxis() {
            var _this = _super.call(this) || this;
            _this.scale = new LogScale();
            _this.scale.clamper = clamper$1;
            return _this;
        }
        Object.defineProperty(LogAxis.prototype, "base", {
            get: function () {
                return this.scale.base;
            },
            set: function (value) {
                this.scale.base = value;
            },
            enumerable: true,
            configurable: true
        });
        LogAxis.className = 'LogAxis';
        LogAxis.type = 'log';
        return LogAxis;
    }(NumberAxis));

    var __assign$5 = (undefined && undefined.__assign) || function () {
        __assign$5 = Object.assign || function(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$5.apply(this, arguments);
    };
    var _a, _b, _c, _d, _e;
    // type RecursiveMapping<T> = 
    //     T extends Primitive | Array<Primitive> ? T :
    //     T extends Array<infer E> ? Mapping<E> :
    //     (
    //         T extends { type: string } ?
    //             {[key: string]: Mapping<T>} | { [P in keyof T]?: T[P] | Mapping<T[P]> | {}; } :
    //         { [P in keyof T]?: T[P] | Mapping<T[P]> | {}; }
    //     ) & BaseDefinition<T>;
    // type PropertyMapping<T> = 
    //     T extends Primitive | Array<Primitive> ? T :
    //     T extends Array<infer E> ? Mapping<E> :
    // type Mapping<T> = {};
    var chartPadding = 20;
    var commonChartMappings = {
        background: {
            meta: {
                defaults: {
                    visible: true,
                    fill: 'white'
                }
            }
        },
        padding: {
            meta: {
                constructor: Padding,
                defaults: {
                    top: chartPadding,
                    right: chartPadding,
                    bottom: chartPadding,
                    left: chartPadding,
                }
            }
        },
        tooltip: {
            meta: {
                defaults: {
                    enabled: true,
                    tracking: true,
                    delay: 0,
                    class: Chart.defaultTooltipClass
                }
            }
        },
        title: {
            meta: {
                constructor: Caption,
                defaults: {
                    enabled: false,
                    padding: {
                        meta: {
                            constructor: Padding,
                            defaults: {
                                top: 10,
                                right: 10,
                                bottom: 10,
                                left: 10
                            }
                        }
                    },
                    text: 'Title',
                    fontStyle: undefined,
                    fontWeight: 'bold',
                    fontSize: 14,
                    fontFamily: 'Verdana, sans-serif',
                    color: 'rgb(70, 70, 70)'
                }
            }
        },
        subtitle: {
            meta: {
                constructor: Caption,
                defaults: {
                    enabled: false,
                    padding: {
                        meta: {
                            constructor: Padding,
                            defaults: {
                                top: 10,
                                right: 10,
                                bottom: 10,
                                left: 10
                            }
                        }
                    },
                    text: 'Subtitle',
                    fontStyle: undefined,
                    fontWeight: undefined,
                    fontSize: 12,
                    fontFamily: 'Verdana, sans-serif',
                    color: 'rgb(140, 140, 140)'
                }
            }
        },
        legend: {
            meta: {
                constructor: Legend,
                defaults: {
                    enabled: true,
                    position: exports.LegendPosition.Right,
                    spacing: 20
                }
            },
            item: {
                meta: {
                    constructor: LegendItem,
                    defaults: {
                        paddingX: 16,
                        paddingY: 8
                    }
                },
                marker: {
                    meta: {
                        constructor: LegendMarker,
                        defaults: {
                            shape: undefined,
                            size: 15,
                            strokeWidth: 1,
                            padding: 8
                        }
                    }
                },
                label: {
                    meta: {
                        constructor: LegendLabel,
                        defaults: {
                            color: 'black',
                            fontStyle: undefined,
                            fontWeight: undefined,
                            fontSize: 12,
                            fontFamily: 'Verdana, sans-serif',
                            formatter: undefined
                        }
                    }
                }
            }
        }
    };
    var chartDefaults = {
        container: undefined,
        autoSize: true,
        width: 600,
        height: 300,
        data: [],
        title: undefined,
        subtitle: undefined,
        padding: {},
        background: {},
        legend: {
            item: {
                marker: {},
                label: {}
            }
        },
        navigator: {
            mask: {},
            minHandle: {},
            maxHandle: {}
        },
        listeners: undefined
    };
    var chartMeta = {
        // Charts components' constructors normally don't take any parameters (which makes things consistent -- everything
        // is configured the same way, via the properties, and makes the factory pattern work well) but the charts
        // themselves are the exceptions.
        // If a chart config has the (optional) `document` property, it will be passed to the constructor.
        // There is no actual `document` property on the chart, it can only be supplied during instantiation.
        // Config object properties to be used as constructor parameters, in that order.
        constructorParams: ['document'],
        // Properties that should be set on the component as is (without pre-processing).
        setAsIs: ['container', 'data'],
        nonSerializable: ['container', 'data'],
    };
    var axisDefaults = {
        visibleRange: [0, 1],
        thickness: 0,
        label: {},
        tick: {},
        title: {},
        line: {},
        gridStyle: [{
                stroke: 'rgb(219, 219, 219)',
                lineDash: [4, 2]
            }],
    };
    var seriesDefaults = {
        visible: true,
        showInLegend: true,
        cursor: 'default',
        listeners: undefined
    };
    var highlightStyleMapping = {
        item: {
            meta: {
                defaults: {
                    fill: 'yellow'
                }
            }
        },
        series: {
            meta: {
                defaults: {
                    dimOpacity: 1
                }
            }
        }
    };
    var columnSeriesDefaults = {
        fillOpacity: 1,
        strokeOpacity: 1,
        xKey: '',
        xName: '',
        yKeys: [],
        yNames: {},
        grouped: false,
        normalizedTo: undefined,
        strokeWidth: 1,
        lineDash: undefined,
        lineDashOffset: 0,
        shadow: undefined
    };
    var shadowMapping = {
        meta: {
            constructor: DropShadow,
            defaults: {
                enabled: true,
                color: 'rgba(0, 0, 0, 0.5)',
                xOffset: 0,
                yOffset: 0,
                blur: 5
            }
        }
    };
    var labelDefaults = {
        enabled: true,
        fontStyle: undefined,
        fontWeight: undefined,
        fontSize: 12,
        fontFamily: 'Verdana, sans-serif',
        color: 'rgb(70, 70, 70)'
    };
    var barLabelMapping = {
        meta: {
            defaults: __assign$5(__assign$5({}, labelDefaults), { formatter: undefined, placement: exports.BarLabelPlacement.Inside })
        }
    };
    var tooltipMapping = {
        meta: {
            defaults: {
                enabled: true,
                renderer: undefined,
                format: undefined,
            }
        }
    };
    var axisMappings = {
        line: {
            meta: {
                defaults: {
                    width: 1,
                    color: 'rgb(195, 195, 195)'
                }
            }
        },
        title: {
            meta: {
                constructor: Caption,
                defaults: {
                    padding: {
                        meta: {
                            constructor: Padding,
                            defaults: {
                                top: 10,
                                right: 10,
                                bottom: 10,
                                left: 10
                            }
                        }
                    },
                    text: 'Axis Title',
                    fontStyle: undefined,
                    fontWeight: 'bold',
                    fontSize: 12,
                    fontFamily: 'Verdana, sans-serif',
                    color: 'rgb(70, 70, 70)'
                }
            }
        },
        label: {
            meta: {
                constructor: AxisLabel,
                defaults: {
                    fontStyle: undefined,
                    fontWeight: undefined,
                    fontSize: 12,
                    fontFamily: 'Verdana, sans-serif',
                    padding: 5,
                    rotation: 0,
                    color: 'rgb(87, 87, 87)',
                    formatter: undefined
                }
            }
        },
        tick: {
            meta: {
                constructor: AxisTick,
                setAsIs: ['count'],
                defaults: {
                    width: 1,
                    size: 6,
                    color: 'rgb(195, 195, 195)',
                    count: 10
                }
            }
        }
    };
    var CARTESIAN_MAPPING = __assign$5(__assign$5({ meta: __assign$5(__assign$5({ constructor: CartesianChart }, chartMeta), { defaults: __assign$5(__assign$5({}, chartDefaults), { axes: [{
                        type: NumberAxis.type,
                        position: exports.ChartAxisPosition.Left,
                    }, {
                        type: CategoryAxis.type,
                        position: exports.ChartAxisPosition.Bottom,
                    }] }) }) }, commonChartMappings), { axes: (_a = {},
            _a['number'] = __assign$5({ meta: {
                    constructor: NumberAxis,
                    setAsIs: ['gridStyle', 'visibleRange'],
                    defaults: axisDefaults,
                } }, axisMappings),
            _a[LogAxis.type] = __assign$5({ meta: {
                    constructor: LogAxis,
                    setAsIs: ['gridStyle', 'visibleRange'],
                    defaults: __assign$5(__assign$5({}, axisDefaults), { base: 10 }),
                } }, axisMappings),
            _a[CategoryAxis.type] = __assign$5({ meta: {
                    constructor: CategoryAxis,
                    setAsIs: ['gridStyle', 'visibleRange'],
                    defaults: axisDefaults,
                } }, axisMappings),
            _a[GroupedCategoryAxis.type] = __assign$5({ meta: {
                    constructor: GroupedCategoryAxis,
                    setAsIs: ['gridStyle', 'visibleRange'],
                    defaults: axisDefaults,
                } }, axisMappings),
            _a[TimeAxis.type] = __assign$5({ meta: {
                    constructor: TimeAxis,
                    setAsIs: ['gridStyle', 'visibleRange'],
                    defaults: axisDefaults,
                } }, axisMappings),
            _a), series: (_b = {
                column: {
                    meta: {
                        constructor: BarSeries,
                        setAsIs: ['lineDash', 'yNames'],
                        defaults: __assign$5(__assign$5({ flipXY: false }, seriesDefaults), columnSeriesDefaults)
                    },
                    highlightStyle: highlightStyleMapping,
                    tooltip: tooltipMapping,
                    label: barLabelMapping,
                    shadow: shadowMapping,
                }
            },
            _b[BarSeries.type] = {
                meta: {
                    constructor: BarSeries,
                    setAsIs: ['lineDash', 'yNames'],
                    defaults: __assign$5(__assign$5({ flipXY: true }, seriesDefaults), columnSeriesDefaults)
                },
                highlightStyle: highlightStyleMapping,
                tooltip: tooltipMapping,
                label: barLabelMapping,
                shadow: shadowMapping,
            },
            _b[LineSeries.type] = {
                meta: {
                    constructor: LineSeries,
                    setAsIs: ['lineDash'],
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { title: undefined, xKey: '', xName: '', yKey: '', yName: '', strokeWidth: 2, strokeOpacity: 1, lineDash: undefined, lineDashOffset: 0 })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                label: {
                    meta: {
                        defaults: __assign$5(__assign$5({}, labelDefaults), { formatter: undefined })
                    }
                },
                marker: {
                    meta: {
                        constructor: CartesianSeriesMarker,
                        defaults: {
                            enabled: true,
                            shape: 'circle',
                            size: 6,
                            maxSize: 30,
                            strokeWidth: 1,
                            formatter: undefined
                        }
                    }
                }
            },
            _b[ScatterSeries.type] = {
                meta: {
                    constructor: ScatterSeries,
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { title: undefined, xKey: '', yKey: '', sizeKey: undefined, labelKey: undefined, xName: '', yName: '', sizeName: 'Size', labelName: 'Label', strokeWidth: 2, fillOpacity: 1, strokeOpacity: 1 })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                marker: {
                    meta: {
                        constructor: CartesianSeriesMarker,
                        defaults: {
                            enabled: true,
                            shape: 'circle',
                            size: 6,
                            maxSize: 30,
                            strokeWidth: 1,
                            formatter: undefined
                        }
                    }
                },
                label: {
                    meta: {
                        defaults: __assign$5({}, labelDefaults)
                    }
                }
            },
            _b[AreaSeries.type] = {
                meta: {
                    constructor: AreaSeries,
                    setAsIs: ['lineDash'],
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { xKey: '', xName: '', yKeys: [], yNames: [], normalizedTo: undefined, fillOpacity: 1, strokeOpacity: 1, strokeWidth: 2, lineDash: undefined, lineDashOffset: 0, shadow: undefined })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                label: {
                    meta: {
                        defaults: __assign$5(__assign$5({}, labelDefaults), { formatter: undefined })
                    }
                },
                marker: {
                    meta: {
                        constructor: CartesianSeriesMarker,
                        defaults: {
                            enabled: true,
                            shape: 'circle',
                            size: 6,
                            maxSize: 30,
                            strokeWidth: 1,
                            formatter: undefined
                        }
                    }
                },
                shadow: shadowMapping,
            },
            _b[HistogramSeries.type] = {
                meta: {
                    constructor: HistogramSeries,
                    setAsIs: ['lineDash'],
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { xKey: '', yKey: '', xName: '', yName: '', strokeWidth: 1, fillOpacity: 1, strokeOpacity: 1, lineDash: undefined, lineDashOffset: 0, areaPlot: false, binCount: undefined, bins: undefined, aggregation: 'sum' })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                label: {
                    meta: {
                        defaults: __assign$5(__assign$5({}, labelDefaults), { formatter: undefined })
                    }
                },
                shadow: shadowMapping,
            },
            _b), navigator: {
            meta: {
                constructor: Navigator,
                defaults: {
                    enabled: false,
                    height: 30,
                }
            },
            mask: {
                meta: {
                    constructor: NavigatorMask,
                    defaults: {
                        fill: '#999999',
                        stroke: '#999999',
                        strokeWidth: 1,
                        fillOpacity: 0.2
                    }
                }
            },
            minHandle: {
                meta: {
                    constructor: NavigatorHandle,
                    defaults: {
                        fill: '#f2f2f2',
                        stroke: '#999999',
                        strokeWidth: 1,
                        width: 8,
                        height: 16,
                        gripLineGap: 2,
                        gripLineLength: 8
                    }
                }
            },
            maxHandle: {
                meta: {
                    constructor: NavigatorHandle,
                    defaults: {
                        fill: '#f2f2f2',
                        stroke: '#999999',
                        strokeWidth: 1,
                        width: 8,
                        height: 16,
                        gripLineGap: 2,
                        gripLineLength: 8
                    }
                }
            }
        } });
    var POLAR_MAPPING = __assign$5(__assign$5({ meta: __assign$5(__assign$5({ constructor: PolarChart }, chartMeta), { defaults: __assign$5(__assign$5({}, chartDefaults), { padding: {
                    meta: {
                        constructor: Padding,
                        defaults: {
                            top: 40,
                            right: 40,
                            bottom: 40,
                            left: 40
                        }
                    }
                } }) }) }, commonChartMappings), { series: (_c = {},
            _c[PieSeries.type] = {
                meta: {
                    constructor: PieSeries,
                    setAsIs: ['lineDash'],
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { title: undefined, angleKey: '', angleName: '', radiusKey: undefined, radiusName: undefined, labelKey: undefined, labelName: undefined, callout: {}, fillOpacity: 1, strokeOpacity: 1, rotation: 0, outerRadiusOffset: 0, innerRadiusOffset: 0, strokeWidth: 1, lineDash: undefined, lineDashOffset: 0, shadow: undefined })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                title: {
                    meta: {
                        constructor: PieTitle,
                        defaults: {
                            enabled: true,
                            showInLegend: false,
                            padding: {
                                meta: {
                                    constructor: Padding,
                                    defaults: {
                                        top: 10,
                                        right: 10,
                                        bottom: 10,
                                        left: 10
                                    }
                                }
                            },
                            text: 'Series Title',
                            fontStyle: undefined,
                            fontWeight: 'bold',
                            fontSize: 14,
                            fontFamily: 'Verdana, sans-serif',
                            color: 'black'
                        }
                    }
                },
                label: {
                    meta: {
                        defaults: __assign$5(__assign$5({}, labelDefaults), { offset: 3, minAngle: 20 })
                    }
                },
                callout: {
                    meta: {
                        defaults: {
                            length: 10,
                            strokeWidth: 1
                        }
                    }
                },
                shadow: shadowMapping,
            },
            _c) });
    var HIERARCHY_MAPPING = __assign$5(__assign$5({ meta: __assign$5(__assign$5({ constructor: HierarchyChart }, chartMeta), { defaults: __assign$5({}, chartDefaults) }) }, commonChartMappings), { series: (_d = {},
            _d[TreemapSeries.type] = {
                meta: {
                    constructor: TreemapSeries,
                    defaults: __assign$5(__assign$5({}, seriesDefaults), { showInLegend: false, labelKey: 'label', sizeKey: 'size', colorKey: 'color', colorDomain: [-5, 5], colorRange: ['#cb4b3f', '#6acb64'], colorParents: false, gradient: true, nodePadding: 2, title: {}, subtitle: {}, labels: {
                            large: {},
                            medium: {},
                            small: {},
                            color: {}
                        } })
                },
                tooltip: tooltipMapping,
                highlightStyle: highlightStyleMapping,
                title: {
                    meta: {
                        defaults: {
                            enabled: true,
                            color: 'white',
                            fontStyle: undefined,
                            fontWeight: 'bold',
                            fontSize: 12,
                            fontFamily: 'Verdana, sans-serif',
                            padding: 15
                        }
                    }
                },
                subtitle: {
                    meta: {
                        defaults: {
                            enabled: true,
                            color: 'white',
                            fontStyle: undefined,
                            fontWeight: undefined,
                            fontSize: 9,
                            fontFamily: 'Verdana, sans-serif',
                            padding: 13
                        }
                    }
                },
                labels: {
                    meta: {
                        defaults: {
                            large: {},
                            medium: {},
                            small: {},
                            color: {}
                        }
                    },
                    large: {
                        meta: {
                            constructor: Label,
                            defaults: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 18,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            }
                        }
                    },
                    medium: {
                        meta: {
                            constructor: Label,
                            defaults: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 14,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            }
                        }
                    },
                    small: {
                        meta: {
                            constructor: Label,
                            defaults: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: 'bold',
                                fontSize: 10,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            }
                        }
                    },
                    color: {
                        meta: {
                            constructor: Label,
                            defaults: {
                                enabled: true,
                                fontStyle: undefined,
                                fontWeight: undefined,
                                fontSize: 12,
                                fontFamily: 'Verdana, sans-serif',
                                color: 'white'
                            }
                        }
                    }
                }
            },
            _d) });
    function tweakAxes(input, newAxes) {
        var _a;
        return __assign$5(__assign$5({}, input), { meta: __assign$5(__assign$5({}, input.meta), { defaults: __assign$5(__assign$5({}, (_a = input.meta) === null || _a === void 0 ? void 0 : _a.defaults), { axes: newAxes }) }) });
    }
    function tweakConstructor(input, constructor) {
        return __assign$5(__assign$5({}, input), { meta: __assign$5(__assign$5({}, input.meta), { constructor: constructor }) });
    }
    var SCATTER_HISTOGRAM_AXES = [{
            type: 'number',
            position: exports.ChartAxisPosition.Bottom,
        }, {
            type: 'number',
            position: exports.ChartAxisPosition.Left,
        }];
    var BAR_AXES = [{
            type: 'number',
            position: exports.ChartAxisPosition.Bottom,
        }, {
            type: 'category',
            position: exports.ChartAxisPosition.Left,
        }];
    var mappings = (_e = {},
        _e[CartesianChart.type] = CARTESIAN_MAPPING,
        _e[GroupedCategoryChart.type] = tweakConstructor(CARTESIAN_MAPPING, GroupedCategoryChart),
        _e['line'] = CARTESIAN_MAPPING,
        _e['area'] = CARTESIAN_MAPPING,
        _e['bar'] = tweakAxes(CARTESIAN_MAPPING, BAR_AXES),
        _e['column'] = CARTESIAN_MAPPING,
        _e['scatter'] = tweakAxes(CARTESIAN_MAPPING, SCATTER_HISTOGRAM_AXES),
        _e['histogram'] = tweakAxes(CARTESIAN_MAPPING, SCATTER_HISTOGRAM_AXES),
        _e[PolarChart.type] = POLAR_MAPPING,
        _e['pie'] = POLAR_MAPPING,
        _e[HierarchyChart.type] = HIERARCHY_MAPPING,
        _e['treemap'] = HIERARCHY_MAPPING,
        _e);

    var __assign$6 = (undefined && undefined.__assign) || function () {
        __assign$6 = Object.assign || function(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$6.apply(this, arguments);
    };
    var __read$h = (undefined && undefined.__read) || function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };
    var __spread$6 = (undefined && undefined.__spread) || function () {
        for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$h(arguments[i]));
        return ar;
    };
    var __values$5 = (undefined && undefined.__values) || function(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };
    var lightTheme = new ChartTheme();
    var darkTheme = new DarkTheme();
    var lightThemes = {
        'undefined': lightTheme,
        'null': lightTheme,
        'ag-default': lightTheme,
        'ag-material': new MaterialLight(),
        'ag-pastel': new PastelLight(),
        'ag-solar': new SolarLight(),
        'ag-vivid': new VividLight(),
    };
    var darkThemes = {
        'undefined': darkTheme,
        'null': darkTheme,
        'ag-default-dark': darkTheme,
        'ag-material-dark': new MaterialDark(),
        'ag-pastel-dark': new PastelDark(),
        'ag-solar-dark': new SolarDark(),
        'ag-vivid-dark': new VividDark(),
    };
    var themes = __assign$6(__assign$6({}, darkThemes), lightThemes);
    function getChartTheme(value) {
        if (value instanceof ChartTheme) {
            return value;
        }
        var stockTheme = themes[value];
        if (stockTheme) {
            return stockTheme;
        }
        value = value;
        if (value.baseTheme || value.overrides || value.palette) {
            var baseTheme = getChartTheme(value.baseTheme);
            return new baseTheme.constructor(value);
        }
        return lightTheme;
    }
    var firstColorIndex = 0;
    var AgChart = /** @class */ (function () {
        function AgChart() {
        }
        AgChart.create = function (options, container, data) {
            options = Object.create(options); // avoid mutating user provided options
            return AgChart.createOrUpdate({
                options: options,
                container: container,
                data: data,
                operation: function (options, theme) { return create(options, undefined, undefined, theme); },
            });
        };
        AgChart.update = function (chart, options, container, data) {
            if (!(chart && options)) {
                return;
            }
            return AgChart.createOrUpdate({
                chart: chart,
                options: options,
                container: container,
                data: data,
                operation: function (options, theme) { return update(chart, options, undefined, theme); },
            });
        };
        AgChart.createOrUpdate = function (_a) {
            var chart = _a.chart, options = _a.options, container = _a.container, data = _a.data, operation = _a.operation;
            if (container) {
                options.container = container;
            }
            if (data) {
                options.data = data;
            }
            if (options.series && options.series.length > 0) {
                options.series = processSeriesOptions(options.series);
            }
            // special handling when both `autoSize` and `width` / `height` are present in the options
            var autoSize = options && options.autoSize !== false;
            var theme = getChartTheme(options.theme);
            firstColorIndex = 0;
            var result = operation(options, theme);
            if (chart == null && result instanceof Chart) {
                chart = result;
            }
            if (chart && autoSize) { // `autoSize` takes precedence over `width` / `height`
                chart.autoSize = true;
            }
            return result;
        };
        AgChart.createComponent = create;
        return AgChart;
    }());
    var pathToSeriesTypeMap = {
        'cartesian.series': 'line',
        'line.series': 'line',
        'area.series': 'area',
        'bar.series': 'bar',
        'column.series': 'column',
        'histogram.series': 'histogram',
        'scatter.series': 'scatter',
        'polar.series': 'pie',
        'pie.series': 'pie'
    };
    var actualSeriesTypeMap = {
        // Identity mappings.
        'area': 'area',
        'bar': 'bar',
        'histogram': 'histogram',
        'line': 'line',
        'pie': 'pie',
        'scatter': 'scatter',
        'ohlc': 'ohlc',
        'treemap': 'treemap',
        // Aliases.
        'column': 'bar',
    };
    function create(options, path, component, theme) {
        var _a;
        // Deprecate `chart.legend.item.marker.type` in integrated chart options.
        options = Object.create(options);
        if (component instanceof LegendMarker) {
            if (options.type) {
                options.shape = options.type;
            }
        }
        else {
            options = provideDefaultType(options, path);
            if (path) {
                if (options.type) {
                    path = path + '.' + options.type;
                }
            }
            else {
                path = options.type;
            }
        }
        if (!path) {
            return;
        }
        var mapping = getValue(mappings, path);
        if (mapping) {
            options = provideDefaultOptions(path, options, mapping, theme);
            var meta = mapping.meta || {};
            var constructorParams = meta.constructorParams || [];
            var skipKeys = ['type', 'listeners'].concat(constructorParams);
            // TODO: Constructor params processing could be improved, but it's good enough for current params.
            var constructorParamValues = constructorParams
                .map(function (param) { return options[param]; })
                .filter(function (value) { return value !== undefined; });
            if (!component) {
                component = new ((_a = meta.constructor).bind.apply(_a, __spread$6([void 0], constructorParamValues)))();
                if (theme && component instanceof Series) {
                    firstColorIndex = theme.setSeriesColors(component, options, firstColorIndex);
                }
            }
            var _loop_1 = function (key) {
                // Process every non-special key in the config object.
                if (skipKeys.indexOf(key) < 0) {
                    var value = options[key];
                    if (value && key in mapping && !(meta.setAsIs && meta.setAsIs.indexOf(key) >= 0)) {
                        if (Array.isArray(value)) {
                            var subComponents = value
                                .map(function (config) {
                                var axis = create(config, path + '.' + key, undefined, theme);
                                if (theme && key === 'axes') {
                                    var fakeTheme = {
                                        getConfig: function (path) {
                                            var parts = path.split('.');
                                            var modifiedPath = parts.slice(0, 3).join('.') + '.' + axis.position;
                                            var after = parts.slice(3);
                                            if (after.length) {
                                                modifiedPath += '.' + after.join('.');
                                            }
                                            var config = theme.getConfig(path);
                                            var modifiedConfig = theme.getConfig(modifiedPath);
                                            isObject(theme.getConfig(modifiedPath));
                                            if (isObject(config) && isObject(modifiedConfig)) {
                                                return deepMerge(config, modifiedConfig, mergeOptions);
                                            }
                                            return modifiedConfig;
                                        }
                                    };
                                    update(axis, config, path + '.' + key, fakeTheme);
                                }
                                return axis;
                            })
                                .filter(function (instance) { return !!instance; });
                            component[key] = subComponents;
                        }
                        else {
                            if (mapping[key] && component[key]) {
                                // The instance property already exists on the component (e.g. chart.legend).
                                // Simply configure the existing instance, without creating a new one.
                                create(value, path + '.' + key, component[key], theme);
                            }
                            else {
                                var subComponent = create(value, value.type ? path : path + '.' + key, undefined, theme);
                                if (subComponent) {
                                    component[key] = subComponent;
                                }
                            }
                        }
                    }
                    else { // if (key in meta.constructor.defaults) { // prevent users from creating custom properties
                        component[key] = value;
                    }
                }
            };
            for (var key in options) {
                _loop_1(key);
            }
            var listeners = options.listeners;
            if (component && component.addEventListener && listeners) {
                for (var key in listeners) {
                    if (listeners.hasOwnProperty(key)) {
                        var listener = listeners[key];
                        if (typeof listener === 'function') {
                            component.addEventListener(key, listener);
                        }
                    }
                }
            }
            return component;
        }
    }
    function update(component, options, path, theme) {
        if (!(options && isObject(options))) {
            return;
        }
        // Deprecate `chart.legend.item.marker.type` in integrated chart options.
        if (component instanceof LegendMarker) {
            if (options.type) {
                options.shape = options.type;
            }
        }
        else {
            options = provideDefaultType(options, path);
            if (path) {
                if (options.type) {
                    path = path + '.' + options.type;
                }
            }
            else {
                path = options.type;
            }
        }
        if (!path) {
            return;
        }
        var chart = path in mappings ? component : undefined;
        var mapping = getValue(mappings, path);
        if (mapping) {
            options = provideDefaultOptions(path, options, mapping, theme);
            var meta = mapping.meta || {};
            var constructorParams = meta && meta.constructorParams || [];
            var skipKeys = ['type'].concat(constructorParams);
            for (var key in options) {
                if (skipKeys.indexOf(key) < 0) {
                    var value = options[key];
                    var keyPath = path + '.' + key;
                    if (meta.setAsIs && meta.setAsIs.indexOf(key) >= 0) {
                        component[key] = value;
                    }
                    else {
                        var oldValue = component[key];
                        if (Array.isArray(oldValue) && Array.isArray(value)) {
                            if (chart) {
                                if (key === 'series') {
                                    updateSeries(component, value, keyPath, theme);
                                }
                                else if (key === 'axes') {
                                    updateAxes(component, value, keyPath, theme);
                                }
                            }
                            else {
                                component[key] = value;
                            }
                        }
                        else if (isObject(oldValue)) {
                            if (value) {
                                update(oldValue, value, value.type ? path : keyPath, theme);
                            }
                            else if (key in options) {
                                component[key] = value;
                            }
                        }
                        else {
                            var subComponent = isObject(value) && create(value, value.type ? path : keyPath, undefined, theme);
                            if (subComponent) {
                                component[key] = subComponent;
                            }
                            else {
                                if (chart && options.autoSize && (key === 'width' || key === 'height')) {
                                    continue;
                                }
                                component[key] = value;
                            }
                        }
                    }
                }
            }
        }
        if (chart) {
            chart.layoutPending = true;
        }
    }
    function updateSeries(chart, configs, keyPath, theme) {
        var allSeries = chart.series.slice();
        var prevSeries;
        var i = 0;
        for (; i < configs.length; i++) {
            var config = configs[i];
            var series = allSeries[i];
            if (series) {
                config = provideDefaultType(config, keyPath);
                var type = actualSeriesTypeMap[config.type];
                if (series.type === type) {
                    if (theme) {
                        firstColorIndex = theme.setSeriesColors(series, config, firstColorIndex);
                    }
                    update(series, config, keyPath, theme);
                }
                else {
                    var newSeries = create(config, keyPath, undefined, theme);
                    chart.removeSeries(series);
                    chart.addSeriesAfter(newSeries, prevSeries);
                    series = newSeries;
                }
            }
            else { // more new configs than existing series
                var newSeries = create(config, keyPath, undefined, theme);
                chart.addSeries(newSeries);
            }
            prevSeries = series;
        }
        // more existing series than new configs
        for (; i < allSeries.length; i++) {
            var series = allSeries[i];
            if (series) {
                chart.removeSeries(series);
            }
        }
    }
    function updateAxes(chart, configs, keyPath, theme) {
        var e_1, _a;
        var axes = chart.axes;
        var axesToAdd = [];
        var axesToUpdate = [];
        var _loop_2 = function (config) {
            var axisToUpdate = find(axes, function (axis) {
                return axis.type === config.type && axis.position === config.position;
            });
            if (axisToUpdate) {
                axesToUpdate.push(axisToUpdate);
                update(axisToUpdate, config, keyPath, theme);
            }
            else {
                var axisToAdd = create(config, keyPath, undefined, theme);
                if (axisToAdd) {
                    axesToAdd.push(axisToAdd);
                }
            }
        };
        try {
            for (var configs_1 = __values$5(configs), configs_1_1 = configs_1.next(); !configs_1_1.done; configs_1_1 = configs_1.next()) {
                var config = configs_1_1.value;
                _loop_2(config);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (configs_1_1 && !configs_1_1.done && (_a = configs_1.return)) _a.call(configs_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        chart.axes = axesToUpdate.concat(axesToAdd);
    }
    function provideDefaultChartType(options) {
        if (options.type) {
            return options;
        }
        // If chart type is not specified, try to infer it from the type of first series.
        var series = options.series && options.series[0];
        if (series && series.type) {
            options = Object.create(options);
            options.type = series.type;
            return options;
        }
        // If chart type is not specified in the first series either, set it to 'cartesian'.
        options = Object.create(options);
        options.type = 'cartesian';
        return options;
    }
    function provideDefaultType(options, path) {
        if (!path) { // if `path` is undefined, `options` is a top-level (chart) config
            path = '';
            options = provideDefaultChartType(options);
        }
        if (!options.type) {
            var seriesType = pathToSeriesTypeMap[path];
            if (seriesType) {
                options = Object.create(options);
                options.type = seriesType;
            }
        }
        return options;
    }
    function skipThemeKey(key) {
        return ['axes', 'series'].indexOf(key) >= 0;
    }
    var enabledKey = 'enabled';
    /**
     * If certain options were not provided by the user, use the defaults from the theme and the mapping.
     * All three objects are provided for the current path in the config tree, not necessarily top-level.
     */
    function provideDefaultOptions(path, options, mapping, theme) {
        var isChartConfig = path.indexOf('.') < 0;
        var themeDefaults = theme && theme.getConfig(path);
        var defaults = mapping && mapping.meta && mapping.meta.defaults;
        var isExplicitlyDisabled = options.enabled === false; // by the user
        if (defaults || themeDefaults) {
            options = Object.create(options);
        }
        // Fill in the gaps for properties not configured by the user using theme provided values.
        for (var key in themeDefaults) {
            // The default values for these special chart configs always come from the mappings, not theme.
            if (isChartConfig && skipThemeKey(key)) {
                continue;
            }
            if (!(key in options)) {
                options[key] = themeDefaults[key];
            }
        }
        // Fill in the gaps for properties not configured by the user, nor theme using chart mappings.
        for (var key in defaults) {
            if ((!themeDefaults || !(key in themeDefaults) || skipThemeKey(key)) && !(key in options)) {
                options[key] = defaults[key];
            }
        }
        // Special handling for the 'enabled' property. For example:
        // title: { text: 'Quarterly Revenue' } // means title is enabled
        // legend: {} // means legend is enabled
        var hasEnabledKey = (themeDefaults && enabledKey in themeDefaults) ||
            (defaults && enabledKey in defaults);
        if (hasEnabledKey && !isExplicitlyDisabled) {
            options[enabledKey] = true;
        }
        return options;
    }
    /**
     * Groups the series options objects if they are of type `column` or `bar` and places them in an array at the index where the first instance of this series type was found.
     * Returns an array of arrays containing the ordered and grouped series options objects.
     */
    function groupSeriesByType(seriesOptions) {
        var e_2, _a;
        var indexMap = {
            column: [],
            bar: [],
            line: [],
            scatter: [],
            area: [],
            histogram: [],
            ohlc: [],
            pie: [],
            treemap: [],
        };
        var result = [];
        try {
            for (var seriesOptions_1 = __values$5(seriesOptions), seriesOptions_1_1 = seriesOptions_1.next(); !seriesOptions_1_1.done; seriesOptions_1_1 = seriesOptions_1.next()) {
                var s = seriesOptions_1_1.value;
                var isColumnOrBar = s.type === 'column' || s.type === 'bar';
                var isStackedArea = s.type === 'area' && s.stacked === true;
                if (!isColumnOrBar && !isStackedArea) {
                    // No need to use index for these cases.
                    result.push([s]);
                    continue;
                }
                var seriesType = s.type || 'line';
                if (seriesType === 'pie' || seriesType === 'treemap') {
                    throw new Error("AG Grid - Unexpected series type of: " + seriesType);
                }
                else if (indexMap[seriesType].length === 0) {
                    // Add indexed array to result on first addition.
                    result.push(indexMap[seriesType]);
                }
                indexMap[seriesType].push(s);
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (seriesOptions_1_1 && !seriesOptions_1_1.done && (_a = seriesOptions_1.return)) _a.call(seriesOptions_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
        return result;
    }
    /**
     * Takes an array of bar or area series options objects and returns a single object with the combined area series options.
     */
    function reduceSeries(series, enableBarSeriesSpecialCases) {
        var e_3, _a;
        var options = {};
        var arrayValueProperties = ['yKeys', 'fills', 'strokes', 'yNames', 'hideInChart', 'hideInLegend'];
        var stringValueProperties = ['yKey', 'fill', 'stroke', 'yName'];
        try {
            for (var series_1 = __values$5(series), series_1_1 = series_1.next(); !series_1_1.done; series_1_1 = series_1.next()) {
                var s = series_1_1.value;
                for (var property in s) {
                    var arrayValueProperty = arrayValueProperties.indexOf(property) > -1;
                    var stringValueProperty = stringValueProperties.indexOf(property) > -1;
                    if (arrayValueProperty && s[property].length > 0) {
                        options[property] = __spread$6((options[property] || []), s[property]);
                    }
                    else if (stringValueProperty) {
                        options[property + "s"] = __spread$6((options[property + "s"] || []), [s[property]]);
                    }
                    else if (enableBarSeriesSpecialCases && property === 'showInLegend') {
                        if (s[property] === false) {
                            options.hideInLegend = __spread$6((options.hideInLegend || []), (s.yKey ? [s.yKey] : s.yKeys));
                        }
                    }
                    else if (enableBarSeriesSpecialCases && property === 'grouped') {
                        if (s[property] === true) {
                            options[property] = s[property];
                        }
                    }
                    else {
                        options[property] = s[property];
                    }
                }
            }
        }
        catch (e_3_1) { e_3 = { error: e_3_1 }; }
        finally {
            try {
                if (series_1_1 && !series_1_1.done && (_a = series_1.return)) _a.call(series_1);
            }
            finally { if (e_3) throw e_3.error; }
        }
        return options;
    }
    /**
     * Transforms provided series options array into an array containing series options which are compatible with standalone charts series options.
     */
    function processSeriesOptions(seriesOptions) {
        var e_4, _a;
        var result = [];
        try {
            for (var _b = __values$5(groupSeriesByType(seriesOptions)), _c = _b.next(); !_c.done; _c = _b.next()) {
                var series = _c.value;
                switch (series[0].type) {
                    case 'column':
                    case 'bar':
                        result.push(reduceSeries(series, true));
                        break;
                    case 'area':
                        result.push(reduceSeries(series, false));
                        break;
                    case 'line':
                    default:
                        if (series.length > 1) {
                            throw new Error('AG-Grid - unexpected grouping of series type: ' + series[0].type);
                        }
                        result.push(series[0]);
                        break;
                }
            }
        }
        catch (e_4_1) { e_4 = { error: e_4_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_4) throw e_4.error; }
        }
        return result;
    }

    var time = {
        millisecond: millisecond,
        second: second,
        minute: minute,
        hour: hour,
        day: day,
        sunday: sunday, monday: monday, tuesday: tuesday, wednesday: wednesday, thursday: thursday, friday: friday, saturday: saturday,
        month: month,
        year: year,
        utcMinute: utcMinute,
        utcHour: utcHour,
        utcDay: utcDay,
        utcMonth: utcMonth,
        utcYear: utcYear
    };

    exports.AgChart = AgChart;
    exports.Arc = Arc;
    exports.AreaSeries = AreaSeries;
    exports.AreaSeriesTooltip = AreaSeriesTooltip;
    exports.BandScale = BandScale;
    exports.BarSeries = BarSeries;
    exports.BarSeriesLabel = BarSeriesLabel;
    exports.BarSeriesTooltip = BarSeriesTooltip;
    exports.Caption = Caption;
    exports.CartesianChart = CartesianChart;
    exports.CategoryAxis = CategoryAxis;
    exports.Chart = Chart;
    exports.ChartAxis = ChartAxis;
    exports.ChartTheme = ChartTheme;
    exports.ChartTooltip = ChartTooltip;
    exports.ClipRect = ClipRect;
    exports.DropShadow = DropShadow;
    exports.Group = Group;
    exports.GroupedCategoryAxis = GroupedCategoryAxis;
    exports.GroupedCategoryChart = GroupedCategoryChart;
    exports.HierarchyChart = HierarchyChart;
    exports.HistogramBin = HistogramBin;
    exports.HistogramSeries = HistogramSeries;
    exports.HistogramSeriesTooltip = HistogramSeriesTooltip;
    exports.Legend = Legend;
    exports.LegendItem = LegendItem;
    exports.LegendLabel = LegendLabel;
    exports.LegendMarker = LegendMarker;
    exports.Line = Line;
    exports.LineSeries = LineSeries;
    exports.LineSeriesTooltip = LineSeriesTooltip;
    exports.LinearScale = LinearScale;
    exports.Marker = Marker;
    exports.NumberAxis = NumberAxis;
    exports.Padding = Padding;
    exports.Path = Path;
    exports.PieSeries = PieSeries;
    exports.PieSeriesTooltip = PieSeriesTooltip;
    exports.PieTitle = PieTitle;
    exports.PolarChart = PolarChart;
    exports.Rect = Rect;
    exports.ScatterSeries = ScatterSeries;
    exports.ScatterSeriesTooltip = ScatterSeriesTooltip;
    exports.Scene = Scene;
    exports.Sector = Sector;
    exports.Shape = Shape;
    exports.TimeAxis = TimeAxis;
    exports.TreemapSeries = TreemapSeries;
    exports.TreemapSeriesLabel = TreemapSeriesLabel;
    exports.TreemapSeriesTooltip = TreemapSeriesTooltip;
    exports.clamper = clamper$1;
    exports.copy = copy;
    exports.darkThemes = darkThemes;
    exports.extent = extent;
    exports.find = find;
    exports.findIndex = findIndex;
    exports.findMinMax = findMinMax;
    exports.flipChartAxisDirection = flipChartAxisDirection;
    exports.getChartTheme = getChartTheme;
    exports.groupSeriesByType = groupSeriesByType;
    exports.lightThemes = lightThemes;
    exports.mergeOptions = mergeOptions;
    exports.normalizeAngle180 = normalizeAngle180;
    exports.normalizeAngle360 = normalizeAngle360;
    exports.normalizeAngle360Inclusive = normalizeAngle360Inclusive;
    exports.processSeriesOptions = processSeriesOptions;
    exports.reduceSeries = reduceSeries;
    exports.themes = themes;
    exports.time = time;
    exports.toDegrees = toDegrees;
    exports.toRadians = toRadians;
    exports.toTooltipHtml = toTooltipHtml;

    Object.defineProperty(exports, '__esModule', { value: true });

})));