function _array_like_to_array(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
    return arr2;
}
function _array_with_holes(arr) {
    if (Array.isArray(arr)) return arr;
}
function _array_without_holes(arr) {
    if (Array.isArray(arr)) return _array_like_to_array(arr);
}
function _assert_this_initialized(self) {
    if (self === void 0) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return self;
}
function _call_super(_this, derived, args) {
    derived = _get_prototype_of(derived);
    return _possible_constructor_return(_this, _is_native_reflect_construct() ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) : derived.apply(_this, args));
}
function _class_call_check(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}
function _defineProperties(target, props) {
    for(var i = 0; i < props.length; i++){
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function _create_class(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
}
function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
function _get_prototype_of(o) {
    _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
    };
    return _get_prototype_of(o);
}
function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function");
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            writable: true,
            configurable: true
        }
    });
    if (superClass) _set_prototype_of(subClass, superClass);
}
function _instanceof(left, right) {
    "@swc/helpers - instanceof";
    if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
        return !!right[Symbol.hasInstance](left);
    } else {
        return left instanceof right;
    }
}
function _iterable_to_array(iter) {
    if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _iterable_to_array_limit(arr, i) {
    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
    if (_i == null) return;
    var _arr = [];
    var _n = true;
    var _d = false;
    var _s, _e;
    try {
        for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
            _arr.push(_s.value);
            if (i && _arr.length === i) break;
        }
    } catch (err) {
        _d = true;
        _e = err;
    } finally{
        try {
            if (!_n && _i["return"] != null) _i["return"]();
        } finally{
            if (_d) throw _e;
        }
    }
    return _arr;
}
function _non_iterable_rest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _non_iterable_spread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _object_spread(target) {
    for(var i = 1; i < arguments.length; i++){
        var source = arguments[i] != null ? arguments[i] : {};
        var ownKeys = Object.keys(source);
        if (typeof Object.getOwnPropertySymbols === "function") {
            ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
                return Object.getOwnPropertyDescriptor(source, sym).enumerable;
            }));
        }
        ownKeys.forEach(function(key) {
            _define_property(target, key, source[key]);
        });
    }
    return target;
}
function ownKeys(object, enumerableOnly) {
    var keys = Object.keys(object);
    if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) {
            symbols = symbols.filter(function(sym) {
                return Object.getOwnPropertyDescriptor(object, sym).enumerable;
            });
        }
        keys.push.apply(keys, symbols);
    }
    return keys;
}
function _object_spread_props(target, source) {
    source = source != null ? source : {};
    if (Object.getOwnPropertyDescriptors) {
        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
        ownKeys(Object(source)).forEach(function(key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
        });
    }
    return target;
}
function _possible_constructor_return(self, call) {
    if (call && (_type_of(call) === "object" || typeof call === "function")) {
        return call;
    }
    return _assert_this_initialized(self);
}
function _set_prototype_of(o, p) {
    _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
        o.__proto__ = p;
        return o;
    };
    return _set_prototype_of(o, p);
}
function _sliced_to_array(arr, i) {
    return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
}
function _to_consumable_array(arr) {
    return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
}
function _type_of(obj) {
    "@swc/helpers - typeof";
    return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
}
function _unsupported_iterable_to_array(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _array_like_to_array(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
function _is_native_reflect_construct() {
    try {
        var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
    } catch (_) {}
    return (_is_native_reflect_construct = function() {
        return !!result;
    })();
}
import { group, max, merge as arrayMerge, min, range, rollup } from "d3-array";
import { brush } from "d3-brush";
import { color } from "d3-color";
import { select } from "d3-selection";
import { scaleOrdinal } from "d3-scale";
import { zoom } from "d3-zoom";
import { colorAssign, colorContrast, colorDefaults } from "@d3plus/color";
import { addToQueue, merge, unique } from "@d3plus/data";
import { assign, date, getSize, inViewport } from "@d3plus/dom";
import { formatAbbreviate } from "@d3plus/format";
import { fontFamily, fontFamilyStringify } from "@d3plus/text";
import { ColorScale, Legend, TextBox, Timeline, Tooltip } from "../components/index.js";
import { accessor, BaseClass, constant } from "../utils/index.js";
// import {Rect} from "../shape/index.js";
import Message from "../components/Message.js";
import drawBack from "./drawSteps/drawBack.js";
import drawColorScale from "./drawSteps/drawColorScale.js";
import { default as drawLegend, legendLabel } from "./drawSteps/drawLegend.js";
import drawSubtitle from "./drawSteps/drawSubtitle.js";
import drawTimeline from "./drawSteps/drawTimeline.js";
import drawTitle from "./drawSteps/drawTitle.js";
import drawTotal from "./drawSteps/drawTotal.js";
import zoomControls from "./drawSteps/zoomControls.js";
import drawAttribution from "./drawSteps/drawAttribution.js";
import clickShape from "./events/click.shape.js";
import clickLegend from "./events/click.legend.js";
import mouseenter from "./events/mouseenter.js";
import mouseleave from "./events/mouseleave.js";
import mousemoveLegend from "./events/mousemove.legend.js";
import mousemoveShape from "./events/mousemove.shape.js";
import touchstartBody from "./events/touchstart.body.js";
function debounce(// eslint-disable-next-line @typescript-eslint/no-explicit-any
func, delay) {
    var timeout;
    return function() {
        for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
            args[_key] = arguments[_key];
        }
        var context = this;
        clearTimeout(timeout);
        timeout = setTimeout(function() {
            return func.apply(context, args);
        }, delay);
    };
}
/**
 * Default padding logic that will return false if the screen is less than 600 pixels wide.
 * @private
 */ function defaultPadding() {
    return typeof window !== "undefined" ? window.innerWidth > 600 : true;
}
/**
 * Turns an array of values into a list string.
 * @private
 */ function listify(n) {
    return n.reduce(function(str, item, i) {
        if (!i) str += item;
        else if (i === n.length - 1 && i === 1) str += " and ".concat(item);
        else if (i === n.length - 1) str += ", and ".concat(item);
        else str += ", ".concat(item);
        return str;
    }, "");
}
/**
 * A function that introspects the `d` Data Object for internally nested
 * d3plus data and indices, runs the accessor function on that user data.
 * @param {Function} acc Accessor function to use.
 * @param {Object} d Data Object
 * @param {Number} i Index of Data Object in Array
 * @private
 */ function accessorFetch(acc, d, i) {
    while(d.__d3plus__ && d.data){
        d = d.data;
        i = d.i;
    }
    return acc(d, i);
}
/**
    Minimal LRU cache backed by a Map (insertion-order iteration enables O(1) eviction).
    Only .get() and .set() are used by Viz.
    @private
*/ var LRU = /*#__PURE__*/ function() {
    "use strict";
    function LRU(capacity) {
        _class_call_check(this, LRU);
        _define_property(this, "_cap", void 0);
        _define_property(this, "_map", void 0);
        this._cap = capacity;
        this._map = new Map();
    }
    _create_class(LRU, [
        {
            key: "get",
            value: function get(key) {
                if (!this._map.has(key)) return undefined;
                var val = this._map.get(key);
                this._map.delete(key);
                this._map.set(key, val);
                return val;
            }
        },
        {
            key: "set",
            value: function set(key, val) {
                this._map.delete(key);
                if (this._map.size >= this._cap) this._map.delete(this._map.keys().next().value);
                this._map.set(key, val);
            }
        }
    ]);
    return LRU;
}();
var Viz = /*#__PURE__*/ function(BaseClass) {
    "use strict";
    _inherits(Viz, BaseClass);
    function Viz() {
        _class_call_check(this, Viz);
        var _this;
        _this = _call_super(this, Viz);
        _this._aggs = {};
        _this._ariaHidden = true;
        _this._attribution = false;
        var attributionBg = "rgba(255, 255, 255, 0.75)";
        _this._attributionStyle = {
            background: attributionBg,
            border: "1px solid rgba(0, 0, 0, 0.25)",
            color: colorContrast(attributionBg),
            display: "block",
            font: "400 11px/11px ".concat(fontFamilyStringify(fontFamily)),
            margin: "5px",
            opacity: 0.75,
            padding: "4px 6px 3px"
        };
        _this._backClass = new TextBox().on("click", function() {
            if (_this._history.length) _this.config(_this._history.pop()).render();
            else _this.depth(_this._drawDepth - 1).filter(false);
            _this.render();
        }).on("mousemove", function() {
            return _this._backClass.select().style("cursor", "pointer");
        });
        _this._backConfig = {
            fontSize: 10,
            padding: 5,
            resize: false
        };
        _this._cache = true;
        _this._color = function(d, i) {
            return _this._groupBy[0](d, i);
        };
        _this._colorDefaults = _object_spread_props(_object_spread({}, colorDefaults), {
            scale: scaleOrdinal().range(colorDefaults.scale.range())
        });
        _this._colorScaleClass = new ColorScale();
        _this._colorScaleConfig = {
            axisConfig: {
                rounding: "inside"
            },
            scale: "jenks"
        };
        _this._colorScalePadding = defaultPadding;
        _this._colorScalePosition = function() {
            return _this._width > _this._height * 1.5 ? "right" : "bottom";
        };
        _this._colorScaleMaxSize = 600;
        _this._data = [];
        _this._dataCutoff = 100;
        _this._detectResize = true;
        _this._detectResizeDelay = 400;
        _this._detectVisible = true;
        _this._detectVisibleInterval = 1000;
        _this._downloadButton = false;
        _this._downloadConfig = {
            type: "png"
        };
        _this._downloadPosition = "top";
        _this._duration = 600;
        _this._fontFamily = fontFamily;
        _this._hidden = [];
        _this._hiddenColor = constant("#aaa");
        _this._hiddenOpacity = constant(0.5);
        _this._history = [];
        _this._groupBy = [
            accessor("id")
        ];
        _this._legend = function(config, arr) {
            var maxGrouped = max(arr, function(d, i) {
                var id = _this._groupBy[_this._legendDepth].bind(_this)(d, i);
                return _instanceof(id, Array) ? id.length : 1;
            });
            return arr.length > 1 && (maxGrouped !== null && maxGrouped !== void 0 ? maxGrouped : 0) <= 2;
        };
        _this._legendClass = new Legend();
        _this._legendConfig = {
            label: legendLabel.bind(_this),
            shapeConfig: {
                ariaLabel: legendLabel.bind(_this),
                labelConfig: {
                    fontColor: undefined,
                    fontResize: false,
                    padding: 0
                }
            }
        };
        _this._legendFilterInvert = constant(false);
        _this._legendPadding = defaultPadding;
        _this._legendPosition = function() {
            return _this._width > _this._height * 1.5 ? "right" : "bottom";
        };
        _this._legendSort = function(a, b) {
            return _this._drawLabel(a).localeCompare(_this._drawLabel(b));
        };
        _this._legendTooltip = {};
        _this._loadingHTML = function() {
            return '\n    <div style="left: 50%; top: 50%; position: absolute; transform: translate(-50%, -50%);">\n      <strong>'.concat(_this._translate("Loading Visualization"), '</strong>\n      <sub style="bottom: 0; display: block; line-height: 1; margin-top: 5px;"><a href="https://d3plus.org" target="_blank">').concat(_this._translate("Powered by D3plus"), "</a></sub>\n    </div>");
        };
        _this._loadingMessage = true;
        _this._lrucache = new LRU(10);
        _this._messageClass = new Message();
        _this._messageMask = "rgba(0, 0, 0, 0.05)";
        _this._messageStyle = {
            bottom: "0",
            left: "0",
            position: "absolute",
            right: "0",
            "text-align": "center",
            top: "0"
        };
        _this._noDataHTML = function() {
            return '\n    <div style="left: 50%; top: 50%; position: absolute; transform: translate(-50%, -50%);">\n      <strong>'.concat(_this._translate("No Data Available"), "</strong>\n    </div>");
        };
        _this._noDataMessage = true;
        _this._on = {
            "click.shape": clickShape.bind(_this),
            "click.legend": clickLegend.bind(_this),
            mouseenter: mouseenter.bind(_this),
            mouseleave: mouseleave.bind(_this),
            "mousemove.shape": mousemoveShape.bind(_this),
            "mousemove.legend": mousemoveLegend.bind(_this)
        };
        _this._queue = [];
        _this._resizeObserver = new ResizeObserver(debounce(function(entries) {
            var _entries__contentRect = entries[0].contentRect, width = _entries__contentRect.width, height = _entries__contentRect.height;
            if ((width !== _this._width && _this._autoWidth || height !== _this._height && _this._autoHeight) && width && height) {
                _this._setSVGSize(width, height);
                if (!_this._callback) _this.render();
            }
        }, _this._detectResizeDelay));
        _this._scrollContainer = typeof window === "undefined" ? "" : window;
        _this._shape = constant("Rect");
        _this._shapes = [];
        _this._shapeConfig = {
            ariaLabel: function ariaLabel(d, i) {
                return _this._drawLabel(d, i);
            },
            fill: function fill(d, i) {
                while(d.__d3plus__ && d.data){
                    d = d.data;
                    i = d.i;
                }
                if (_this._colorScale) {
                    var c = _this._colorScale(d, i);
                    if (c !== undefined && c !== null) {
                        var scale = _this._colorScaleClass._colorScale;
                        var colors = _this._colorScaleClass.color();
                        if (!scale) return _instanceof(colors, Array) ? colors[colors.length - 1] : colors;
                        else if (!scale.domain().length) return scale.range()[scale.range().length - 1];
                        return scale(c);
                    }
                }
                var c1 = _this._color(d, i);
                if (color(c1)) return c1;
                return colorAssign(typeof c1 === "string" ? c1 : JSON.stringify(c1), _this._colorDefaults);
            },
            labelConfig: {
                fontColor: function fontColor(d, i) {
                    var c = typeof _this._shapeConfig.fill === "function" ? _this._shapeConfig.fill(d, i) : _this._shapeConfig.fill;
                    return colorContrast(c);
                }
            },
            opacity: constant(1),
            stroke: function stroke(d, i) {
                var c = typeof _this._shapeConfig.fill === "function" ? _this._shapeConfig.fill(d, i) : _this._shapeConfig.fill;
                return color(c).darker(0.25);
            },
            role: "presentation",
            strokeWidth: constant(0)
        };
        _this._solo = [];
        _this._subtitleClass = new TextBox();
        _this._subtitleConfig = {
            ariaHidden: true,
            fontSize: 12,
            padding: 5,
            resize: false,
            textAnchor: "middle"
        };
        _this._subtitlePadding = defaultPadding;
        _this._svgDesc = "";
        _this._svgTitle = "";
        _this._timeline = true;
        _this._timelineClass = new Timeline().align("end");
        _this._timelineConfig = {
            padding: 5
        };
        _this._timelinePadding = defaultPadding;
        _this._threshold = constant(0.0001);
        _this._thresholdKey = undefined;
        _this._thresholdName = function() {
            return _this._translate("Values");
        };
        _this._titleClass = new TextBox();
        _this._titleConfig = {
            ariaHidden: true,
            fontSize: 16,
            padding: 5,
            resize: false,
            textAnchor: "middle"
        };
        _this._titlePadding = defaultPadding;
        _this._tooltip = constant(true);
        _this._tooltipClass = new Tooltip();
        _this._tooltipConfig = {
            pointerEvents: "none",
            titleStyle: {
                "max-width": "200px"
            }
        };
        _this._totalClass = new TextBox();
        _this._totalConfig = {
            fontSize: 10,
            padding: 5,
            resize: false,
            textAnchor: "middle"
        };
        _this._totalFormat = function(d) {
            return "".concat(_this._translate("Total"), ": ").concat(formatAbbreviate(d, _this._locale));
        };
        _this._totalPadding = defaultPadding;
        _this._zoom = false;
        _this._zoomBehavior = zoom();
        _this._zoomBrush = brush();
        _this._zoomBrushHandleSize = 1;
        _this._zoomBrushHandleStyle = {
            fill: "#444"
        };
        _this._zoomBrushSelectionStyle = {
            fill: "#777",
            "stroke-width": 0
        };
        var zoomBg = "rgba(255, 255, 255, 0.75)";
        _this._zoomControlStyle = {
            background: zoomBg,
            border: "1px solid rgba(0, 0, 0, 0.75)",
            color: colorContrast(zoomBg),
            display: "block",
            font: "900 15px/21px ".concat(fontFamilyStringify(fontFamily)),
            height: "20px",
            margin: "5px",
            opacity: 0.75,
            padding: 0,
            "text-align": "center",
            width: "20px"
        };
        var zoomActiveBg = "rgba(0, 0, 0, 0.75)";
        _this._zoomControlStyleActive = {
            background: zoomActiveBg,
            color: colorContrast(zoomActiveBg),
            opacity: 1
        };
        _this._zoomControlStyleHover = {
            cursor: "pointer",
            opacity: 1
        };
        _this._zoomFactor = 2;
        _this._zoomMax = 16;
        _this._zoomPadding = 20;
        _this._zoomPan = true;
        _this._zoomScroll = true;
        return _this;
    }
    _create_class(Viz, [
        {
            /**
   Called by draw before anything is drawn. Formats the data and performs preparations for draw.
   @private
   */ key: "_preDraw",
            value: function _preDraw() {
                var _this = this;
                var _this1 = this;
                var that = this;
                // based on the groupBy, determine the draw depth and current depth id
                this._drawDepth = this._depth !== void 0 ? min([
                    this._depth >= 0 ? this._depth : 0,
                    this._groupBy.length - 1
                ]) : this._groupBy.length - 1;
                // Returns the current unique ID for a data point, coerced to a String.
                this._id = function(d, i) {
                    var groupByDrawDepth = accessorFetch(_this._groupBy[_this._drawDepth], d, i);
                    return typeof groupByDrawDepth === "number" ? "".concat(groupByDrawDepth) : groupByDrawDepth;
                };
                // Returns an array of the current unique groupBy ID for a data point, coerced to Strings.
                this._ids = function(d, i) {
                    return _this._groupBy.map(function(g) {
                        return "".concat(accessorFetch(g, d, i));
                    }).filter(Boolean);
                };
                this._drawLabel = function(d, i) {
                    var depth = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : _this1._drawDepth;
                    if (!d) return "";
                    while(d.__d3plus__ && d.data){
                        d = d.data;
                        i = d.i;
                    }
                    if (d._isAggregation) {
                        return "".concat(_this1._thresholdName(d, i), " < ").concat(formatAbbreviate(d._threshold * 100, _this1._locale), "%");
                    }
                    if (_this1._label && depth === _this1._drawDepth) return "".concat(_this1._label(d, i));
                    var l = that._ids(d, i).slice(0, depth + 1);
                    var n = l.reverse().find(function(ll) {
                        return !_instanceof(ll, Array);
                    }) || l[l.length - 1];
                    return _instanceof(n, Array) ? listify(n) : "".concat(n);
                };
                // set the default timeFilter if it has not been specified
                if (this._time && !this._timeFilter && this._data.length) {
                    var dates = this._data.map(this._time).map(date);
                    var d = this._data[0], i = 0;
                    if (this._discrete && "_".concat(this._discrete) in this && this["_".concat(this._discrete)](d, i) === this._time(d, i)) {
                        this._timeFilter = function() {
                            return true;
                        };
                    } else {
                        var latestTime = +max(dates);
                        this._timeFilter = function(d, i) {
                            return +date(_this._time(d, i)) === latestTime;
                        };
                    }
                }
                this._filteredData = [];
                this._legendData = [];
                var flatData = [];
                if (this._data.length) {
                    flatData = this._timeFilter ? this._data.filter(this._timeFilter) : this._data;
                    if (this._filter) flatData = flatData.filter(this._filter);
                    var nestKeys = [];
                    for(var i1 = 0; i1 <= this._drawDepth; i1++)nestKeys.push(this._groupBy[i1]);
                    if (this._discrete && "_".concat(this._discrete) in this) nestKeys.push(this["_".concat(this._discrete)]);
                    if (this._discrete && "_".concat(this._discrete, "2") in this) nestKeys.push(this["_".concat(this._discrete, "2")]);
                    var tree = rollup.apply(void 0, [
                        flatData,
                        function(leaves) {
                            var index = _this._data.indexOf(leaves[0]);
                            var shape = _this._shape(leaves[0], index);
                            var id = _this._id(leaves[0], index);
                            var d = merge(leaves, _this._aggs);
                            if (!_this._hidden.includes(id) && (!_this._solo.length || _this._solo.includes(id))) {
                                if (!_this._discrete && shape === "Line") _this._filteredData = _this._filteredData.concat(leaves);
                                else _this._filteredData.push(d);
                            }
                            _this._legendData.push(d);
                        }
                    ].concat(_to_consumable_array(nestKeys)));
                    this._filteredData = this._thresholdFunction(this._filteredData, tree);
                }
                // overrides the hoverOpacity of shapes if data is larger than cutoff
                var uniqueIds = group(this._filteredData, this._id).size;
                if (uniqueIds > this._dataCutoff) {
                    if (this._userHover === undefined) this._userHover = this._shapeConfig.hoverOpacity || 0.5;
                    if (this._userDuration === undefined) this._userDuration = this._shapeConfig.duration || 600;
                    this._shapeConfig.hoverOpacity = 1;
                    this._shapeConfig.duration = 0;
                } else if (this._userHover !== undefined) {
                    this._shapeConfig.hoverOpacity = this._userHover;
                    this._shapeConfig.duration = this._userDuration;
                }
                if (this._noDataMessage && !this._filteredData.length) {
                    this._messageClass.render({
                        container: this._select.node().parentNode,
                        html: this._noDataHTML(this),
                        mask: false,
                        style: this._messageStyle
                    });
                    this._select.transition().duration(this._duration).attr("opacity", 0);
                }
            }
        },
        {
            /**
      Called by render once all checks are passed.
      @private
  */ key: "_draw",
            value: function _draw() {
                // Sanitizes user input for legendPosition and colorScalePosition
                var legendPosition = this._legendPosition.bind(this)(this.config());
                if (![
                    false,
                    "top",
                    "bottom",
                    "left",
                    "right"
                ].includes(legendPosition)) legendPosition = "bottom";
                var colorScalePosition = this._colorScalePosition.bind(this)(this.config());
                if (![
                    false,
                    "top",
                    "bottom",
                    "left",
                    "right"
                ].includes(colorScalePosition)) colorScalePosition = "bottom";
                // Draws legend and colorScale if they are positioned "left" or "right"
                if (legendPosition === "left" || legendPosition === "right") drawLegend.bind(this)(this._legendData);
                if (colorScalePosition === "left" || colorScalePosition === "right" || colorScalePosition === false) drawColorScale.bind(this)();
                // Draws all of the top/bottom UI elements
                drawBack.bind(this)();
                drawTitle.bind(this)(this._filteredData);
                drawSubtitle.bind(this)(this._filteredData);
                drawTotal.bind(this)(this._filteredData);
                drawTimeline.bind(this)(this._filteredData);
                // Draws legend and colorScale if they are positioned "top" or "bottom"
                if (legendPosition === "top" || legendPosition === "bottom") drawLegend.bind(this)(this._legendData);
                if (colorScalePosition === "top" || colorScalePosition === "bottom") drawColorScale.bind(this)();
                this._shapes = [];
            // Draws a container and zoomGroup to test functionality.
            // this._testGroup = this._select.selectAll("g.d3plus-viz-testGroup").data([0]);
            // const enterTest = this._testGroup.enter().append("g").attr("class", "d3plus-viz-testGroup")
            //   .merge(this._testGroup);
            // this._testGroup = enterTest.merge(this._testGroup);
            // const bgHeight = this._height - this._margin.top - this._margin.bottom;
            // const bgWidth = this._width - this._margin.left - this._margin.right;
            // new Rect()
            //   .data([{id: "background"}])
            //   .select(this._testGroup.node())
            //   .x(bgWidth / 2 + this._margin.left)
            //   .y(bgHeight / 2 + this._margin.top)
            //   .width(bgWidth)
            //   .height(bgHeight)
            //   .fill("#ccc")
            //   .render();
            // this._zoomGroup = this._select.selectAll("g.d3plus-viz-zoomGroup").data([0]);
            // const enter = this._zoomGroup.enter().append("g").attr("class", "d3plus-viz-zoomGroup")
            //   .merge(this._zoomGroup);
            // this._zoomGroup = enter.merge(this._zoomGroup);
            // const testConfig = {
            //   on: {
            //     click: this._on["click.shape"],
            //     mouseenter: this._on.mouseenter,
            //     mouseleave: this._on.mouseleave,
            //     mousemove: this._on["mousemove.shape"]
            //   }
            // };
            // const testWidth = 50;
            // this._shapes.push(new Rect()
            //   .config(this._shapeConfig)
            //   .config(configPrep.bind(this)(testConfig))
            //   .data(this._filteredData)
            //   .label("Test Label")
            //   .select(this._zoomGroup.node())
            //   .id(this._id)
            //   .x(d => {
            //     if (!d.x) d.x = Math.random() * bgWidth;
            //     return d.x;
            //   })
            //   .y(d => {
            //     if (!d.y) d.y = Math.random() * bgHeight;
            //     return d.y;
            //   })
            //   .width(testWidth)
            //   .height(testWidth)
            //   .render());
            }
        },
        {
            /**
   * Applies the threshold algorithm according to the type of chart used.
   * @param {Array} data The data to process.
   * @private
   */ key: "_thresholdFunction",
            value: function _thresholdFunction(data, _tree) {
                return data;
            }
        },
        {
            /**
   * Detects width and height and sets SVG properties
   * @private
   */ key: "_setSVGSize",
            value: function _setSVGSize(width, height) {
                var _ref = _sliced_to_array(width && height ? [
                    width,
                    height
                ] : getSize(this._select.node().parentNode), 2), w = _ref[0], h = _ref[1];
                w -= parseFloat(this._select.style("border-left-width"));
                w -= parseFloat(this._select.style("border-right-width"));
                h -= parseFloat(this._select.style("border-top-width"));
                h -= parseFloat(this._select.style("border-bottom-width"));
                if (this._autoWidth && this._width !== w) {
                    this.width(w);
                    this._select.style("width", "".concat(this._width, "px")).attr("width", "".concat(this._width, "px"));
                }
                if (this._autoHeight && this._height !== h) {
                    this.height(h);
                    this._select.style("height", "".concat(this._height, "px")).attr("height", "".concat(this._height, "px"));
                }
            }
        },
        {
            /**
      Draws the visualization given the specified configuration.
    @param callback Optional callback invoked after rendering completes.
  */ key: "render",
            value: function render(callback) {
                var _this = this;
                this._callback = callback;
                // Resets margins and padding
                this._margin = {
                    bottom: 0,
                    left: 0,
                    right: 0,
                    top: 0
                };
                this._padding = {
                    bottom: 0,
                    left: 0,
                    right: 0,
                    top: 0
                };
                // Appends a fullscreen SVG to the BODY if a container has not been provided through .select().
                if (this._select === void 0 || this._select.node().tagName.toLowerCase() !== "svg") {
                    var parent = this._select === void 0 ? select("body").insert("div", "#d3plus-portal").style("height", "100dvh").style("width", "100%").style("min-height", "150px") : this._select;
                    var svg = parent.select(".d3plus-viz").size() ? parent.select(".d3plus-viz") : parent.append("svg");
                    this.select(svg.node());
                }
                // Calculates the width and/or height of the Viz based on the this._select, if either has not been defined.
                if ((!this._width || !this._height) && (!this._detectVisible || inViewport(this._select.node()))) {
                    this._autoWidth = this._width === undefined;
                    this._autoHeight = this._height === undefined;
                    this._setSVGSize();
                }
                var parent1 = select(this._select.node().parentNode);
                this._select.attr("class", "d3plus-viz").attr("aria-hidden", this._ariaHidden).attr("aria-labelledby", "".concat(this._uuid, "-title ").concat(this._uuid, "-desc")).attr("role", "img").attr("xmlns", "http://www.w3.org/2000/svg").attr("xmlns:xlink", "http://www.w3.org/1999/xlink").style("position", "absolute").style("top", parent1.style("padding-top")).style("left", parent1.style("padding-left")).transition().duration(this._duration).style("width", this._width !== undefined ? "".concat(this._width, "px") : undefined).style("height", this._height !== undefined ? "".concat(this._height, "px") : undefined).attr("width", this._width !== undefined ? "".concat(this._width, "px") : undefined).attr("height", this._height !== undefined ? "".concat(this._height, "px") : undefined);
                // sets "position: relative" on the SVG parent if currently undefined
                var position = parent1.style("position");
                if (position === "static") parent1.style("position", "relative");
                parent1.style("font-family", fontFamilyStringify(this._fontFamily));
                // sets initial opacity to 1, if it has not already been set
                if (this._select.attr("opacity") === null) this._select.attr("opacity", 1);
                // Updates the <title> tag if already exists else creates a new <title> tag on this.select.
                var svgTitle = this._select.selectAll("title").data([
                    0
                ]);
                var svgTitleEnter = svgTitle.enter().append("title").attr("id", "".concat(this._uuid, "-title"));
                svgTitle.merge(svgTitleEnter).text(this._svgTitle);
                // Updates the <desc> tag if already exists else creates a new <desc> tag on this.select.
                var svgDesc = this._select.selectAll("desc").data([
                    0
                ]);
                var svgDescEnter = svgDesc.enter().append("desc").attr("id", "".concat(this._uuid, "-desc"));
                svgDesc.merge(svgDescEnter).text(this._svgDesc);
                this._visiblePoll = clearInterval(this._visiblePoll);
                this._resizePoll = clearTimeout(this._resizePoll);
                this._scrollPoll = clearTimeout(this._scrollPoll);
                select(this._scrollContainer).on("scroll.".concat(this._uuid), null);
                if (this._detectVisible && this._select.style("visibility") === "hidden") {
                    this._visiblePoll = setInterval(function() {
                        if (_this._select.style("visibility") !== "hidden") {
                            _this._visiblePoll = clearInterval(_this._visiblePoll);
                            _this.render(callback);
                        }
                    }, this._detectVisibleInterval);
                } else if (this._detectVisible && this._select.style("display") === "none") {
                    this._visiblePoll = setInterval(function() {
                        if (_this._select.style("display") !== "none") {
                            _this._visiblePoll = clearInterval(_this._visiblePoll);
                            _this.render(callback);
                        }
                    }, this._detectVisibleInterval);
                } else if (this._detectVisible && !inViewport(this._select.node())) {
                    select(this._scrollContainer).on("scroll.".concat(this._uuid), function() {
                        if (!_this._scrollPoll) {
                            _this._scrollPoll = setTimeout(function() {
                                if (inViewport(_this._select.node())) {
                                    select(_this._scrollContainer).on("scroll.".concat(_this._uuid), null);
                                    _this.render(callback);
                                }
                                _this._scrollPoll = clearTimeout(_this._scrollPoll);
                            }, _this._detectVisibleInterval);
                        }
                    });
                } else {
                    var promises = [];
                    this._queue.forEach(function(p) {
                        var cache = _this._cache ? _this._lrucache.get("".concat(p[3], "_").concat(p[1])) : undefined;
                        if (!cache) {
                            promises.push(new Promise(function(resolve) {
                                p[0](p[1], p[2], p[3], function(err) {
                                    if (err) console.error(err);
                                    resolve();
                                });
                            }));
                        } else _this["_".concat(p[3])] = p[2] ? p[2](cache) : cache;
                    });
                    this._queue = [];
                    if (this._loadingMessage && promises.length) {
                        this._messageClass.render({
                            container: this._select.node().parentNode,
                            html: this._loadingHTML(this),
                            mask: this._filteredData ? this._messageMask : false,
                            style: this._messageStyle
                        });
                    }
                    Promise.all(promises).then(function() {
                        // creates a data table as DOM elements inside of the SVG for accessibility
                        // only if this._ariaHidden is set to true
                        var columns = _instanceof(_this._data, Array) && _this._data.length > 0 ? Object.keys(_this._data[0]) : [];
                        var svgTable = _this._select.selectAll("g.data-table").data(!_this._ariaHidden && _instanceof(_this._data, Array) && _this._data.length ? [
                            0
                        ] : []);
                        var svgTableEnter = svgTable.enter().append("g").attr("class", "data-table").attr("role", "table");
                        svgTable.exit().remove();
                        var rows = svgTable.merge(svgTableEnter).selectAll("text").data(_instanceof(_this._data, Array) ? range(0, _this._data.length + 1) : []);
                        rows.exit().remove();
                        var cells = rows.merge(rows.enter().append("text").attr("role", "row")).selectAll("tspan").data(function(d, i) {
                            return columns.map(function(c) {
                                return {
                                    role: i ? "cell" : "columnheader",
                                    text: i ? _this._data[i - 1][c] : c
                                };
                            });
                        });
                        cells.exit().remove();
                        cells.merge(cells.enter().append("tspan")).attr("role", function(d) {
                            return d.role;
                        }).attr("dy", "-1000px").html(function(d) {
                            return d.text;
                        });
                        // finishes the draw cycle
                        _this._preDraw();
                        _this._draw();
                        zoomControls.bind(_this)();
                        drawAttribution.bind(_this)();
                        if (_this._messageClass._isVisible && (!_this._noDataMessage || _this._filteredData.length)) {
                            _this._messageClass.hide();
                            if (_this._select.attr("opacity") === "0") _this._select.transition().duration(_this._duration).attr("opacity", 1);
                        }
                        if (_this._detectResize && (_this._autoWidth || _this._autoHeight)) {
                            _this._resizeObserver.observe(_this._select.node().parentNode);
                        } else {
                            _this._resizeObserver.unobserve(_this._select.node().parentNode);
                        }
                        if (callback) setTimeout(function() {
                            callback();
                            _this._callback = undefined;
                        }, _this._duration + 100);
                    });
                }
                // Attaches touchstart event listener to the BODY to hide the tooltip when the user touches any element without data
                select("body").on("touchstart.".concat(this._uuid), touchstartBody.bind(this));
                return this;
            }
        },
        {
            /**
      Tears down the visualization: disconnects the ResizeObserver and removes DOM event listeners. Call this when unmounting to avoid memory leaks.
  */ key: "destroy",
            value: function destroy() {
                this._resizeObserver.disconnect();
                this._tooltipClass.data([]).render();
                select("body").on("touchstart.".concat(this._uuid), null);
                return this;
            }
        },
        {
            /**
      The active callback function for highlighting shapes.
*/ key: "active",
            value: function active(_) {
                this._active = _;
                if (this._shapeConfig.activeOpacity !== 1) {
                    this._shapes.forEach(function(s) {
                        return s.active(_);
                    });
                    if (this._legend) this._legendClass.active(_);
                }
                return this;
            }
        },
        {
            /**
      Custom aggregation methods for each data key.
*/ key: "aggs",
            value: function aggs(_) {
                return arguments.length ? (this._aggs = assign(this._aggs, _), this) : this._aggs;
            }
        },
        {
            /**
      The "aria-hidden" attribute of the containing SVG element. The default value is "false", but if you need to hide the SVG from screen readers set this property to "true".
*/ key: "ariaHidden",
            value: function ariaHidden(_) {
                return arguments.length ? (this._ariaHidden = _, this) : this._ariaHidden;
            }
        },
        {
            /**
      Sets text to be shown positioned absolute on top of the visualization in the bottom-right corner. This is most often used in Geomaps to display the copyright of map tiles. The text is rendered as HTML, so any valid HTML string will render as expected (eg. anchor links work).
*/ key: "attribution",
            value: function attribution(_) {
                return arguments.length ? (this._attribution = _, this) : this._attribution;
            }
        },
        {
            /**
      Configuration object for the attribution style.
*/ key: "attributionStyle",
            value: function attributionStyle(_) {
                return arguments.length ? (this._attributionStyle = assign(this._attributionStyle, _), this) : this._attributionStyle;
            }
        },
        {
            /**
      Configuration object for the back button.
*/ key: "backConfig",
            value: function backConfig(_) {
                return arguments.length ? (this._backConfig = assign(this._backConfig, _), this) : this._backConfig;
            }
        },
        {
            /**
      Enables a lru cache that stores up to 5 previously loaded files/URLs. Helpful when constantly writing over the data array with a URL in the render function of a react component.
*/ key: "cache",
            value: function cache(_) {
                return arguments.length ? (this._cache = _, this) : this._cache;
            }
        },
        {
            /**
      Defines the main color to be used for each data point in a visualization. Can be either an accessor function or a string key to reference in each data point. If a color value is returned, it will be used as is. If a string is returned, a unique color will be assigned based on the string.
*/ key: "color",
            value: function color(_) {
                return arguments.length ? (this._color = !_ || typeof _ === "function" ? _ : accessor(_), this) : this._color;
            }
        },
        {
            /**
      Defines the value to be used for a color scale. Can be either an accessor function or a string key to reference in each data point.
*/ key: "colorScale",
            value: function colorScale(_) {
                return arguments.length ? (this._colorScale = !_ || typeof _ === "function" ? _ : accessor(_), this) : this._colorScale;
            }
        },
        {
            /**
      A pass-through to the config method of ColorScale.
*/ key: "colorScaleConfig",
            value: function colorScaleConfig(_) {
                return arguments.length ? (this._colorScaleConfig = assign(this._colorScaleConfig, _), this) : this._colorScaleConfig;
            }
        },
        {
            /**
      Tells the colorScale whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the colorScale appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "colorScalePadding",
            value: function colorScalePadding(_) {
                return arguments.length ? (this._colorScalePadding = typeof _ === "function" ? _ : constant(_), this) : this._colorScalePadding;
            }
        },
        {
            /**
      Defines which side of the visualization to anchor the color scale. Acceptable values are `"top"`, `"bottom"`, `"left"`, `"right"`, and `false`. A `false` value will cause the color scale to not be displayed, but will still color shapes based on the scale.
*/ key: "colorScalePosition",
            value: function colorScalePosition(_) {
                return arguments.length ? (this._colorScalePosition = typeof _ === "function" ? _ : constant(_), this) : this._colorScalePosition;
            }
        },
        {
            /**
      The maximum pixel size for drawing the color scale: width for horizontal scales and height for vertical scales.
*/ key: "colorScaleMaxSize",
            value: function colorScaleMaxSize(_) {
                return arguments.length ? (this._colorScaleMaxSize = _, this) : this._colorScaleMaxSize;
            }
        },
        {
            /**
      The primary data array used to draw the visualization. The value passed should be an *Array* of objects or a *String* representing a filepath or URL to be loaded. The following filetypes are supported: `csv`, `tsv`, `txt`, and `json`.

If your data URL needs specific headers to be set, an Object with "url" and "headers" keys may also be passed.

Additionally, a custom formatting function can be passed as a second argument to this method. This custom function will be passed the data that has been loaded, as long as there are no errors. This function should return the final array of obejcts to be used as the primary data array. For example, some JSON APIs return the headers split from the data values to save bandwidth. These would need be joined using a custom formatter.

If you would like to specify certain configuration options based on the yet-to-be-loaded data, you can also return a full `config` object from the data formatter (including the new `data` array as a key in the object).

Defaults to an empty array (`[]`).
    @param f The data array or a URL string to load data from.
  */ key: "data",
            value: function data(_, f) {
                if (arguments.length) {
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    addToQueue.bind(this)(_, f, "data");
                    this._hidden = [];
                    this._solo = [];
                    if (this._userData && JSON.stringify(_) !== JSON.stringify(this._userData)) {
                        this._timeFilter = false;
                        this._timelineSelection = false;
                    }
                    this._userData = _;
                    return this;
                }
                return this._data;
            }
        },
        {
            /**
      If the number of visible data points exceeds this number, the default hover behavior will be disabled (helpful for very large visualizations bogging down the DOM with opacity updates).
*/ key: "dataCutoff",
            value: function dataCutoff(_) {
                return arguments.length ? (this._dataCutoff = _, this) : this._dataCutoff;
            }
        },
        {
            /**
      The current depth of the visualization. The value should correspond with an index in the [groupBy](#groupBy) array.
*/ key: "depth",
            value: function depth(_) {
                return arguments.length ? (this._depth = _, this) : this._depth;
            }
        },
        {
            /**
      If the width and/or height of a Viz is not user-defined, it is determined by the size of it's parent element. When this method is set to `true`, the Viz will listen for the `window.onresize` event and adjust it's dimensions accordingly.
*/ key: "detectResize",
            value: function detectResize(_) {
                return arguments.length ? (this._detectResize = _, this) : this._detectResize;
            }
        },
        {
            /**
      When resizing the browser window, this is the millisecond delay to trigger the resize event.
*/ key: "detectResizeDelay",
            value: function detectResizeDelay(_) {
                return arguments.length ? (this._detectResizeDelay = _, this) : this._detectResizeDelay;
            }
        },
        {
            /**
      Toggles whether or not the Viz should try to detect if it visible in the current viewport. When this method is set to `true`, the Viz will only be rendered when it has entered the viewport either through scrolling or if it's display or visibility is changed.
*/ key: "detectVisible",
            value: function detectVisible(_) {
                return arguments.length ? (this._detectVisible = _, this) : this._detectVisible;
            }
        },
        {
            /**
      The interval, in milliseconds, for checking if the visualization is visible on the page.
*/ key: "detectVisibleInterval",
            value: function detectVisibleInterval(_) {
                return arguments.length ? (this._detectVisibleInterval = _, this) : this._detectVisibleInterval;
            }
        },
        {
            /**
      If *value* is specified, sets the discrete accessor to the specified method name (usually an axis) and returns the current class instance.
*/ key: "discrete",
            value: function discrete(_) {
                return arguments.length ? (this._discrete = _, this) : this._discrete;
            }
        },
        {
            /**
      Shows a button that allows for downloading the current visualization.
*/ key: "downloadButton",
            value: function downloadButton(_) {
                return arguments.length ? (this._downloadButton = _, this) : this._downloadButton;
            }
        },
        {
            /**
      Sets specific options of the saveElement function used when downloading the visualization.
*/ key: "downloadConfig",
            value: function downloadConfig(_) {
                return arguments.length ? (this._downloadConfig = assign(this._downloadConfig, _), this) : this._downloadConfig;
            }
        },
        {
            /**
      Defines which control group to add the download button into.
*/ key: "downloadPosition",
            value: function downloadPosition(_) {
                return arguments.length ? (this._downloadPosition = _, this) : this._downloadPosition;
            }
        },
        {
            /**
      The animation duration in milliseconds.
*/ key: "duration",
            value: function duration(_) {
                return arguments.length ? (this._duration = _, this) : this._duration;
            }
        },
        {
            /**
      A filter function applied to the data before drawing.
*/ key: "filter",
            value: function filter(_) {
                return arguments.length ? (this._filter = _, this) : this._filter;
            }
        },
        {
            /**
      The font family used throughout the visualization.
*/ key: "fontFamily",
            value: function fontFamily(_) {
                var _this = this;
                if (arguments.length) {
                    var labelConfig = {
                        fontFamily: _
                    };
                    var axisConfig = {
                        titleConfig: labelConfig,
                        shapeConfig: {
                            labelConfig: labelConfig
                        }
                    };
                    this.shapeConfig({
                        labelConfig: labelConfig
                    });
                    this.colorScaleConfig({
                        axisConfig: axisConfig
                    });
                    [
                        "axis",
                        "column",
                        "row",
                        "timeline",
                        "x",
                        "y",
                        "x2",
                        "y2"
                    ].forEach(function(axis) {
                        var method = "".concat(axis, "Config");
                        if (_this[method]) _this[method](axisConfig);
                    });
                    [
                        "back",
                        "title",
                        "total",
                        "subtitle"
                    ].forEach(function(label) {
                        var method = "".concat(label, "Config");
                        if (_this[method]) _this[method](labelConfig);
                    });
                    this.tooltipConfig({
                        tooltipStyle: {
                            "font-family": fontFamilyStringify(_)
                        }
                    });
                    this._fontFamily = _;
                    return this;
                }
                return this._fontFamily;
            }
        },
        {
            /**
      Defines the mapping between data and shape. The value can be a String matching a key in each data point (default is "id"), or an accessor Function that returns a unique value for each data point. Additionally, an Array of these values may be provided if the visualization supports nested hierarchies.
*/ key: "groupBy",
            value: function groupBy(_) {
                var _this = this;
                if (!arguments.length) return this._groupBy;
                this._groupByRaw = _;
                var arr = _instanceof(_, Array) ? _ : [
                    _
                ];
                return this._groupBy = arr.map(function(k) {
                    if (typeof k === "function") return k;
                    else {
                        if (!_this._aggs[k]) {
                            _this._aggs[k] = function(a, c) {
                                var v = unique(a.map(c));
                                return v.length === 1 ? v[0] : v;
                            };
                        }
                        return accessor(k);
                    }
                }), this;
            }
        },
        {
            /**
      The overall height of the visualization in pixels.
*/ key: "height",
            value: function height(_) {
                return arguments.length ? (this._height = _, this) : this._height;
            }
        },
        {
            /**
      Defines the color used for legend shapes when the corresponding grouping is hidden from display (by clicking on the legend).
*/ key: "hiddenColor",
            value: function hiddenColor(_) {
                return arguments.length ? (this._hiddenColor = typeof _ === "function" ? _ : constant(_), this) : this._hiddenColor;
            }
        },
        {
            /**
      Defines the opacity used for legend labels when the corresponding grouping is hidden from display (by clicking on the legend).
*/ key: "hiddenOpacity",
            value: function hiddenOpacity(_) {
                return arguments.length ? (this._hiddenOpacity = typeof _ === "function" ? _ : constant(_), this) : this._hiddenOpacity;
            }
        },
        {
            /**
      The hover callback function for highlighting shapes on mouseover.
*/ key: "hover",
            value: function hover(_) {
                var _this = this;
                var hoverFunction = this._hover = _;
                if (this._shapeConfig.hoverOpacity !== 1 && _ !== undefined) {
                    if (typeof _ === "function") {
                        var shapeData = arrayMerge(this._shapes.map(function(s) {
                            return s.data();
                        }));
                        shapeData = shapeData.concat(this._legendClass.data());
                        var activeData = _ ? shapeData.filter(_) : [];
                        var activeIds = [];
                        activeData.map(this._ids).forEach(function(ids) {
                            for(var x = 1; x <= ids.length; x++){
                                activeIds.push(JSON.stringify(ids.slice(0, x)));
                            }
                        });
                        activeIds = activeIds.filter(function(id, i) {
                            return activeIds.indexOf(id) === i;
                        });
                        if (activeIds.length) hoverFunction = function hoverFunction(d, i) {
                            return activeIds.includes(JSON.stringify(_this._ids(d, i)));
                        };
                    }
                    this._shapes.forEach(function(s) {
                        return s.hover(hoverFunction);
                    });
                    if (this._legend) this._legendClass.hover(hoverFunction);
                }
                return this;
            }
        },
        {
            /**
      Accessor function or string key for the label of each data point.
*/ key: "label",
            value: function label(_) {
                return arguments.length ? (this._label = typeof _ === "function" ? _ : constant(_), this) : this._label;
            }
        },
        {
            /**
      Whether to display the legend.
*/ key: "legend",
            value: function legend(_) {
                return arguments.length ? (this._legend = typeof _ === "function" ? _ : constant(_), this) : this._legend;
            }
        },
        {
            /**
      Configuration object passed to the legend's config method.
*/ key: "legendConfig",
            value: function legendConfig(_) {
                return arguments.length ? (this._legendConfig = assign(this._legendConfig, _), this) : this._legendConfig;
            }
        },
        {
            /**
      Defines the click functionality of categorical legend squares. When set to false, clicking will hide that category and shift+clicking will solo that category. When set to true, clicking with solo that category and shift+clicking will hide that category.
*/ key: "legendFilterInvert",
            value: function legendFilterInvert(_) {
                return arguments.length ? (this._legendFilterInvert = typeof _ === "function" ? _ : constant(_), this) : this._legendFilterInvert;
            }
        },
        {
            /**
      Tells the legend whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the legend appears centered underneath the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "legendPadding",
            value: function legendPadding(_) {
                return arguments.length ? (this._legendPadding = typeof _ === "function" ? _ : constant(_), this) : this._legendPadding;
            }
        },
        {
            /**
      Defines which side of the visualization to anchor the legend. Expected values are `"top"`, `"bottom"`, `"left"`, and `"right"`.
*/ key: "legendPosition",
            value: function legendPosition(_) {
                return arguments.length ? (this._legendPosition = typeof _ === "function" ? _ : constant(_), this) : this._legendPosition;
            }
        },
        {
            /**
      A JavaScript [sort comparator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) used to sort the legend.
*/ key: "legendSort",
            value: function legendSort(_) {
                return arguments.length ? (this._legendSort = _, this) : this._legendSort;
            }
        },
        {
            /**
      Configuration object for the legend tooltip.
*/ key: "legendTooltip",
            value: function legendTooltip(_) {
                return arguments.length ? (this._legendTooltip = assign(this._legendTooltip, _), this) : this._legendTooltip;
            }
        },
        {
            /**
      The inner HTML of the status message displayed when loading AJAX requests and displaying errors. Must be a valid HTML string or a function that, when passed this Viz instance, returns a valid HTML string.
*/ key: "loadingHTML",
            value: function loadingHTML(_) {
                return arguments.length ? (this._loadingHTML = typeof _ === "function" ? _ : constant(_), this) : this._loadingHTML;
            }
        },
        {
            /**
      Toggles the visibility of the status message that is displayed when loading AJAX requests and displaying errors.
*/ key: "loadingMessage",
            value: function loadingMessage(_) {
                return arguments.length ? (this._loadingMessage = _, this) : this._loadingMessage;
            }
        },
        {
            /**
      The color of the mask displayed underneath the status message when loading AJAX requests and displaying errors. Set to `false` to turn off the mask completely.
*/ key: "messageMask",
            value: function messageMask(_) {
                return arguments.length ? (this._messageMask = _, this) : this._messageMask;
            }
        },
        {
            /**
      Defines the CSS style properties for the status message that is displayed when loading AJAX requests and displaying errors.
*/ key: "messageStyle",
            value: function messageStyle(_) {
                return arguments.length ? (this._messageStyle = assign(this._messageStyle, _), this) : this._messageStyle;
            }
        },
        {
            /**
      The inner HTML of the status message displayed when no data is supplied to the visualization. Must be a valid HTML string or a function that, when passed this Viz instance, returns a valid HTML string.
*/ key: "noDataHTML",
            value: function noDataHTML(_) {
                return arguments.length ? (this._noDataHTML = typeof _ === "function" ? _ : constant(_), this) : this._noDataHTML;
            }
        },
        {
            /**
     Toggles the visibility of the status message that is displayed when no data is supplied to the visualization.
*/ key: "noDataMessage",
            value: function noDataMessage(_) {
                return arguments.length ? (this._noDataMessage = _, this) : this._noDataMessage;
            }
        },
        {
            /**
      If using scroll or visibility detection, this method allow a custom override of the element to which the scroll detection function gets attached.
*/ key: "scrollContainer",
            value: function scrollContainer(_) {
                return arguments.length ? (this._scrollContainer = _, this) : this._scrollContainer;
            }
        },
        {
            /**
      The SVG container element as a d3 selector or DOM element. Defaults to `undefined`.
*/ key: "select",
            value: function select1(_) {
                return arguments.length ? (this._select = select(_), this) : this._select;
            }
        },
        {
            /**
      Changes the primary shape used to represent each data point in a visualization. Not all visualizations support changing shapes, this method can be provided the String name of a D3plus shape class (for example, "Rect" or "Circle"), or an accessor Function that returns the String class name to be used for each individual data point.
*/ key: "shape",
            value: function shape(_) {
                return arguments.length ? (this._shape = typeof _ === "function" ? _ : constant(_), this) : this._shape;
            }
        },
        {
            /**
      Configuration object with key/value pairs applied as method calls on each shape.
*/ key: "shapeConfig",
            value: function shapeConfig(_) {
                return arguments.length ? (this._shapeConfig = assign(this._shapeConfig, _), this) : this._shapeConfig;
            }
        },
        {
            /**
      Accessor function or string for the visualization's subtitle.
*/ key: "subtitle",
            value: function subtitle(_) {
                return arguments.length ? (this._subtitle = typeof _ === "function" ? _ : constant(_), this) : this._subtitle;
            }
        },
        {
            /**
      Configuration object for the subtitle.
*/ key: "subtitleConfig",
            value: function subtitleConfig(_) {
                return arguments.length ? (this._subtitleConfig = assign(this._subtitleConfig, _), this) : this._subtitleConfig;
            }
        },
        {
            /**
      Tells the subtitle whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the subtitle appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "subtitlePadding",
            value: function subtitlePadding(_) {
                return arguments.length ? (this._subtitlePadding = typeof _ === "function" ? _ : constant(_), this) : this._subtitlePadding;
            }
        },
        {
            /**
      The description text for the SVG `<desc>` element, used for accessibility.
*/ key: "svgDesc",
            value: function svgDesc(_) {
                return arguments.length ? (this._svgDesc = _, this) : this._svgDesc;
            }
        },
        {
            /**
      The title text for the SVG `<title>` element, used for accessibility.
*/ key: "svgTitle",
            value: function svgTitle(_) {
                return arguments.length ? (this._svgTitle = _, this) : this._svgTitle;
            }
        },
        {
            /**
      The threshold value for bucketing small data points together.
*/ key: "threshold",
            value: function threshold(_) {
                if (arguments.length) {
                    if (typeof _ === "function") {
                        this._threshold = _;
                    } else if (isFinite(_) && !isNaN(_)) {
                        this._threshold = constant(_ * 1);
                    }
                    return this;
                } else return this._threshold;
            }
        },
        {
            /**
      Accessor for the value used in the threshold algorithm.
    @param key The data key used to group values for thresholding.
*/ key: "thresholdKey",
            value: function thresholdKey(key) {
                if (arguments.length) {
                    if (typeof key === "function") {
                        this._thresholdKey = key;
                    } else {
                        this._thresholdKey = accessor(key);
                    }
                    return this;
                } else return this._thresholdKey;
            }
        },
        {
            /**
      The label displayed for bucketed threshold items.
*/ key: "thresholdName",
            value: function thresholdName(_) {
                return arguments.length ? (this._thresholdName = typeof _ === "function" ? _ : constant(_), this) : this._thresholdName;
            }
        },
        {
            /**
      Accessor function or string key for the time dimension of each data point.
*/ key: "time",
            value: function time(_) {
                if (arguments.length) {
                    if (typeof _ === "function") {
                        this._time = _;
                    } else if (_) {
                        this._time = accessor(_);
                        if (!this._aggs[_]) {
                            this._aggs[_] = function(a, c) {
                                var v = unique(a.map(c));
                                return v.length === 1 ? v[0] : v;
                            };
                        }
                        if (this._userTime && JSON.stringify(_) !== JSON.stringify(this._userTime)) {
                            this._timeFilter = false;
                            this._timelineSelection = false;
                        }
                        this._userTime = _;
                    } else {
                        this._time = undefined;
                        this._userTime = undefined;
                        this._timeFilter = false;
                        this._timelineSelection = false;
                    }
                    return this;
                } else return this._time;
            }
        },
        {
            /**
      A filter function that limits which time periods are shown.
*/ key: "timeFilter",
            value: function timeFilter(_) {
                return arguments.length ? (this._timeFilter = _, this) : this._timeFilter;
            }
        },
        {
            /**
      Whether to display the timeline.
*/ key: "timeline",
            value: function timeline(_) {
                return arguments.length ? (this._timeline = _, this) : this._timeline;
            }
        },
        {
            /**
      Configuration object for the timeline.
*/ key: "timelineConfig",
            value: function timelineConfig(_) {
                return arguments.length ? (this._timelineConfig = assign(this._timelineConfig, _), this) : this._timelineConfig;
            }
        },
        {
            /**
      The starting time or range for the timeline. Can be a single Date/String, or an Array of 2 values representing the min and max.
*/ key: "timelineDefault",
            value: function timelineDefault(_) {
                if (arguments.length) {
                    if (!_instanceof(_, Array)) _ = [
                        _,
                        _
                    ];
                    this._timelineDefault = _.map(function(d) {
                        return date(d);
                    }).filter(function(d) {
                        return d !== false;
                    });
                    return this;
                } else return this._timelineDefault;
            }
        },
        {
            /**
      Tells the timeline whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the timeline appears centered underneath the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "timelinePadding",
            value: function timelinePadding(_) {
                return arguments.length ? (this._timelinePadding = typeof _ === "function" ? _ : constant(_), this) : this._timelinePadding;
            }
        },
        {
            /**
      Accessor function or string for the visualization's title.
*/ key: "title",
            value: function title(_) {
                return arguments.length ? (this._title = typeof _ === "function" ? _ : constant(_), this) : this._title;
            }
        },
        {
            /**
      Configuration object for the title.
*/ key: "titleConfig",
            value: function titleConfig(_) {
                return arguments.length ? (this._titleConfig = assign(this._titleConfig, _), this) : this._titleConfig;
            }
        },
        {
            /**
      Tells the title whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the title appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "titlePadding",
            value: function titlePadding(_) {
                return arguments.length ? (this._titlePadding = typeof _ === "function" ? _ : constant(_), this) : this._titlePadding;
            }
        },
        {
            /**
      Whether to display tooltips on hover.
*/ key: "tooltip",
            value: function tooltip(_) {
                return arguments.length ? (this._tooltip = typeof _ === "function" ? _ : constant(_), this) : this._tooltip;
            }
        },
        {
            /**
      Configuration object for the tooltip.
*/ key: "tooltipConfig",
            value: function tooltipConfig(_) {
                return arguments.length ? (this._tooltipConfig = assign(this._tooltipConfig, _), this) : this._tooltipConfig;
            }
        },
        {
            /**
      Accessor function or string key for the total value displayed in the visualization.
*/ key: "total",
            value: function total(_) {
                if (arguments.length) {
                    if (typeof _ === "function") this._total = _;
                    else if (_) this._total = accessor(_);
                    else this._total = false;
                    return this;
                } else return this._total;
            }
        },
        {
            /**
      Configuration object for the total bar.
*/ key: "totalConfig",
            value: function totalConfig(_) {
                return arguments.length ? (this._totalConfig = assign(this._totalConfig, _), this) : this._totalConfig;
            }
        },
        {
            /**
      Formatter function for the value in the total bar.
*/ key: "totalFormat",
            value: function totalFormat(_) {
                return arguments.length ? (this._totalFormat = _, this) : this._totalFormat;
            }
        },
        {
            /**
      Tells the total whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the total appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
*/ key: "totalPadding",
            value: function totalPadding(_) {
                return arguments.length ? (this._totalPadding = typeof _ === "function" ? _ : constant(_), this) : this._totalPadding;
            }
        },
        {
            /**
      The overall width of the visualization in pixels.
*/ key: "width",
            value: function width(_) {
                return arguments.length ? (this._width = _, this) : this._width;
            }
        },
        {
            /**
      Toggles the ability to zoom/pan the visualization. Certain parameters for zooming are required to be hooked up on a visualization by visualization basis.
*/ key: "zoom",
            value: function zoom(_) {
                return arguments.length ? (this._zoom = _, this) : this._zoom;
            }
        },
        {
            /**
      The pixel stroke-width of the zoom brush area.
*/ key: "zoomBrushHandleSize",
            value: function zoomBrushHandleSize(_) {
                return arguments.length ? (this._zoomBrushHandleSize = _, this) : this._zoomBrushHandleSize;
            }
        },
        {
            /**
      An object containing CSS key/value pairs that is used to style the outer handle area of the zoom brush. Passing `false` will remove all default styling.
*/ key: "zoomBrushHandleStyle",
            value: function zoomBrushHandleStyle(_) {
                return arguments.length ? (this._zoomBrushHandleStyle = _, this) : this._zoomBrushHandleStyle;
            }
        },
        {
            /**
      An object containing CSS key/value pairs that is used to style the inner selection area of the zoom brush. Passing `false` will remove all default styling.
*/ key: "zoomBrushSelectionStyle",
            value: function zoomBrushSelectionStyle(_) {
                return arguments.length ? (this._zoomBrushSelectionStyle = _, this) : this._zoomBrushSelectionStyle;
            }
        },
        {
            /**
      An object containing CSS key/value pairs that is used to style each zoom control button (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
*/ key: "zoomControlStyle",
            value: function zoomControlStyle(_) {
                return arguments.length ? (this._zoomControlStyle = _, this) : this._zoomControlStyle;
            }
        },
        {
            /**
      An object containing CSS key/value pairs that is used to style each zoom control button when active (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
*/ key: "zoomControlStyleActive",
            value: function zoomControlStyleActive(_) {
                return arguments.length ? (this._zoomControlStyleActive = _, this) : this._zoomControlStyleActive;
            }
        },
        {
            /**
      An object containing CSS key/value pairs that is used to style each zoom control button on hover (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
*/ key: "zoomControlStyleHover",
            value: function zoomControlStyleHover(_) {
                return arguments.length ? (this._zoomControlStyleHover = _, this) : this._zoomControlStyleHover;
            }
        },
        {
            /**
      The multiplier that is used in with the control buttons when zooming in and out.
*/ key: "zoomFactor",
            value: function zoomFactor(_) {
                return arguments.length ? (this._zoomFactor = _, this) : this._zoomFactor;
            }
        },
        {
            /**
      The max zoom scale.
*/ key: "zoomMax",
            value: function zoomMax(_) {
                return arguments.length ? (this._zoomMax = _, this) : this._zoomMax;
            }
        },
        {
            /**
      Toggles panning.
*/ key: "zoomPan",
            value: function zoomPan(_) {
                return arguments.length ? (this._zoomPan = _, this) : this._zoomPan;
            }
        },
        {
            /**
      A pixel value to be used to pad all sides of a zoomed area.
*/ key: "zoomPadding",
            value: function zoomPadding(_) {
                return arguments.length ? (this._zoomPadding = _, this) : this._zoomPadding;
            }
        },
        {
            /**
      Toggles scroll zooming.
*/ key: "zoomScroll",
            value: function zoomScroll(_) {
                return arguments.length ? (this._zoomScroll = _, this) : this._zoomScroll;
            }
        }
    ]);
    return Viz;
}(BaseClass);
/**
    Creates an x/y plot based on an array of data. See [this example](https://d3plus.org/examples/d3plus-treemap/getting-started/) for help getting started using the treemap generator.
*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any
export { Viz as default };
