Hacked By AnonymousFox

Current Path : C:/AppServ/www/financial/stacked/code/es5/
Upload File :
Current File : C:/AppServ/www/financial/stacked/code/es5/highcharts-gantt.src.js

/**
 * @license Highcharts JS v12.1.2 (2025-01-09)
 * @module highcharts/highcharts
 *
 * (c) 2009-2024 Torstein Honsi
 *
 * License: www.highcharts.com/license
 */
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define("highcharts/highcharts", [], factory);
	else if(typeof exports === 'object')
		exports["highcharts"] = factory();
	else
		((root["Highcharts"] && root["Highcharts"].error(16, true)), root["Highcharts"] = factory());
})(this, function() {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "default": function() { return /* binding */ highcharts_gantt_src; }
});

;// ./code/es5/es-modules/Core/Globals.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Namespace
 *
 * */
/**
 * Shared Highcharts properties.
 * @private
 */
var Globals;
(function (Globals) {
    /* *
     *
     *  Constants
     *
     * */
    var _a,
        _b;
    Globals.SVG_NS = 'http://www.w3.org/2000/svg', Globals.product = 'Highcharts', Globals.version = '12.1.2', Globals.win = (typeof window !== 'undefined' ?
        window :
        {}), // eslint-disable-line node/no-unsupported-features/es-builtins
    Globals.doc = Globals.win.document, Globals.svg = (Globals.doc &&
        Globals.doc.createElementNS &&
        !!Globals.doc.createElementNS(Globals.SVG_NS, 'svg').createSVGRect), Globals.pageLang = (_b = (_a = Globals.doc === null || Globals.doc === void 0 ? void 0 : Globals.doc.documentElement) === null || _a === void 0 ? void 0 : _a.closest('[lang]')) === null || _b === void 0 ? void 0 : _b.lang, Globals.userAgent = (Globals.win.navigator && Globals.win.navigator.userAgent) || '', Globals.isChrome = Globals.win.chrome, Globals.isFirefox = Globals.userAgent.indexOf('Firefox') !== -1, Globals.isMS = /(edge|msie|trident)/i.test(Globals.userAgent) && !Globals.win.opera, Globals.isSafari = !Globals.isChrome && Globals.userAgent.indexOf('Safari') !== -1, Globals.isTouchDevice = /(Mobile|Android|Windows Phone)/.test(Globals.userAgent), Globals.isWebKit = Globals.userAgent.indexOf('AppleWebKit') !== -1, Globals.deg2rad = Math.PI * 2 / 360, Globals.marginNames = [
        'plotTop',
        'marginRight',
        'marginBottom',
        'plotLeft'
    ], Globals.noop = function () { }, Globals.supportsPassiveEvents = (function () {
        // Checks whether the browser supports passive events, (#11353).
        var supportsPassive = false;
        // Object.defineProperty doesn't work on IE as well as passive
        // events - instead of using polyfill, we can exclude IE totally.
        if (!Globals.isMS) {
            var opts = Object.defineProperty({}, 'passive', {
                    get: function () {
                        supportsPassive = true;
                }
            });
            if (Globals.win.addEventListener && Globals.win.removeEventListener) {
                Globals.win.addEventListener('testPassive', Globals.noop, opts);
                Globals.win.removeEventListener('testPassive', Globals.noop, opts);
            }
        }
        return supportsPassive;
    }());
    /**
     * An array containing the current chart objects in the page. A chart's
     * position in the array is preserved throughout the page's lifetime. When
     * a chart is destroyed, the array item becomes `undefined`.
     *
     * @name Highcharts.charts
     * @type {Array<Highcharts.Chart|undefined>}
     */
    Globals.charts = [];
    /**
     * A shared registry between all bundles to keep track of applied
     * compositions.
     * @private
     */
    Globals.composed = [];
    /**
     * A hook for defining additional date format specifiers. New
     * specifiers are defined as key-value pairs by using the
     * specifier as key, and a function which takes the timestamp as
     * value. This function returns the formatted portion of the
     * date.
     *
     * Using `dateFormats` is also a convenient way to define new keys for
     * complex locale-aware date formats compatible with the
     * [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)
     * browser API, whenever the built-in formats are not sufficient.
     *
     * @sample highcharts/global/dateformats/
     *         Adding support for week number
     * @sample highcharts/global/dateformats-object/
     *         A locale-aware date format using `Intl.DateTimeFormat`
     *
     * @name Highcharts.dateFormats
     * @type {Record<string, Highcharts.TimeFormatCallbackFunction>}
     */
    Globals.dateFormats = {};
    /**
     * @private
     * @deprecated
     * @todo Use only `Core/Series/SeriesRegistry.seriesTypes`
     */
    Globals.seriesTypes = {};
    /**
     * @private
     */
    Globals.symbolSizes = {};
    /* *
     *
     *  Properties
     *
     * */
    // eslint-disable-next-line prefer-const
    Globals.chartCount = 0;
})(Globals || (Globals = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Core_Globals = (Globals);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Theme options that should get applied to the chart. In module mode it
 * might not be possible to change this property because of read-only
 * restrictions, instead use {@link Highcharts.setOptions}.
 *
 * @deprecated
 * @name Highcharts.theme
 * @type {Highcharts.Options}
 */
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Utilities.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};

var charts = Core_Globals.charts, doc = Core_Globals.doc, win = Core_Globals.win;
/* *
 *
 *  Functions
 *
 * */
/**
 * Provide error messages for debugging, with links to online explanation. This
 * function can be overridden to provide custom error handling.
 *
 * @sample highcharts/chart/highcharts-error/
 *         Custom error handler
 *
 * @function Highcharts.error
 *
 * @param {number|string} code
 *        The error code. See
 *        [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml)
 *        for available codes. If it is a string, the error message is printed
 *        directly in the console.
 *
 * @param {boolean} [stop=false]
 *        Whether to throw an error or just log a warning in the console.
 *
 * @param {Highcharts.Chart} [chart]
 *        Reference to the chart that causes the error. Used in 'debugger'
 *        module to display errors directly on the chart.
 *        Important note: This argument is undefined for errors that lack
 *        access to the Chart instance. In such case, the error will be
 *        displayed on the last created chart.
 *
 * @param {Highcharts.Dictionary<string>} [params]
 *        Additional parameters for the generated message.
 *
 * @return {void}
 */
function error(code, stop, chart, params) {
    var severity = stop ? 'Highcharts error' : 'Highcharts warning';
    if (code === 32) {
        code = "" + severity + ": Deprecated member";
    }
    var isCode = isNumber(code);
    var message = isCode ?
            "" + severity + " #" + code + ": www.highcharts.com/errors/" + code + "/" :
            code.toString();
    var defaultHandler = function () {
            if (stop) {
                throw new Error(message);
        }
        // Else ...
        if (win.console &&
            error.messages.indexOf(message) === -1 // Prevent console flooting
        ) {
            console.warn(message); // eslint-disable-line no-console
        }
    };
    if (typeof params !== 'undefined') {
        var additionalMessages_1 = '';
        if (isCode) {
            message += '?';
        }
        objectEach(params, function (value, key) {
            additionalMessages_1 += "\n - ".concat(key, ": ").concat(value);
            if (isCode) {
                message += encodeURI(key) + '=' + encodeURI(value);
            }
        });
        message += additionalMessages_1;
    }
    fireEvent(Core_Globals, 'displayError', { chart: chart, code: code, message: message, params: params }, defaultHandler);
    error.messages.push(message);
}
(function (error) {
    error.messages = [];
})(error || (error = {}));
/**
 * Utility function to deep merge two or more objects and return a third object.
 * If the first argument is true, the contents of the second object is copied
 * into the first object. The merge function can also be used with a single
 * object argument to create a deep copy of an object.
 *
 * @function Highcharts.merge<T>
 *
 * @param {true | T} extendOrSource
 *        Whether to extend the left-side object,
 *        or the first object to merge as a deep copy.
 *
 * @param {...Array<object|undefined>} [sources]
 *        Object(s) to merge into the previous one.
 *
 * @return {T}
 *         The merged object. If the first argument is true, the return is the
 *         same as the second argument.
 */
function merge(extendOrSource) {
    var sources = [];
    for (var _a = 1; _a < arguments.length; _a++) {
        sources[_a - 1] = arguments[_a];
    }
    var i,
        args = __spreadArray([extendOrSource],
        sources,
        true),
        ret = {};
    var doCopy = function (copy,
        original) {
            // An object is replacing a primitive
            if (typeof copy !== 'object') {
                copy = {};
        }
        objectEach(original, function (value, key) {
            // Prototype pollution (#14883)
            if (key === '__proto__' || key === 'constructor') {
                return;
            }
            // Copy the contents of objects, but not arrays or DOM nodes
            if (isObject(value, true) &&
                !isClass(value) &&
                !isDOMElement(value)) {
                copy[key] = doCopy(copy[key] || {}, value);
                // Primitives and arrays are copied over directly
            }
            else {
                copy[key] = original[key];
            }
        });
        return copy;
    };
    // If first argument is true, copy into the existing object. Used in
    // setOptions.
    if (extendOrSource === true) {
        ret = args[1];
        args = Array.prototype.slice.call(args, 2);
    }
    // For each argument, extend the return
    var len = args.length;
    for (i = 0; i < len; i++) {
        ret = doCopy(ret, args[i]);
    }
    return ret;
}
/**
 * Constrain a value to within a lower and upper threshold.
 *
 * @private
 * @param {number} value The initial value
 * @param {number} min The lower threshold
 * @param {number} max The upper threshold
 * @return {number} Returns a number value within min and max.
 */
function clamp(value, min, max) {
    return value > min ? value < max ? value : max : min;
}
/**
 * Utility for crisping a line position to the nearest full pixel depening on
 * the line width
 * @param {number} value       The raw pixel position
 * @param {number} lineWidth   The line width
 * @param {boolean} [inverted] Whether the containing group is inverted.
 *                             Crisping round numbers on the y-scale need to go
 *                             to the other side because the coordinate system
 *                             is flipped (scaleY is -1)
 * @return {number}            The pixel position to use for a crisp display
 */
function crisp(value, lineWidth, inverted) {
    if (lineWidth === void 0) { lineWidth = 0; }
    var mod = lineWidth % 2 / 2,
        inverter = inverted ? -1 : 1;
    return (Math.round(value * inverter - mod) + mod) * inverter;
}
// eslint-disable-next-line valid-jsdoc
/**
 * Return the deep difference between two objects. It can either return the new
 * properties, or optionally return the old values of new properties.
 * @private
 */
function diffObjects(newer, older, keepOlder, collectionsWithUpdate) {
    var ret = {};
    /**
     * Recurse over a set of options and its current values, and store the
     * current values in the ret object.
     */
    function diff(newer, older, ret, depth) {
        var keeper = keepOlder ? older : newer;
        objectEach(newer, function (newerVal, key) {
            if (!depth &&
                collectionsWithUpdate &&
                collectionsWithUpdate.indexOf(key) > -1 &&
                older[key]) {
                newerVal = splat(newerVal);
                ret[key] = [];
                // Iterate over collections like series, xAxis or yAxis and map
                // the items by index.
                for (var i = 0; i < Math.max(newerVal.length, older[key].length); i++) {
                    // Item exists in current data (#6347)
                    if (older[key][i]) {
                        // If the item is missing from the new data, we need to
                        // save the whole config structure. Like when
                        // responsively updating from a dual axis layout to a
                        // single axis and back (#13544).
                        if (newerVal[i] === void 0) {
                            ret[key][i] = older[key][i];
                            // Otherwise, proceed
                        }
                        else {
                            ret[key][i] = {};
                            diff(newerVal[i], older[key][i], ret[key][i], depth + 1);
                        }
                    }
                }
            }
            else if (isObject(newerVal, true) &&
                !newerVal.nodeType // #10044
            ) {
                ret[key] = isArray(newerVal) ? [] : {};
                diff(newerVal, older[key] || {}, ret[key], depth + 1);
                // Delete empty nested objects
                if (Object.keys(ret[key]).length === 0 &&
                    // Except colorAxis which is a special case where the empty
                    // object means it is enabled. Which is unfortunate and we
                    // should try to find a better way.
                    !(key === 'colorAxis' && depth === 0)) {
                    delete ret[key];
                }
            }
            else if (newer[key] !== older[key] ||
                // If the newer key is explicitly undefined, keep it (#10525)
                (key in newer && !(key in older))) {
                if (key !== '__proto__' && key !== 'constructor') {
                    ret[key] = keeper[key];
                }
            }
        });
    }
    diff(newer, older, ret, 0);
    return ret;
}
/**
 * Shortcut for parseInt
 *
 * @private
 * @function Highcharts.pInt
 *
 * @param {*} s
 *        any
 *
 * @param {number} [mag]
 *        Magnitude
 *
 * @return {number}
 *         number
 */
function pInt(s, mag) {
    return parseInt(s, mag || 10);
}
/**
 * Utility function to check for string type.
 *
 * @function Highcharts.isString
 *
 * @param {*} s
 *        The item to check.
 *
 * @return {boolean}
 *         True if the argument is a string.
 */
function isString(s) {
    return typeof s === 'string';
}
/**
 * Utility function to check if an item is an array.
 *
 * @function Highcharts.isArray
 *
 * @param {*} obj
 *        The item to check.
 *
 * @return {boolean}
 *         True if the argument is an array.
 */
function isArray(obj) {
    var str = Object.prototype.toString.call(obj);
    return str === '[object Array]' || str === '[object Array Iterator]';
}
/**
 * Utility function to check if an item is of type object.
 *
 * @function Highcharts.isObject
 *
 * @param {*} obj
 *        The item to check.
 *
 * @param {boolean} [strict=false]
 *        Also checks that the object is not an array.
 *
 * @return {boolean}
 *         True if the argument is an object.
 */
function isObject(obj, strict) {
    return (!!obj &&
        typeof obj === 'object' &&
        (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any
}
/**
 * Utility function to check if an Object is a HTML Element.
 *
 * @function Highcharts.isDOMElement
 *
 * @param {*} obj
 *        The item to check.
 *
 * @return {boolean}
 *         True if the argument is a HTML Element.
 */
function isDOMElement(obj) {
    return isObject(obj) && typeof obj.nodeType === 'number';
}
/**
 * Utility function to check if an Object is a class.
 *
 * @function Highcharts.isClass
 *
 * @param {object|undefined} obj
 *        The item to check.
 *
 * @return {boolean}
 *         True if the argument is a class.
 */
function isClass(obj) {
    var c = obj && obj.constructor;
    return !!(isObject(obj, true) &&
        !isDOMElement(obj) &&
        (c && c.name && c.name !== 'Object'));
}
/**
 * Utility function to check if an item is a number and it is finite (not NaN,
 * Infinity or -Infinity).
 *
 * @function Highcharts.isNumber
 *
 * @param {*} n
 *        The item to check.
 *
 * @return {boolean}
 *         True if the item is a finite number
 */
function isNumber(n) {
    return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity;
}
/**
 * Remove the last occurence of an item from an array.
 *
 * @function Highcharts.erase
 *
 * @param {Array<*>} arr
 *        The array.
 *
 * @param {*} item
 *        The item to remove.
 *
 * @return {void}
 */
function erase(arr, item) {
    var i = arr.length;
    while (i--) {
        if (arr[i] === item) {
            arr.splice(i, 1);
            break;
        }
    }
}
/**
 * Insert a series or an axis in a collection with other items, either the
 * chart series or yAxis series or axis collections, in the correct order
 * according to the index option and whether it is internal. Used internally
 * when adding series and axes.
 *
 * @private
 * @function Highcharts.Chart#insertItem
 * @param  {Highcharts.Series|Highcharts.Axis} item
 *         The item to insert
 * @param  {Array<Highcharts.Series>|Array<Highcharts.Axis>} collection
 *         A collection of items, like `chart.series` or `xAxis.series`.
 * @return {number} The index of the series in the collection.
 */
function insertItem(item, collection) {
    var indexOption = item.options.index,
        length = collection.length;
    var i;
    for (
    // Internal item (navigator) should always be pushed to the end
    i = item.options.isInternal ? length : 0; i < length + 1; i++) {
        if (
        // No index option, reached the end of the collection,
        // equivalent to pushing
        !collection[i] ||
            // Handle index option, the element to insert has lower index
            (isNumber(indexOption) &&
                indexOption < pick(collection[i].options.index, collection[i]._i)) ||
            // Insert the new item before other internal items
            // (navigator)
            collection[i].options.isInternal) {
            collection.splice(i, 0, item);
            break;
        }
    }
    return i;
}
/**
 * Adds an item to an array, if it is not present in the array.
 *
 * @function Highcharts.pushUnique
 *
 * @param {Array<unknown>} array
 * The array to add the item to.
 *
 * @param {unknown} item
 * The item to add.
 *
 * @return {boolean}
 * Returns true, if the item was not present and has been added.
 */
function pushUnique(array, item) {
    return array.indexOf(item) < 0 && !!array.push(item);
}
/**
 * Check if an object is null or undefined.
 *
 * @function Highcharts.defined
 *
 * @param {*} obj
 *        The object to check.
 *
 * @return {boolean}
 *         False if the object is null or undefined, otherwise true.
 */
function defined(obj) {
    return typeof obj !== 'undefined' && obj !== null;
}
/**
 * Set or get an attribute or an object of attributes.
 *
 * To use as a setter, pass a key and a value, or let the second argument be a
 * collection of keys and values. When using a collection, passing a value of
 * `null` or `undefined` will remove the attribute.
 *
 * To use as a getter, pass only a string as the second argument.
 *
 * @function Highcharts.attr
 *
 * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem
 *        The DOM element to receive the attribute(s).
 *
 * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [keyOrAttribs]
 *        The property or an object of key-value pairs.
 *
 * @param {number|string} [value]
 *        The value if a single property is set.
 *
 * @return {string|null|undefined}
 *         When used as a getter, return the value.
 */
function attr(elem, keyOrAttribs, value) {
    var isGetter = isString(keyOrAttribs) && !defined(value);
    var ret;
    var attrSingle = function (value,
        key) {
            // Set the value
            if (defined(value)) {
                elem.setAttribute(key,
        value);
            // Get the value
        }
        else if (isGetter) {
            ret = elem.getAttribute(key);
            // IE7 and below cannot get class through getAttribute (#7850)
            if (!ret && key === 'class') {
                ret = elem.getAttribute(key + 'Name');
            }
            // Remove the value
        }
        else {
            elem.removeAttribute(key);
        }
    };
    // If keyOrAttribs is a string
    if (isString(keyOrAttribs)) {
        attrSingle(value, keyOrAttribs);
        // Else if keyOrAttribs is defined, it is a hash of key/value pairs
    }
    else {
        objectEach(keyOrAttribs, attrSingle);
    }
    return ret;
}
/**
 * Check if an element is an array, and if not, make it into an array.
 *
 * @function Highcharts.splat
 *
 * @param {*} obj
 *        The object to splat.
 *
 * @return {Array}
 *         The produced or original array.
 */
function splat(obj) {
    return isArray(obj) ? obj : [obj];
}
/**
 * Set a timeout if the delay is given, otherwise perform the function
 * synchronously.
 *
 * @function Highcharts.syncTimeout
 *
 * @param {Function} fn
 *        The function callback.
 *
 * @param {number} delay
 *        Delay in milliseconds.
 *
 * @param {*} [context]
 *        An optional context to send to the function callback.
 *
 * @return {number}
 *         An identifier for the timeout that can later be cleared with
 *         Highcharts.clearTimeout. Returns -1 if there is no timeout.
 */
function syncTimeout(fn, delay, context) {
    if (delay > 0) {
        return setTimeout(fn, delay, context);
    }
    fn.call(0, context);
    return -1;
}
/**
 * Internal clear timeout. The function checks that the `id` was not removed
 * (e.g. by `chart.destroy()`). For the details see
 * [issue #7901](https://github.com/highcharts/highcharts/issues/7901).
 *
 * @function Highcharts.clearTimeout
 *
 * @param {number|undefined} id
 * Id of a timeout.
 */
function internalClearTimeout(id) {
    if (defined(id)) {
        clearTimeout(id);
    }
}
/* eslint-disable valid-jsdoc */
/**
 * Utility function to extend an object with the members of another.
 *
 * @function Highcharts.extend<T>
 *
 * @param {T|undefined} a
 *        The object to be extended.
 *
 * @param {Partial<T>} b
 *        The object to add to the first one.
 *
 * @return {T}
 *         Object a, the original object.
 */
function extend(a, b) {
    /* eslint-enable valid-jsdoc */
    var n;
    if (!a) {
        a = {};
    }
    for (n in b) { // eslint-disable-line guard-for-in
        a[n] = b[n];
    }
    return a;
}
/* eslint-disable valid-jsdoc */
/**
 * Return the first value that is not null or undefined.
 *
 * @function Highcharts.pick<T>
 *
 * @param {...Array<T|null|undefined>} items
 *        Variable number of arguments to inspect.
 *
 * @return {T}
 *         The value of the first argument that is not null or undefined.
 */
function pick() {
    var args = arguments;
    var length = args.length;
    for (var i = 0; i < length; i++) {
        var arg = args[i];
        if (typeof arg !== 'undefined' && arg !== null) {
            return arg;
        }
    }
}
/**
 * Set CSS on a given element.
 *
 * @function Highcharts.css
 *
 * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
 *        An HTML DOM element.
 *
 * @param {Highcharts.CSSObject} styles
 *        Style object with camel case property names.
 *
 * @return {void}
 */
function css(el, styles) {
    extend(el.style, styles);
}
/**
 * Utility function to create an HTML element with attributes and styles.
 *
 * @function Highcharts.createElement
 *
 * @param {string} tag
 *        The HTML tag.
 *
 * @param {Highcharts.HTMLAttributes} [attribs]
 *        Attributes as an object of key-value pairs.
 *
 * @param {Highcharts.CSSObject} [styles]
 *        Styles as an object of key-value pairs.
 *
 * @param {Highcharts.HTMLDOMElement} [parent]
 *        The parent HTML object.
 *
 * @param {boolean} [nopad=false]
 *        If true, remove all padding, border and margin.
 *
 * @return {Highcharts.HTMLDOMElement}
 *         The created DOM element.
 */
function createElement(tag, attribs, styles, parent, nopad) {
    var el = doc.createElement(tag);
    if (attribs) {
        extend(el, attribs);
    }
    if (nopad) {
        css(el, { padding: '0', border: 'none', margin: '0' });
    }
    if (styles) {
        css(el, styles);
    }
    if (parent) {
        parent.appendChild(el);
    }
    return el;
}
// eslint-disable-next-line valid-jsdoc
/**
 * Extend a prototyped class by new members.
 *
 * @deprecated
 * @function Highcharts.extendClass<T>
 *
 * @param {Highcharts.Class<T>} parent
 *        The parent prototype to inherit.
 *
 * @param {Highcharts.Dictionary<*>} members
 *        A collection of prototype members to add or override compared to the
 *        parent prototype.
 *
 * @return {Highcharts.Class<T>}
 *         A new prototype.
 */
function extendClass(parent, members) {
    var obj = (function () { });
    obj.prototype = new parent(); // eslint-disable-line new-cap
    extend(obj.prototype, members);
    return obj;
}
/**
 * Left-pad a string to a given length by adding a character repetitively.
 *
 * @function Highcharts.pad
 *
 * @param {number} number
 *        The input string or number.
 *
 * @param {number} [length]
 *        The desired string length.
 *
 * @param {string} [padder=0]
 *        The character to pad with.
 *
 * @return {string}
 *         The padded string.
 */
function pad(number, length, padder) {
    return new Array((length || 2) +
        1 -
        String(number)
            .replace('-', '')
            .length).join(padder || '0') + number;
}
/**
 * Return a length based on either the integer value, or a percentage of a base.
 *
 * @function Highcharts.relativeLength
 *
 * @param {Highcharts.RelativeSize} value
 *        A percentage string or a number.
 *
 * @param {number} base
 *        The full length that represents 100%.
 *
 * @param {number} [offset=0]
 *        A pixel offset to apply for percentage values. Used internally in
 *        axis positioning.
 *
 * @return {number}
 *         The computed length.
 */
function relativeLength(value, base, offset) {
    return (/%$/).test(value) ?
        (base * parseFloat(value) / 100) + (offset || 0) :
        parseFloat(value);
}
/**
 * Replaces text in a string with a given replacement in a loop to catch nested
 * matches after previous replacements.
 *
 * @function Highcharts.replaceNested
 *
 * @param {string} text
 * Text to search and modify.
 *
 * @param {...Array<(RegExp|string)>} replacements
 * One or multiple tuples with search pattern (`[0]: (string|RegExp)`) and
 * replacement (`[1]: string`) for matching text.
 *
 * @return {string}
 * Text with replacements.
 */
function replaceNested(text) {
    var replacements = [];
    for (var _a = 1; _a < arguments.length; _a++) {
        replacements[_a - 1] = arguments[_a];
    }
    var previous,
        replacement;
    do {
        previous = text;
        for (var _b = 0, replacements_1 = replacements; _b < replacements_1.length; _b++) {
            replacement = replacements_1[_b];
            text = text.replace(replacement[0], replacement[1]);
        }
    } while (text !== previous);
    return text;
}
/**
 * Wrap a method with extended functionality, preserving the original function.
 *
 * @function Highcharts.wrap
 *
 * @param {*} obj
 *        The context object that the method belongs to. In real cases, this is
 *        often a prototype.
 *
 * @param {string} method
 *        The name of the method to extend.
 *
 * @param {Highcharts.WrapProceedFunction} func
 *        A wrapper function callback. This function is called with the same
 *        arguments as the original function, except that the original function
 *        is unshifted and passed as the first argument.
 */
function wrap(obj, method, func) {
    var proceed = obj[method];
    obj[method] = function () {
        var outerArgs = arguments,
            scope = this;
        return func.apply(this, [
            function () {
                return proceed.apply(scope, arguments.length ? arguments : outerArgs);
            }
        ].concat([].slice.call(arguments)));
    };
}
/**
 * Get the magnitude of a number.
 *
 * @function Highcharts.getMagnitude
 *
 * @param {number} num
 *        The number.
 *
 * @return {number}
 *         The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc.
 */
function getMagnitude(num) {
    return Math.pow(10, Math.floor(Math.log(num) / Math.LN10));
}
/**
 * Take an interval and normalize it to multiples of round numbers.
 *
 * @deprecated
 * @function Highcharts.normalizeTickInterval
 *
 * @param {number} interval
 *        The raw, un-rounded interval.
 *
 * @param {Array<*>} [multiples]
 *        Allowed multiples.
 *
 * @param {number} [magnitude]
 *        The magnitude of the number.
 *
 * @param {boolean} [allowDecimals]
 *        Whether to allow decimals.
 *
 * @param {boolean} [hasTickAmount]
 *        If it has tickAmount, avoid landing on tick intervals lower than
 *        original.
 *
 * @return {number}
 *         The normalized interval.
 *
 * @todo
 * Move this function to the Axis prototype. It is here only for historical
 * reasons.
 */
function normalizeTickInterval(interval, multiples, magnitude, allowDecimals, hasTickAmount) {
    var i,
        retInterval = interval;
    // Round to a tenfold of 1, 2, 2.5 or 5
    magnitude = pick(magnitude, getMagnitude(interval));
    var normalized = interval / magnitude;
    // Multiples for a linear scale
    if (!multiples) {
        multiples = hasTickAmount ?
            // Finer grained ticks when the tick amount is hard set, including
            // when alignTicks is true on multiple axes (#4580).
            [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] :
            // Else, let ticks fall on rounder numbers
            [1, 2, 2.5, 5, 10];
        // The allowDecimals option
        if (allowDecimals === false) {
            if (magnitude === 1) {
                multiples = multiples.filter(function (num) {
                    return num % 1 === 0;
                });
            }
            else if (magnitude <= 0.1) {
                multiples = [1 / magnitude];
            }
        }
    }
    // Normalize the interval to the nearest multiple
    for (i = 0; i < multiples.length; i++) {
        retInterval = multiples[i];
        // Only allow tick amounts smaller than natural
        if ((hasTickAmount &&
            retInterval * magnitude >= interval) ||
            (!hasTickAmount &&
                (normalized <=
                    (multiples[i] +
                        (multiples[i + 1] || multiples[i])) / 2))) {
            break;
        }
    }
    // Multiply back to the correct magnitude. Correct floats to appropriate
    // precision (#6085).
    retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10));
    return retInterval;
}
/**
 * Sort an object array and keep the order of equal items. The ECMAScript
 * standard does not specify the behaviour when items are equal.
 *
 * @function Highcharts.stableSort
 *
 * @param {Array<*>} arr
 *        The array to sort.
 *
 * @param {Function} sortFunction
 *        The function to sort it with, like with regular Array.prototype.sort.
 */
function stableSort(arr, sortFunction) {
    // @todo It seems like Chrome since v70 sorts in a stable way internally,
    // plus all other browsers do it, so over time we may be able to remove this
    // function
    var length = arr.length;
    var sortValue,
        i;
    // Add index to each item
    for (i = 0; i < length; i++) {
        arr[i].safeI = i; // Stable sort index
    }
    arr.sort(function (a, b) {
        sortValue = sortFunction(a, b);
        return sortValue === 0 ? a.safeI - b.safeI : sortValue;
    });
    // Remove index from items
    for (i = 0; i < length; i++) {
        delete arr[i].safeI; // Stable sort index
    }
}
/**
 * Non-recursive method to find the lowest member of an array. `Math.min` raises
 * a maximum call stack size exceeded error in Chrome when trying to apply more
 * than 150.000 points. This method is slightly slower, but safe.
 *
 * @function Highcharts.arrayMin
 *
 * @param {Array<*>} data
 *        An array of numbers.
 *
 * @return {number}
 *         The lowest number.
 */
function arrayMin(data) {
    var i = data.length,
        min = data[0];
    while (i--) {
        if (data[i] < min) {
            min = data[i];
        }
    }
    return min;
}
/**
 * Non-recursive method to find the lowest member of an array. `Math.max` raises
 * a maximum call stack size exceeded error in Chrome when trying to apply more
 * than 150.000 points. This method is slightly slower, but safe.
 *
 * @function Highcharts.arrayMax
 *
 * @param {Array<*>} data
 *        An array of numbers.
 *
 * @return {number}
 *         The highest number.
 */
function arrayMax(data) {
    var i = data.length,
        max = data[0];
    while (i--) {
        if (data[i] > max) {
            max = data[i];
        }
    }
    return max;
}
/**
 * Utility method that destroys any SVGElement instances that are properties on
 * the given object. It loops all properties and invokes destroy if there is a
 * destroy method. The property is then delete.
 *
 * @function Highcharts.destroyObjectProperties
 *
 * @param {*} obj
 *        The object to destroy properties on.
 *
 * @param {*} [except]
 *        Exception, do not destroy this property, only delete it.
 */
function destroyObjectProperties(obj, except, destructablesOnly) {
    objectEach(obj, function (val, n) {
        // If the object is non-null and destroy is defined
        if (val !== except && (val === null || val === void 0 ? void 0 : val.destroy)) {
            // Invoke the destroy
            val.destroy();
        }
        // Delete the property from the object
        if ((val === null || val === void 0 ? void 0 : val.destroy) || !destructablesOnly) {
            delete obj[n];
        }
    });
}
/**
 * Discard a HTML element
 *
 * @function Highcharts.discardElement
 *
 * @param {Highcharts.HTMLDOMElement} element
 *        The HTML node to discard.
 */
function discardElement(element) {
    if (element && element.parentElement) {
        element.parentElement.removeChild(element);
    }
}
/**
 * Fix JS round off float errors.
 *
 * @function Highcharts.correctFloat
 *
 * @param {number} num
 *        A float number to fix.
 *
 * @param {number} [prec=14]
 *        The precision.
 *
 * @return {number}
 *         The corrected float number.
 */
function correctFloat(num, prec) {
    // When the number is higher than 1e14 use the number (#16275)
    return num > 1e14 ? num : parseFloat(num.toPrecision(prec || 14));
}
/**
 * The time unit lookup
 *
 * @ignore
 */
var timeUnits = {
    millisecond: 1,
    second: 1000,
    minute: 60000,
    hour: 3600000,
    day: 24 * 3600000,
    week: 7 * 24 * 3600000,
    month: 28 * 24 * 3600000,
    year: 364 * 24 * 3600000
};
/**
 * Easing definition
 *
 * @private
 * @function Math.easeInOutSine
 *
 * @param {number} pos
 *        Current position, ranging from 0 to 1.
 *
 * @return {number}
 *         Ease result
 */
Math.easeInOutSine = function (pos) {
    return -0.5 * (Math.cos(Math.PI * pos) - 1);
};
/**
 * Convenience function to get the align factor, used several places for
 * computing positions
 * @private
 */
var getAlignFactor = function (align) {
    if (align === void 0) { align = ''; }
    return ({
        center: 0.5,
        right: 1,
        middle: 0.5,
        bottom: 1
    }[align] || 0);
};
/**
 * Find the closest distance between two values of a two-dimensional array
 * @private
 * @function Highcharts.getClosestDistance
 *
 * @param {Array<Array<number>>} arrays
 *          An array of arrays of numbers
 *
 * @return {number | undefined}
 *          The closest distance between values
 */
function getClosestDistance(arrays, onError) {
    var allowNegative = !onError;
    var closest,
        loopLength,
        distance,
        i;
    arrays.forEach(function (xData) {
        if (xData.length > 1) {
            loopLength = xData.length - 1;
            for (i = loopLength; i > 0; i--) {
                distance = xData[i] - xData[i - 1];
                if (distance < 0 && !allowNegative) {
                    onError === null || onError === void 0 ? void 0 : onError();
                    // Only one call
                    onError = void 0;
                }
                else if (distance && (typeof closest === 'undefined' || distance < closest)) {
                    closest = distance;
                }
            }
        }
    });
    return closest;
}
/**
 * Returns the value of a property path on a given object.
 *
 * @private
 * @function getNestedProperty
 *
 * @param {string} path
 * Path to the property, for example `custom.myValue`.
 *
 * @param {unknown} obj
 * Instance containing the property on the specific path.
 *
 * @return {unknown}
 * The unknown property value.
 */
function getNestedProperty(path, parent) {
    var pathElements = path.split('.');
    while (pathElements.length && defined(parent)) {
        var pathElement = pathElements.shift();
        // Filter on the key
        if (typeof pathElement === 'undefined' ||
            pathElement === '__proto__') {
            return; // Undefined
        }
        if (pathElement === 'this') {
            var thisProp = void 0;
            if (isObject(parent)) {
                thisProp = parent['@this'];
            }
            return thisProp !== null && thisProp !== void 0 ? thisProp : parent;
        }
        var child = parent[pathElement.replace(/[\\'"]/g, '')];
        // Filter on the child
        if (!defined(child) ||
            typeof child === 'function' ||
            typeof child.nodeType === 'number' ||
            child === win) {
            return; // Undefined
        }
        // Else, proceed
        parent = child;
    }
    return parent;
}
/**
 * Get the computed CSS value for given element and property, only for numerical
 * properties. For width and height, the dimension of the inner box (excluding
 * padding) is returned. Used for fitting the chart within the container.
 *
 * @function Highcharts.getStyle
 *
 * @param {Highcharts.HTMLDOMElement} el
 * An HTML element.
 *
 * @param {string} prop
 * The property name.
 *
 * @param {boolean} [toInt=true]
 * Parse to integer.
 *
 * @return {number|string|undefined}
 * The style value.
 */
function getStyle(el, prop, toInt) {
    var style;
    // For width and height, return the actual inner pixel size (#4913)
    if (prop === 'width') {
        var offsetWidth = Math.min(el.offsetWidth,
            el.scrollWidth);
        // In flex boxes, we need to use getBoundingClientRect and floor it,
        // because scrollWidth doesn't support subpixel precision (#6427) ...
        var boundingClientRectWidth = el.getBoundingClientRect &&
                el.getBoundingClientRect().width;
        // ...unless if the containing div or its parents are transform-scaled
        // down, in which case the boundingClientRect can't be used as it is
        // also scaled down (#9871, #10498).
        if (boundingClientRectWidth < offsetWidth &&
            boundingClientRectWidth >= offsetWidth - 1) {
            offsetWidth = Math.floor(boundingClientRectWidth);
        }
        return Math.max(0, // #8377
        (offsetWidth -
            (getStyle(el, 'padding-left', true) || 0) -
            (getStyle(el, 'padding-right', true) || 0)));
    }
    if (prop === 'height') {
        return Math.max(0, // #8377
        (Math.min(el.offsetHeight, el.scrollHeight) -
            (getStyle(el, 'padding-top', true) || 0) -
            (getStyle(el, 'padding-bottom', true) || 0)));
    }
    // Otherwise, get the computed style
    var css = win.getComputedStyle(el,
        void 0); // eslint-disable-line no-undefined
        if (css) {
            style = css.getPropertyValue(prop);
        if (pick(toInt, prop !== 'opacity')) {
            style = pInt(style);
        }
    }
    return style;
}
/**
 * Return the value of the first element in the array that satisfies the
 * provided testing function.
 *
 * @function Highcharts.find<T>
 *
 * @param {Array<T>} arr
 *        The array to test.
 *
 * @param {Function} callback
 *        The callback function. The function receives the item as the first
 *        argument. Return `true` if this item satisfies the condition.
 *
 * @return {T|undefined}
 *         The value of the element.
 */
var find = Array.prototype.find ?
    function (arr, callback) {
        return arr.find(callback);
    } :
    // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
    function (arr, callback) {
        var i;
        var length = arr.length;
        for (i = 0; i < length; i++) {
            if (callback(arr[i], i)) { // eslint-disable-line node/callback-return
                return arr[i];
            }
        }
    };
/**
 * Get the element's offset position, corrected for `overflow: auto`.
 *
 * @function Highcharts.offset
 *
 * @param {global.Element} el
 *        The DOM element.
 *
 * @return {Highcharts.OffsetObject}
 *         An object containing `left` and `top` properties for the position in
 *         the page.
 */
function offset(el) {
    var docElem = doc.documentElement,
        box = (el.parentElement || el.parentNode) ?
            el.getBoundingClientRect() :
            { top: 0,
        left: 0,
        width: 0,
        height: 0 };
    return {
        top: box.top + (win.pageYOffset || docElem.scrollTop) -
            (docElem.clientTop || 0),
        left: box.left + (win.pageXOffset || docElem.scrollLeft) -
            (docElem.clientLeft || 0),
        width: box.width,
        height: box.height
    };
}
/* eslint-disable valid-jsdoc */
/**
 * Iterate over object key pairs in an object.
 *
 * @function Highcharts.objectEach<T>
 *
 * @param {*} obj
 *        The object to iterate over.
 *
 * @param {Highcharts.ObjectEachCallbackFunction<T>} fn
 *        The iterator callback. It passes three arguments:
 *        * value - The property value.
 *        * key - The property key.
 *        * obj - The object that objectEach is being applied to.
 *
 * @param {T} [ctx]
 *        The context.
 */
function objectEach(obj, fn, ctx) {
    /* eslint-enable valid-jsdoc */
    for (var key in obj) {
        if (Object.hasOwnProperty.call(obj, key)) {
            fn.call(ctx || obj[key], obj[key], key, obj);
        }
    }
}
/* eslint-disable valid-jsdoc */
/**
 * Add an event listener.
 *
 * @function Highcharts.addEvent<T>
 *
 * @param  {Highcharts.Class<T>|T} el
 *         The element or object to add a listener to. It can be a
 *         {@link HTMLDOMElement}, an {@link SVGElement} or any other object.
 *
 * @param  {string} type
 *         The event type.
 *
 * @param  {Highcharts.EventCallbackFunction<T>|Function} fn
 *         The function callback to execute when the event is fired.
 *
 * @param  {Highcharts.EventOptionsObject} [options]
 *         Options for adding the event.
 *
 * @sample highcharts/members/addevent
 *         Use a general `render` event to draw shapes on a chart
 *
 * @return {Function}
 *         A callback function to remove the added event.
 */
function addEvent(el, type, fn, options) {
    /* eslint-enable valid-jsdoc */
    if (options === void 0) { options = {}; }
    // Add hcEvents to either the prototype (in case we're running addEvent on a
    // class) or the instance. If hasOwnProperty('hcEvents') is false, it is
    // inherited down the prototype chain, in which case we need to set the
    // property on this instance (which may itself be a prototype).
    var owner = typeof el === 'function' && el.prototype || el;
    if (!Object.hasOwnProperty.call(owner, 'hcEvents')) {
        owner.hcEvents = {};
    }
    var events = owner.hcEvents;
    // Allow click events added to points, otherwise they will be prevented by
    // the TouchPointer.pinch function after a pinch zoom operation (#7091).
    if (Core_Globals.Point && // Without H a dependency loop occurs
        el instanceof Core_Globals.Point &&
        el.series &&
        el.series.chart) {
        el.series.chart.runTrackerClick = true;
    }
    // Handle DOM events
    // If the browser supports passive events, add it to improve performance
    // on touch events (#11353).
    var addEventListener = el.addEventListener;
    if (addEventListener) {
        addEventListener.call(el, type, fn, Core_Globals.supportsPassiveEvents ? {
            passive: options.passive === void 0 ?
                type.indexOf('touch') !== -1 : options.passive,
            capture: false
        } : false);
    }
    if (!events[type]) {
        events[type] = [];
    }
    var eventObject = {
            fn: fn,
            order: typeof options.order === 'number' ? options.order : Infinity
        };
    events[type].push(eventObject);
    // Order the calls
    events[type].sort(function (a, b) { return a.order - b.order; });
    // Return a function that can be called to remove this event.
    return function () {
        removeEvent(el, type, fn);
    };
}
/* eslint-disable valid-jsdoc */
/**
 * Remove an event that was added with {@link Highcharts#addEvent}.
 *
 * @function Highcharts.removeEvent<T>
 *
 * @param {Highcharts.Class<T>|T} el
 *        The element to remove events on.
 *
 * @param {string} [type]
 *        The type of events to remove. If undefined, all events are removed
 *        from the element.
 *
 * @param {Highcharts.EventCallbackFunction<T>} [fn]
 *        The specific callback to remove. If undefined, all events that match
 *        the element and optionally the type are removed.
 *
 * @return {void}
 */
function removeEvent(el, type, fn) {
    /* eslint-enable valid-jsdoc */
    /**
     * @private
     */
    function removeOneEvent(type, fn) {
        var removeEventListener = el.removeEventListener;
        if (removeEventListener) {
            removeEventListener.call(el, type, fn, false);
        }
    }
    /**
     * @private
     */
    function removeAllEvents(eventCollection) {
        var types,
            len;
        if (!el.nodeName) {
            return; // Break on non-DOM events
        }
        if (type) {
            types = {};
            types[type] = true;
        }
        else {
            types = eventCollection;
        }
        objectEach(types, function (_val, n) {
            if (eventCollection[n]) {
                len = eventCollection[n].length;
                while (len--) {
                    removeOneEvent(n, eventCollection[n][len].fn);
                }
            }
        });
    }
    var owner = typeof el === 'function' && el.prototype || el;
    if (Object.hasOwnProperty.call(owner, 'hcEvents')) {
        var events = owner.hcEvents;
        if (type) {
            var typeEvents = (events[type] || []);
            if (fn) {
                events[type] = typeEvents.filter(function (obj) {
                    return fn !== obj.fn;
                });
                removeOneEvent(type, fn);
            }
            else {
                removeAllEvents(events);
                events[type] = [];
            }
        }
        else {
            removeAllEvents(events);
            delete owner.hcEvents;
        }
    }
}
/* eslint-disable valid-jsdoc */
/**
 * Fire an event that was registered with {@link Highcharts#addEvent}.
 *
 * @function Highcharts.fireEvent<T>
 *
 * @param {T} el
 *        The object to fire the event on. It can be a {@link HTMLDOMElement},
 *        an {@link SVGElement} or any other object.
 *
 * @param {string} type
 *        The type of event.
 *
 * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
 *        Custom event arguments that are passed on as an argument to the event
 *        handler.
 *
 * @param {Highcharts.EventCallbackFunction<T>|Function} [defaultFunction]
 *        The default function to execute if the other listeners haven't
 *        returned false.
 *
 * @return {void}
 */
function fireEvent(el, type, eventArguments, defaultFunction) {
    /* eslint-enable valid-jsdoc */
    eventArguments = eventArguments || {};
    if (doc.createEvent &&
        (el.dispatchEvent ||
            (el.fireEvent &&
                // Enable firing events on Highcharts instance.
                el !== Core_Globals))) {
        var e = doc.createEvent('Events');
        e.initEvent(type, true, true);
        eventArguments = extend(e, eventArguments);
        if (el.dispatchEvent) {
            el.dispatchEvent(eventArguments);
        }
        else {
            el.fireEvent(type, eventArguments);
        }
    }
    else if (el.hcEvents) {
        if (!eventArguments.target) {
            // We're running a custom event
            extend(eventArguments, {
                // Attach a simple preventDefault function to skip
                // default handler if called. The built-in
                // defaultPrevented property is not overwritable (#5112)
                preventDefault: function () {
                    eventArguments.defaultPrevented = true;
                },
                // Setting target to native events fails with clicking
                // the zoom-out button in Chrome.
                target: el,
                // If the type is not set, we're running a custom event
                // (#2297). If it is set, we're running a browser event.
                type: type
            });
        }
        var events = [];
        var object = el;
        var multilevel = false;
        // Recurse up the inheritance chain and collect hcEvents set as own
        // objects on the prototypes.
        while (object.hcEvents) {
            if (Object.hasOwnProperty.call(object, 'hcEvents') &&
                object.hcEvents[type]) {
                if (events.length) {
                    multilevel = true;
                }
                events.unshift.apply(events, object.hcEvents[type]);
            }
            object = Object.getPrototypeOf(object);
        }
        // For performance reasons, only sort the event handlers in case we are
        // dealing with multiple levels in the prototype chain. Otherwise, the
        // events are already sorted in the addEvent function.
        if (multilevel) {
            // Order the calls
            events.sort(function (a, b) { return a.order - b.order; });
        }
        // Call the collected event handlers
        events.forEach(function (obj) {
            // If the event handler returns false, prevent the default handler
            // from executing
            if (obj.fn.call(el, eventArguments) === false) {
                eventArguments.preventDefault();
            }
        });
    }
    // Run the default if not prevented
    if (defaultFunction && !eventArguments.defaultPrevented) {
        defaultFunction.call(el, eventArguments);
    }
}
var serialMode;
/**
 * Get a unique key for using in internal element id's and pointers. The key is
 * composed of a random hash specific to this Highcharts instance, and a
 * counter.
 *
 * @example
 * let id = uniqueKey(); // => 'highcharts-x45f6hp-0'
 *
 * @function Highcharts.uniqueKey
 *
 * @return {string}
 * A unique key.
 */
var uniqueKey = (function () {
    var hash = Math.random().toString(36).substring(2, 9) + '-';
    var id = 0;
    return function () {
        return 'highcharts-' + (serialMode ? '' : hash) + id++;
    };
}());
/**
 * Activates a serial mode for element IDs provided by
 * {@link Highcharts.uniqueKey}. This mode can be used in automated tests, where
 * a simple comparison of two rendered SVG graphics is needed.
 *
 * **Note:** This is only for testing purposes and will break functionality in
 * webpages with multiple charts.
 *
 * @example
 * if (
 *   process &&
 *   process.env.NODE_ENV === 'development'
 * ) {
 *   Highcharts.useSerialIds(true);
 * }
 *
 * @function Highcharts.useSerialIds
 *
 * @param {boolean} [mode]
 * Changes the state of serial mode.
 *
 * @return {boolean|undefined}
 * State of the serial mode.
 */
function useSerialIds(mode) {
    return (serialMode = pick(mode, serialMode));
}
function isFunction(obj) {
    return typeof obj === 'function';
}
function ucfirst(s) {
    return ((isString(s) ?
        s.substring(0, 1).toUpperCase() + s.substring(1) :
        String(s)));
}
/* *
 *
 *  External
 *
 * */
// Register Highcharts as a plugin in jQuery
if (win.jQuery) {
    /**
     * Highcharts-extended JQuery.
     *
     * @external JQuery
     */
    /**
     * Helper function to return the chart of the current JQuery selector
     * element.
     *
     * @function external:JQuery#highcharts
     *
     * @return {Highcharts.Chart}
     *         The chart that is linked to the JQuery selector element.
     */ /**
    * Factory function to create a chart in the current JQuery selector
    * element.
    *
    * @function external:JQuery#highcharts
    *
    * @param {'Chart'|'Map'|'StockChart'|string} [className]
    *        Name of the factory class in the Highcharts namespace.
    *
    * @param {Highcharts.Options} [options]
    *        The chart options structure.
    *
    * @param {Highcharts.ChartCallbackFunction} [callback]
    *        Function to run when the chart has loaded and all external
    *        images are loaded. Defining a
    *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
    *        handler is equivalent.
    *
    * @return {JQuery}
    *         The current JQuery selector.
    */
    win.jQuery.fn.highcharts = function () {
        var args = [].slice.call(arguments);
        if (this[0]) { // `this[0]` is the renderTo div
            // Create the chart
            if (args[0]) {
                new Core_Globals[ // eslint-disable-line computed-property-spacing, no-new
                // Constructor defaults to Chart
                isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]);
                return this;
            }
            // When called without parameters or with the return argument,
            // return an existing chart
            return charts[attr(this[0], 'data-highcharts-chart')];
        }
    };
}
/* *
 *
 *  Default Export
 *
 * */
// TODO use named exports when supported.
var Utilities = {
    addEvent: addEvent,
    arrayMax: arrayMax,
    arrayMin: arrayMin,
    attr: attr,
    clamp: clamp,
    clearTimeout: internalClearTimeout,
    correctFloat: correctFloat,
    createElement: createElement,
    crisp: crisp,
    css: css,
    defined: defined,
    destroyObjectProperties: destroyObjectProperties,
    diffObjects: diffObjects,
    discardElement: discardElement,
    erase: erase,
    error: error,
    extend: extend,
    extendClass: extendClass,
    find: find,
    fireEvent: fireEvent,
    getAlignFactor: getAlignFactor,
    getClosestDistance: getClosestDistance,
    getMagnitude: getMagnitude,
    getNestedProperty: getNestedProperty,
    getStyle: getStyle,
    insertItem: insertItem,
    isArray: isArray,
    isClass: isClass,
    isDOMElement: isDOMElement,
    isFunction: isFunction,
    isNumber: isNumber,
    isObject: isObject,
    isString: isString,
    merge: merge,
    normalizeTickInterval: normalizeTickInterval,
    objectEach: objectEach,
    offset: offset,
    pad: pad,
    pick: pick,
    pInt: pInt,
    pushUnique: pushUnique,
    relativeLength: relativeLength,
    removeEvent: removeEvent,
    replaceNested: replaceNested,
    splat: splat,
    stableSort: stableSort,
    syncTimeout: syncTimeout,
    timeUnits: timeUnits,
    ucfirst: ucfirst,
    uniqueKey: uniqueKey,
    useSerialIds: useSerialIds,
    wrap: wrap
};
/* harmony default export */ var Core_Utilities = (Utilities);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * An animation configuration. Animation configurations can also be defined as
 * booleans, where `false` turns off animation and `true` defaults to a duration
 * of 500ms and defer of 0ms.
 *
 * @interface Highcharts.AnimationOptionsObject
 */ /**
* A callback function to execute when the animation finishes.
* @name Highcharts.AnimationOptionsObject#complete
* @type {Function|undefined}
*/ /**
* The animation defer in milliseconds.
* @name Highcharts.AnimationOptionsObject#defer
* @type {number|undefined}
*/ /**
* The animation duration in milliseconds.
* @name Highcharts.AnimationOptionsObject#duration
* @type {number|undefined}
*/ /**
* The name of an easing function as defined on the `Math` object.
* @name Highcharts.AnimationOptionsObject#easing
* @type {string|Function|undefined}
*/ /**
* A callback function to execute on each step of each attribute or CSS property
* that's being animated. The first argument contains information about the
* animation and progress.
* @name Highcharts.AnimationOptionsObject#step
* @type {Function|undefined}
*/
/**
 * Creates a frame for the animated SVG element.
 *
 * @callback Highcharts.AnimationStepCallbackFunction
 *
 * @param {Highcharts.SVGElement} this
 *        The SVG element to animate.
 *
 * @return {void}
 */
/**
 * Interface description for a class.
 *
 * @interface Highcharts.Class<T>
 * @extends Function
 */ /**
* Class constructor.
* @function Highcharts.Class<T>#new
* @param {...Array<*>} args
*        Constructor arguments.
* @return {T}
*         Class instance.
*/
/**
 * A style object with camel case property names to define visual appearance of
 * a SVG element or HTML element. The properties can be whatever styles are
 * supported on the given SVG or HTML element.
 *
 * @example
 * {
 *    fontFamily: 'monospace',
 *    fontSize: '1.2em'
 * }
 *
 * @interface Highcharts.CSSObject
 */ /**
* @name Highcharts.CSSObject#[key:string]
* @type {boolean|number|string|undefined}
*/ /**
* Background style for the element.
* @name Highcharts.CSSObject#background
* @type {string|undefined}
*/ /**
* Background color of the element.
* @name Highcharts.CSSObject#backgroundColor
* @type {Highcharts.ColorString|undefined}
*/ /**
* Border style for the element.
* @name Highcharts.CSSObject#border
* @type {string|undefined}
*/ /**
* Radius of the element border.
* @name Highcharts.CSSObject#borderRadius
* @type {number|undefined}
*/ /**
* Color used in the element. The 'contrast' option is a Highcharts custom
* property that results in black or white, depending on the background of the
* element.
* @name Highcharts.CSSObject#color
* @type {'contrast'|Highcharts.ColorString|undefined}
*/ /**
* Style of the mouse cursor when resting over the element.
* @name Highcharts.CSSObject#cursor
* @type {Highcharts.CursorValue|undefined}
*/ /**
* Font family of the element text. Multiple values have to be in decreasing
* preference order and separated by comma.
* @name Highcharts.CSSObject#fontFamily
* @type {string|undefined}
*/ /**
* Font size of the element text.
* @name Highcharts.CSSObject#fontSize
* @type {string|undefined}
*/ /**
* Font weight of the element text.
* @name Highcharts.CSSObject#fontWeight
* @type {string|undefined}
*/ /**
* Height of the element.
* @name Highcharts.CSSObject#height
* @type {number|undefined}
*/ /**
* The maximum number of lines. If lines are cropped away, an ellipsis will be
* added.
* @name Highcharts.CSSObject#lineClamp
* @type {number|undefined}
*/ /**
* Width of the element border.
* @name Highcharts.CSSObject#lineWidth
* @type {number|undefined}
*/ /**
* Opacity of the element.
* @name Highcharts.CSSObject#opacity
* @type {number|undefined}
*/ /**
* Space around the element content.
* @name Highcharts.CSSObject#padding
* @type {string|undefined}
*/ /**
* Behaviour of the element when the mouse cursor rests over it.
* @name Highcharts.CSSObject#pointerEvents
* @type {string|undefined}
*/ /**
* Positioning of the element.
* @name Highcharts.CSSObject#position
* @type {string|undefined}
*/ /**
* Alignment of the element text.
* @name Highcharts.CSSObject#textAlign
* @type {string|undefined}
*/ /**
* Additional decoration of the element text.
* @name Highcharts.CSSObject#textDecoration
* @type {string|undefined}
*/ /**
* Outline style of the element text.
* @name Highcharts.CSSObject#textOutline
* @type {string|undefined}
*/ /**
* Line break style of the element text. Highcharts SVG elements support
* `ellipsis` when a `width` is set.
* @name Highcharts.CSSObject#textOverflow
* @type {string|undefined}
*/ /**
* Top spacing of the element relative to the parent element.
* @name Highcharts.CSSObject#top
* @type {string|undefined}
*/ /**
* Animated transition of selected element properties.
* @name Highcharts.CSSObject#transition
* @type {string|undefined}
*/ /**
* Line break style of the element text.
* @name Highcharts.CSSObject#whiteSpace
* @type {string|undefined}
*/ /**
* Width of the element.
* @name Highcharts.CSSObject#width
* @type {number|undefined}
*/
/**
 * All possible cursor styles.
 *
 * @typedef {'alias'|'all-scroll'|'auto'|'cell'|'col-resize'|'context-menu'|'copy'|'crosshair'|'default'|'e-resize'|'ew-resize'|'grab'|'grabbing'|'help'|'move'|'n-resize'|'ne-resize'|'nesw-resize'|'no-drop'|'none'|'not-allowed'|'ns-resize'|'nw-resize'|'nwse-resize'|'pointer'|'progress'|'row-resize'|'s-resize'|'se-resize'|'sw-resize'|'text'|'vertical-text'|'w-resize'|'wait'|'zoom-in'|'zoom-out'} Highcharts.CursorValue
 */
/**
 * All possible dash styles.
 *
 * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue
 */
/**
 * Generic dictionary in TypeScript notation.
 * Use the native `AnyRecord` instead.
 *
 * @deprecated
 * @interface Highcharts.Dictionary<T>
 */ /**
* @name Highcharts.Dictionary<T>#[key:string]
* @type {T}
*/
/**
 * The function callback to execute when the event is fired. The `this` context
 * contains the instance, that fired the event.
 *
 * @callback Highcharts.EventCallbackFunction<T>
 *
 * @param {T} this
 *
 * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
 *        Event arguments.
 *
 * @return {boolean|void}
 */
/**
 * The event options for adding function callback.
 *
 * @interface Highcharts.EventOptionsObject
 */ /**
* The order the event handler should be called. This opens for having one
* handler be called before another, independent of in which order they were
* added.
* @name Highcharts.EventOptionsObject#order
* @type {number}
*/ /**
* Whether an event should be passive or not.
* When set to `true`, the function specified by listener will never call
* `preventDefault()`.
* @name Highcharts.EventOptionsObject#passive
* @type boolean
*/
/**
 * Formats data as a string. Usually the data is accessible through the `this`
 * keyword.
 *
 * @callback Highcharts.FormatterCallbackFunction<T>
 *
 * @param {T} this
 *        Context to format
 *
 * @return {string}
 *         Formatted text
 */
/**
 * An object of key-value pairs for HTML attributes.
 *
 * @typedef {Highcharts.Dictionary<boolean|number|string|Function>} Highcharts.HTMLAttributes
 */
/**
 * An HTML DOM element. The type is a reference to the regular HTMLElement in
 * the global scope.
 *
 * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
 */
/**
 * The iterator callback.
 *
 * @callback Highcharts.ObjectEachCallbackFunction<T>
 *
 * @param {T} this
 *        The context.
 *
 * @param {*} value
 *        The property value.
 *
 * @param {string} key
 *        The property key.
 *
 * @param {*} obj
 *        The object that objectEach is being applied to.
 */
/**
 * An object containing `left` and `top` properties for the position in the
 * page.
 *
 * @interface Highcharts.OffsetObject
 */ /**
* Left distance to the page border.
* @name Highcharts.OffsetObject#left
* @type {number}
*/ /**
* Top distance to the page border.
* @name Highcharts.OffsetObject#top
* @type {number}
*/
/**
 * Describes a range.
 *
 * @interface Highcharts.RangeObject
 */ /**
* Maximum number of the range.
* @name Highcharts.RangeObject#max
* @type {number}
*/ /**
* Minimum number of the range.
* @name Highcharts.RangeObject#min
* @type {number}
*/
/**
 * If a number is given, it defines the pixel length. If a percentage string is
 * given, like for example `'50%'`, the setting defines a length relative to a
 * base size, for example the size of a container.
 *
 * @typedef {number|string} Highcharts.RelativeSize
 */
/**
 * Proceed function to call original (wrapped) function.
 *
 * @callback Highcharts.WrapProceedFunction
 *
 * @param {*} [arg1]
 *        Optional argument. Without any arguments defaults to first argument of
 *        the wrapping function.
 *
 * @param {*} [arg2]
 *        Optional argument. Without any arguments defaults to second argument
 *        of the wrapping function.
 *
 * @param {*} [arg3]
 *        Optional argument. Without any arguments defaults to third argument of
 *        the wrapping function.
 *
 * @return {*}
 *         Return value of the original function.
 */
/**
 * The Highcharts object is the placeholder for all other members, and various
 * utility functions. The most important member of the namespace would be the
 * chart constructor.
 *
 * @example
 * let chart = Highcharts.chart('container', { ... });
 *
 * @namespace Highcharts
 */
''; // Detach doclets above

;// ./code/es5/es-modules/Core/Chart/ChartDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * General options for the chart.
 *
 * @optionparent chart
 */
var ChartDefaults = {
    /**
     * Default `mapData` for all series, in terms of a GeoJSON or TopoJSON
     * object. If set to a string, it functions as an index into the
     * `Highcharts.maps` array.
     *
     * For picking out individual shapes and geometries to use for each series
     * of the map, see [series.mapData](#series.map.mapData).
     *
     * @sample    maps/demo/geojson
     *            Loading GeoJSON data
     * @sample    maps/chart/topojson
     *            Loading TopoJSON data
     *
     * @type      {string|Array<*>|Highcharts.GeoJSON|Highcharts.TopoJSON}
     * @since     5.0.0
     * @product   highmaps
     * @apioption chart.map
     */
    /**
     * Set lat/lon transformation definitions for the chart. If not defined,
     * these are extracted from the map data.
     *
     * @type      {*}
     * @since     5.0.0
     * @product   highmaps
     * @apioption chart.mapTransforms
     */
    /**
     * When using multiple axes, the ticks of two or more opposite axes
     * will automatically be aligned by adding ticks to the axis or axes
     * with the least ticks, as if `tickAmount` were specified.
     *
     * This can be prevented by setting `alignTicks` to false. If the grid
     * lines look messy, it's a good idea to hide them for the secondary
     * axis by setting `gridLineWidth` to 0.
     *
     * If `startOnTick` or `endOnTick` in the axis options are set to false,
     * then the `alignTicks ` will be disabled for the axis.
     *
     * Disabled for logarithmic axes.
     *
     * @sample {highcharts} highcharts/chart/alignticks-true/
     *         True by default
     * @sample {highcharts} highcharts/chart/alignticks-false/
     *         False
     * @sample {highstock} stock/chart/alignticks-true/
     *         True by default
     * @sample {highstock} stock/chart/alignticks-false/
     *         False
     *
     * @type      {boolean}
     * @default   true
     * @product   highcharts highstock gantt
     * @apioption chart.alignTicks
     */
    /**
     * When using multiple axes, align the thresholds. When this is true, other
     * ticks will also be aligned.
     *
     * Note that for line series and some other series types, the `threshold`
     * option is set to `null` by default. This will in turn cause their y-axis
     * to not have a threshold. In order to avoid that, set the series
     * `threshold` to 0 or another number.
     *
     * If `startOnTick` or `endOnTick` in the axis options are set to false, or
     * if the axis is logarithmic, the threshold will not be aligned.
     *
     * @sample {highcharts} highcharts/chart/alignthresholds/ Set to true
     *
     * @since 10.0.0
     * @product   highcharts highstock gantt
     * @apioption chart.alignThresholds
     */
    alignThresholds: false,
    /**
     * Set the overall animation for all chart updating. Animation can be
     * disabled throughout the chart by setting it to false here. It can
     * be overridden for each individual API method as a function parameter.
     * The only animation not affected by this option is the initial series
     * animation, see [plotOptions.series.animation](
     * #plotOptions.series.animation).
     *
     * The animation can either be set as a boolean or a configuration
     * object. If `true`, it will use the 'swing' jQuery easing and a
     * duration of 500 ms. If used as a configuration object, the following
     * properties are supported:
     *
     * - `defer`: The animation delay time in milliseconds.
     *
     * - `duration`: The duration of the animation in milliseconds.
     *
     * - `easing`: A string reference to an easing function set on the
     *   `Math` object. See
     *   [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/).
     *
     * When zooming on a series with less than 100 points, the chart redraw
     * will be done with animation, but in case of more data points, it is
     * necessary to set this option to ensure animation on zoom.
     *
     * @sample {highcharts} highcharts/chart/animation-none/
     *         Updating with no animation
     * @sample {highcharts} highcharts/chart/animation-duration/
     *         With a longer duration
     * @sample {highcharts} highcharts/chart/animation-easing/
     *         With a jQuery UI easing
     * @sample {highmaps} maps/chart/animation-none/
     *         Updating with no animation
     * @sample {highmaps} maps/chart/animation-duration/
     *         With a longer duration
     *
     * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
     * @default   true
     * @apioption chart.animation
     */
    /**
     * A CSS class name to apply to the charts container `div`, allowing
     * unique CSS styling for each chart.
     *
     * @type      {string}
     * @apioption chart.className
     */
    /**
     * Event listeners for the chart.
     *
     * @apioption chart.events
     */
    /**
     * Fires when a series is added to the chart after load time, using the
     * `addSeries` method. One parameter, `event`, is passed to the
     * function, containing common event information. Through
     * `event.options` you can access the series options that were passed to
     * the `addSeries` method. Returning false prevents the series from
     * being added.
     *
     * @sample {highcharts} highcharts/chart/events-addseries/
     *         Alert on add series
     * @sample {highstock} stock/chart/events-addseries/
     *         Alert on add series
     *
     * @type      {Highcharts.ChartAddSeriesCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Chart
     * @apioption chart.events.addSeries
     */
    /**
     * Fires when clicking on the plot background. One parameter, `event`,
     * is passed to the function, containing common event information.
     *
     * Information on the clicked spot can be found through `event.xAxis`
     * and `event.yAxis`, which are arrays containing the axes of each
     * dimension and each axis' value at the clicked spot. The primary axes
     * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
     * datetime axis is milliseconds since 1970-01-01 00:00:00.
     *
     * ```js
     * click: function(e) {
     *     console.log(
     *         Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value),
     *         e.yAxis[0].value
     *     )
     * }
     * ```
     *
     * @sample {highcharts} highcharts/chart/events-click/
     *         Alert coordinates on click
     * @sample {highcharts} highcharts/chart/events-container/
     *         Alternatively, attach event to container
     * @sample {highstock} stock/chart/events-click/
     *         Alert coordinates on click
     * @sample {highstock} highcharts/chart/events-container/
     *         Alternatively, attach event to container
     * @sample {highmaps} maps/chart/events-click/
     *         Record coordinates on click
     * @sample {highmaps} highcharts/chart/events-container/
     *         Alternatively, attach event to container
     *
     * @type      {Highcharts.ChartClickCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Chart
     * @apioption chart.events.click
     */
    /**
     * Fires when the chart is finished loading. Since v4.2.2, it also waits
     * for images to be loaded, for example from point markers. One
     * parameter, `event`, is passed to the function, containing common
     * event information.
     *
     * There is also a second parameter to the chart constructor where a
     * callback function can be passed to be executed on chart.load.
     *
     * @sample {highcharts} highcharts/chart/events-load/
     *         Alert on chart load
     * @sample {highcharts} highcharts/chart/events-render/
     *         Load vs Redraw vs Render
     * @sample {highstock} stock/chart/events-load/
     *         Alert on chart load
     * @sample {highmaps} maps/chart/events-load/
     *         Add series on chart load
     *
     * @type      {Highcharts.ChartLoadCallbackFunction}
     * @context   Highcharts.Chart
     * @apioption chart.events.load
     */
    /**
     * Fires when the chart is redrawn, either after a call to
     * `chart.redraw()` or after an axis, series or point is modified with
     * the `redraw` option set to `true`. One parameter, `event`, is passed
     * to the function, containing common event information.
     *
     * @sample {highcharts} highcharts/chart/events-redraw/
     *         Alert on chart redraw
     * @sample {highcharts} highcharts/chart/events-render/
     *         Load vs Redraw vs Render
     * @sample {highstock} stock/chart/events-redraw/
     *         Alert on chart redraw when adding a series or moving the
     *         zoomed range
     * @sample {highmaps} maps/chart/events-redraw/
     *         Set subtitle on chart redraw
     *
     * @type      {Highcharts.ChartRedrawCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Chart
     * @apioption chart.events.redraw
     */
    /**
     * Fires after initial load of the chart (directly after the `load`
     * event), and after each redraw (directly after the `redraw` event).
     *
     * @sample {highcharts} highcharts/chart/events-render/
     *         Load vs Redraw vs Render
     *
     * @type      {Highcharts.ChartRenderCallbackFunction}
     * @since     5.0.7
     * @context   Highcharts.Chart
     * @apioption chart.events.render
     */
    /**
     * Fires when an area of the chart has been selected. Selection is
     * enabled by setting the chart's zoomType. One parameter, `event`, is
     * passed to the function, containing common event information. The
     * default action for the selection event is to zoom the chart to the
     * selected area. It can be prevented by calling
     * `event.preventDefault()` or return false.
     *
     * Information on the selected area can be found through `event.xAxis`
     * and `event.yAxis`, which are arrays containing the axes of each
     * dimension and each axis' min and max values. The primary axes are
     * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
     * datetime axis is milliseconds since 1970-01-01 00:00:00.
     *
     * ```js
     * selection: function(event) {
     *     // log the min and max of the primary, datetime x-axis
     *     console.log(
     *         Highcharts.dateFormat(
     *             '%Y-%m-%d %H:%M:%S',
     *             event.xAxis[0].min
     *         ),
     *         Highcharts.dateFormat(
     *             '%Y-%m-%d %H:%M:%S',
     *             event.xAxis[0].max
     *         )
     *     );
     *     // log the min and max of the y axis
     *     console.log(event.yAxis[0].min, event.yAxis[0].max);
     * }
     * ```
     *
     * @sample {highcharts} highcharts/chart/events-selection/
     *         Report on selection and reset
     * @sample {highcharts} highcharts/chart/events-selection-points/
     *         Select a range of points through a drag selection
     * @sample {highstock} stock/chart/events-selection/
     *         Report on selection and reset
     * @sample {highstock} highcharts/chart/events-selection-points/
     *         Select a range of points through a drag selection
     *         (Highcharts)
     *
     * @type      {Highcharts.ChartSelectionCallbackFunction}
     * @apioption chart.events.selection
     */
    /**
     * The margin between the outer edge of the chart and the plot area.
     * The numbers in the array designate top, right, bottom and left
     * respectively. Use the options `marginTop`, `marginRight`,
     * `marginBottom` and `marginLeft` for shorthand setting of one option.
     *
     * By default there is no margin. The actual space is dynamically
     * calculated from the offset of axis labels, axis title, title,
     * subtitle and legend in addition to the `spacingTop`, `spacingRight`,
     * `spacingBottom` and `spacingLeft` options.
     *
     * @sample {highcharts} highcharts/chart/margins-zero/
     *         Zero margins
     * @sample {highstock} stock/chart/margin-zero/
     *         Zero margins
     *
     * @type      {number|Array<number>}
     * @apioption chart.margin
     */
    /**
     * The margin between the bottom outer edge of the chart and the plot
     * area. Use this to set a fixed pixel value for the margin as opposed
     * to the default dynamic margin. See also `spacingBottom`.
     *
     * @sample {highcharts} highcharts/chart/marginbottom/
     *         100px bottom margin
     * @sample {highstock} stock/chart/marginbottom/
     *         100px bottom margin
     * @sample {highmaps} maps/chart/margin/
     *         100px margins
     *
     * @type      {number}
     * @since     2.0
     * @apioption chart.marginBottom
     */
    /**
     * The margin between the left outer edge of the chart and the plot
     * area. Use this to set a fixed pixel value for the margin as opposed
     * to the default dynamic margin. See also `spacingLeft`.
     *
     * @sample {highcharts} highcharts/chart/marginleft/
     *         150px left margin
     * @sample {highstock} stock/chart/marginleft/
     *         150px left margin
     * @sample {highmaps} maps/chart/margin/
     *         100px margins
     *
     * @type      {number}
     * @since     2.0
     * @apioption chart.marginLeft
     */
    /**
     * The margin between the right outer edge of the chart and the plot
     * area. Use this to set a fixed pixel value for the margin as opposed
     * to the default dynamic margin. See also `spacingRight`.
     *
     * @sample {highcharts} highcharts/chart/marginright/
     *         100px right margin
     * @sample {highstock} stock/chart/marginright/
     *         100px right margin
     * @sample {highmaps} maps/chart/margin/
     *         100px margins
     *
     * @type      {number}
     * @since     2.0
     * @apioption chart.marginRight
     */
    /**
     * The margin between the top outer edge of the chart and the plot area.
     * Use this to set a fixed pixel value for the margin as opposed to
     * the default dynamic margin. See also `spacingTop`.
     *
     * @sample {highcharts} highcharts/chart/margintop/ 100px top margin
     * @sample {highstock} stock/chart/margintop/
     *         100px top margin
     * @sample {highmaps} maps/chart/margin/
     *         100px margins
     *
     * @type      {number}
     * @since     2.0
     * @apioption chart.marginTop
     */
    /**
     * Callback function to override the default function that formats all
     * the numbers in the chart. Returns a string with the formatted number.
     *
     * @sample highcharts/members/highcharts-numberformat
     *      Arabic digits in Highcharts
     * @type {Highcharts.NumberFormatterCallbackFunction}
     * @since 8.0.0
     * @apioption chart.numberFormatter
     */
    /**
     * When a chart with an x and a y-axis is rendered, we first pre-render the
     * labels of both in order to measure them. Then, if either of the axis
     * labels take up so much space that it significantly affects the length of
     * the other axis, we repeat the process.
     *
     * By default we stop at two axis layout runs, but it may be that the second
     * run also alter the space required by either axis, for example if it
     * causes the labels to rotate. In this situation, a subsequent redraw of
     * the chart may cause the tick and label placement to change for apparently
     * no reason.
     *
     * Use the `axisLayoutRuns` option to set the maximum allowed number of
     * repetitions. But keep in mind that the default value of 2 is set because
     * every run costs performance time.
     *
     * **Note:** Changing that option to higher than the default might decrease
     * performance significantly, especially with bigger sets of data.
     *
     * @type      {number}
     * @default   2
     * @since     11.3.0
     * @apioption chart.axisLayoutRuns
     */
    /**
     * Allows setting a key to switch between zooming and panning. Can be
     * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows
     * key on Windows) or `shift`. The keys are mapped directly to the key
     * properties of the click event argument (`event.altKey`,
     * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`).
     *
     * @type       {string}
     * @since      4.0.3
     * @product    highcharts gantt
     * @validvalue ["alt", "ctrl", "meta", "shift"]
     * @apioption  chart.panKey
     */
    /**
     * Allow panning in a chart. Best used with [panKey](#chart.panKey)
     * to combine zooming and panning.
     *
     * On touch devices, when the [tooltip.followTouchMove](
     * #tooltip.followTouchMove) option is `true` (default), panning
     * requires two fingers. To allow panning with one finger, set
     * `followTouchMove` to `false`.
     *
     * @sample  {highcharts} highcharts/chart/pankey/ Zooming and panning
     * @sample  {highstock} stock/chart/panning/ Zooming and xy panning
     */
    panning: {
        /**
         * Enable or disable chart panning.
         *
         * @type      {boolean}
         * @default   {highcharts} false
         * @default   {highstock|highmaps} true
         */
        enabled: false,
        /**
         * Decides in what dimensions the user can pan the chart. Can be
         * one of `x`, `y`, or `xy`.
         *
         * During panning, all axes will behave as if
         * [`startOnTick`](#yAxis.startOnTick) and
         * [`endOnTick`](#yAxis.endOnTick) were set to `false`. After the
         * panning action is finished, the axes will adjust to their actual
         * settings.
         *
         * @sample {highcharts} highcharts/chart/panning-type
         *         Zooming and xy panning
         *
         * @declare    Highcharts.OptionsChartPanningTypeValue
         * @type       {string}
         * @validvalue ["x", "y", "xy"]
         * @product    highcharts highstock gantt
         */
        type: 'x'
    },
    /**
     * Equivalent to [zoomType](#chart.zoomType), but for multitouch
     * gestures only. By default, the `pinchType` is the same as the
     * `zoomType` setting. However, pinching can be enabled separately in
     * some cases, for example in stock charts where a mouse drag pans the
     * chart, while pinching is enabled. When [tooltip.followTouchMove](
     * #tooltip.followTouchMove) is true, pinchType only applies to
     * two-finger touches.
     *
     * @type       {string}
     * @default    {highcharts} undefined
     * @default    {highstock} undefined
     * @since      3.0
     * @product    highcharts highstock gantt
     * @deprecated
     * @validvalue ["x", "y", "xy"]
     * @apioption  chart.pinchType
     */
    /**
     * Whether to apply styled mode. When in styled mode, no presentational
     * attributes or CSS are applied to the chart SVG. Instead, CSS rules
     * are required to style the chart. The default style sheet is
     * available from `https://code.highcharts.com/css/highcharts.css`.
     *
     * [Read more in the docs](https://www.highcharts.com/docs/chart-design-and-style/style-by-css)
     * on what classes and variables are available.
     *
     * @sample highcharts/css/colors
     *         Color theming with CSS
     * @sample highcharts/css/prefers-color-scheme
     *         Dynamic theme based on system settings
     * @type       {boolean}
     * @default    false
     * @since      7.0
     * @apioption  chart.styledMode
     */
    styledMode: false,
    /**
     * The corner radius of the outer chart border.
     *
     * @sample {highcharts} highcharts/chart/borderradius/
     *         20px radius
     * @sample {highstock} stock/chart/border/
     *         10px radius
     * @sample {highmaps} maps/chart/border/
     *         Border options
     *
     */
    borderRadius: 0,
    /**
     * In styled mode, this sets how many colors the class names
     * should rotate between. With ten colors, series (or points) are
     * given class names like `highcharts-color-0`, `highcharts-color-1`
     * [...] `highcharts-color-9`. The equivalent in non-styled mode
     * is to set colors using the [colors](#colors) setting.
     *
     * @since      5.0.0
     */
    colorCount: 10,
    /**
     * By default, (because of memory and performance reasons) the chart does
     * not copy the data but keeps it as a reference. In some cases, this might
     * result in mutating the original data source. In order to prevent that,
     * set that property to false. Please note that changing that might decrease
     * performance, especially with bigger sets of data.
     *
     * @type       {boolean}
     * @since 10.1.0
     */
    allowMutatingData: true,
    /**
     * If true, the axes will scale to the remaining visible series once
     * one series is hidden. If false, hiding and showing a series will
     * not affect the axes or the other series. For stacks, once one series
     * within the stack is hidden, the rest of the stack will close in
     * around it even if the axis is not affected.
     *
     * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/
     *         True by default
     * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/
     *         False
     * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/
     *         True with stack
     * @sample {highstock} stock/chart/ignorehiddenseries-true/
     *         True by default
     * @sample {highstock} stock/chart/ignorehiddenseries-false/
     *         False
     *
     * @since   1.2.0
     * @product highcharts highstock gantt
     */
    ignoreHiddenSeries: true,
    /**
     * Whether to invert the axes so that the x axis is vertical and y axis
     * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed)
     * by default.
     *
     * @productdesc {highcharts}
     * If a bar series is present in the chart, it will be inverted
     * automatically. Inverting the chart doesn't have an effect if there
     * are no cartesian series in the chart.
     *
     * @sample {highcharts} highcharts/chart/inverted/
     *         Inverted line
     * @sample {highstock} stock/navigator/inverted/
     *         Inverted stock chart
     *
     * @type      {boolean}
     * @default   false
     * @product   highcharts highstock gantt
     * @apioption chart.inverted
     */
    /**
     * The distance between the outer edge of the chart and the content,
     * like title or legend, or axis title and labels if present. The
     * numbers in the array designate top, right, bottom and left
     * respectively. Use the options spacingTop, spacingRight, spacingBottom
     * and spacingLeft options for shorthand setting of one option.
     *
     * @type    {Array<number>}
     * @see     [chart.margin](#chart.margin)
     * @default [10, 10, 15, 10]
     * @since   3.0.6
     */
    spacing: [10, 10, 15, 10],
    /**
     * The button that appears after a selection zoom, allowing the user
     * to reset zoom. This option is deprecated in favor of
     * [zooming](#chart.zooming).
     *
     * @since      2.2
     * @deprecated 10.2.1
     */
    resetZoomButton: {
        /**
         * What frame the button placement should be related to. Can be
         * either `plotBox` or `spacingBox`.
         *
         * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/
         *         Relative to the chart
         * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/
         *         Relative to the chart
         *
         * @type      {Highcharts.ButtonRelativeToValue}
         * @apioption chart.resetZoomButton.relativeTo
         */
        /**
         * A collection of attributes for the button. The object takes SVG
         * attributes like `fill`, `stroke`, `stroke-width` or `r`, the
         * border radius. The theme also supports `style`, a collection of
         * CSS properties for the text. Equivalent attributes for the hover
         * state are given in `theme.states.hover`.
         *
         * @sample {highcharts} highcharts/chart/resetzoombutton-theme/
         *         Theming the button
         * @sample {highstock} highcharts/chart/resetzoombutton-theme/
         *         Theming the button
         *
         * @type {Highcharts.SVGAttributes}
         */
        theme: {
        /**
         * The z-index of the button.
         *
         * @type {number}
         * @apioption chart.resetZoomButton.theme.zIndex
         */
        },
        /**
         * The position of the button.
         *
         * @sample {highcharts} highcharts/chart/resetzoombutton-position/
         *         Above the plot area
         * @sample {highstock} highcharts/chart/resetzoombutton-position/
         *         Above the plot area
         * @sample {highmaps} highcharts/chart/resetzoombutton-position/
         *         Above the plot area
         *
         * @type {Highcharts.AlignObject}
         */
        position: {
        /**
         * The horizontal alignment of the button.
         *
         * @type {number}
         * @apioption chart.resetZoomButton.position.align
         */
        /**
         * The horizontal offset of the button.
         *
         * @type {number}
         * @apioption chart.resetZoomButton.position.x
         */
        /**
         * The vertical alignment of the button.
         *
         * @type      {Highcharts.VerticalAlignValue}
         * @apioption chart.resetZoomButton.position.verticalAlign
         */
        /**
         * The vertical offset of the button.
         *
         * @type {number}
         * @apioption chart.resetZoomButton.position.y
         */
        }
    },
    /**
     * The pixel width of the plot area border.
     *
     * @sample {highcharts} highcharts/chart/plotborderwidth/
     *         1px border
     * @sample {highstock} stock/chart/plotborder/
     *         2px border
     * @sample {highmaps} maps/chart/plotborder/
     *         Plot border options
     *
     * @type      {number}
     * @default   0
     * @apioption chart.plotBorderWidth
     */
    /**
     * Whether to apply a drop shadow to the plot area. Requires that
     * plotBackgroundColor be set. The shadow can be an object configuration
     * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
     *
     * @sample {highcharts} highcharts/chart/plotshadow/
     *         Plot shadow
     * @sample {highstock} stock/chart/plotshadow/
     *         Plot shadow
     * @sample {highmaps} maps/chart/plotborder/
     *         Plot border options
     *
     * @type      {boolean|Highcharts.ShadowOptionsObject}
     * @default   false
     * @apioption chart.plotShadow
     */
    /**
     * When true, cartesian charts like line, spline, area and column are
     * transformed into the polar coordinate system. This produces _polar
     * charts_, also known as _radar charts_.
     *
     * @sample {highcharts} highcharts/demo/polar/
     *         Polar chart
     * @sample {highcharts} highcharts/demo/polar-wind-rose/
     *         Wind rose, stacked polar column chart
     * @sample {highcharts} highcharts/demo/polar-spider/
     *         Spider web chart
     * @sample {highcharts} highcharts/parallel-coordinates/polar/
     *         Star plot, multivariate data in a polar chart
     *
     * @type      {boolean}
     * @default   false
     * @since     2.3.0
     * @product   highcharts
     * @requires  highcharts-more
     * @apioption chart.polar
     */
    /**
     * Whether to reflow the chart to fit the width of the container div
     * on resizing the window.
     *
     * @sample {highcharts} highcharts/chart/reflow-true/
     *         True by default
     * @sample {highcharts} highcharts/chart/reflow-false/
     *         False
     * @sample {highstock} stock/chart/reflow-true/
     *         True by default
     * @sample {highstock} stock/chart/reflow-false/
     *         False
     * @sample {highmaps} maps/chart/reflow-true/
     *         True by default
     * @sample {highmaps} maps/chart/reflow-false/
     *         False
     *
     * @since     2.1
     */
    reflow: true,
    /**
     * The HTML element where the chart will be rendered. If it is a string,
     * the element by that id is used. The HTML element can also be passed
     * by direct reference, or as the first argument of the chart
     * constructor, in which case the option is not needed.
     *
     * @sample {highcharts} highcharts/chart/reflow-true/
     *         String
     * @sample {highcharts} highcharts/chart/renderto-object/
     *         Object reference
     * @sample {highstock} stock/chart/renderto-string/
     *         String
     * @sample {highstock} stock/chart/renderto-object/
     *         Object reference
     *
     * @type      {string|Highcharts.HTMLDOMElement}
     * @apioption chart.renderTo
     */
    /**
     * The background color of the marker square when selecting (zooming
     * in on) an area of the chart.
     *
     * @see In styled mode, the selection marker fill is set with the
     *      `.highcharts-selection-marker` class.
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default   rgba(51,92,173,0.25)
     * @since     2.1.7
     * @apioption chart.selectionMarkerFill
     */
    /**
     * Whether to apply a drop shadow to the global series group. This causes
     * all the series to have the same shadow. Contrary to the `series.shadow`
     * option, this prevents items from casting shadows on each other, like for
     * others series in a stack. The shadow can be an object configuration
     * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
     *
     * @sample highcharts/chart/seriesgroupshadow/ Shadow
     *
     * @type      {boolean|Highcharts.ShadowOptionsObject}
     * @default   false
     * @apioption chart.shadow
     */
    /**
     * Whether to apply a drop shadow to the outer chart area. Requires
     * that backgroundColor be set. The shadow can be an object
     * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and
     * `width`.
     *
     * @sample {highcharts} highcharts/chart/shadow/
     *         Shadow
     * @sample {highstock} stock/chart/shadow/
     *         Shadow
     * @sample {highmaps} maps/chart/border/
     *         Chart border and shadow
     *
     * @type      {boolean|Highcharts.ShadowOptionsObject}
     * @default   false
     * @apioption chart.shadow
     */
    /**
     * Whether to show the axes initially. This only applies to empty charts
     * where series are added dynamically, as axes are automatically added
     * to cartesian series.
     *
     * @sample {highcharts} highcharts/chart/showaxes-false/
     *         False by default
     * @sample {highcharts} highcharts/chart/showaxes-true/
     *         True
     *
     * @type      {boolean}
     * @since     1.2.5
     * @product   highcharts gantt
     * @apioption chart.showAxes
     */
    /**
     * The space between the bottom edge of the chart and the content (plot
     * area, axis title and labels, title, subtitle or legend in top
     * position).
     *
     * @sample {highcharts} highcharts/chart/spacingbottom/
     *         Spacing bottom set to 100
     * @sample {highstock} stock/chart/spacingbottom/
     *         Spacing bottom set to 100
     * @sample {highmaps} maps/chart/spacing/
     *         Spacing 100 all around
     *
     * @type      {number}
     * @default   15
     * @since     2.1
     * @apioption chart.spacingBottom
     */
    /**
     * The space between the left edge of the chart and the content (plot
     * area, axis title and labels, title, subtitle or legend in top
     * position).
     *
     * @sample {highcharts} highcharts/chart/spacingleft/
     *         Spacing left set to 100
     * @sample {highstock} stock/chart/spacingleft/
     *         Spacing left set to 100
     * @sample {highmaps} maps/chart/spacing/
     *         Spacing 100 all around
     *
     * @type      {number}
     * @default   10
     * @since     2.1
     * @apioption chart.spacingLeft
     */
    /**
     * The space between the right edge of the chart and the content (plot
     * area, axis title and labels, title, subtitle or legend in top
     * position).
     *
     * @sample {highcharts} highcharts/chart/spacingright-100/
     *         Spacing set to 100
     * @sample {highcharts} highcharts/chart/spacingright-legend/
     *         Legend in right position with default spacing
     * @sample {highstock} stock/chart/spacingright/
     *         Spacing set to 100
     * @sample {highmaps} maps/chart/spacing/
     *         Spacing 100 all around
     *
     * @type      {number}
     * @default   10
     * @since     2.1
     * @apioption chart.spacingRight
     */
    /**
     * The space between the top edge of the chart and the content (plot
     * area, axis title and labels, title, subtitle or legend in top
     * position).
     *
     * @sample {highcharts} highcharts/chart/spacingtop-100/
     *         A top spacing of 100
     * @sample {highcharts} highcharts/chart/spacingtop-10/
     *         Floating chart title makes the plot area align to the default
     *         spacingTop of 10.
     * @sample {highstock} stock/chart/spacingtop/
     *         A top spacing of 100
     * @sample {highmaps} maps/chart/spacing/
     *         Spacing 100 all around
     *
     * @type      {number}
     * @default   10
     * @since     2.1
     * @apioption chart.spacingTop
     */
    /**
     * Additional CSS styles to apply inline to the container `div` and the root
     * SVG.
     *
     * According to the CSS syntax documentation, it is recommended to quote
     * font family names that contain white space, digits, or punctuation
     * characters other than hyphens. In such cases, wrap the fontFamily
     * name as follows: `fontFamily: '"Font name"'`.
     *
     * Since v11, the root font size is 1rem by default, and all child element
     * are given a relative `em` font size by default. This allows implementers
     * to control all the chart's font sizes by only setting the root level.
     *
     * @see    In styled mode, general chart styles can be set with the
     *         `.highcharts-root` class.
     * @sample {highcharts} highcharts/chart/style-serif-font/
     *         Using a serif type font
     * @sample {highcharts} highcharts/chart/style-special-font/
     *         Using a font with special character in name
     * @sample {highcharts} highcharts/members/relative-font-size/
     *         Relative font sizes
     * @sample {highcharts} highcharts/css/em/
     *         Styled mode with relative font sizes
     * @sample {highstock} stock/chart/style/
     *         Using a serif type font
     * @sample {highmaps} maps/chart/style-serif-font/
     *         Using a serif type font
     *
     * @type      {Highcharts.CSSObject}
     * @default   {"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif", "fontSize":"1rem"}
     * @apioption chart.style
     */
    /**
     * The default series type for the chart. Can be any of the chart types
     * listed under [plotOptions](#plotOptions) and [series](#series) or can
     * be a series provided by an additional module.
     *
     * In TypeScript this option has no effect in sense of typing and
     * instead the `type` option must always be set in the series.
     *
     * @sample {highcharts} highcharts/chart/type-bar/
     *         Bar
     * @sample {highstock} stock/chart/type/
     *         Areaspline
     * @sample {highmaps} maps/chart/type-mapline/
     *         Mapline
     *
     * @type       {string}
     * @default    {highcharts} line
     * @default    {highstock} line
     * @default    {highmaps} map
     * @since      2.1.0
     * @apioption  chart.type
     */
    type: 'line',
    /**
     * Decides in what dimensions the user can zoom by dragging the mouse.
     * Can be one of `x`, `y` or `xy`.
     *
     * @see [panKey](#chart.panKey)
     *
     * @sample {highcharts} highcharts/chart/zoomtype-none/
     *         None by default
     * @sample {highcharts} highcharts/chart/zoomtype-x/
     *         X
     * @sample {highcharts} highcharts/chart/zoomtype-y/
     *         Y
     * @sample {highcharts} highcharts/chart/zoomtype-xy/
     *         Xy
     * @sample {highcharts} highcharts/chart/zoomtype-polar/
     *         Zoom on polar chart
     * @sample {highstock} stock/demo/basic-line/
     *         None by default
     * @sample {highstock} stock/chart/zoomtype-x/
     *         X
     * @sample {highstock} stock/chart/zoomtype-y/
     *         Y
     * @sample {highstock} stock/chart/zoomtype-xy/
     *         Xy
     * @sample {highmaps} maps/chart/zoomtype-xy/
     *         Map with selection zoom
     *
     * @type       {string}
     * @validvalue ["x", "y", "xy"]
     * @deprecated
     * @apioption  chart.zoomType
     */
    /**
     * Enables zooming by a single touch, in combination with
     * [chart.zoomType](#chart.zoomType). When enabled, two-finger pinch
     * will still work as set up by [chart.pinchType](#chart.pinchType).
     * However, `zoomBySingleTouch` will interfere with touch-dragging the
     * chart to read the tooltip. And especially when vertical zooming is
     * enabled, it will make it hard to scroll vertically on the page.
     * @since      9.0.0
     * @sample     highcharts/chart/zoombysingletouch
     *             Zoom by single touch enabled, with buttons to toggle
     * @product    highcharts highstock gantt
     * @deprecated
     */
    /**
     * Chart zooming options.
     * @since 10.2.1
     */
    zooming: {
        /**
         * Equivalent to [type](#chart.zooming.type), but for multitouch
         * gestures only. By default, the `pinchType` is the same as the
         * `type` setting. However, pinching can be enabled separately in
         * some cases, for example in stock charts where a mouse drag pans the
         * chart, while pinching is enabled. When [tooltip.followTouchMove](
         * #tooltip.followTouchMove) is true, pinchType only applies to
         * two-finger touches.
         *
         * @type       {string}
         * @default    {highcharts} undefined
         * @default    {highstock} x
         * @product    highcharts highstock gantt
         * @validvalue ["x", "y", "xy"]
         * @apioption  chart.zooming.pinchType
         */
        /**
         * Decides in what dimensions the user can zoom by dragging the mouse.
         * Can be one of `x`, `y` or `xy`.
         *
         * @declare    Highcharts.OptionsChartZoomingTypeValue
         * @type       {string}
         * @default    {highcharts} undefined
         * @product    highcharts highstock gantt
         * @validvalue ["x", "y", "xy"]
         * @apioption  chart.zooming.type
         */
        /**
         * Set a key to hold when dragging to zoom the chart. This is useful to
         * avoid zooming while moving points. Should be set different than
         * [chart.panKey](#chart.panKey).
         *
         * @type       {string}
         * @default    {highcharts} undefined
         * @validvalue ["alt", "ctrl", "meta", "shift"]
         * @requires   modules/draggable-points
         * @apioption  chart.zooming.key
         */
        /**
         * Enables zooming by a single touch, in combination with
         * [chart.zooming.type](#chart.zooming.type). When enabled, two-finger
         * pinch will still work as set up by [chart.zooming.pinchType]
         * (#chart.zooming.pinchType). However, `singleTouch` will interfere
         * with touch-dragging the chart to read the tooltip. And especially
         * when vertical zooming is enabled, it will make it hard to scroll
         * vertically on the page.
         *
         * @sample  highcharts/chart/zoombysingletouch
         *          Zoom by single touch enabled, with buttons to toggle
         *
         * @product highcharts highstock gantt
         */
        singleTouch: false,
        /**
         * The button that appears after a selection zoom, allowing the user
         * to reset zoom.
         */
        resetButton: {
            /**
             * What frame the button placement should be related to. Can be
             * either `plotBox` or `spacingBox`.
             *
             * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/
             *         Relative to the chart
             * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/
             *         Relative to the chart
             *
             * @type      {Highcharts.ButtonRelativeToValue}
             * @default   plot
             * @apioption chart.zooming.resetButton.relativeTo
             */
            /**
             * A collection of attributes for the button. The object takes SVG
             * attributes like `fill`, `stroke`, `stroke-width` or `r`, the
             * border radius. The theme also supports `style`, a collection of
             * CSS properties for the text. Equivalent attributes for the hover
             * state are given in `theme.states.hover`.
             *
             * @sample {highcharts} highcharts/chart/resetzoombutton-theme/
             *         Theming the button
             * @sample {highstock} highcharts/chart/resetzoombutton-theme/
             *         Theming the button
             *
             * @type  {Highcharts.SVGAttributes}
             * @since 10.2.1
             */
            theme: {
                /** @internal */
                zIndex: 6
            },
            /**
             * The position of the button.
             *
             * Note: Adjusting position values might cause overlap with chart
             * elements. Ensure coordinates do not obstruct other components or
             * data visibility.
             *
             * @sample {highcharts} highcharts/chart/resetzoombutton-position/
             *         Above the plot area
             * @sample {highstock} highcharts/chart/resetzoombutton-position/
             *         Above the plot area
             * @sample {highmaps} highcharts/chart/resetzoombutton-position/
             *         Above the plot area
             *
             * @type  {Highcharts.AlignObject}
             * @since 10.2.1
             */
            position: {
                /**
                 * The horizontal alignment of the button.
                 */
                align: 'right',
                /**
                 * The horizontal offset of the button.
                 */
                x: -10,
                /**
                 * The vertical alignment of the button.
                 *
                 * @type       {Highcharts.VerticalAlignValue}
                 * @default    top
                 * @apioption  chart.zooming.resetButton.position.verticalAlign
                 */
                /**
                 * The vertical offset of the button.
                 */
                y: 10
            }
        }
    },
    /**
     * An explicit width for the chart. By default (when `null`) the width
     * is calculated from the offset width of the containing element.
     *
     * @sample {highcharts} highcharts/chart/width/
     *         800px wide
     * @sample {highstock} stock/chart/width/
     *         800px wide
     * @sample {highmaps} maps/chart/size/
     *         Chart with explicit size
     *
     * @type {null|number|string}
     */
    width: null,
    /**
     * An explicit height for the chart. If a _number_, the height is
     * given in pixels. If given a _percentage string_ (for example
     * `'56%'`), the height is given as the percentage of the actual chart
     * width. This allows for preserving the aspect ratio across responsive
     * sizes.
     *
     * By default (when `null`) the height is calculated from the offset
     * height of the containing element, or 400 pixels if the containing
     * element's height is 0.
     *
     * @sample {highcharts} highcharts/chart/height/
     *         Forced 200px height
     * @sample {highstock} stock/chart/height/
     *         300px height
     * @sample {highmaps} maps/chart/size/
     *         Chart with explicit size
     * @sample highcharts/chart/height-percent/
     *         Highcharts with percentage height
     * @sample highcharts/chart/height-inherited/
     *         Chart with inherited height
     *
     * @type {null|number|string}
     */
    height: null,
    /**
     * The color of the outer chart border.
     *
     * @see In styled mode, the stroke is set with the
     *      `.highcharts-background` class.
     *
     * @sample {highcharts} highcharts/chart/bordercolor/
     *         Brown border
     * @sample {highstock} stock/chart/border/
     *         Brown border
     * @sample {highmaps} maps/chart/border/
     *         Border options
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    borderColor: "#334eff" /* Palette.highlightColor80 */,
    /**
     * The pixel width of the outer chart border.
     *
     * @see In styled mode, the stroke is set with the
     *      `.highcharts-background` class.
     *
     * @sample {highcharts} highcharts/chart/borderwidth/
     *         5px border
     * @sample {highstock} stock/chart/border/
     *         2px border
     * @sample {highmaps} maps/chart/border/
     *         Border options
     *
     * @type      {number}
     * @default   0
     * @apioption chart.borderWidth
     */
    /**
     * The background color or gradient for the outer chart area.
     *
     * @see In styled mode, the background is set with the
     *      `.highcharts-background` class.
     *
     * @sample {highcharts} highcharts/chart/backgroundcolor-color/
     *         Color
     * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/
     *         Gradient
     * @sample {highstock} stock/chart/backgroundcolor-color/
     *         Color
     * @sample {highstock} stock/chart/backgroundcolor-gradient/
     *         Gradient
     * @sample {highmaps} maps/chart/backgroundcolor-color/
     *         Color
     * @sample {highmaps} maps/chart/backgroundcolor-gradient/
     *         Gradient
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    backgroundColor: "#ffffff" /* Palette.backgroundColor */,
    /**
     * The background color or gradient for the plot area.
     *
     * @see In styled mode, the plot background is set with the
     *      `.highcharts-plot-background` class.
     *
     * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/
     *         Color
     * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/
     *         Gradient
     * @sample {highstock} stock/chart/plotbackgroundcolor-color/
     *         Color
     * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/
     *         Gradient
     * @sample {highmaps} maps/chart/plotbackgroundcolor-color/
     *         Color
     * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
     *         Gradient
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @apioption chart.plotBackgroundColor
     */
    /**
     * The URL for an image to use as the plot background. To set an image
     * as the background for the entire chart, set a CSS background image
     * to the container element. Note that for the image to be applied to
     * exported charts, its URL needs to be accessible by the export server.
     *
     * @see In styled mode, a plot background image can be set with the
     *      `.highcharts-plot-background` class and a [custom pattern](
     *      https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns).
     *
     * @sample {highcharts} highcharts/chart/plotbackgroundimage/
     *         Skies
     * @sample {highstock} stock/chart/plotbackgroundimage/
     *         Skies
     *
     * @type      {string}
     * @apioption chart.plotBackgroundImage
     */
    /**
     * The color of the inner chart or plot area border.
     *
     * @see In styled mode, a plot border stroke can be set with the
     *      `.highcharts-plot-border` class.
     *
     * @sample {highcharts} highcharts/chart/plotbordercolor/
     *         Blue border
     * @sample {highstock} stock/chart/plotborder/
     *         Blue border
     * @sample {highmaps} maps/chart/plotborder/
     *         Plot border options
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    plotBorderColor: "#cccccc" /* Palette.neutralColor20 */
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Chart_ChartDefaults = (ChartDefaults);

;// ./code/es5/es-modules/Core/Color/Palettes.js
/*
 * Series palettes for Highcharts. Series colors are defined in highcharts.css.
 * **Do not edit this file!** This file is generated using the 'gulp palette' task.
 */
var SeriesPalettes = {
    /**
     * Colors for data series and points
     */
    colors: [
        '#2caffe',
        '#544fc5',
        '#00e272',
        '#fe6a35',
        '#6b8abc',
        '#d568fb',
        '#2ee0ca',
        '#fa4b42',
        '#feb56a',
        '#91e8e1'
    ],
};
/* harmony default export */ var Palettes = (SeriesPalettes);

;// ./code/es5/es-modules/Core/Time.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var pageLang = Core_Globals.pageLang, Time_win = Core_Globals.win;

var Time_defined = Core_Utilities.defined, Time_error = Core_Utilities.error, Time_extend = Core_Utilities.extend, Time_isNumber = Core_Utilities.isNumber, Time_isObject = Core_Utilities.isObject, Time_isString = Core_Utilities.isString, Time_merge = Core_Utilities.merge, Time_objectEach = Core_Utilities.objectEach, Time_pad = Core_Utilities.pad, Time_splat = Core_Utilities.splat, Time_timeUnits = Core_Utilities.timeUnits, Time_ucfirst = Core_Utilities.ucfirst;
/* *
 *
 *  Constants
 *
 * */
// To do: Remove this when we no longer need support for Safari < v14.1
var hasOldSafariBug = Core_Globals.isSafari &&
    Time_win.Intl &&
    !Time_win.Intl.DateTimeFormat.prototype.formatRange;
var isDateTimeFormatOptions = function (obj) {
    return obj.main === void 0;
};
// We use the Spanish locale for internal weekday handling because it uses
// unique letters for narrow weekdays
var spanishWeekdayIndex = function (weekday) {
    return ['D', 'L', 'M', 'X', 'J', 'V', 'S'].indexOf(weekday);
};
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * The Time class. Time settings are applied in general for each page using
 * `Highcharts.setOptions`, or individually for each Chart item through the
 * [time](https://api.highcharts.com/highcharts/time) options set.
 *
 * The Time object is available from {@link Highcharts.Chart#time}, which refers
 * to  `Highcharts.time` unless individual time settings are applied for each
 * chart.
 *
 * When configuring time settings for individual chart instances, be aware that
 * using `Highcharts.dateFormat` or `Highcharts.time.dateFormat` within
 * formatter callbacks relies on the global time object, which applies the
 * global language and time zone settings. To ensure charts with local time
 * settings function correctly, use `chart.time.dateFormat? instead. However,
 * the recommended best practice is to use `setOptions` to define global time
 * settings unless specific configurations are needed for each chart.
 *
 * @example
 * // Apply time settings globally
 * Highcharts.setOptions({
 *     time: {
 *         timezone: 'Europe/London'
 *     }
 * });
 *
 * // Apply time settings by instance
 * const chart = Highcharts.chart('container', {
 *     time: {
 *         timezone: 'America/New_York'
 *     },
 *     series: [{
 *         data: [1, 4, 3, 5]
 *     }]
 * });
 *
 * // Use the Time object of a chart instance
 * console.log(
 *        'Current time in New York',
 *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
 * );
 *
 * // Standalone use
 * const time = new Highcharts.Time({
 *    timezone: 'America/New_York'
 * });
 * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1));
 * console.log(s); // => 2019-12-31 19:00:00
 *
 * @since 6.0.5
 *
 * @class
 * @name Highcharts.Time
 *
 * @param {Highcharts.TimeOptions} [options] Time options as defined in
 * [chart.options.time](/highcharts/time).
 */
var Time = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Time(options) {
        /* *
         *
         *  Properties
         *
         * */
        this.options = {
            timezone: 'UTC'
        };
        this.variableTimezone = false;
        this.Date = Time_win.Date;
        this.update(options);
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Update the Time object with current options. It is called internally on
     * initializing Highcharts, after running `Highcharts.setOptions` and on
     * `Chart.update`.
     *
     * @private
     * @function Highcharts.Time#update
     *
     * @param {Highcharts.TimeOptions} [options]
     *
     */
    Time.prototype.update = function (options) {
        var _this = this;
        if (options === void 0) { options = {}; }
        this.dTLCache = {};
        this.options = options = Time_merge(true, this.options, options);
        var timezoneOffset = options.timezoneOffset,
            useUTC = options.useUTC;
        // Allow using a different Date class
        this.Date = options.Date || Time_win.Date || Date;
        // Assign the time zone. Handle the legacy, deprecated `useUTC` option.
        var timezone = options.timezone;
        if (Time_defined(useUTC)) {
            timezone = useUTC ? 'UTC' : void 0;
        }
        // The Etc/GMT time zones do not support offsets with half-hour
        // resolutions
        if (timezoneOffset && timezoneOffset % 60 === 0) {
            timezone = 'Etc/GMT' + ((timezoneOffset > 0 ? '+' : '')) + timezoneOffset / 60;
        }
        /*
         * The time object has options allowing for variable time zones, meaning
         * the axis ticks or series data needs to consider this.
         */
        this.variableTimezone = timezone !== 'UTC' &&
            (timezone === null || timezone === void 0 ? void 0 : timezone.indexOf('Etc/GMT')) !== 0;
        this.timezone = timezone;
        // Assign default time formats from locale strings
        ['months', 'shortMonths', 'weekdays', 'shortWeekdays'].forEach(function (name) {
            var isMonth = /months/i.test(name), isShort = /short/.test(name), options = { timeZone: 'UTC' };
            options[isMonth ? 'month' : 'weekday'] = isShort ? 'short' : 'long';
            _this[name] = (isMonth ?
                [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] :
                [3, 4, 5, 6, 7, 8, 9]).map(function (position) { return _this.dateFormat(options, (isMonth ? 31 : 1) * 24 * 36e5 * position); });
        });
    };
    /**
     * Get a date in terms of numbers (year, month, day etc) for further
     * processing. Takes the current `timezone` setting into account. Inverse of
     * `makeTime` and the native `Date` constructor and `Date.UTC`.
     *
     * The date is returned in array format with the following indices:
     *
     * 0: year,
     * 1: month (zero based),
     * 2: day,
     * 3: hours,
     * 4: minutes,
     * 5: seconds,
     * 6: milliseconds,
     * 7: weekday (Sunday as 0)
     *
     * @function Highcharts.Time#toParts
     *
     * @param {number|Date} [timestamp]
     *                 The timestamp in milliseconds since January 1st 1970.
     *                 A Date object is also accepted.
     *
     * @return {Array<number>} The date parts in array format.
     */
    Time.prototype.toParts = function (timestamp) {
        var _a = this.dateTimeFormat({
                weekday: 'narrow',
                day: 'numeric',
                month: 'numeric',
                year: 'numeric',
                hour: 'numeric',
                minute: 'numeric',
                second: 'numeric'
            }, timestamp, 'es')
                .split(/(?:, |\/|:)/g), weekday = _a[0], dayOfMonth = _a[1], month = _a[2], year = _a[3], hours = _a[4], minutes = _a[5], seconds = _a[6];
        return [
            year,
            +month - 1,
            dayOfMonth,
            hours,
            minutes,
            seconds,
            // Milliseconds
            Math.floor(Number(timestamp) || 0) % 1000,
            // Weekday index
            spanishWeekdayIndex(weekday)
        ].map(Number);
    };
    /**
     * Shorthand to get a cached `Intl.DateTimeFormat` instance.
     */
    Time.prototype.dateTimeFormat = function (options, timestamp, locale) {
        var _a;
        if (locale === void 0) { locale = this.options.locale || pageLang; }
        var cacheKey = JSON.stringify(options) + locale;
        if (Time_isString(options)) {
            options = this.str2dtf(options);
        }
        var dTL = this.dTLCache[cacheKey];
        if (!dTL) {
            (_a = options.timeZone) !== null && _a !== void 0 ? _a : (options.timeZone = this.timezone);
            try {
                dTL = new Intl.DateTimeFormat(locale, options);
            }
            catch (e) {
                if (/Invalid time zone/i.test(e.message)) {
                    Time_error(34);
                    options.timeZone = 'UTC';
                    dTL = new Intl.DateTimeFormat(locale, options);
                }
                else {
                    Time_error(e.message, false);
                }
            }
        }
        this.dTLCache[cacheKey] = dTL;
        return (dTL === null || dTL === void 0 ? void 0 : dTL.format(timestamp)) || '';
    };
    /**
     * Take a locale-aware string format and return a full DateTimeFormat in
     * object form.
     */
    Time.prototype.str2dtf = function (s, dtf) {
        if (dtf === void 0) { dtf = {}; }
        var mapping = {
                L: { fractionalSecondDigits: 3 },
                S: { second: '2-digit' },
                M: { minute: 'numeric' },
                H: { hour: '2-digit' },
                k: { hour: 'numeric' },
                E: { weekday: 'narrow' },
                a: { weekday: 'short' },
                A: { weekday: 'long' },
                d: { day: '2-digit' },
                e: { day: 'numeric' },
                b: { month: 'short' },
                B: { month: 'long' },
                m: { month: '2-digit' },
                o: { month: 'numeric' },
                y: { year: '2-digit' },
                Y: { year: 'numeric' }
            };
        Object.keys(mapping).forEach(function (key) {
            if (s.indexOf(key) !== -1) {
                Time_extend(dtf, mapping[key]);
            }
        });
        return dtf;
    };
    /**
     * Make a time and returns milliseconds. Similar to `Date.UTC`, but takes
     * the current `timezone` setting into account.
     *
     * @function Highcharts.Time#makeTime
     *
     * @param {number} year
     *        The year
     *
     * @param {number} month
     *        The month. Zero-based, so January is 0.
     *
     * @param {number} [date=1]
     *        The day of the month
     *
     * @param {number} [hours=0]
     *        The hour of the day, 0-23.
     *
     * @param {number} [minutes=0]
     *        The minutes
     *
     * @param {number} [seconds=0]
     *        The seconds
     *
     * @return {number}
     *         The time in milliseconds since January 1st 1970.
     */
    Time.prototype.makeTime = function (year, month, date, hours, minutes, seconds, milliseconds) {
        if (date === void 0) { date = 1; }
        if (hours === void 0) { hours = 0; }
        // eslint-disable-next-line new-cap
        var d = this.Date.UTC(year,
            month,
            date,
            hours,
            minutes || 0,
            seconds || 0,
            milliseconds || 0);
        if (this.timezone !== 'UTC') {
            var offset = this.getTimezoneOffset(d);
            d += offset;
            // Adjustments close to DST transitions
            if (
            // Optimize for speed by limiting the number of calls to
            // `getTimezoneOffset`. According to
            // https://en.wikipedia.org/wiki/Daylight_saving_time_by_country,
            // DST change may only occur in these months.
            [2, 3, 8, 9, 10, 11].indexOf(month) !== -1 &&
                // DST transitions occur only in the night-time
                (hours < 5 || hours > 20)) {
                var newOffset = this.getTimezoneOffset(d);
                if (offset !== newOffset) {
                    d += newOffset - offset;
                    // A special case for transitioning from summer time to winter
                    // time. When the clock is set back, the same time is repeated
                    // twice, i.e. 02:30 am is repeated since the clock is set back
                    // from 3 am to 2 am. We need to make the same time as local
                    // Date does.
                }
                else if (offset - 36e5 === this.getTimezoneOffset(d - 36e5) &&
                    !hasOldSafariBug) {
                    d -= 36e5;
                }
            }
        }
        return d;
    };
    /**
     * Parse a datetime string. Unless the string contains time zone
     * information, apply the current `timezone` from options. If the argument
     * is a number, return it.
     *
     * @function Highcharts.Time#parse
     * @param    {string|number|undefined} s The datetime string to parse
     * @return   {number|undefined}          Parsed JavaScript timestamp
     */
    Time.prototype.parse = function (s) {
        if (!Time_isString(s)) {
            return s !== null && s !== void 0 ? s : void 0;
        }
        s = s
            // Firefox fails on YYYY/MM/DD
            .replace(/\//g, '-')
            // Replace some non-standard notations
            .replace(/(GMT|UTC)/, '');
        // Extend shorthand hour timezone offset like +02
        // .replace(/([+-][0-9]{2})$/, '$1:00');
        // Check if the string has time zone information
        var hasTimezone = s.indexOf('Z') > -1 ||
                /([+-][0-9]{2}):?[0-9]{2}$/.test(s), isYYYYMMDD = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(s);
        if (!hasTimezone && !isYYYYMMDD) {
            s += 'Z';
        }
        var ts = Date.parse(s);
        if (Time_isNumber(ts)) {
            // Unless the string contains time zone information, convert from
            // the local time result of `Date.parse` via UTC into the current
            // timezone of the time object.
            return ts + ((!hasTimezone || isYYYYMMDD) ?
                this.getTimezoneOffset(ts) :
                0);
        }
    };
    /**
     * Get the time zone offset based on the current timezone information as
     * set in the global options.
     *
     * @function Highcharts.Time#getTimezoneOffset
     *
     * @param {number} timestamp
     *        The JavaScript timestamp to inspect.
     *
     * @return {number}
     *         The timezone offset in minutes compared to UTC.
     */
    Time.prototype.getTimezoneOffset = function (timestamp) {
        if (this.timezone !== 'UTC') {
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            var _a = this.dateTimeFormat({ timeZoneName: 'shortOffset' }, timestamp, 'en')
                    .split(/(GMT|:)/)
                    .map(Number), date = _a[0], gmt = _a[1], hours = _a[2], colon = _a[3], _b = _a[4], minutes = _b === void 0 ? 0 : _b, offset = -(hours + minutes / 60) * 60 * 60000;
            // Possible future NaNs stop here
            if (Time_isNumber(offset)) {
                return offset;
            }
        }
        return 0;
    };
    /**
     * Formats a JavaScript date timestamp (milliseconds since January 1 1970)
     * into a human readable date string.
     *
     * The `format` parameter accepts two types of values:
     * - An object containing settings that are passed directly on to
     *   [Intl.DateTimeFormat.prototype.format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format).
     * - A format string containing either individual or locale-aware format
     *   keys. **Individual keys**, for example `%Y-%m-%d`, are listed below.
     *   **Locale-aware keys** are grouped by square brackets, for example
     *   `%[Ymd]`. The order of keys within the square bracket doesn't affect
     *   the output, which is determined by the locale. See example below.
     *   Internally, the locale-aware format keys are just a shorthand for the
     *   full object formats, but are particularly practical in
     *   [templating](https://www.highcharts.com/docs/chart-concepts/templating)
     *   where full object definitions are not an option.
     *
     * The available string format keys are listed below. Additional formats can
     * be given in the {@link Highcharts.dateFormats} hook.
     *
     * Supported format keys:
     * | Key  | Description                     | Notes on locale-aware format |
     * -------|----------------------------------------------|-------|
     * | `%A` | Long weekday, like 'Monday'                  |       |
     * | `%a` | Short weekday, like 'Mon'                    |       |
     * | `%E` | Narrow weekday, single character             |       |
     * | `%d` | Two digit day of the month, 01 to 31         |       |
     * | `%e` | Day of the month, 1 through 31               |       |
     * | `%w` | Day of the week, 0 through 6                 | N/A   |
     * | `%b` | Short month, like 'Jan'                      |       |
     * | `%B` | Long month, like 'January'                   |       |
     * | `%m` | Two digit month number, 01 through 12        |       |
     * | `%o` | Month number, 1 through 12                   |       |
     * | `%y` | Two digits year, like 24 for 2024            |       |
     * | `%Y` | Four digits year, like 2024                  |       |
     * | `%H` | Two digits hours in 24h format, 00 through 23 | Depending on the locale, 12h format may be instered. |
     * | `%k` | Hours in 24h format, 0 through 23            | Depending on the locale, 12h format may be instered. |
     * | `%I` | Two digits hours in 12h format, 00 through 11 | N/A. The locale determines the hour format. |
     * | `%l` | Hours in 12h format, 1 through 12            | N/A. The locale determines the hour format. |
     * | `%M` | Two digits minutes, 00 through 59            |       |
     * | `%p` | Upper case AM or PM                          | N/A. The locale determines whether to add AM and PM. |
     * | `%P` | Lower case AM or PM                          | N/A. The locale determines whether to add AM and PM. |
     * | `%S` | Two digits seconds, 00 through 59            |       |
     * | `%L` | Milliseconds (naming from Ruby)              |       |
     *
     * @example
     * // Object format, US English
     * const time1 = new Highcharts.Time({ locale: 'en-US' });
     * console.log(
     *     time1.dateFormat({
     *         day: 'numeric',
     *         month: 'short',
     *         year: 'numeric',
     *         hour: 'numeric',
     *         minute: 'numeric'
     *     }, Date.UTC(2024, 11, 31))
     * ); // => Dec 31, 2024, 12:00 AM
     *
     * // Object format, British English
     * const time2 = new Highcharts.Time({ locale: 'en-GB' });
     * console.log(
     *     time2.dateFormat({
     *         day: 'numeric',
     *         month: 'short',
     *         year: 'numeric',
     *         hour: 'numeric',
     *         minute: 'numeric'
     *     }, Date.UTC(2024, 11, 31))
     * ); // => 31 Dec 2024, 00:00
     *
     * // Individual key string replacement
     * const time3 = new Highcharts.Time();
     * console.log(
     *     time3.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2024, 11, 31))
     * ); // => 2024-12-31 00:00:00
     *
     * // Locale-aware keys, US English
     * const time4 = new Highcharts.Time({ locale: 'en-US' });
     * console.log(
     *     time4.dateFormat('%[YebHM]', Date.UTC(2024, 11, 31))
     * ); // => Dec 31, 2024, 12:00 AM
     *
     * // Locale-aware keys, British English
     * const time5 = new Highcharts.Time({ locale: 'en-GB' });
     * console.log(
     *     time5.dateFormat('%[YebHM]', Date.UTC(2024, 11, 31))
     * ); // => 31 Dec 2024, 00:00
     *
     * // Mixed locale-aware and individual keys
     * console.log(
     *     time5.dateFormat('%[Yeb], %H:%M', Date.UTC(2024, 11, 31))
     * ); // => 31 Dec 2024, 00:00
     *
     * @function Highcharts.Time#dateFormat
     *
     * @param {string|Highcharts.DateTimeFormatOptions} format
     *        The desired string format where various time representations are
     *        prefixed with %, or an object representing the locale-aware format
     *        options.
     *
     * @param {number} [timestamp]
     *        The JavaScript timestamp.
     *
     * @param {boolean} [upperCaseFirst=false]
     *        Upper case first letter in the return.
     *
     * @return {string}
     *         The formatted date.
     */
    Time.prototype.dateFormat = function (format, timestamp, upperCaseFirst) {
        var _a;
        var lang = (_a = Core_Globals.defaultOptions) === null || _a === void 0 ? void 0 : _a.lang;
        if (!Time_defined(timestamp) || isNaN(timestamp)) {
            return (lang === null || lang === void 0 ? void 0 : lang.invalidDate) || '';
        }
        format = format !== null && format !== void 0 ? format : '%Y-%m-%d %H:%M:%S';
        // First, identify and replace locale-aware formats like %[Ymd]
        if (Time_isString(format)) {
            var localeAwareRegex = /%\[([a-zA-Z]+)\]/g;
            var match = void 0;
            while ((match = localeAwareRegex.exec(format))) {
                format = format.replace(match[0], this.dateTimeFormat(match[1], timestamp));
            }
        }
        // Then, replace static formats like %Y, %m, %d etc.
        if (Time_isString(format) && format.indexOf('%') !== -1) {
            var time_1 = this,
                _b = this.toParts(timestamp),
                fullYear = _b[0],
                month = _b[1],
                dayOfMonth = _b[2],
                hours = _b[3],
                minutes = _b[4],
                seconds = _b[5],
                milliseconds = _b[6],
                weekday = _b[7],
                langWeekdays = (lang === null || lang === void 0 ? void 0 : lang.weekdays) || this.weekdays,
                shortWeekdays = (lang === null || lang === void 0 ? void 0 : lang.shortWeekdays) || this.shortWeekdays,
                months = (lang === null || lang === void 0 ? void 0 : lang.months) || this.months,
                shortMonths = (lang === null || lang === void 0 ? void 0 : lang.shortMonths) || this.shortMonths, 
                // List all format keys. Custom formats can be added from the
                // outside.
                replacements = Time_extend({
                    // Day
                    // Short weekday, like 'Mon'
                    a: shortWeekdays ?
                        shortWeekdays[weekday] :
                        langWeekdays[weekday].substr(0, 3),
                    // Long weekday, like 'Monday'
                    A: langWeekdays[weekday],
                    // Two digit day of the month, 01 to 31
                    d: Time_pad(dayOfMonth),
                    // Day of the month, 1 through 31
                    e: Time_pad(dayOfMonth, 2, ' '),
                    // Day of the week, 0 through 6
                    w: weekday,
                    // Week (none implemented)
                    // 'W': weekNumber(),
                    // Month
                    // Short month, like 'Jan'
                    b: shortMonths[month],
                    // Long month, like 'January'
                    B: months[month],
                    // Two digit month number, 01 through 12
                    m: Time_pad(month + 1),
                    // Month number, 1 through 12 (#8150)
                    o: month + 1,
                    // Year
                    // Two digits year, like 09 for 2009
                    y: fullYear.toString().substr(2, 2),
                    // Four digits year, like 2009
                    Y: fullYear,
                    // Time
                    // Two digits hours in 24h format, 00 through 23
                    H: Time_pad(hours),
                    // Hours in 24h format, 0 through 23
                    k: hours,
                    // Two digits hours in 12h format, 00 through 11
                    I: Time_pad((hours % 12) || 12),
                    // Hours in 12h format, 1 through 12
                    l: (hours % 12) || 12,
                    // Two digits minutes, 00 through 59
                    M: Time_pad(minutes),
                    // Upper case AM or PM
                    p: hours < 12 ? 'AM' : 'PM',
                    // Lower case AM or PM
                    P: hours < 12 ? 'am' : 'pm',
                    // Two digits seconds, 00 through 59
                    S: Time_pad(seconds),
                    // Milliseconds (naming from Ruby)
                    L: Time_pad(milliseconds, 3)
                },
                Core_Globals.dateFormats);
            // Do the replaces
            Time_objectEach(replacements, function (val, key) {
                if (Time_isString(format)) {
                    // Regex would do it in one line, but this is faster
                    while (format.indexOf('%' + key) !== -1) {
                        format = format.replace('%' + key, typeof val === 'function' ?
                            val.call(time_1, timestamp) :
                            val);
                    }
                }
            });
        }
        else if (Time_isObject(format)) {
            var tzHours = (this.getTimezoneOffset(timestamp) || 0) /
                    (60000 * 60), timeZone = this.timezone || ('Etc/GMT' + (tzHours >= 0 ? '+' : '') + tzHours), _c = format.prefix, prefix = _c === void 0 ? '' : _c, _d = format.suffix, suffix = _d === void 0 ? '' : _d;
            format = prefix + this.dateTimeFormat(Time_extend({ timeZone: timeZone }, format), timestamp) + suffix;
        }
        // Optionally sentence-case the string and return
        return upperCaseFirst ? Time_ucfirst(format) : format;
    };
    /**
     * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into
     * an object.
     * @private
     * @param {string|Array<T>|Highcharts.Dictionary<T>} f
     * General format description
     * @return {Highcharts.Dictionary<T>}
     * The object definition
     */
    Time.prototype.resolveDTLFormat = function (f) {
        if (!Time_isObject(f, true)) { // Check for string or array
            f = Time_splat(f);
            return {
                main: f[0],
                from: f[1],
                to: f[2]
            };
        }
        // Type-check DateTimeFormatOptions against DateTimeLabelFormatObject
        if (Time_isObject(f, true) && isDateTimeFormatOptions(f)) {
            return { main: f };
        }
        return f;
    };
    /**
     * Return an array with time positions distributed on round time values
     * right and right after min and max. Used in datetime axes as well as for
     * grouping data on a datetime axis.
     *
     * @function Highcharts.Time#getTimeTicks
     *
     * @param {Highcharts.TimeNormalizedObject} normalizedInterval
     *        The interval in axis values (ms) and the count
     *
     * @param {number} [min]
     *        The minimum in axis values
     *
     * @param {number} [max]
     *        The maximum in axis values
     *
     * @param {number} [startOfWeek=1]
     *
     * @return {Highcharts.AxisTickPositionsArray}
     * Time positions
     */
    Time.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek) {
        var time = this,
            tickPositions = [],
            higherRanks = {},
            _a = normalizedInterval.count,
            count = _a === void 0 ? 1 : _a,
            unitRange = normalizedInterval.unitRange;
        var _b = time.toParts(min),
            year = _b[0],
            month = _b[1],
            dayOfMonth = _b[2],
            hours = _b[3],
            minutes = _b[4],
            seconds = _b[5],
            milliseconds = (min || 0) % 1000,
            variableDayLength;
        startOfWeek !== null && startOfWeek !== void 0 ? startOfWeek : (startOfWeek = 1);
        if (Time_defined(min)) { // #1300
            milliseconds = unitRange >= Time_timeUnits.second ?
                0 : // #3935
                count * Math.floor(milliseconds / count);
            if (unitRange >= Time_timeUnits.second) { // Second
                seconds = unitRange >= Time_timeUnits.minute ?
                    0 : // #3935
                    count * Math.floor(seconds / count);
            }
            if (unitRange >= Time_timeUnits.minute) { // Minute
                minutes = unitRange >= Time_timeUnits.hour ?
                    0 :
                    count * Math.floor(minutes / count);
            }
            if (unitRange >= Time_timeUnits.hour) { // Hour
                hours = unitRange >= Time_timeUnits.day ?
                    0 :
                    count * Math.floor(hours / count);
            }
            if (unitRange >= Time_timeUnits.day) { // Day
                dayOfMonth = unitRange >= Time_timeUnits.month ?
                    1 :
                    Math.max(1, count * Math.floor(dayOfMonth / count));
            }
            if (unitRange >= Time_timeUnits.month) { // Month
                month = unitRange >= Time_timeUnits.year ? 0 :
                    count * Math.floor(month / count);
            }
            if (unitRange >= Time_timeUnits.year) { // Year
                year -= year % count;
            }
            // Week is a special case that runs outside the hierarchy
            if (unitRange === Time_timeUnits.week) {
                if (count) {
                    min = time.makeTime(year, month, dayOfMonth, hours, minutes, seconds, milliseconds);
                }
                // Get start of current week, independent of count
                var weekday = this.dateTimeFormat({
                        timeZone: this.timezone,
                        weekday: 'narrow'
                    },
                    min, 'es'),
                    weekdayNo = spanishWeekdayIndex(weekday);
                dayOfMonth += -weekdayNo + startOfWeek +
                    // We don't want to skip days that are before
                    // startOfWeek (#7051)
                    (weekdayNo < startOfWeek ? -7 : 0);
            }
            min = time.makeTime(year, month, dayOfMonth, hours, minutes, seconds, milliseconds);
            // Handle local timezone offset
            if (time.variableTimezone && Time_defined(max)) {
                // Detect whether we need to take the DST crossover into
                // consideration. If we're crossing over DST, the day length may
                // be 23h or 25h and we need to compute the exact clock time for
                // each tick instead of just adding hours. This comes at a cost,
                // so first we find out if it is needed (#4951).
                variableDayLength = (
                // Long range, assume we're crossing over.
                max - min > 4 * Time_timeUnits.month ||
                    // Short range, check if min and max are in different time
                    // zones.
                    time.getTimezoneOffset(min) !==
                        time.getTimezoneOffset(max));
            }
            // Iterate and add tick positions at appropriate values
            var t = min,
                i = 1;
            while (t < max) {
                tickPositions.push(t);
                // Increase the years
                if (unitRange === Time_timeUnits.year) {
                    t = time.makeTime(year + i * count, 0);
                    // Increase the months
                }
                else if (unitRange === Time_timeUnits.month) {
                    t = time.makeTime(year, month + i * count);
                    // If we're using local time, the interval is not fixed as it
                    // jumps one hour at the DST crossover
                }
                else if (variableDayLength && (unitRange === Time_timeUnits.day ||
                    unitRange === Time_timeUnits.week)) {
                    t = time.makeTime(year, month, dayOfMonth +
                        i * count * (unitRange === Time_timeUnits.day ? 1 : 7));
                }
                else if (variableDayLength &&
                    unitRange === Time_timeUnits.hour &&
                    count > 1) {
                    // Make sure higher ranks are preserved across DST (#6797,
                    // #7621)
                    t = time.makeTime(year, month, dayOfMonth, hours + i * count);
                    // Else, the interval is fixed and we use simple addition
                }
                else {
                    t += unitRange * count;
                }
                i++;
            }
            // Push the last time
            tickPositions.push(t);
            // Handle higher ranks. Mark new days if the time is on midnight
            // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold
            // to prevent looping over dense data grouping (#6156).
            if (unitRange <= Time_timeUnits.hour && tickPositions.length < 10000) {
                tickPositions.forEach(function (t) {
                    if (
                    // Speed optimization, no need to run dateFormat unless
                    // we're on a full or half hour
                    t % 1800000 === 0 &&
                        // Check for local or global midnight
                        time.dateFormat('%H%M%S%L', t) === '000000000') {
                        higherRanks[t] = 'day';
                    }
                });
            }
        }
        // Record information on the chosen unit - for dynamic label formatter
        tickPositions.info = Time_extend(normalizedInterval, {
            higherRanks: higherRanks,
            totalRange: unitRange * count
        });
        return tickPositions;
    };
    /**
     * Get the optimal date format for a point, based on a range.
     *
     * @private
     * @function Highcharts.Time#getDateFormat
     *
     * @param {number} range
     *        The time range
     *
     * @param {number} timestamp
     *        The timestamp of the date
     *
     * @param {number} startOfWeek
     *        An integer representing the first day of the week, where 0 is
     *        Sunday.
     *
     * @param {Highcharts.Dictionary<string>} dateTimeLabelFormats
     *        A map of time units to formats.
     *
     * @return {string}
     *         The optimal date format for a point.
     */
    Time.prototype.getDateFormat = function (range, timestamp, startOfWeek, dateTimeLabelFormats) {
        var dateStr = this.dateFormat('%m-%d %H:%M:%S.%L', timestamp), blank = '01-01 00:00:00.000', strpos = {
                millisecond: 15,
                second: 12,
                minute: 9,
                hour: 6,
                day: 3
            };
        var n = 'millisecond', 
            // For sub-millisecond data, #4223
            lastN = n;
        for (n in Time_timeUnits) { // eslint-disable-line guard-for-in
            // If the range is exactly one week and we're looking at a
            // Sunday/Monday, go for the week format
            if (range === Time_timeUnits.week &&
                +this.dateFormat('%w', timestamp) === startOfWeek &&
                dateStr.substr(6) === blank.substr(6)) {
                n = 'week';
                break;
            }
            // The first format that is too great for the range
            if (Time_timeUnits[n] > range) {
                n = lastN;
                break;
            }
            // If the point is placed every day at 23:59, we need to show
            // the minutes as well. #2637.
            if (strpos[n] &&
                dateStr.substr(strpos[n]) !== blank.substr(strpos[n])) {
                break;
            }
            // Weeks are outside the hierarchy, only apply them on
            // Mondays/Sundays like in the first condition
            if (n !== 'week') {
                lastN = n;
            }
        }
        return this.resolveDTLFormat(dateTimeLabelFormats[n]).main;
    };
    return Time;
}());
/* *
 *
 * Default export
 *
 * */
/* harmony default export */ var Core_Time = (Time);
/* *
 *
 * API Declarations
 *
 * */
/**
 * Normalized interval.
 *
 * @interface Highcharts.TimeNormalizedObject
 */ /**
* The count.
*
* @name Highcharts.TimeNormalizedObject#count
* @type {number|undefined}
*/ /**
* The interval in axis values (ms).
*
* @name Highcharts.TimeNormalizedObject#unitRange
* @type {number}
*/
/**
 * Function of an additional date format specifier.
 *
 * @callback Highcharts.TimeFormatCallbackFunction
 *
 * @param {number} timestamp
 *        The time to format.
 *
 * @return {string}
 *         The formatted portion of the date.
 */
/**
 * Time ticks.
 *
 * @interface Highcharts.AxisTickPositionsArray
 * @extends global.Array<number>
 */ /**
* @name Highcharts.AxisTickPositionsArray#info
* @type {Highcharts.TimeTicksInfoObject|undefined}
*/
/**
 * A callback to return the time zone offset for a given datetime. It
 * takes the timestamp in terms of milliseconds since January 1 1970,
 * and returns the timezone offset in minutes. This provides a hook
 * for drawing time based charts in specific time zones using their
 * local DST crossover dates, with the help of external libraries.
 *
 * @callback Highcharts.TimezoneOffsetCallbackFunction
 *
 * @param {number} timestamp
 * Timestamp in terms of milliseconds since January 1 1970.
 *
 * @return {number}
 * Timezone offset in minutes.
 */
/**
 * Options for formatting dates and times using the [Intl.DateTimeFormat](
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
 * ) API, and extended with some custom options for Highcharts.
 *
 * @interface Highcharts.DateTimeFormatOptions
 */ /**
* The locale matching algorithm to use.
*
* @name Highcharts.DateTimeFormatOptions#localeMatcher
* @type {string|undefined}
*/ /**
* The time zone to use. The default is the browser's default time zone.
*
* @name Highcharts.DateTimeFormatOptions#timeZone
* @type {string|undefined}
*/ /**
* Whether to use 12-hour time (as opposed to 24-hour time).
*
* @name Highcharts.DateTimeFormatOptions#hour12
* @type {'auto'|'always'|'never'|undefined}
*/ /**
* The format matching algorithm to use.
*
* @name Highcharts.DateTimeFormatOptions#formatMatcher
* @type {string|undefined}
*/ /**
* The representation of the weekday.
*
* @name Highcharts.DateTimeFormatOptions#weekday
* @type {'narrow'|'short'|'long'|undefined}
*/ /**
* The representation of the era.
*
* @name Highcharts.DateTimeFormatOptions#era
* @type {'narrow'|'short'|'long'|undefined}
*/ /**
* The representation of the year.
*
* @name Highcharts.DateTimeFormatOptions#year
* @type {'numeric'|'2-digit'|undefined}
*/ /**
* The representation of the month.
* "narrow", "short", "long".
*
* @name Highcharts.DateTimeFormatOptions#month
* @type {'numeric'|'2-digit'|'narrow'|'short'|'long'|undefined}
*/ /**
* The representation of the day.
*
* @name Highcharts.DateTimeFormatOptions#day
* @type {'numeric'|'2-digit'|undefined}
*/ /**
* The representation of the hour.
*
* @name Highcharts.DateTimeFormatOptions#hour
* @type {'numeric'|'2-digit'|undefined}
*/ /**
* The representation of the minute.
*
* @name Highcharts.DateTimeFormatOptions#minute
* @type {'numeric'|'2-digit'|undefined}
*/ /**
* The representation of the second.
*
* @name Highcharts.DateTimeFormatOptions#second
* @type {'numeric'|'2-digit'|undefined}
*/ /**
* The number of fractional digits to use. 3 means milliseconds.
*
* @name Highcharts.DateTimeFormatOptions#fractionalSecondDigits
* @type {number|undefined}
*/ /**
* The representation of the time zone name.
*
* @name Highcharts.DateTimeFormatOptions#timeZoneName
* @type {'short'|'long'|undefined}
*/ /**
* A prefix for the time string. Custom Highcharts option.
*
* @name Highcharts.DateTimeFormatOptions#prefix
* @type {'string'|undefined}
*/ /**
* A suffix for the time string. Custom Highcharts option.
*
* @name Highcharts.DateTimeFormatOptions#suffix
* @type {'string'|undefined}
*/
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Defaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var isTouchDevice = Core_Globals.isTouchDevice;



var Defaults_fireEvent = Core_Utilities.fireEvent, Defaults_merge = Core_Utilities.merge;
/* *
 *
 *  API Options
 *
 * */
/**
 * Global default settings.
 *
 * @name Highcharts.defaultOptions
 * @type {Highcharts.Options}
 */ /**
* @optionparent
* @private
*/
var defaultOptions = {
    /**
     * An array containing the default colors for the chart's series. When
     * all colors are used, new colors are pulled from the start again.
     *
     * Default colors can also be set on a series or series.type basis,
     * see [column.colors](#plotOptions.column.colors),
     * [pie.colors](#plotOptions.pie.colors).
     *
     * In styled mode, the colors option doesn't exist. Instead, colors
     * are defined in CSS and applied either through series or point class
     * names, or through the [chart.colorCount](#chart.colorCount) option.
     *
     * @sample {highcharts} highcharts/chart/colors/
     *         Assign a global color theme
     * @sample highcharts/members/theme-v10/
     *         Latest release styled like version 10
     *
     * @type    {Array<(Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject)>}
     * @default [
     *     "#2caffe",
     *     "#544fc5",
     *     "#00e272",
     *     "#fe6a35",
     *     "#6b8abc",
     *     "#d568fb",
     *     "#2ee0ca",
     *     "#fa4b42",
     *     "#feb56a",
     *     "#91e8e1"
     * ]
     */
    colors: Palettes.colors,
    /**
     * Styled mode only. Configuration object for adding SVG definitions for
     * reusable elements. See [gradients, shadows and
     * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns)
     * for more information and code examples.
     *
     * @type      {*}
     * @since     5.0.0
     * @apioption defs
     */
    /**
     * @ignore-option
     */
    symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
    /**
     * An object containing language-related strings and settings. A typical
     * setup uses `Highcharts.setOptions` to make the options apply to all
     * charts in the same page.
     *
     * ```js
     * Highcharts.setOptions({
     *     lang: {
     *         locale: 'fr'
     *     }
     * });
     * ```
     */
    lang: {
        /**
         * The browser locale to use for date and number formatting. The actual
         * locale used for each chart is determined in three steps:
         * 1. If this `lang.locale` option is specified, it is used.
         * 2. Else, look for the closest ancestor HTML element with a `lang`
         *    attribute, typically the `<html>` element.
         * 3. If no 'lang' attribute is found, use the default browser locale.
         *
         * Use `en-GB`, British English, for approximate consistency with
         * Highcharts v < 12.
         *
         * @sample highcharts/lang/locale/
         *         Set the locale using the `lang.locale` option
         * @sample highcharts/lang/locale-attribute/
         *         Pick up the locale from the HTML `lang` attribute
         * @sample highcharts/members/highcharts-numberformat
         *         Arabic locale with digits and dates         *
         *
         * @since 12.0.0
         * @type {string|Array<string>}
         */
        locale: void 0,
        /**
         * The loading text that appears when the chart is set into the loading
         * state following a call to `chart.showLoading`.
         */
        loading: 'Loading...',
        /**
         * An array containing the months names. Corresponds to the `%B` format
         * in `Highcharts.dateFormat()`. Defaults to 'undefined',
         * meaning the default month names are used according to the
         * `lang.locale` setting.
         *
         * @type    {Array<string>}
         */
        months: void 0,
        /**
         * An array containing the months names in abbreviated form. Corresponds
         * to the `%b` format in `Highcharts.dateFormat()`. Defaults to
         * 'undefined', meaning the default short month names are used according
         * to the `lang.locale` setting.
         *
         * @type    {Array<string>}
         */
        shortMonths: void 0,
        /**
         * An array containing the weekday names. Defaults to 'undefined',
         * meaning the default weekday names are used according to the
         * `lang.locale` setting.
         *
         * @type    {Array<string>}
         */
        weekdays: void 0,
        /**
         * Short week days, starting Sunday. Defaults to 'undefined', meaning
         * the default short weekday names are used according to the
         * `lang.locale` setting.
         *
         * @sample highcharts/lang/shortweekdays/
         *         Finnish two-letter abbreviations
         *
         * @type      {Array<string>}
         * @since     4.2.4
         * @apioption lang.shortWeekdays
         */
        /**
         * What to show in a date field for invalid dates. Defaults to an empty
         * string.
         *
         * @type      {string}
         * @since     4.1.8
         * @product   highcharts highstock
         * @apioption lang.invalidDate
         */
        /**
         * The title appearing on hovering the zoom in button. The text itself
         * defaults to "+" and can be changed in the button options.
         *
         * @type      {string}
         * @default   Zoom in
         * @product   highmaps
         * @apioption lang.zoomIn
         */
        /**
         * The title appearing on hovering the zoom out button. The text itself
         * defaults to "-" and can be changed in the button options.
         *
         * @type      {string}
         * @default   Zoom out
         * @product   highmaps
         * @apioption lang.zoomOut
         */
        /**
         * The default decimal point used in the `Highcharts.numberFormat`
         * method unless otherwise specified in the function arguments. Defaults
         * to the locale decimal point as determined by `lang.locale`.
         *
         * @type      {string}
         * @default   undefined
         * @since     1.2.2
         * @apioption lang.decimalPoint
         */
        /**
         * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used
         * to shorten high numbers in axis labels. Replacing any of the
         * positions with `null` causes the full number to be written. Setting
         * `numericSymbols` to `undefined` disables shortening altogether.
         *
         * @sample {highcharts} highcharts/lang/numericsymbols/
         *         Replacing the symbols with text
         * @sample {highstock} highcharts/lang/numericsymbols/
         *         Replacing the symbols with text
         *
         * @type    {Array<string>}
         * @default ["k", "M", "G", "T", "P", "E"]
         * @since   2.3.0
         */
        numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'],
        /**
         * The magnitude of [numericSymbols](#lang.numericSymbol) replacements.
         * Use 10000 for Japanese, Korean and various Chinese locales, which
         * use symbols for 10^4, 10^8 and 10^12.
         *
         * @sample highcharts/lang/numericsymbolmagnitude/
         *         10000 magnitude for Japanese
         *
         * @type      {number}
         * @default   1000
         * @since     5.0.3
         * @apioption lang.numericSymbolMagnitude
         */
        /**
         * The default thousands separator used in the `Highcharts.numberFormat`
         * method unless otherwise specified in the function arguments. Defaults
         * to the locale thousands separator as determined by `lang.locale`.
         *
         * @type      {string}
         * @default   undefined
         * @since     1.2.2
         * @apioption lang.thousandsSep
         */
        /**
         * The text for the label appearing when a chart is zoomed.
         *
         * @since 1.2.4
         */
        resetZoom: 'Reset zoom',
        /**
         * The tooltip title for the label appearing when a chart is zoomed.
         *
         * @since 1.2.4
         */
        resetZoomTitle: 'Reset zoom level 1:1'
    },
    /**
     * Global options that don't apply to each chart. These options, like
     * the `lang` options, must be set using the `Highcharts.setOptions`
     * method.
     *
     * ```js
     * Highcharts.setOptions({
     *     global: {
     *         buttonTheme: {
     *             fill: '#d0d0d0'
     *         }
     *     }
     * });
     * ```
     */
    global: {
        /**
         * General theme for buttons. This applies to the zoom button, exporting
         * context menu, map navigation, range selector buttons and custom
         * buttons generated using the `SVGRenderer.button` function. However,
         * each of these may be overridden with more specific options.
         *
         * @sample highcharts/global/buttontheme
         *         General button theme
         * @since 11.4.2
         */
        buttonTheme: {
            /**
             * The fill color for buttons
             */
            fill: "#f7f7f7" /* Palette.neutralColor3 */,
            /**
             * The padding of buttons
             */
            padding: 8,
            /**
             * The border radius for buttons
             */
            r: 2,
            /**
             * The stroke color for buttons
             */
            stroke: "#cccccc" /* Palette.neutralColor20 */,
            /**
             * The stroke width for buttons
             */
            'stroke-width': 1,
            /**
             * CSS styling for the buttons' text
             */
            style: {
                color: "#333333" /* Palette.neutralColor80 */,
                cursor: 'pointer',
                fontSize: '0.8em',
                fontWeight: 'normal'
            },
            /**
             * State overrides for the buttons
             */
            states: {
                /**
                 * Hover state overrides for the buttons are applied in addition
                 * to the normal state options
                 */
                hover: {
                    fill: "#e6e6e6" /* Palette.neutralColor10 */
                },
                /**
                 * Select state overrides for the buttons are applied in
                 * addition to the normal state options
                 */
                select: {
                    fill: "#e6e9ff" /* Palette.highlightColor10 */,
                    style: {
                        color: "#000000" /* Palette.neutralColor100 */,
                        fontWeight: 'bold'
                    }
                },
                /**
                 * Disabled state overrides for the buttons are applied in
                 * addition to the normal state options
                 */
                disabled: {
                    /**
                     * Disabled state CSS style overrides for the buttons' text
                     */
                    style: {
                        color: "#cccccc" /* Palette.neutralColor20 */
                    }
                }
            }
        }
    },
    /**
     * Time options that can apply globally or to individual charts. These
     * settings affect how `datetime` axes are laid out, how tooltips are
     * formatted, how series
     * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how
     * the Highcharts Stock range selector handles time.
     *
     * The common use case is that all charts in the same Highcharts object
     * share the same time settings, in which case the global settings are set
     * using `setOptions`.
     *
     * ```js
     * // Apply time settings globally
     * Highcharts.setOptions({
     *     time: {
     *         timezone: 'Europe/London'
     *     }
     * });
     * // Apply time settings by instance
     * const chart = Highcharts.chart('container', {
     *     time: {
     *         timezone: 'America/New_York'
     *     },
     *     series: [{
     *         data: [1, 4, 3, 5]
     *     }]
     * });
     *
     * // Use the Time object
     * console.log(
     *        'Current time in New York',
     *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
     * );
     * ```
     *
     * Since v6.0.5, the time options were moved from the `global` object to the
     * `time` object, and time options can be set on each individual chart.
     *
     * @sample {highcharts|highstock}
     *         highcharts/time/timezone/
     *         Set the timezone globally
     * @sample {highcharts}
     *         highcharts/time/individual/
     *         Set the timezone per chart instance
     * @sample {highstock}
     *         stock/time/individual/
     *         Set the timezone per chart instance
     *
     * @since     6.0.5
     * @optionparent time
     */
    time: {
        /**
         * A custom `Date` class for advanced date handling. For example,
         * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to
         * handle Jalali dates.
         *
         * @type      {*}
         * @since     4.0.4
         * @product   highcharts highstock gantt
         */
        Date: void 0,
        /**
         * A named time zone. Supported time zone names rely on the browser
         * implementations, as described in the [mdn
         * docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#timezone).
         * If the given time zone is not recognized by the browser, Highcharts
         * provides a warning and falls back to returning a 0 offset,
         * corresponding to the UTC time zone.
         *
         * The time zone affects axis scaling, tickmark placement and
         * time display in `Highcharts.dateFormat`.
         *
         * Setting `timezone` to `undefined` falls back to the default browser
         * timezone setting.
         *
         * Until v11.2.0, this option depended on moment.js.
         *
         * @sample {highcharts|highstock} highcharts/time/timezone/ Europe/Oslo
         *
         * @type      {string}
         * @since     5.0.7
         * @product   highcharts highstock gantt
         */
        timezone: 'UTC',
        /**
         * The timezone offset in minutes. Positive values are west, negative
         * values are east of UTC, as in the ECMAScript
         * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)
         * method. Use this to display UTC based data in a predefined time zone.
         *
         * This option is deprecated as of v11.4.1 and will be removed in a
         * future release. Use the [time.timezone](#time.timezone) option
         * instead.
         *
         * @see [time.getTimezoneOffset](#time.getTimezoneOffset)
         *
         * @sample {highcharts|highstock} highcharts/time/timezoneoffset/
         *         Timezone offset
         *
         * @since     3.0.8
         * @deprecated 11.4.2
         * @product   highcharts highstock gantt
         */
        timezoneOffset: 0,
        /**
         * Whether to use UTC time for axis scaling, tickmark placement and
         * time display in `Highcharts.dateFormat`. Advantages of using UTC
         * is that the time displays equally regardless of the user agent's
         * time zone settings. Local time can be used when the data is loaded
         * in real time or when correct Daylight Saving Time transitions are
         * required.
         *
         * Setting `useUTC` to true is equivalent to setting `time.timezone` to
         * `"UTC"`. Setting `useUTC` to false is equivalent to setting
         * `time.timezone` to `undefined`.
         *
         * @see [time.timezone](#timezone)
         *
         * @sample {highcharts} highcharts/time/useutc-true/
         *         True by default
         * @sample {highcharts} highcharts/time/useutc-false/
         *         False
         *
         * @deprecated
         */
        useUTC: void 0
    },
    chart: Chart_ChartDefaults,
    /**
     * The chart's main title.
     *
     * @sample {highmaps} maps/title/title/
     *         Title options demonstrated
     * @sample {highcharts} highcharts/title/align-auto/
     *         Default title alignment
     */
    title: {
        /**
         * When the title is floating, the plot area will not move to make space
         * for it.
         *
         * @sample {highcharts} highcharts/chart/zoomtype-none/
         *         False by default
         * @sample {highcharts} highcharts/title/floating/
         *         True - title on top of the plot area
         * @sample {highstock} stock/chart/title-floating/
         *         True - title on top of the plot area
         *
         * @type      {boolean}
         * @default   false
         * @since     2.1
         * @apioption title.floating
         */
        /**
         * Whether to
         * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the text.
         *
         * @type      {boolean}
         * @default   false
         * @apioption title.useHTML
         */
        /**
         * The vertical alignment of the title. Can be one of `"top"`,
         * `"middle"` and `"bottom"`. When a value is given, the title behaves
         * as if [floating](#title.floating) were `true`.
         *
         * @sample {highcharts} highcharts/title/verticalalign/
         *         Chart title in bottom right corner
         * @sample {highstock} stock/chart/title-verticalalign/
         *         Chart title in bottom right corner
         *
         * @type      {Highcharts.VerticalAlignValue}
         * @since     2.1
         * @apioption title.verticalAlign
         */
        /**
         * The x position of the title relative to the alignment within
         * `chart.spacingLeft` and `chart.spacingRight`.
         *
         * @sample {highcharts} highcharts/title/align/
         *         Aligned to the plot area (x = 70px = margin left - spacing
         *         left)
         * @sample {highstock} stock/chart/title-align/
         *         Aligned to the plot area (x = 50px = margin left - spacing
         *         left)
         *
         * @type      {number}
         * @default   0
         * @since     2.0
         * @apioption title.x
         */
        /**
         * The y position of the title relative to the alignment within
         * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom](
         * #chart.spacingBottom). By default it depends on the font size.
         *
         * @sample {highcharts} highcharts/title/y/
         *         Title inside the plot area
         * @sample {highstock} stock/chart/title-verticalalign/
         *         Chart title in bottom right corner
         *
         * @type      {number}
         * @since     2.0
         * @apioption title.y
         */
        /**
         * CSS styles for the title. Use this for font styling, but use `align`,
         * `x` and `y` for text alignment.
         *
         * Note that the default [title.minScale](#title.minScale) option also
         * affects the rendered font size. In order to keep the font size fixed
         * regardless of title length, set `minScale` to 1.
         *
         * In styled mode, the title style is given in the `.highcharts-title`
         * class.
         *
         * @sample {highcharts} highcharts/title/style/
         *         Custom color and weight
         * @sample {highstock} stock/chart/title-style/
         *         Custom color and weight
         * @sample highcharts/css/titles/
         *         Styled mode
         *
         * @type      {Highcharts.CSSObject}
         * @default   {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" }
         * @default   {highstock} { "color": "#333333", "fontSize": "16px" }
         */
        style: {
            color: "#333333" /* Palette.neutralColor80 */,
            fontWeight: 'bold'
        },
        /**
         * The title of the chart. To disable the title, set the `text` to
         * `undefined`.
         *
         * @sample {highcharts} highcharts/title/text/
         *         Custom title
         * @sample {highstock} stock/chart/title-text/
         *         Custom title
         *
         * @default {highcharts|highmaps} Chart title
         * @default {highstock} undefined
         */
        text: 'Chart title',
        /**
         * The horizontal alignment of the title. Can be one of "left", "center"
         * and "right".
         *
         * Since v12 it defaults to `undefined`, meaning the alignment is
         * computed for best fit. If the text fits in one line, it aligned to
         * the center, but if it is wrapped into multiple lines, it is aligned
         * to the left.
         *
         * @sample {highcharts} highcharts/title/align-auto/
         *         Default alignment, dynamic
         * @sample {highcharts} highcharts/title/align/
         *         Aligned to the plot area (x = 70px = margin left - spacing
         *         left)
         * @sample {highstock} stock/chart/title-align/
         *         Aligned to the plot area (x = 50px = margin left - spacing
         *         left)
         *
         * @type      {Highcharts.AlignValue}
         * @default   undefined
         * @since     2.0
         * @apioption title.align
         */
        /**
         * The margin between the title and the plot area, or if a subtitle
         * is present, the margin between the subtitle and the plot area.
         *
         * @sample {highcharts} highcharts/title/margin-50/
         *         A chart title margin of 50
         * @sample {highcharts} highcharts/title/margin-subtitle/
         *         The same margin applied with a subtitle
         * @sample {highstock} stock/chart/title-margin/
         *         A chart title margin of 50
         *
         * @since 2.1
         */
        margin: 15,
        /**
         * When the title is too wide to fit in the chart, the default behavior
         * is to scale it down to fit, or apply word wrap if it is scaled down
         * to `minScale` and still doesn't fit.
         *
         * The default value reflects the scale, when using default font sizes,
         * when the title font size matches that of the subtitle. The title
         * still stands out as it is bold by default.
         *
         * Set `minScale` to 1 to avoid downscaling.
         *
         * @sample {highcharts} highcharts/title/align-auto/
         *         Downscaling demonstrated
         *
         * @since 12.0.0
         */
        minScale: 0.67
    },
    /**
     * The chart's subtitle. This can be used both to display a subtitle below
     * the main title, and to display random text anywhere in the chart. The
     * subtitle can be updated after chart initialization through the
     * `Chart.setTitle` method.
     *
     * @sample {highcharts} highcharts/title/align-auto/
     *         Default title alignment
     * @sample {highmaps} maps/title/subtitle/
     *         Subtitle options demonstrated
     */
    subtitle: {
        /**
         * When the subtitle is floating, the plot area will not move to make
         * space for it.
         *
         * @sample {highcharts} highcharts/subtitle/floating/
         *         Floating title and subtitle
         * @sample {highstock} stock/chart/subtitle-footnote
         *         Footnote floating at bottom right of plot area
         *
         * @type      {boolean}
         * @default   false
         * @since     2.1
         * @apioption subtitle.floating
         */
        /**
         * CSS styles for the title.
         *
         * In styled mode, the subtitle style is given in the
         * `.highcharts-subtitle` class.
         *
         * @sample {highcharts} highcharts/subtitle/style/
         *         Custom color and weight
         * @sample {highcharts} highcharts/css/titles/
         *         Styled mode
         * @sample {highstock} stock/chart/subtitle-style
         *         Custom color and weight
         * @sample {highstock} highcharts/css/titles/
         *         Styled mode
         * @sample {highmaps} highcharts/css/titles/
         *         Styled mode
         *
         * @type      {Highcharts.CSSObject}
         * @default   {"color": "#666666"}
         * @apioption subtitle.style
         */
        /**
         * Whether to
         * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the text.
         *
         * @type      {boolean}
         * @default   false
         * @apioption subtitle.useHTML
         */
        /**
         * The vertical alignment of the title. Can be one of `"top"`,
         * `"middle"` and `"bottom"`. When middle, the subtitle behaves as
         * floating.
         *
         * @sample {highcharts} highcharts/subtitle/verticalalign/
         *         Footnote at the bottom right of plot area
         * @sample {highstock} stock/chart/subtitle-footnote
         *         Footnote at the bottom right of plot area
         *
         * @type      {Highcharts.VerticalAlignValue}
         * @since     2.1
         * @apioption subtitle.verticalAlign
         */
        /**
         * The x position of the subtitle relative to the alignment within
         * `chart.spacingLeft` and `chart.spacingRight`.
         *
         * @sample {highcharts} highcharts/subtitle/align/
         *         Footnote at right of plot area
         * @sample {highstock} stock/chart/subtitle-footnote
         *         Footnote at the bottom right of plot area
         *
         * @type      {number}
         * @default   0
         * @since     2.0
         * @apioption subtitle.x
         */
        /**
         * The y position of the subtitle relative to the alignment within
         * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle
         * is laid out below the title unless the title is floating.
         *
         * @sample {highcharts} highcharts/subtitle/verticalalign/
         *         Footnote at the bottom right of plot area
         * @sample {highstock} stock/chart/subtitle-footnote
         *         Footnote at the bottom right of plot area
         *
         * @type      {number}
         * @since     2.0
         * @apioption subtitle.y
         */
        /**
         * CSS styles for the title.
         *
         * In styled mode, the subtitle style is given in the
         * `.highcharts-subtitle` class.
         *
         * @sample {highcharts} highcharts/subtitle/style/
         *         Custom color and weight
         * @sample {highcharts} highcharts/css/titles/
         *         Styled mode
         * @sample {highstock} stock/chart/subtitle-style
         *         Custom color and weight
         * @sample {highstock} highcharts/css/titles/
         *         Styled mode
         * @sample {highmaps} highcharts/css/titles/
         *         Styled mode
         *
         * @type      {Highcharts.CSSObject}
         * @default   {"color": "#666666"}
         */
        style: {
            color: "#666666" /* Palette.neutralColor60 */,
            /**
             * @type {number|string}
             */
            fontSize: '0.8em'
        },
        /**
         * The subtitle of the chart.
         *
         * @sample {highcharts|highstock} highcharts/subtitle/text/
         *         Custom subtitle
         * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/
         *         Formatted and linked text.
         */
        text: ''
        /**
         * The horizontal alignment of the subtitle. Can be one of "left",
         * "center" and "right". Since v12, it defaults to `undefined`, meaning
         * the actual alignment is inherited from the alignment of the main
         * title.
         *
         * @sample {highcharts} highcharts/title/align-auto/
         *         Default title and subtitle alignment, dynamic
         * @sample {highcharts} highcharts/subtitle/align/
         *         Footnote at right of plot area
         * @sample {highstock} stock/chart/subtitle-footnote
         *         Footnote at bottom right of plot area
         *
         * @type  {Highcharts.AlignValue}
         * @default undefined
         * @since 2.0
         * @apioption subtitle.align
         */
    },
    /**
     * The chart's caption, which will render below the chart and will be part
     * of exported charts. The caption can be updated after chart initialization
     * through the `Chart.update` or `Chart.caption.update` methods.
     *
     * @sample highcharts/caption/text/
     *         A chart with a caption
     * @since  7.2.0
     */
    caption: {
        /**
         * When the caption is floating, the plot area will not move to make
         * space for it.
         *
         * @type      {boolean}
         * @default   false
         * @apioption caption.floating
         */
        /**
         * The margin between the caption and the plot area.
         */
        margin: 15,
        /**
         * Whether to
         * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the text.
         *
         * @type      {boolean}
         * @default   false
         * @apioption caption.useHTML
         */
        /**
         * The x position of the caption relative to the alignment within
         * `chart.spacingLeft` and `chart.spacingRight`.
         *
         * @type      {number}
         * @default   0
         * @apioption caption.x
         */
        /**
         * The y position of the caption relative to the alignment within
         * `chart.spacingTop` and `chart.spacingBottom`.
         *
         * @type      {number}
         * @apioption caption.y
         */
        /**
         * CSS styles for the caption.
         *
         * In styled mode, the caption style is given in the
         * `.highcharts-caption` class.
         *
         * @sample {highcharts} highcharts/css/titles/
         *         Styled mode
         *
         * @type      {Highcharts.CSSObject}
         * @default   {"color": "#666666"}
         */
        style: {
            color: "#666666" /* Palette.neutralColor60 */,
            /**
             * @type {number|string}
             */
            fontSize: '0.8em'
        },
        /**
         * The caption text of the chart.
         *
         * @sample {highcharts} highcharts/caption/text/
         *         Custom caption
         */
        text: '',
        /**
         * The horizontal alignment of the caption. Can be one of "left",
         *  "center" and "right".
         *
         * @type  {Highcharts.AlignValue}
         */
        align: 'left',
        /**
         * The vertical alignment of the caption. Can be one of `"top"`,
         * `"middle"` and `"bottom"`. When middle, the caption behaves as
         * floating.
         *
         * @type      {Highcharts.VerticalAlignValue}
         */
        verticalAlign: 'bottom'
    },
    /**
     * The plotOptions is a wrapper object for config objects for each series
     * type. The config objects for each series can also be overridden for
     * each series item as given in the series array.
     *
     * Configuration options for the series are given in three levels. Options
     * for all series in a chart are given in the [plotOptions.series](
     * #plotOptions.series) object. Then options for all series of a specific
     * type are given in the plotOptions of that type, for example
     * `plotOptions.line`. Next, options for one single series are given in
     * [the series array](#series).
     */
    plotOptions: {},
    /**
     * The legend is a box containing a symbol and name for each series
     * item or point item in the chart. Each series (or points in case
     * of pie charts) is represented by a symbol and its name in the legend.
     *
     * It is possible to override the symbol creator function and create
     * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/).
     *
     * @productdesc {highmaps}
     * A Highmaps legend by default contains one legend item per series, but if
     * a `colorAxis` is defined, the axis will be displayed in the legend.
     * Either as a gradient, or as multiple legend items for `dataClasses`.
     */
    legend: {
        /**
         * The background color of the legend.
         *
         * @see In styled mode, the legend background fill can be applied with
         *      the `.highcharts-legend-box` class.
         *
         * @sample {highcharts} highcharts/legend/backgroundcolor/
         *         Yellowish background
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/border-background/
         *         Border and background options
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @apioption legend.backgroundColor
         */
        /**
         * The width of the drawn border around the legend.
         *
         * @see In styled mode, the legend border stroke width can be applied
         *      with the `.highcharts-legend-box` class.
         *
         * @sample {highcharts} highcharts/legend/borderwidth/
         *         2px border width
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/border-background/
         *         Border and background options
         *
         * @type      {number}
         * @default   0
         * @apioption legend.borderWidth
         */
        /**
         * Enable or disable the legend. There is also a series-specific option,
         * [showInLegend](#plotOptions.series.showInLegend), that can hide the
         * series from the legend. In some series types this is `false` by
         * default, so it must set to `true` in order to show the legend for the
         * series.
         *
         * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled
         * @sample {highstock} stock/legend/align/ Various legend options
         * @sample {highmaps} maps/legend/enabled-false/ Legend disabled
         *
         * @default {highstock} false
         * @default {highmaps} true
         * @default {gantt} false
         */
        enabled: true,
        /**
         * The horizontal alignment of the legend box within the chart area.
         * Valid values are `left`, `center` and `right`.
         *
         * In the case that the legend is aligned in a corner position, the
         * `layout` option will determine whether to place it above/below
         * or on the side of the plot area.
         *
         * @sample {highcharts} highcharts/legend/align/
         *         Legend at the right of the chart
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/alignment/
         *         Legend alignment
         *
         * @type  {Highcharts.AlignValue}
         * @since 2.0
         */
        align: 'center',
        /**
         * If the [layout](legend.layout) is `horizontal` and the legend items
         * span over two lines or more, whether to align the items into vertical
         * columns. Setting this to `false` makes room for more items, but will
         * look more messy.
         *
         * @since 6.1.0
         */
        alignColumns: true,
        /**
         * A CSS class name to apply to the legend group.
         */
        className: 'highcharts-no-tooltip',
        /**
         * General event handlers for the legend. These event hooks can
         * also be attached to the legend at run time using the
         * `Highcharts.addEvent` function.
         *
         * @declare Highcharts.LegendEventsOptionsObject
         *
         * @private
         */
        events: {},
        /**
         * Fires when the legend item belonging to the series is clicked. One
         * parameter, `event`, is passed to the function. The default action
         * is to toggle the visibility of the series, point or data class. This
         * can be prevented by returning `false` or calling
         * `event.preventDefault()`.
         *
         * @sample {highcharts} highcharts/legend/itemclick/
         *         Confirm hiding and showing
         * @sample {highcharts} highcharts/legend/pie-legend-itemclick/
         *         Confirm toggle visibility of pie slices
         *
         * @type      {Highcharts.LegendItemClickCallbackFunction}
         * @context   Highcharts.Legend
         * @apioption legend.events.itemClick
         */
        /**
         * When the legend is floating, the plot area ignores it and is allowed
         * to be placed below it.
         *
         * @sample {highcharts} highcharts/legend/floating-false/
         *         False by default
         * @sample {highcharts} highcharts/legend/floating-true/
         *         True
         * @sample {highmaps} maps/legend/alignment/
         *         Floating legend
         *
         * @type      {boolean}
         * @default   false
         * @since     2.1
         * @apioption legend.floating
         */
        /**
         * The layout of the legend items. Can be one of `horizontal` or
         * `vertical` or `proximate`. When `proximate`, the legend items will be
         * placed as close as possible to the graphs they're representing,
         * except in inverted charts or when the legend position doesn't allow
         * it.
         *
         * @sample {highcharts} highcharts/legend/layout-horizontal/
         *         Horizontal by default
         * @sample {highcharts} highcharts/legend/layout-vertical/
         *         Vertical
         * @sample highcharts/legend/layout-proximate
         *         Labels proximate to the data
         * @sample {highstock} stock/legend/layout-horizontal/
         *         Horizontal by default
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         Vertical with data classes
         * @sample {highmaps} maps/legend/layout-vertical/
         *         Vertical with color axis gradient
         *
         * @validvalue ["horizontal", "vertical", "proximate"]
         */
        layout: 'horizontal',
        /**
         * In a legend with horizontal layout, the itemDistance defines the
         * pixel distance between each item.
         *
         * @sample {highcharts} highcharts/legend/layout-horizontal/
         *         50px item distance
         * @sample {highstock} highcharts/legend/layout-horizontal/
         *         50px item distance
         *
         * @type      {number}
         * @default   {highcharts} 20
         * @default   {highstock} 20
         * @default   {highmaps} 8
         * @since     3.0.3
         * @apioption legend.itemDistance
         */
        /**
         * The pixel bottom margin for each legend item.
         *
         * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         *
         * @since     2.2.0
         */
        itemMarginBottom: 2,
        /**
         * The pixel top margin for each legend item.
         *
         * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         *
         * @since     2.2.0
         */
        itemMarginTop: 2,
        /**
         * The width for each legend item. By default the items are laid out
         * successively. In a [horizontal layout](legend.layout), if the items
         * are laid out across two rows or more, they will be vertically aligned
         * depending on the [legend.alignColumns](legend.alignColumns) option.
         *
         * @sample {highcharts} highcharts/legend/itemwidth-default/
         *         Undefined by default
         * @sample {highcharts} highcharts/legend/itemwidth-80/
         *         80 for aligned legend items
         *
         * @type      {number}
         * @since     2.0
         * @apioption legend.itemWidth
         */
        /**
         * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
         * for each legend label. Available variables relates to properties on
         * the series, or the point in case of pies.
         *
         * @type      {string}
         * @default   {name}
         * @since     1.3
         * @apioption legend.labelFormat
         */
        /* eslint-disable valid-jsdoc */
        /**
         * Callback function to format each of the series' labels. The `this`
         * keyword refers to the series object, or the point object in case of
         * pie charts. By default the series or point name is printed.
         *
         * @productdesc {highmaps}
         * In Highmaps the context can also be a data class in case of a
         * `colorAxis`.
         *
         * @sample {highcharts} highcharts/legend/labelformatter/
         *         Add text
         * @sample {highmaps} maps/legend/labelformatter/
         *         Data classes with label formatter
         *
         * @type {Highcharts.FormatterCallbackFunction<Point|Series>}
         */
        labelFormatter: function () {
            // eslint-enable valid-jsdoc
            return this.name;
        },
        /**
         * Line height for the legend items. Deprecated as of 2.1\. Instead,
         * the line height for each item can be set using
         * `itemStyle.lineHeight`, and the padding between items using
         * `itemMarginTop` and `itemMarginBottom`.
         *
         * @sample {highcharts} highcharts/legend/lineheight/
         *         Setting padding
         *
         * @deprecated
         *
         * @type      {number}
         * @default   16
         * @since     2.0
         * @product   highcharts gantt
         * @apioption legend.lineHeight
         */
        /**
         * If the plot area sized is calculated automatically and the legend is
         * not floating, the legend margin is the space between the legend and
         * the axis labels or plot area.
         *
         * @sample {highcharts} highcharts/legend/margin-default/
         *         12 pixels by default
         * @sample {highcharts} highcharts/legend/margin-30/
         *         30 pixels
         *
         * @type      {number}
         * @default   12
         * @since     2.1
         * @apioption legend.margin
         */
        /**
         * Maximum pixel height for the legend. When the maximum height is
         * extended, navigation will show.
         *
         * @type      {number}
         * @since     2.3.0
         * @apioption legend.maxHeight
         */
        /**
         * The color of the drawn border around the legend.
         *
         * @see In styled mode, the legend border stroke can be applied with the
         *      `.highcharts-legend-box` class.
         *
         * @sample {highcharts} highcharts/legend/bordercolor/
         *         Brown border
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/border-background/
         *         Border and background options
         *
         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         */
        borderColor: "#999999" /* Palette.neutralColor40 */,
        /**
         * The border corner radius of the legend.
         *
         * @sample {highcharts} highcharts/legend/borderradius-default/
         *         Square by default
         * @sample {highcharts} highcharts/legend/borderradius-round/
         *         5px rounded
         * @sample {highmaps} maps/legend/border-background/
         *         Border and background options
         */
        borderRadius: 0,
        /**
         * Options for the paging or navigation appearing when the legend is
         * overflown. Navigation works well on screen, but not in static
         * exported images. One way of working around that is to
         * [increase the chart height in
         * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/).
         *
         * @sample highcharts/legend/scrollable-vertical/
         *         Legend with vertical scrollable extension
         * @sample highcharts/legend/scrollable-horizontal/
         *         Legend with horizontal scrollable extension
         *
         */
        navigation: {
            /**
             * How to animate the pages when navigating up or down. A value of
             * `true` applies the default navigation given in the
             * `chart.animation` option. Additional options can be given as an
             * object containing values for easing and duration.
             *
             * @sample {highcharts} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             * @sample {highstock} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             *
             * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
             * @default   true
             * @since     2.2.4
             * @apioption legend.navigation.animation
             */
            /**
             * The pixel size of the up and down arrows in the legend paging
             * navigation.
             *
             * @sample {highcharts} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             * @sample {highstock} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             *
             * @type      {number}
             * @default   12
             * @since     2.2.4
             * @apioption legend.navigation.arrowSize
             */
            /**
             * Whether to enable the legend navigation. In most cases, disabling
             * the navigation results in an unwanted overflow.
             *
             * See also the
             * [adapt chart to legend](https://github.com/highcharts/adapt-chart-to-legend)
             * plugin for a solution to extend the chart height to make room for
             * the legend, optionally in exported charts only.
             *
             * @type      {boolean}
             * @default   true
             * @since     4.2.4
             * @apioption legend.navigation.enabled
             */
            /**
             * Text styles for the legend page navigation.
             *
             * @see In styled mode, the navigation items are styled with the
             *      `.highcharts-legend-navigation` class.
             *
             * @sample {highcharts} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             * @sample {highstock} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             *
             * @type      {Highcharts.CSSObject}
             * @since     2.2.4
             * @apioption legend.navigation.style
             */
            style: {
                /**
                 * @type {number|string}
                 */
                fontSize: '0.8em'
            },
            /**
             * The color for the active up or down arrow in the legend page
             * navigation.
             *
             * @see In styled mode, the active arrow be styled with the
             *      `.highcharts-legend-nav-active` class.
             *
             * @sample  {highcharts} highcharts/legend/navigation/
             *          Legend page navigation demonstrated
             * @sample  {highstock} highcharts/legend/navigation/
             *          Legend page navigation demonstrated
             *
             * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @since 2.2.4
             */
            activeColor: "#0022ff" /* Palette.highlightColor100 */,
            /**
             * The color of the inactive up or down arrow in the legend page
             * navigation. .
             *
             * @see In styled mode, the inactive arrow be styled with the
             *      `.highcharts-legend-nav-inactive` class.
             *
             * @sample {highcharts} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             * @sample {highstock} highcharts/legend/navigation/
             *         Legend page navigation demonstrated
             *
             * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @since 2.2.4
             */
            inactiveColor: "#cccccc" /* Palette.neutralColor20 */
        },
        /**
         * The inner padding of the legend box.
         *
         * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         *
         * @type      {number}
         * @default   8
         * @since     2.2.0
         * @apioption legend.padding
         */
        /**
         * Whether to reverse the order of the legend items compared to the
         * order of the series or points as defined in the configuration object.
         *
         * @see [yAxis.reversedStacks](#yAxis.reversedStacks),
         *      [series.legendIndex](#series.legendIndex)
         *
         * @sample {highcharts} highcharts/legend/reversed/
         *         Stacked bar with reversed legend
         *
         * @type      {boolean}
         * @default   false
         * @since     1.2.5
         * @apioption legend.reversed
         */
        /**
         * Whether to show the symbol on the right side of the text rather than
         * the left side. This is common in Arabic and Hebrew.
         *
         * @sample {highcharts} highcharts/legend/rtl/
         *         Symbol to the right
         *
         * @type      {boolean}
         * @default   false
         * @since     2.2
         * @apioption legend.rtl
         */
        /**
         * CSS styles for the legend area. In the 1.x versions the position
         * of the legend area was determined by CSS. In 2.x, the position is
         * determined by properties like `align`, `verticalAlign`, `x` and `y`,
         * but the styles are still parsed for backwards compatibility.
         *
         * @deprecated
         *
         * @type      {Highcharts.CSSObject}
         * @product   highcharts highstock
         * @apioption legend.style
         */
        /**
         * CSS styles for each legend item. Only a subset of CSS is supported,
         * notably those options related to text. The default `textOverflow`
         * property makes long texts truncate. Set it to `undefined` to wrap
         * text instead. A `width` property can be added to control the text
         * width.
         *
         * @see In styled mode, the legend items can be styled with the
         *      `.highcharts-legend-item` class.
         *
         * @sample {highcharts} highcharts/legend/itemstyle/
         *         Bold black text
         * @sample {highmaps} maps/legend/itemstyle/
         *         Item text styles
         *
         * @type    {Highcharts.CSSObject}
         * @default {"color": "#333333", "cursor": "pointer", "fontSize": "0.8em", "fontWeight": "bold", "textOverflow": "ellipsis"}
         */
        itemStyle: {
            /**
             * @ignore
             */
            color: "#333333" /* Palette.neutralColor80 */,
            /**
             * @ignore
             */
            cursor: 'pointer',
            /**
             * @ignore
             */
            fontSize: '0.8em',
            /**
             * @ignore
             */
            textDecoration: 'none',
            /**
             * @ignore
             */
            textOverflow: 'ellipsis'
        },
        /**
         * CSS styles for each legend item in hover mode. Only a subset of
         * CSS is supported, notably those options related to text. Properties
         * are inherited from `style` unless overridden here.
         *
         * @see In styled mode, the hovered legend items can be styled with
         *      the `.highcharts-legend-item:hover` pseudo-class.
         *
         * @sample {highcharts} highcharts/legend/itemhoverstyle/
         *         Red on hover
         * @sample {highmaps} maps/legend/itemstyle/
         *         Item text styles
         *
         * @type    {Highcharts.CSSObject}
         * @default {"color": "#000000"}
         */
        itemHoverStyle: {
            /**
             * @ignore
             */
            color: "#000000" /* Palette.neutralColor100 */
        },
        /**
         * CSS styles for each legend item when the corresponding series or
         * point is hidden. Only a subset of CSS is supported, notably those
         * options related to text. Properties are inherited from `style`
         * unless overridden here.
         *
         * @see In styled mode, the hidden legend items can be styled with
         *      the `.highcharts-legend-item-hidden` class.
         *
         * @sample {highcharts} highcharts/legend/itemhiddenstyle/
         *         Darker gray color
         *
         * @type    {Highcharts.CSSObject}
         * @default {"color": "#cccccc"}
         */
        itemHiddenStyle: {
            /**
             * @ignore
             */
            color: "#666666" /* Palette.neutralColor60 */,
            /**
             * @ignore
             */
            textDecoration: 'line-through'
        },
        /**
         * Whether to apply a drop shadow to the legend. A `backgroundColor`
         * also needs to be applied for this to take effect. The shadow can be
         * an object configuration containing `color`, `offsetX`, `offsetY`,
         * `opacity` and `width`.
         *
         * @sample {highcharts} highcharts/legend/shadow/
         *         White background and drop shadow
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/border-background/
         *         Border and background options
         *
         * @type {boolean|Highcharts.CSSObject}
         */
        shadow: false,
        /**
         * Default styling for the checkbox next to a legend item when
         * `showCheckbox` is true.
         *
         * @type {Highcharts.CSSObject}
         * @default {"width": "13px", "height": "13px", "position":"absolute"}
         */
        itemCheckboxStyle: {
            /**
             * @ignore
             */
            position: 'absolute',
            /**
             * @ignore
             */
            width: '13px', // For IE precision
            /**
             * @ignore
             */
            height: '13px'
        },
        /// itemWidth: undefined,
        /**
         * When this is true, the legend symbol width will be the same as
         * the symbol height, which in turn defaults to the font size of the
         * legend items.
         *
         * @since 5.0.0
         */
        squareSymbol: true,
        /**
         * The pixel height of the symbol for series types that use a rectangle
         * in the legend. Defaults to the font size of legend items.
         *
         * Note: This option is a default source of color axis height, if the
         * [colorAxis.height](https://api.highcharts.com/highcharts/colorAxis.height)
         * option is not set.
         *
         * @productdesc {highmaps}
         * In Highmaps, when the symbol is the gradient of a vertical color
         * axis, the height defaults to 200.
         *
         * @sample {highmaps} maps/legend/layout-vertical-sized/
         *         Sized vertical gradient
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         No distance between data classes
         *
         * @type      {number}
         * @since     3.0.8
         * @apioption legend.symbolHeight
         */
        /**
         * The border radius of the symbol for series types that use a rectangle
         * in the legend. Defaults to half the `symbolHeight`, effectively
         * creating a circle.
         *
         * For color axis scales, it defaults to 3.
         *
         * @sample {highcharts} highcharts/legend/symbolradius/
         *         Round symbols
         * @sample {highstock} highcharts/legend/symbolradius/
         *         Round symbols
         * @sample {highmaps} highcharts/legend/symbolradius/
         *         Round symbols
         *
         * @type      {number}
         * @since     3.0.8
         * @apioption legend.symbolRadius
         */
        /**
         * The pixel width of the legend item symbol. When the `squareSymbol`
         * option is set, this defaults to the `symbolHeight`, otherwise 16.
         *
         * Note: This option is a default source of color axis width, if the
         * [colorAxis.width](https://api.highcharts.com/highcharts/colorAxis.width)
         * option is not set.
         *
         * @productdesc {highmaps}
         * In Highmaps, when the symbol is the gradient of a horizontal color
         * axis, the width defaults to 200.
         *
         * @sample {highcharts} highcharts/legend/symbolwidth/
         *         Greater symbol width and padding
         * @sample {highmaps} maps/legend/padding-itemmargin/
         *         Padding and item margins demonstrated
         * @sample {highmaps} maps/legend/layout-vertical-sized/
         *         Sized vertical gradient
         *
         * @type      {number}
         * @apioption legend.symbolWidth
         */
        /**
         * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the legend item texts.
         *
         * Prior to 4.1.7, when using HTML, [legend.navigation](
         * #legend.navigation) was disabled.
         *
         * @sample highcharts/legend/scrollable-vertical/
         *         Legend with vertical scrollable extension
         * @sample highcharts/legend/scrollable-horizontal/
         *         Legend with horizontal scrollable extension
         *
         * @type      {boolean}
         * @default   false
         * @apioption legend.useHTML
         */
        /**
         * For a color axis with data classes, how many decimals to render in
         * the legend. The default preserves the decimals of the range numbers.
         *
         * @type      {number}
         * @default   -1
         * @product   highcharts highmaps
         * @apioption legend.valueDecimals
         */
        /**
         * For a color axis with data classes, a suffix for the range numbers in
         * the legend.
         *
         * @type      {string}
         * @default   ''
         * @product   highcharts highmaps
         * @apioption legend.valueSuffix
         */
        /**
         * The width of the legend box. If a number is set, it translates to
         * pixels. Since v7.0.2 it allows setting a percent string of the full
         * chart width, for example `40%`.
         *
         * Defaults to the full chart width for legends below or above the
         * chart, half the chart width for legends to the left and right.
         *
         * @sample {highcharts} highcharts/legend/width/
         *         Aligned to the plot area
         * @sample {highcharts} highcharts/legend/width-percent/
         *         A percent of the chart width
         *
         * @type      {number|string}
         * @since     2.0
         * @apioption legend.width
         */
        /**
         * The pixel padding between the legend item symbol and the legend
         * item text.
         *
         * @sample {highcharts} highcharts/legend/symbolpadding/
         *         Greater symbol width and padding
         */
        symbolPadding: 5,
        /**
         * The vertical alignment of the legend box. Can be one of `top`,
         * `middle` or `bottom`. Vertical position can be further determined
         * by the `y` option.
         *
         * In the case that the legend is aligned in a corner position, the
         * `layout` option will determine whether to place it above/below
         * or on the side of the plot area.
         *
         * When the [layout](#legend.layout) option is `proximate`, the
         * `verticalAlign` option doesn't apply.
         *
         * @sample {highcharts} highcharts/legend/verticalalign/
         *         Legend 100px from the top of the chart
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/alignment/
         *         Legend alignment
         *
         * @type  {Highcharts.VerticalAlignValue}
         * @since 2.0
         */
        verticalAlign: 'bottom',
        // Width: undefined,
        /**
         * The x offset of the legend relative to its horizontal alignment
         * `align` within chart.spacingLeft and chart.spacingRight. Negative
         * x moves it to the left, positive x moves it to the right.
         *
         * @sample {highcharts} highcharts/legend/width/
         *         Aligned to the plot area
         *
         * @since 2.0
         */
        x: 0,
        /**
         * The vertical offset of the legend relative to it's vertical alignment
         * `verticalAlign` within chart.spacingTop and chart.spacingBottom.
         *  Negative y moves it up, positive y moves it down.
         *
         * @sample {highcharts} highcharts/legend/verticalalign/
         *         Legend 100px from the top of the chart
         * @sample {highstock} stock/legend/align/
         *         Various legend options
         * @sample {highmaps} maps/legend/alignment/
         *         Legend alignment
         *
         * @since 2.0
         */
        y: 0,
        /**
         * A title to be added on top of the legend.
         *
         * @sample {highcharts} highcharts/legend/title/
         *         Legend title
         * @sample {highmaps} maps/legend/alignment/
         *         Legend with title
         *
         * @since 3.0
         */
        title: {
            /**
             * A text or HTML string for the title.
             *
             * @type      {string}
             * @since     3.0
             * @apioption legend.title.text
             */
            /**
             * Generic CSS styles for the legend title.
             *
             * @see In styled mode, the legend title is styled with the
             *      `.highcharts-legend-title` class.
             *
             * @type    {Highcharts.CSSObject}
             * @default {"fontSize": "0.8em", "fontWeight": "bold"}
             * @since   3.0
             */
            style: {
                /**
                 * @ignore
                 */
                fontSize: '0.8em',
                /**
                 * @ignore
                 */
                fontWeight: 'bold'
            }
        }
    },
    /**
     * The loading options control the appearance of the loading screen
     * that covers the plot area on chart operations. This screen only
     * appears after an explicit call to `chart.showLoading()`. It is a
     * utility for developers to communicate to the end user that something
     * is going on, for example while retrieving new data via an XHR connection.
     * The "Loading..." text itself is not part of this configuration
     * object, but part of the `lang` object.
     */
    loading: {
        /**
         * The duration in milliseconds of the fade out effect.
         *
         * @sample highcharts/loading/hideduration/
         *         Fade in and out over a second
         *
         * @type      {number}
         * @default   100
         * @since     1.2.0
         * @apioption loading.hideDuration
         */
        /**
         * The duration in milliseconds of the fade in effect.
         *
         * @sample highcharts/loading/hideduration/
         *         Fade in and out over a second
         *
         * @type      {number}
         * @default   100
         * @since     1.2.0
         * @apioption loading.showDuration
         */
        /**
         * CSS styles for the loading label `span`.
         *
         * @see In styled mode, the loading label is styled with the
         *      `.highcharts-loading-inner` class.
         *
         * @sample {highcharts|highmaps} highcharts/loading/labelstyle/
         *         Vertically centered
         * @sample {highstock} stock/loading/general/
         *         Label styles
         *
         * @type    {Highcharts.CSSObject}
         * @default {"fontWeight": "bold", "position": "relative", "top": "45%"}
         * @since   1.2.0
         */
        labelStyle: {
            /**
             * @ignore
             */
            fontWeight: 'bold',
            /**
             * @ignore
             */
            position: 'relative',
            /**
             * @ignore
             */
            top: '45%'
        },
        /**
         * CSS styles for the loading screen that covers the plot area.
         *
         * In styled mode, the loading label is styled with the
         * `.highcharts-loading` class.
         *
         * @sample  {highcharts|highmaps} highcharts/loading/style/
         *          Gray plot area, white text
         * @sample  {highstock} stock/loading/general/
         *          Gray plot area, white text
         *
         * @type    {Highcharts.CSSObject}
         * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"}
         * @since   1.2.0
         */
        style: {
            /**
             * @ignore
             */
            position: 'absolute',
            /**
             * @ignore
             */
            backgroundColor: "#ffffff" /* Palette.backgroundColor */,
            /**
             * @ignore
             */
            opacity: 0.5,
            /**
             * @ignore
             */
            textAlign: 'center'
        }
    },
    /**
     * Options for the tooltip that appears when the user hovers over a
     * series or point.
     *
     * @declare Highcharts.TooltipOptions
     */
    tooltip: {
        /**
         * The color of the tooltip border. When `undefined`, the border takes
         * the color of the corresponding series or point.
         *
         * Note that the [borderWidth](#tooltip.borderWidth) is usually 0 by
         * default, so the border color may not be visible until a border width
         * is set.
         *
         * @sample {highcharts} highcharts/tooltip/bordercolor-default/ Follow
         *         series by default
         * @sample {highcharts} highcharts/tooltip/bordercolor-black/ Black
         *         border
         * @sample {highstock} stock/tooltip/general/ Styled tooltip
         * @sample {highmaps} maps/tooltip/background-border/ Background and
         *         border demo
         *
         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @apioption tooltip.borderColor
         */
        /**
         * A CSS class name to apply to the tooltip's container div,
         * allowing unique CSS styling for each chart.
         *
         * @type      {string}
         * @apioption tooltip.className
         */
        /**
         * Since 4.1, the crosshair definitions are moved to the Axis object
         * in order for a better separation from the tooltip. See
         * [xAxis.crosshair](#xAxis.crosshair).
         *
         * @sample {highcharts} highcharts/tooltip/crosshairs-x/
         *         Enable a crosshair for the x value
         *
         * @deprecated
         *
         * @type      {*}
         * @default   true
         * @apioption tooltip.crosshairs
         */
        /**
         * Distance from point to tooltip in pixels.
         *
         * @type      {number}
         * @default   16
         * @apioption tooltip.distance
         */
        /**
         * Whether the tooltip should follow the mouse as it moves across
         * columns, pie slices and other point types with an extent.
         * By default it behaves this way for pie, polygon, map, sankey
         * and wordcloud series by override in the `plotOptions`
         * for those series types.
         *
         * Does not apply if [split](#tooltip.split) is `true`.
         *
         * For touch moves to behave the same way, [followTouchMove](
         * #tooltip.followTouchMove) must be `true` also.
         *
         * @sample highcharts/tooltip/followpointer/
         *         Tooltip follow pointer comparison
         *
         * @type      {boolean}
         * @default   {highcharts} false
         * @default   {highstock} false
         * @default   {highmaps} true
         * @since     3.0
         * @apioption tooltip.followPointer
         */
        /**
         * Whether the tooltip should update as the finger moves on a touch
         * device. If this is `true` and [chart.panning](#chart.panning) is
         * set,`followTouchMove` will take over one-finger touches, so the user
         * needs to use two fingers for zooming and panning.
         *
         * Note the difference to [followPointer](#tooltip.followPointer) that
         * only defines the _position_ of the tooltip. If `followPointer` is
         * false in for example a column series, the tooltip will show above or
         * below the column, but as `followTouchMove` is true, the tooltip will
         * jump from column to column as the user swipes across the plot area.
         *
         * @type      {boolean}
         * @default   {highcharts} true
         * @default   {highstock} true
         * @default   {highmaps} false
         * @since     3.0.1
         * @apioption tooltip.followTouchMove
         */
        /**
         * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
         * for the whole shared tooltip. When format strings are a requirement,
         * it is usually more convenient to use `headerFormat`, `pointFormat`
         * and `footerFormat`, but the `format` option allows combining them
         * into one setting.
         *
         * The context of the format string is the same as that of the
         * `tooltip.formatter` callback.
         *
         * @sample {highcharts} highcharts/tooltip/format-shared/
         *         Format for shared tooltip
         *
         * @type      {string}
         * @default   undefined
         * @since     11.1.0
         * @apioption tooltip.format
         */
        /**
         * Callback function to format the text of the tooltip from scratch. In
         * case of single or [shared](#tooltip.shared) tooltips, a string should
         * be returned. In case of [split](#tooltip.split) tooltips, it should
         * return an array where the first item is the header, and subsequent
         * items are mapped to the points. Return `false` to disable tooltip for
         * a specific point on series.
         *
         * A subset of HTML is supported. Unless `useHTML` is true, the HTML of
         * the tooltip is parsed and converted to SVG, therefore this isn't a
         * complete HTML renderer. The following HTML tags are supported: `b`,
         * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style`
         * attribute, but only text-related CSS, that is shared with SVG, is
         * handled.
         *
         * The context of the formatter (since v12) is the
         * [Point](https://api.highcharts.com/class-reference/Highcharts.Point)
         * instance. If the tooltip is shared or split, an array `this.points`
         * contains all points of the hovered x-value.
         *
         * Common properties from the Point to use in the formatter include:
         *
         * - **Point.percentage**:
         *   Stacked series and pies only. The point's percentage of the total.
         *
         * - **Point.points**:
         *   In a shared or split tooltip, this is an array containing all the
         *   hovered points.
         *
         * - **this.series**:
         *   The series object. The series name is available through
         *   `this.series.name`.
         *
         * - **this.total**:
         *   The total value at this point's x value in a stacked series, or the
         *   sum of all slices in a pie series.
         *
         * - **this.x**:
         *   The x value.
         *
         * - **this.y**:
         *   The y value.
         *
         * @sample {highcharts} highcharts/tooltip/formatter-simple/
         *         Simple string formatting
         * @sample {highcharts} highcharts/tooltip/formatter-shared/
         *         Formatting with shared tooltip
         * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
         *         Formatting with split tooltip
         * @sample highcharts/tooltip/formatter-conditional-default/
         *         Extending default formatter
         * @sample {highstock} stock/tooltip/formatter/
         *         Formatting with shared tooltip
         * @sample {highmaps} maps/tooltip/formatter/
         *         String formatting
         *
         * @type      {Highcharts.TooltipFormatterCallbackFunction}
         * @apioption tooltip.formatter
         */
        /**
         * Callback function to format the text of the tooltip for
         * visible null points.
         * Works analogously to [formatter](#tooltip.formatter).
         *
         * @sample highcharts/plotoptions/series-nullformat
         *         Format data label and tooltip for null point.
         *
         * @type      {Highcharts.TooltipFormatterCallbackFunction}
         * @apioption tooltip.nullFormatter
         */
        /**
         * Whether to allow the tooltip to render outside the chart's SVG
         * element box. By default (`false`), the tooltip is rendered within the
         * chart's SVG element, which results in the tooltip being aligned
         * inside the chart area. For small charts, this may result in clipping
         * or overlapping. When `true`, a separate SVG element is created and
         * overlaid on the page, allowing the tooltip to be aligned inside the
         * page itself. Beware that with this option active, CSS classes on the
         * chart's target container, with classnames matching the pattern
         * 'highcharts-*', will be set on the tooltip as well. This is done to
         * support theming for tooltips with this option.
         *
         * Defaults to `true` if `chart.scrollablePlotArea` is activated,
         * otherwise `false`.
         *
         * @sample highcharts/tooltip/outside
         *         Small charts with tooltips outside
         *
         * @type      {boolean|undefined}
         * @default   undefined
         * @since     6.1.1
         * @apioption tooltip.outside
         */
        /**
         * A callback function for formatting the HTML output for a single point
         * in the tooltip. Like the `pointFormat` string, but with more
         * flexibility.
         *
         * @type      {Highcharts.FormatterCallbackFunction<Highcharts.Point>}
         * @since     4.1.0
         * @context   Highcharts.Point
         * @apioption tooltip.pointFormatter
         */
        /**
         * A callback function to place the tooltip in a custom position. The
         * callback receives three parameters: `labelWidth`, `labelHeight` and
         * `point`, where point contains values for `plotX` and `plotY` telling
         * where the reference point is in the plot area. Add `chart.plotLeft`
         * and `chart.plotTop` to get the full coordinates.
         *
         * To find the actual hovered `Point` instance, use
         * `this.chart.hoverPoint`. For shared or split tooltips, all the hover
         * points are available in `this.chart.hoverPoints`.
         *
         * Since v7, when [tooltip.split](#tooltip.split) option is enabled,
         * positioner is called for each of the boxes separately, including
         * xAxis header. xAxis header is not a point, instead `point` argument
         * contains info: `{ plotX: Number, plotY: Number, isHeader: Boolean }`
         *
         * The return should be an object containing x and y values, for example
         * `{ x: 100, y: 100 }`.
         *
         * @sample {highcharts} highcharts/tooltip/positioner/
         *         A fixed tooltip position
         * @sample {highstock} stock/tooltip/positioner/
         *         A fixed tooltip position on top of the chart
         * @sample {highmaps} maps/tooltip/positioner/
         *         A fixed tooltip position
         * @sample {highstock} stock/tooltip/split-positioner/
         *         Split tooltip with fixed positions
         * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/
         *         Scrollable plot area combined with tooltip positioner
         *
         * @type      {Highcharts.TooltipPositionerCallbackFunction}
         * @since     2.2.4
         * @apioption tooltip.positioner
         */
        /**
         * Shows tooltip for all points with the same X value. Splits the
         * tooltip into one label per series, with the header close to the axis.
         * This is recommended over [shared](#tooltip.shared)
         * tooltips for charts with multiple line series, generally making them
         * easier to read. This option takes precedence over `tooltip.shared`.
         *
         * Not supported for [polar](#chart.polar) and [inverted](#chart.inverted) charts.
         *
         * @productdesc {highstock} In Highcharts Stock, tooltips are split
         * by default since v6.0.0. Stock charts typically contain
         * multi-dimension points and multiple panes, making split tooltips
         * the preferred layout over
         * the previous `shared` tooltip.
         *
         * @sample highcharts/tooltip/split/
         *         Split tooltip
         * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
         *         Split tooltip and custom formatter callback
         *
         * @type      {boolean}
         * @default   {highcharts} false
         * @default   {highstock} true
         * @since     5.0.0
         * @product   highcharts highstock
         * @apioption tooltip.split
         */
        /**
         * Prevents the tooltip from switching or closing, when touched or
         * pointed.
         *
         * @sample highcharts/tooltip/stickoncontact/
         *         Tooltip sticks on pointer contact
         *
         * @type      {boolean}
         * @since     8.0.1
         * @apioption tooltip.stickOnContact
         */
        /**
         * Use HTML to render the contents of the tooltip instead of SVG. Using
         * HTML allows advanced formatting like tables and images in the
         * tooltip. It is also recommended for rtl languages as it works around
         * rtl bugs in early Firefox.
         *
         * @sample {highcharts|highstock} highcharts/tooltip/footerformat/
         *         A table for value alignment
         * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/
         *         Full HTML tooltip
         * @sample {highmaps} maps/tooltip/usehtml/
         *         Pure HTML tooltip
         *
         * @type      {boolean}
         * @default   false
         * @since     2.2
         * @apioption tooltip.useHTML
         */
        /**
         * How many decimals to show in each series' y value. This is
         * overridable in each series' tooltip options object. The default is to
         * preserve all decimals.
         *
         * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         * @sample {highmaps} maps/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         *
         * @type      {number|undefined}
         * @since     2.2
         * @apioption tooltip.valueDecimals
         */
        /**
         * A string to prepend to each series' y value. Overridable in each
         * series' tooltip options object.
         *
         * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         * @sample {highmaps} maps/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         *
         * @type      {string}
         * @since     2.2
         * @apioption tooltip.valuePrefix
         */
        /**
         * A string to append to each series' y value. Overridable in each
         * series' tooltip options object.
         *
         * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         * @sample {highmaps} maps/tooltip/valuedecimals/
         *         Set decimals, prefix and suffix for the value
         *
         * @type      {string}
         * @since     2.2
         * @apioption tooltip.valueSuffix
         */
        /**
         * The format for the date in the tooltip header if the X axis is a
         * datetime axis. The default is a best guess based on the smallest
         * distance between points in the chart.
         *
         * @sample {highcharts} highcharts/tooltip/xdateformat/
         *         A different format
         *
         * @type      {string|Highcharts.DateTimeFormatOptions}
         * @product   highcharts highstock gantt
         * @apioption tooltip.xDateFormat
         */
        /**
         * How many decimals to show for the `point.change`
         * or the `point.cumulativeSum` value when the `series.compare`
         * or the `series.cumulative` option is set.
         * This is overridable in each series' tooltip options object.
         *
         * @type      {number}
         * @default   2
         * @since     1.0.1
         * @product   highstock
         * @apioption tooltip.changeDecimals
         */
        /**
         * Enable or disable the tooltip.
         *
         * @sample {highcharts} highcharts/tooltip/enabled/
         *         Disabled
         * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
         *         Disable tooltip and show values on chart instead
         */
        enabled: true,
        /**
         * Enable or disable animation of the tooltip.
         *
         * @type       {boolean|Partial<Highcharts.AnimationOptionsObject>}
         * @since      2.3.0
         */
        animation: {
            duration: 300,
            // EaseOutCirc
            easing: function (x) { return Math.sqrt(1 - Math.pow(x - 1, 2)); }
        },
        /**
         * The radius of the rounded border corners.
         *
         * @sample {highcharts} highcharts/tooltip/bordercolor-default/
         *         Default border radius
         * @sample {highcharts} highcharts/tooltip/borderradius-0/
         *         Square borders
         * @sample {highmaps} maps/tooltip/background-border/
         *         Background and border demo
         */
        borderRadius: 3,
        /**
         * For series on datetime axes, the date format in the tooltip's
         * header will by default be guessed based on the closest data points.
         * This member gives the default string representations used for
         * each unit. For an overview of the string or object configuration, see
         * [dateFormat](/class-reference/Highcharts.Time#dateFormat).
         *
         * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats)
         *
         * @type    {Highcharts.Dictionary<string|Highcharts.DateTimeFormatOptions>}
         * @product highcharts highstock gantt
         */
        dateTimeLabelFormats: {
            /** @internal */
            millisecond: '%[AebHMSL]',
            /** @internal */
            second: '%[AebHMS]',
            /** @internal */
            minute: '%[AebHM]',
            /** @internal */
            hour: '%[AebHM]',
            /** @internal */
            day: '%[AebY]',
            /** @internal */
            week: 'Week from %[AebY]',
            /** @internal */
            month: '%[BY]',
            /** @internal */
            year: '%Y'
        },
        /**
         * A string to append to the tooltip format.
         *
         * @sample {highcharts} highcharts/tooltip/footerformat/
         *         A table for value alignment
         * @sample {highmaps} maps/tooltip/format/
         *         Format demo
         *
         * @since 2.2
         */
        footerFormat: '',
        /**
         * The name of a symbol to use for the border around the tooltip
         * header. Applies only when [tooltip.split](#tooltip.split) is
         * enabled.
         *
         * Custom callbacks for symbol path generation can also be added to
         * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
         * [series.marker.symbol](plotOptions.line.marker.symbol).
         *
         * @see [tooltip.shape](#tooltip.shape)
         *
         * @sample {highstock} stock/tooltip/split-positioner/
         *         Different shapes for header and split boxes
         *
         * @type       {Highcharts.TooltipShapeValue}
         * @validvalue ["callout", "rect"]
         * @since      7.0
         */
        headerShape: 'callout',
        /**
         * The number of milliseconds to wait until the tooltip is hidden when
         * mouse out from a point or chart.
         *
         * @since 3.0
         */
        hideDelay: 500,
        /**
         * Padding inside the tooltip, in pixels.
         *
         * @since 5.0.0
         */
        padding: 8,
        /**
         * The name of a symbol to use for the border around the tooltip. Can
         * be one of: `"callout"`, `"circle"` or `"rect"`. When
         * [tooltip.split](#tooltip.split)
         * option is enabled, shape is applied to all boxes except header, which
         * is controlled by
         * [tooltip.headerShape](#tooltip.headerShape).
         *
         * Custom callbacks for symbol path generation can also be added to
         * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
         * [series.marker.symbol](plotOptions.line.marker.symbol).
         *
         * @type  {Highcharts.TooltipShapeValue}
         * @since 4.0
         */
        shape: 'callout',
        /**
         * Shows information in the tooltip for all points with the same X
         * value. When the tooltip is shared, the entire plot area will capture
         * mouse movement or touch events. Tooltip texts for series types with
         * ordered data (not pie, scatter, flags etc) will be shown in a single
         * bubble. This is recommended for single series charts and for
         * tablet/mobile optimized charts.
         *
         * See also [tooltip.split](#tooltip.split), that is better suited for
         * charts with many series, especially line-type series. The
         * `tooltip.split` option takes precedence over `tooltip.shared`.
         *
         * @sample {highcharts} highcharts/tooltip/shared-false/
         *         False by default
         * @sample {highcharts} highcharts/tooltip/shared-true/
         *         True
         * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/
         *         True with x axis crosshair
         * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/
         *         True with mixed series types
         *
         * @since   2.1
         * @product highcharts highstock
         */
        shared: false,
        /**
         * Proximity snap for graphs or single points. It defaults to 10 for
         * mouse-powered devices and 25 for touch devices.
         *
         * Note that in most cases the whole plot area captures the mouse
         * movement, and in these cases `tooltip.snap` doesn't make sense. This
         * applies when [stickyTracking](#plotOptions.series.stickyTracking)
         * is `true` (default) and when the tooltip is [shared](#tooltip.shared)
         * or [split](#tooltip.split).
         *
         * @sample {highcharts} highcharts/tooltip/bordercolor-default/
         *         10 px by default
         * @sample {highcharts} highcharts/tooltip/snap-50/
         *         50 px on graph
         *
         * @type    {number}
         * @default 10/25
         * @since   1.2.0
         * @product highcharts highstock
         */
        snap: isTouchDevice ? 25 : 10,
        /**
         * The HTML of the tooltip header line. The context is the
         * [Point class](https://api.highcharts.com/class-reference/Highcharts.Point).
         * Variables are enclosed in curly brackets. Examples of common
         * variables to include are `x`, `y`, `series.name` and `series.color`
         * and other properties on the same form. The `point.key` variable
         * contains the category name, x value or datetime string depending on
         * the type of axis. For datetime axes, the `point.key` date format can
         * be set using `tooltip.xDateFormat`.
         *
         * @sample {highcharts} highcharts/tooltip/footerformat/
         *         An HTML table in the tooltip
         * @sample {highstock} highcharts/tooltip/footerformat/
         *         An HTML table in the tooltip
         * @sample {highmaps} maps/tooltip/format/
         *         Format demo
         *
         * @type      {string}
         * @apioption tooltip.headerFormat
         */
        headerFormat: '<span style="font-size: 0.8em">{ucfirst point.key}</span><br/>',
        /**
         * The HTML of the null point's line in the tooltip. Works analogously
         * to [pointFormat](#tooltip.pointFormat).
         *
         * @sample {highcharts} highcharts/plotoptions/series-nullformat
         *         Format data label and tooltip for null point.
         *
         * @type      {string}
         * @apioption tooltip.nullFormat
         */
        /**
         * The HTML of the point's line in the tooltip. The context is the
         * [Point class](https://api.highcharts.com/class-reference/Highcharts.Point).
         * Variables are enclosed in curly brackets. Examples of common
         * variables to include are `x`, `y`, `series.name` and `series.color`
         * and other properties on the same form. Furthermore, `y` can be
         * extended by the `tooltip.valuePrefix` and `tooltip.valueSuffix`
         * variables. This can also be overridden for each series, which makes
         * it a good hook for displaying units.
         *
         * In styled mode, the dot is colored by a class name rather than the
         * point color.
         *
         * @sample {highcharts} highcharts/tooltip/pointformat/
         *         A different point format with value suffix
         * @sample {highcharts|highstock} highcharts/tooltip/pointformat-extra-information/
         *         Show extra information about points in the tooltip
         * @sample {highmaps} maps/tooltip/format/
         *         Format demo
         *
         * @type       {string}
         * @since      2.2
         * @apioption  tooltip.pointFormat
         */
        pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>',
        /**
         * The background color or gradient for the tooltip.
         *
         * In styled mode, the stroke width is set in the
         * `.highcharts-tooltip-box` class.
         *
         * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/
         *         Yellowish background
         * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/
         *         Gradient
         * @sample {highcharts} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         * @sample {highstock} stock/tooltip/general/
         *         Custom tooltip
         * @sample {highstock} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         * @sample {highmaps} maps/tooltip/background-border/
         *         Background and border demo
         * @sample {highmaps} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         *
         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         */
        backgroundColor: "#ffffff" /* Palette.backgroundColor */,
        /**
         * The pixel width of the tooltip border. Defaults to 0 for single
         * tooltips and 1 for split tooltips.
         *
         * In styled mode, the stroke width is set in the
         * `.highcharts-tooltip-box` class.
         *
         * @sample {highcharts} highcharts/tooltip/bordercolor-default/
         *         2 pixels
         * @sample {highcharts} highcharts/tooltip/borderwidth/
         *         No border (shadow only)
         * @sample {highcharts} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         * @sample {highstock} stock/tooltip/general/
         *         Custom tooltip
         * @sample {highstock} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         * @sample {highmaps} maps/tooltip/background-border/
         *         Background and border demo
         * @sample {highmaps} highcharts/css/tooltip-border-background/
         *         Tooltip in styled mode
         *
         * @type {number}
         */
        borderWidth: void 0,
        /**
         * Whether to apply a drop shadow to the tooltip.
         *
         * @sample {highcharts} highcharts/tooltip/bordercolor-default/
         *         True by default
         * @sample {highcharts} highcharts/tooltip/shadow/
         *         False
         * @sample {highmaps} maps/tooltip/positioner/
         *         Fixed tooltip position, border and shadow disabled
         *
         * @type {boolean|Highcharts.ShadowOptionsObject}
         */
        shadow: true,
        /**
         * Prevents the tooltip from switching or closing when touched or
         * pointed.
         *
         * @sample highcharts/tooltip/stickoncontact/
         *         Tooltip sticks on pointer contact
         *
         * @since 8.0.1
         */
        stickOnContact: false,
        /**
         * CSS styles for the tooltip. The tooltip can also be styled through
         * the CSS class `.highcharts-tooltip`.
         *
         * Note that the default `pointerEvents` style makes the tooltip ignore
         * mouse events, so in order to use clickable tooltips, this value must
         * be set to `auto`.
         *
         * @sample {highcharts} highcharts/tooltip/style/
         *         Greater padding, bold text
         *
         * @type {Highcharts.CSSObject}
         */
        style: {
            /** @internal */
            color: "#333333" /* Palette.neutralColor80 */,
            /** @internal */
            cursor: 'default',
            /**
             * @type {number|string}
             */
            fontSize: '0.8em'
        },
        /**
         * Use HTML to render the contents of the tooltip instead of SVG. Using
         * HTML allows advanced formatting like tables and images in the
         * tooltip. It is also recommended for rtl languages as it works around
         * rtl bugs in early Firefox.
         *
         * @sample {highcharts|highstock} highcharts/tooltip/footerformat/
         *         A table for value alignment
         * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/
         *         Full HTML tooltip
         * @sample {highmaps} maps/tooltip/usehtml/
         *         Pure HTML tooltip
         *
         * @since 2.2
         */
        useHTML: false
    },
    /**
     * Highchart by default puts a credits label in the lower right corner
     * of the chart. This can be changed using these options.
     */
    credits: {
        /**
         * Credits for map source to be concatenated with conventional credit
         * text. By default this is a format string that collects copyright
         * information from the map if available.
         *
         * @see [mapTextFull](#credits.mapTextFull)
         * @see [text](#credits.text)
         *
         * @type      {string}
         * @default   \u00a9 <a href="{geojson.copyrightUrl}">{geojson.copyrightShort}</a>
         * @since     4.2.2
         * @product   highmaps
         * @apioption credits.mapText
         */
        /**
         * Detailed credits for map source to be displayed on hover of credits
         * text. By default this is a format string that collects copyright
         * information from the map if available.
         *
         * @see [mapText](#credits.mapText)
         * @see [text](#credits.text)
         *
         * @type      {string}
         * @default   {geojson.copyright}
         * @since     4.2.2
         * @product   highmaps
         * @apioption credits.mapTextFull
         */
        /**
         * Whether to show the credits text.
         *
         * @sample {highcharts} highcharts/credits/enabled-false/
         *         Credits disabled
         * @sample {highstock} stock/credits/enabled/
         *         Credits disabled
         * @sample {highmaps} maps/credits/enabled-false/
         *         Credits disabled
         */
        enabled: true,
        /**
         * The URL for the credits label.
         *
         * @sample {highcharts} highcharts/credits/href/
         *         Custom URL and text
         * @sample {highmaps} maps/credits/customized/
         *         Custom URL and text
         */
        href: 'https://www.highcharts.com?credits',
        /**
         * Position configuration for the credits label.
         *
         * @sample {highcharts} highcharts/credits/position-left/
         *         Left aligned
         * @sample {highcharts} highcharts/credits/position-left/
         *         Left aligned
         * @sample {highmaps} maps/credits/customized/
         *         Left aligned
         * @sample {highmaps} maps/credits/customized/
         *         Left aligned
         *
         * @type    {Highcharts.AlignObject}
         * @since   2.1
         */
        position: {
            /** @internal */
            align: 'right',
            /** @internal */
            x: -10,
            /** @internal */
            verticalAlign: 'bottom',
            /** @internal */
            y: -5
        },
        /**
         * CSS styles for the credits label.
         *
         * @see In styled mode, credits styles can be set with the
         *      `.highcharts-credits` class.
         *
         * @type {Highcharts.CSSObject}
         */
        style: {
            /** @internal */
            cursor: 'pointer',
            /** @internal */
            color: "#999999" /* Palette.neutralColor40 */,
            /**
             * @type {number|string}
             */
            fontSize: '0.6em'
        },
        /**
         * The text for the credits label.
         *
         * @productdesc {highmaps}
         * If a map is loaded as GeoJSON, the text defaults to
         * `Highcharts @ {map-credits}`. Otherwise, it defaults to
         * `Highcharts.com`.
         *
         * @sample {highcharts} highcharts/credits/href/
         *         Custom URL and text
         * @sample {highmaps} maps/credits/customized/
         *         Custom URL and text
         */
        text: 'Highcharts.com'
    }
};
var defaultTime = new Core_Time(defaultOptions.time);
/**
 * Get the updated default options. Until 3.0.7, merely exposing defaultOptions
 * for outside modules wasn't enough because the setOptions method created a new
 * object.
 *
 * @function Highcharts.getOptions
 *
 * @return {Highcharts.Options}
 * Default options.
 */
function getOptions() {
    return defaultOptions;
}
/**
 * Merge the default options with custom options and return the new options
 * structure. Commonly used for defining reusable templates.
 *
 * @sample highcharts/members/setoptions Applying a global theme
 *
 * @function Highcharts.setOptions
 *
 * @param {Highcharts.Options} options
 * The new custom chart options.
 *
 * @return {Highcharts.Options}
 * Updated options.
 */
function setOptions(options) {
    Defaults_fireEvent(Core_Globals, 'setOptions', { options: options });
    // Copy in the default options
    Defaults_merge(true, defaultOptions, options);
    // Update the time object
    if (options.time) {
        defaultTime.update(defaultOptions.time);
    }
    if (options.lang && 'locale' in options.lang) {
        defaultTime.update({
            locale: options.lang.locale
        });
    }
    return defaultOptions;
}
/* *
 *
 *  Default Export
 *
 * */
var DefaultOptions = {
    defaultOptions: defaultOptions,
    defaultTime: defaultTime,
    getOptions: getOptions,
    setOptions: setOptions
};
/* harmony default export */ var Defaults = (DefaultOptions);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue
 */
/**
 * Gets fired when a series is added to the chart after load time, using the
 * `addSeries` method. Returning `false` prevents the series from being added.
 *
 * @callback Highcharts.ChartAddSeriesCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {Highcharts.ChartAddSeriesEventObject} event
 *        The event that occurred.
 */
/**
 * Contains common event information. Through the `options` property you can
 * access the series options that were passed to the `addSeries` method.
 *
 * @interface Highcharts.ChartAddSeriesEventObject
 */ /**
* The series options that were passed to the `addSeries` method.
* @name Highcharts.ChartAddSeriesEventObject#options
* @type {Highcharts.SeriesOptionsType}
*/ /**
* Prevents the default behaviour of the event.
* @name Highcharts.ChartAddSeriesEventObject#preventDefault
* @type {Function}
*/ /**
* The event target.
* @name Highcharts.ChartAddSeriesEventObject#target
* @type {Highcharts.Chart}
*/ /**
* The event type.
* @name Highcharts.ChartAddSeriesEventObject#type
* @type {"addSeries"}
*/
/**
 * Gets fired when clicking on the plot background.
 *
 * @callback Highcharts.ChartClickCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {Highcharts.PointerEventObject} event
 *        The event that occurred.
 */
/**
 * Contains an axes of the clicked spot.
 *
 * @interface Highcharts.ChartClickEventAxisObject
 */ /**
* Axis at the clicked spot.
* @name Highcharts.ChartClickEventAxisObject#axis
* @type {Highcharts.Axis}
*/ /**
* Axis value at the clicked spot.
* @name Highcharts.ChartClickEventAxisObject#value
* @type {number}
*/
/**
 * Contains information about the clicked spot on the chart. Remember the unit
 * of a datetime axis is milliseconds since 1970-01-01 00:00:00.
 *
 * @interface Highcharts.ChartClickEventObject
 * @extends Highcharts.PointerEventObject
 */ /**
* Information about the x-axis on the clicked spot.
* @name Highcharts.ChartClickEventObject#xAxis
* @type {Array<Highcharts.ChartClickEventAxisObject>}
*/ /**
* Information about the y-axis on the clicked spot.
* @name Highcharts.ChartClickEventObject#yAxis
* @type {Array<Highcharts.ChartClickEventAxisObject>}
*/ /**
* Information about the z-axis on the clicked spot.
* @name Highcharts.ChartClickEventObject#zAxis
* @type {Array<Highcharts.ChartClickEventAxisObject>|undefined}
*/
/**
 * Gets fired when the chart is finished loading.
 *
 * @callback Highcharts.ChartLoadCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {global.Event} event
 *        The event that occurred.
 */
/**
 * Fires when the chart is redrawn, either after a call to `chart.redraw()` or
 * after an axis, series or point is modified with the `redraw` option set to
 * `true`.
 *
 * @callback Highcharts.ChartRedrawCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {global.Event} event
 *        The event that occurred.
 */
/**
 * Gets fired after initial load of the chart (directly after the `load` event),
 * and after each redraw (directly after the `redraw` event).
 *
 * @callback Highcharts.ChartRenderCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {global.Event} event
 *        The event that occurred.
 */
/**
 * Gets fired when an area of the chart has been selected. The default action
 * for the selection event is to zoom the chart to the selected area. It can be
 * prevented by calling `event.preventDefault()` or return false.
 *
 * @callback Highcharts.ChartSelectionCallbackFunction
 *
 * @param {Highcharts.Chart} this
 *        The chart on which the event occurred.
 *
 * @param {Highcharts.SelectEventObject} event
 *        Event informations
 *
 * @return {boolean|undefined}
 *         Return false to prevent the default action, usually zoom.
 */
(''); // Detach doclets above

;// ./code/es5/es-modules/Core/Color/Color.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var Color_isNumber = Core_Utilities.isNumber, Color_merge = Core_Utilities.merge, Color_pInt = Core_Utilities.pInt, Color_defined = Core_Utilities.defined;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable valid-jsdoc */
/**
 * Handle color operations. Some object methods are chainable.
 *
 * @class
 * @name Highcharts.Color
 *
 * @param {Highcharts.ColorType} input
 * The input color in either rgba or hex format
 */
var Color = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function Color(input) {
        this.rgba = [NaN, NaN, NaN, NaN];
        this.input = input;
        var GlobalColor = Core_Globals.Color;
        // Backwards compatibility, allow class overwrite
        if (GlobalColor && GlobalColor !== Color) {
            return new GlobalColor(input);
        }
        var result,
            rgba,
            i,
            parser;
        // Gradients
        if (typeof input === 'object' &&
            typeof input.stops !== 'undefined') {
            this.stops = input.stops.map(function (stop) { return new Color(stop[1]); });
            // Solid colors
        }
        else if (typeof input === 'string') {
            this.input = input = (Color.names[input.toLowerCase()] || input);
            i = Color.parsers.length;
            while (i-- && !rgba) {
                parser = Color.parsers[i];
                result = parser.regex.exec(input);
                if (result) {
                    rgba = parser.parse(result);
                }
            }
        }
        if (rgba) {
            this.rgba = rgba;
        }
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * Creates a color instance out of a color string or object.
     *
     * @function Highcharts.Color.parse
     *
     * @param {Highcharts.ColorType} [input]
     * The input color in either rgba or hex format.
     *
     * @return {Highcharts.Color}
     * Color instance.
     */
    Color.parse = function (input) {
        return input ? new Color(input) : Color.None;
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Return the color or gradient stops in the specified format
     *
     * @function Highcharts.Color#get
     *
     * @param {string} [format]
     * Possible values are 'a', 'rgb', 'rgba' (default).
     *
     * @return {Highcharts.ColorType}
     * This color as a string or gradient stops.
     */
    Color.prototype.get = function (format) {
        var input = this.input,
            rgba = this.rgba;
        if (typeof input === 'object' &&
            typeof this.stops !== 'undefined') {
            var ret_1 = Color_merge(input);
            ret_1.stops = [].slice.call(ret_1.stops);
            this.stops.forEach(function (stop, i) {
                ret_1.stops[i] = [
                    ret_1.stops[i][0],
                    stop.get(format)
                ];
            });
            return ret_1;
        }
        // It's NaN if gradient colors on a column chart
        if (rgba && Color_isNumber(rgba[0])) {
            if (format === 'rgb' || (!format && rgba[3] === 1)) {
                return 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')';
            }
            if (format === 'a') {
                return "".concat(rgba[3]);
            }
            return 'rgba(' + rgba.join(',') + ')';
        }
        return input;
    };
    /**
     * Brighten the color instance.
     *
     * @function Highcharts.Color#brighten
     *
     * @param {number} alpha
     * The alpha value.
     *
     * @return {Highcharts.Color}
     * This color with modifications.
     */
    Color.prototype.brighten = function (alpha) {
        var rgba = this.rgba;
        if (this.stops) {
            this.stops.forEach(function (stop) {
                stop.brighten(alpha);
            });
        }
        else if (Color_isNumber(alpha) && alpha !== 0) {
            for (var i = 0; i < 3; i++) {
                rgba[i] += Color_pInt(alpha * 255);
                if (rgba[i] < 0) {
                    rgba[i] = 0;
                }
                if (rgba[i] > 255) {
                    rgba[i] = 255;
                }
            }
        }
        return this;
    };
    /**
     * Set the color's opacity to a given alpha value.
     *
     * @function Highcharts.Color#setOpacity
     *
     * @param {number} alpha
     *        Opacity between 0 and 1.
     *
     * @return {Highcharts.Color}
     *         Color with modifications.
     */
    Color.prototype.setOpacity = function (alpha) {
        this.rgba[3] = alpha;
        return this;
    };
    /**
     * Return an intermediate color between two colors.
     *
     * @function Highcharts.Color#tweenTo
     *
     * @param {Highcharts.Color} to
     * The color object to tween to.
     *
     * @param {number} pos
     * The intermediate position, where 0 is the from color (current color
     * item), and 1 is the `to` color.
     *
     * @return {Highcharts.ColorType}
     * The intermediate color in rgba notation, or unsupported type.
     */
    Color.prototype.tweenTo = function (to, pos) {
        var fromRgba = this.rgba,
            toRgba = to.rgba;
        // Unsupported color, return to-color (#3920, #7034)
        if (!Color_isNumber(fromRgba[0]) || !Color_isNumber(toRgba[0])) {
            return to.input || 'none';
        }
        // Check for has alpha, because rgba colors perform worse due to
        // lack of support in WebKit.
        var hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1),
            channel = function (to,
            i) {
                return to + (fromRgba[i] - to) * (1 - pos);
        }, rgba = toRgba.slice(0, 3).map(channel).map(Math.round);
        if (hasAlpha) {
            rgba.push(channel(toRgba[3], 3));
        }
        return (hasAlpha ? 'rgba(' : 'rgb(') + rgba.join(',') + ')';
    };
    /* *
     *
     *  Static Properties
     *
     * */
    /**
     * Collection of named colors. Can be extended from the outside by adding
     * colors to Highcharts.Color.names.
     * @private
     */
    Color.names = {
        white: '#ffffff',
        black: '#000000'
    };
    /**
     * Collection of parsers. This can be extended from the outside by pushing
     * parsers to `Color.parsers`.
     * @private
     */
    Color.parsers = [{
            // RGBA color
            // eslint-disable-next-line max-len
            regex: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d?(?:\.\d+)?)\s*\)/,
            parse: function (result) {
                return [
                    Color_pInt(result[1]),
                    Color_pInt(result[2]),
                    Color_pInt(result[3]),
                    parseFloat(result[4], 10)
                ];
            }
        }, {
            // RGB color
            regex: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/,
            parse: function (result) {
                return [Color_pInt(result[1]), Color_pInt(result[2]), Color_pInt(result[3]), 1];
            }
        }, {
            // RGBA 3 & 4 digit hex color, e.g. #F0F, #F0FA
            regex: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?$/i,
            parse: function (result) {
                // #abcd => #aabbccdd, hence result + result.
                return [
                    (Color_pInt(result[1] + result[1], 16)),
                    (Color_pInt(result[2] + result[2], 16)),
                    (Color_pInt(result[3] + result[3], 16)),
                    !Color_defined(result[4]) ?
                        1 :
                        (Color_pInt(result[4] + result[4], 16) / 255)
                ];
            }
        }, {
            // RGBA 6 & 8 digit hex color, e.g. #FFCC00, #FFCC00FF
            regex: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i,
            parse: function (result) {
                return [
                    Color_pInt(result[1], 16),
                    Color_pInt(result[2], 16),
                    Color_pInt(result[3], 16),
                    !Color_defined(result[4]) ?
                        1 :
                        (Color_pInt(result[4], 16) / 255)
                ];
            }
        }];
    // Must be last static member for init cycle
    Color.None = new Color('');
    return Color;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Color_Color = (Color);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * A valid color to be parsed and handled by Highcharts. Highcharts internally
 * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and
 * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the
 * browsers and displayed correctly, but Highcharts is not able to process them
 * and apply concepts like opacity and brightening.
 *
 * @typedef {string} Highcharts.ColorString
 */
/**
 * A valid color type than can be parsed and handled by Highcharts. It can be a
 * color string, a gradient object, or a pattern object.
 *
 * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType
 */
/**
 * Gradient options instead of a solid color.
 *
 * @example
 * // Linear gradient used as a color option
 * color: {
 *     linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 },
 *     stops: [
 *         [0, '#003399'], // start
 *         [0.5, '#ffffff'], // middle
 *         [1, '#3366AA'] // end
 *     ]
 * }
 *
 * @interface Highcharts.GradientColorObject
 */ /**
* Holds an object that defines the start position and the end position relative
* to the shape.
* @name Highcharts.GradientColorObject#linearGradient
* @type {Highcharts.LinearGradientColorObject|undefined}
*/ /**
* Holds an object that defines the center position and the radius.
* @name Highcharts.GradientColorObject#radialGradient
* @type {Highcharts.RadialGradientColorObject|undefined}
*/ /**
* The first item in each tuple is the position in the gradient, where 0 is the
* start of the gradient and 1 is the end of the gradient. Multiple stops can be
* applied. The second item is the color for each stop. This color can also be
* given in the rgba format.
* @name Highcharts.GradientColorObject#stops
* @type {Array<Highcharts.GradientColorStopObject>}
*/
/**
 * Color stop tuple.
 *
 * @see Highcharts.GradientColorObject
 *
 * @interface Highcharts.GradientColorStopObject
 */ /**
* @name Highcharts.GradientColorStopObject#0
* @type {number}
*/ /**
* @name Highcharts.GradientColorStopObject#1
* @type {Highcharts.ColorString}
*/ /**
* @name Highcharts.GradientColorStopObject#color
* @type {Highcharts.Color|undefined}
*/
/**
 * Defines the start position and the end position for a gradient relative
 * to the shape. Start position (x1, y1) and end position (x2, y2) are relative
 * to the shape, where 0 means top/left and 1 is bottom/right.
 *
 * @interface Highcharts.LinearGradientColorObject
 */ /**
* Start horizontal position of the gradient. Float ranges 0-1.
* @name Highcharts.LinearGradientColorObject#x1
* @type {number}
*/ /**
* End horizontal position of the gradient. Float ranges 0-1.
* @name Highcharts.LinearGradientColorObject#x2
* @type {number}
*/ /**
* Start vertical position of the gradient. Float ranges 0-1.
* @name Highcharts.LinearGradientColorObject#y1
* @type {number}
*/ /**
* End vertical position of the gradient. Float ranges 0-1.
* @name Highcharts.LinearGradientColorObject#y2
* @type {number}
*/
/**
 * Defines the center position and the radius for a gradient.
 *
 * @interface Highcharts.RadialGradientColorObject
 */ /**
* Center horizontal position relative to the shape. Float ranges 0-1.
* @name Highcharts.RadialGradientColorObject#cx
* @type {number}
*/ /**
* Center vertical position relative to the shape. Float ranges 0-1.
* @name Highcharts.RadialGradientColorObject#cy
* @type {number}
*/ /**
* Radius relative to the shape. Float ranges 0-1.
* @name Highcharts.RadialGradientColorObject#r
* @type {number}
*/
/**
 * Creates a color instance out of a color string.
 *
 * @function Highcharts.color
 *
 * @param {Highcharts.ColorType} input
 *        The input color in either rgba or hex format
 *
 * @return {Highcharts.Color}
 *         Color instance
 */
(''); // Detach doclets above

;// ./code/es5/es-modules/Core/Animation/Fx.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var color = Color_Color.parse;

var Fx_win = Core_Globals.win;

var Fx_isNumber = Core_Utilities.isNumber, Fx_objectEach = Core_Utilities.objectEach;
/* eslint-disable no-invalid-this, valid-jsdoc */
/* *
 *
 *  Class
 *
 * */
/**
 * An animator object used internally. One instance applies to one property
 * (attribute or style prop) on one element. Animation is always initiated
 * through {@link SVGElement#animate}.
 *
 * @example
 * let rect = renderer.rect(0, 0, 10, 10).add();
 * rect.animate({ width: 100 });
 *
 * @private
 * @class
 * @name Highcharts.Fx
 *
 * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem
 * The element to animate.
 *
 * @param {Partial<Highcharts.AnimationOptionsObject>} options
 * Animation options.
 *
 * @param {string} prop
 * The single attribute or CSS property to animate.
 */
var Fx = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Fx(elem, options, prop) {
        this.pos = NaN;
        this.options = options;
        this.elem = elem;
        this.prop = prop;
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Set the current step of a path definition on SVGElement.
     *
     * @function Highcharts.Fx#dSetter
     *
     */
    Fx.prototype.dSetter = function () {
        var paths = this.paths,
            start = paths && paths[0],
            end = paths && paths[1],
            now = this.now || 0;
        var path = [];
        // Land on the final path without adjustment points appended in the ends
        if (now === 1 || !start || !end) {
            path = this.toD || [];
        }
        else if (start.length === end.length && now < 1) {
            for (var i = 0; i < end.length; i++) {
                // Tween between the start segment and the end segment. Start
                // with a copy of the end segment and tween the appropriate
                // numerics
                var startSeg = start[i];
                var endSeg = end[i];
                var tweenSeg = [];
                for (var j = 0; j < endSeg.length; j++) {
                    var startItem = startSeg[j];
                    var endItem = endSeg[j];
                    // Tween numbers
                    if (Fx_isNumber(startItem) &&
                        Fx_isNumber(endItem) &&
                        // Arc boolean flags
                        !(endSeg[0] === 'A' && (j === 4 || j === 5))) {
                        tweenSeg[j] = startItem + now * (endItem - startItem);
                        // Strings, take directly from the end segment
                    }
                    else {
                        tweenSeg[j] = endItem;
                    }
                }
                path.push(tweenSeg);
            }
            // If animation is finished or length not matching, land on right value
        }
        else {
            path = end;
        }
        this.elem.attr('d', path, void 0, true);
    };
    /**
     * Update the element with the current animation step.
     *
     * @function Highcharts.Fx#update
     *
     */
    Fx.prototype.update = function () {
        var elem = this.elem,
            prop = this.prop, // If destroyed, it is null
            now = this.now,
            step = this.options.step;
        // Animation setter defined from outside
        if (this[prop + 'Setter']) {
            this[prop + 'Setter']();
            // Other animations on SVGElement
        }
        else if (elem.attr) {
            if (elem.element) {
                elem.attr(prop, now, null, true);
            }
            // HTML styles, raw HTML content like container size
        }
        else {
            elem.style[prop] = now + this.unit;
        }
        if (step) {
            step.call(elem, now, this);
        }
    };
    /**
     * Run an animation.
     *
     * @function Highcharts.Fx#run
     *
     * @param {number} from
     *        The current value, value to start from.
     *
     * @param {number} to
     *        The end value, value to land on.
     *
     * @param {string} unit
     *        The property unit, for example `px`.
     *
     */
    Fx.prototype.run = function (from, to, unit) {
        var self = this,
            options = self.options,
            timer = function (gotoEnd) {
                return timer.stopped ? false : self.step(gotoEnd);
        }, requestAnimationFrame = Fx_win.requestAnimationFrame ||
            function (step) {
                setTimeout(step, 13);
            }, step = function () {
            for (var i = 0; i < Fx.timers.length; i++) {
                if (!Fx.timers[i]()) {
                    Fx.timers.splice(i--, 1);
                }
            }
            if (Fx.timers.length) {
                requestAnimationFrame(step);
            }
        };
        if (from === to && !this.elem['forceAnimate:' + this.prop]) {
            delete options.curAnim[this.prop];
            if (options.complete &&
                Object.keys(options.curAnim).length === 0) {
                options.complete.call(this.elem);
            }
        }
        else { // #7166
            this.startTime = +new Date();
            this.start = from;
            this.end = to;
            this.unit = unit;
            this.now = this.start;
            this.pos = 0;
            timer.elem = this.elem;
            timer.prop = this.prop;
            if (timer() && Fx.timers.push(timer) === 1) {
                requestAnimationFrame(step);
            }
        }
    };
    /**
     * Run a single step in the animation.
     *
     * @function Highcharts.Fx#step
     *
     * @param {boolean} [gotoEnd]
     *        Whether to go to the endpoint of the animation after abort.
     *
     * @return {boolean}
     *         Returns `true` if animation continues.
     */
    Fx.prototype.step = function (gotoEnd) {
        var t = +new Date(),
            options = this.options,
            elem = this.elem,
            complete = options.complete,
            duration = options.duration,
            curAnim = options.curAnim;
        var ret,
            done;
        if (!!elem.attr && !elem.element) { // #2616, element is destroyed
            ret = false;
        }
        else if (gotoEnd || t >= duration + this.startTime) {
            this.now = this.end;
            this.pos = 1;
            this.update();
            curAnim[this.prop] = true;
            done = true;
            Fx_objectEach(curAnim, function (val) {
                if (val !== true) {
                    done = false;
                }
            });
            if (done && complete) {
                complete.call(elem);
            }
            ret = false;
        }
        else {
            this.pos = options.easing((t - this.startTime) / duration);
            this.now = this.start + ((this.end -
                this.start) * this.pos);
            this.update();
            ret = true;
        }
        return ret;
    };
    /**
     * Prepare start and end values so that the path can be animated one to one.
     *
     * @function Highcharts.Fx#initPath
     *
     * @param {Highcharts.SVGElement} elem
     *        The SVGElement item.
     *
     * @param {Highcharts.SVGPathArray|undefined} fromD
     *        Starting path definition.
     *
     * @param {Highcharts.SVGPathArray} toD
     *        Ending path definition.
     *
     * @return {Array<Highcharts.SVGPathArray,Highcharts.SVGPathArray>}
     *         An array containing start and end paths in array form so that
     *         they can be animated in parallel.
     */
    Fx.prototype.initPath = function (elem, fromD, toD) {
        var startX = elem.startX,
            endX = elem.endX,
            end = toD.slice(), // Copy
            isArea = elem.isArea,
            positionFactor = isArea ? 2 : 1,
            disableAnimation = fromD &&
                toD.length > fromD.length &&
                toD.hasStackedCliffs; // #16925
            var shift,
            fullLength,
            i,
            reverse,
            start = fromD && fromD.slice(); // Copy
            if (!start || disableAnimation) {
                return [end,
            end];
        }
        /**
         * If shifting points, prepend a dummy point to the end path.
         * @private
         */
        function prepend(arr, other) {
            while (arr.length < fullLength) {
                // Move to, line to or curve to?
                var moveSegment = arr[0],
                    otherSegment = other[fullLength - arr.length];
                if (otherSegment && moveSegment[0] === 'M') {
                    if (otherSegment[0] === 'C') {
                        arr[0] = [
                            'C',
                            moveSegment[1],
                            moveSegment[2],
                            moveSegment[1],
                            moveSegment[2],
                            moveSegment[1],
                            moveSegment[2]
                        ];
                    }
                    else {
                        arr[0] = ['L', moveSegment[1], moveSegment[2]];
                    }
                }
                // Prepend a copy of the first point
                arr.unshift(moveSegment);
                // For areas, the bottom path goes back again to the left, so we
                // need to append a copy of the last point.
                if (isArea) {
                    var z = arr.pop();
                    arr.push(arr[arr.length - 1], z); // Append point and the Z
                }
            }
        }
        /**
         * Copy and append last point until the length matches the end length.
         * @private
         */
        function append(arr) {
            while (arr.length < fullLength) {
                // Pull out the slice that is going to be appended or inserted.
                // In a line graph, the positionFactor is 1, and the last point
                // is sliced out. In an area graph, the positionFactor is 2,
                // causing the middle two points to be sliced out, since an area
                // path starts at left, follows the upper path then turns and
                // follows the bottom back.
                var segmentToAdd = arr[Math.floor(arr.length / positionFactor) - 1].slice();
                // Disable the first control point of curve segments
                if (segmentToAdd[0] === 'C') {
                    segmentToAdd[1] = segmentToAdd[5];
                    segmentToAdd[2] = segmentToAdd[6];
                }
                if (!isArea) {
                    arr.push(segmentToAdd);
                }
                else {
                    var lowerSegmentToAdd = arr[Math.floor(arr.length / positionFactor)].slice();
                    arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd);
                }
            }
        }
        // For sideways animation, find out how much we need to shift to get the
        // start path Xs to match the end path Xs.
        if (startX && endX && endX.length) {
            for (i = 0; i < startX.length; i++) {
                // Moving left, new points coming in on right
                if (startX[i] === endX[0]) {
                    shift = i;
                    break;
                    // Moving right
                }
                else if (startX[0] ===
                    endX[endX.length - startX.length + i]) {
                    shift = i;
                    reverse = true;
                    break;
                    // Fixed from the right side, "scaling" left
                }
                else if (startX[startX.length - 1] ===
                    endX[endX.length - startX.length + i]) {
                    shift = startX.length - i;
                    break;
                }
            }
            if (typeof shift === 'undefined') {
                start = [];
            }
        }
        if (start.length && Fx_isNumber(shift)) {
            // The common target length for the start and end array, where both
            // arrays are padded in opposite ends
            fullLength = end.length + shift * positionFactor;
            if (!reverse) {
                prepend(end, start);
                append(start);
            }
            else {
                prepend(start, end);
                append(end);
            }
        }
        return [start, end];
    };
    /**
     * Handle animation of the color attributes directly.
     *
     * @function Highcharts.Fx#fillSetter
     *
     */
    Fx.prototype.fillSetter = function () {
        Fx.prototype.strokeSetter.apply(this, arguments);
    };
    /**
     * Handle animation of the color attributes directly.
     *
     * @function Highcharts.Fx#strokeSetter
     *
     */
    Fx.prototype.strokeSetter = function () {
        this.elem.attr(this.prop, color(this.start).tweenTo(color(this.end), this.pos), void 0, true);
    };
    /* *
     *
     *  Static Properties
     *
     * */
    Fx.timers = [];
    return Fx;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Animation_Fx = (Fx);

;// ./code/es5/es-modules/Core/Animation/AnimationUtilities.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var AnimationUtilities_defined = Core_Utilities.defined, AnimationUtilities_getStyle = Core_Utilities.getStyle, AnimationUtilities_isArray = Core_Utilities.isArray, AnimationUtilities_isNumber = Core_Utilities.isNumber, AnimationUtilities_isObject = Core_Utilities.isObject, AnimationUtilities_merge = Core_Utilities.merge, AnimationUtilities_objectEach = Core_Utilities.objectEach, AnimationUtilities_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/**
 * Set the global animation to either a given value, or fall back to the given
 * chart's animation option.
 *
 * @function Highcharts.setAnimation
 *
 * @param {boolean|Partial<Highcharts.AnimationOptionsObject>|undefined} animation
 *        The animation object.
 *
 * @param {Highcharts.Chart} chart
 *        The chart instance.
 *
 * @todo
 * This function always relates to a chart, and sets a property on the renderer,
 * so it should be moved to the SVGRenderer.
 */
function setAnimation(animation, chart) {
    chart.renderer.globalAnimation = AnimationUtilities_pick(animation, chart.options.chart.animation, true);
}
/**
 * Get the animation in object form, where a disabled animation is always
 * returned as `{ duration: 0 }`.
 *
 * @function Highcharts.animObject
 *
 * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0]
 *        An animation setting. Can be an object with duration, complete and
 *        easing properties, or a boolean to enable or disable.
 *
 * @return {Highcharts.AnimationOptionsObject}
 *         An object with at least a duration property.
 */
function animObject(animation) {
    return AnimationUtilities_isObject(animation) ?
        AnimationUtilities_merge({ duration: 500, defer: 0 }, animation) :
        { duration: animation ? 500 : 0, defer: 0 };
}
/**
 * Get the defer as a number value from series animation options.
 *
 * @function Highcharts.getDeferredAnimation
 *
 * @param {Highcharts.Chart} chart
 *        The chart instance.
 *
 * @param {boolean|Highcharts.AnimationOptionsObject} animation
 *        An animation setting. Can be an object with duration, complete and
 *        easing properties, or a boolean to enable or disable.
 *
 * @param {Highcharts.Series} [series]
 *        Series to defer animation.
 *
 * @return {number}
 *        The numeric value.
 */
function getDeferredAnimation(chart, animation, series) {
    var labelAnimation = animObject(animation),
        s = series ? [series] : chart.series;
    var defer = 0,
        duration = 0;
    s.forEach(function (series) {
        var seriesAnim = animObject(series.options.animation);
        defer = AnimationUtilities_isObject(animation) && AnimationUtilities_defined(animation.defer) ?
            labelAnimation.defer :
            Math.max(defer, seriesAnim.duration + seriesAnim.defer);
        duration = Math.min(labelAnimation.duration, seriesAnim.duration);
    });
    // Disable defer for exporting
    if (chart.renderer.forExport) {
        defer = 0;
    }
    var anim = {
            defer: Math.max(0,
        defer - duration),
            duration: Math.min(defer,
        duration)
        };
    return anim;
}
/**
 * The global animate method, which uses Fx to create individual animators.
 *
 * @function Highcharts.animate
 *
 * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el
 *        The element to animate.
 *
 * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params
 *        An object containing key-value pairs of the properties to animate.
 *        Supports numeric as pixel-based CSS properties for HTML objects and
 *        attributes for SVGElements.
 *
 * @param {Partial<Highcharts.AnimationOptionsObject>} [opt]
 *        Animation options.
 *
 * @return {void}
 */
function animate(el, params, opt) {
    var start,
        unit = '',
        end,
        fx,
        args;
    if (!AnimationUtilities_isObject(opt)) { // Number or undefined/null
        args = arguments;
        opt = {
            duration: args[2],
            easing: args[3],
            complete: args[4]
        };
    }
    if (!AnimationUtilities_isNumber(opt.duration)) {
        opt.duration = 400;
    }
    opt.easing = typeof opt.easing === 'function' ?
        opt.easing :
        (Math[opt.easing] || Math.easeInOutSine);
    opt.curAnim = AnimationUtilities_merge(params);
    AnimationUtilities_objectEach(params, function (val, prop) {
        // Stop current running animation of this property
        stop(el, prop);
        fx = new Animation_Fx(el, opt, prop);
        end = void 0;
        if (prop === 'd' && AnimationUtilities_isArray(params.d)) {
            fx.paths = fx.initPath(el, el.pathArray, params.d);
            fx.toD = params.d;
            start = 0;
            end = 1;
        }
        else if (el.attr) {
            start = el.attr(prop);
        }
        else {
            start = parseFloat(AnimationUtilities_getStyle(el, prop)) || 0;
            if (prop !== 'opacity') {
                unit = 'px';
            }
        }
        if (!end) {
            end = val;
        }
        if (typeof end === 'string' && end.match('px')) {
            end = end.replace(/px/g, ''); // #4351
        }
        fx.run(start, end, unit);
    });
}
/**
 * Stop running animation.
 *
 * @function Highcharts.stop
 *
 * @param {Highcharts.SVGElement} el
 *        The SVGElement to stop animation on.
 *
 * @param {string} [prop]
 *        The property to stop animating. If given, the stop method will stop a
 *        single property from animating, while others continue.
 *
 * @return {void}
 *
 * @todo
 * A possible extension to this would be to stop a single property, when
 * we want to continue animating others. Then assign the prop to the timer
 * in the Fx.run method, and check for the prop here. This would be an
 * improvement in all cases where we stop the animation from .attr. Instead of
 * stopping everything, we can just stop the actual attributes we're setting.
 */
function stop(el, prop) {
    var i = Animation_Fx.timers.length;
    // Remove timers related to this element (#4519)
    while (i--) {
        if (Animation_Fx.timers[i].elem === el && (!prop || prop === Animation_Fx.timers[i].prop)) {
            Animation_Fx.timers[i].stopped = true; // #4667
        }
    }
}
var animationExports = {
    animate: animate,
    animObject: animObject,
    getDeferredAnimation: getDeferredAnimation,
    setAnimation: setAnimation,
    stop: stop
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var AnimationUtilities = (animationExports);

;// ./code/es5/es-modules/Core/Renderer/HTML/AST.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var SVG_NS = Core_Globals.SVG_NS, AST_win = Core_Globals.win;

var AST_attr = Core_Utilities.attr, AST_createElement = Core_Utilities.createElement, AST_css = Core_Utilities.css, AST_error = Core_Utilities.error, AST_isFunction = Core_Utilities.isFunction, AST_isString = Core_Utilities.isString, AST_objectEach = Core_Utilities.objectEach, AST_splat = Core_Utilities.splat;
var trustedTypes = AST_win.trustedTypes;
/* *
 *
 *  Constants
 *
 * */
// Create the trusted type policy. This should not be exposed.
var trustedTypesPolicy = (trustedTypes &&
    AST_isFunction(trustedTypes.createPolicy) &&
    trustedTypes.createPolicy('highcharts', {
        createHTML: function (s) { return s; }
    }));
var emptyHTML = trustedTypesPolicy ?
    trustedTypesPolicy.createHTML('') :
    '';
/* *
 *
 *  Class
 *
 * */
/**
 * The AST class represents an abstract syntax tree of HTML or SVG content. It
 * can take HTML as an argument, parse it, optionally transform it to SVG, then
 * perform sanitation before inserting it into the DOM.
 *
 * @class
 * @name Highcharts.AST
 *
 * @param {string|Array<Highcharts.ASTNode>} source
 * Either an HTML string or an ASTNode list to populate the tree.
 */
var AST = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    // Construct an AST from HTML markup, or wrap an array of existing AST nodes
    function AST(source) {
        this.nodes = typeof source === 'string' ?
            this.parseMarkup(source) : source;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * Filter an object of SVG or HTML attributes against the allow list.
     *
     * @static
     *
     * @function Highcharts.AST#filterUserAttributes
     *
     * @param {Highcharts.SVGAttributes} attributes The attributes to filter
     *
     * @return {Highcharts.SVGAttributes}
     * The filtered attributes
     */
    AST.filterUserAttributes = function (attributes) {
        AST_objectEach(attributes, function (val, key) {
            var valid = true;
            if (AST.allowedAttributes.indexOf(key) === -1) {
                valid = false;
            }
            if (['background', 'dynsrc', 'href', 'lowsrc', 'src']
                .indexOf(key) !== -1) {
                valid = AST_isString(val) && AST.allowedReferences.some(function (ref) { return val.indexOf(ref) === 0; });
            }
            if (!valid) {
                AST_error(33, false, void 0, {
                    'Invalid attribute in config': "".concat(key)
                });
                delete attributes[key];
            }
            // #17753, < is not allowed in SVG attributes
            if (AST_isString(val) && attributes[key]) {
                attributes[key] = val.replace(/</g, '&lt;');
            }
        });
        return attributes;
    };
    AST.parseStyle = function (style) {
        return style
            .split(';')
            .reduce(function (styles, line) {
            var pair = line.split(':').map(function (s) { return s.trim(); }),
                key = pair.shift();
            if (key && pair.length) {
                styles[key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); })] = pair.join(':'); // #17146
            }
            return styles;
        }, {});
    };
    /**
     * Utility function to set html content for an element by passing in a
     * markup string. The markup is safely parsed by the AST class to avoid
     * XSS vulnerabilities. This function should be used instead of setting
     * `innerHTML` in all cases where the content is not fully trusted.
     *
     * @static
     * @function Highcharts.AST#setElementHTML
     *
     * @param {SVGDOMElement|HTMLDOMElement} el
     * Node to set content of.
     *
     * @param {string} html
     * Markup string
     */
    AST.setElementHTML = function (el, html) {
        el.innerHTML = AST.emptyHTML; // Clear previous
        if (html) {
            var ast = new AST(html);
            ast.addToDOM(el);
        }
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Add the tree defined as a hierarchical JS structure to the DOM
     *
     * @function Highcharts.AST#addToDOM
     *
     * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} parent
     * The node where it should be added
     *
     * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement}
     * The inserted node.
     */
    AST.prototype.addToDOM = function (parent) {
        /**
         * @private
         * @param {Highcharts.ASTNode} subtree
         * HTML/SVG definition
         * @param {Element} [subParent]
         * parent node
         * @return {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement}
         * The inserted node.
         */
        function recurse(subtree, subParent) {
            var ret;
            AST_splat(subtree).forEach(function (item) {
                var tagName = item.tagName;
                var textNode = item.textContent ?
                        Core_Globals.doc.createTextNode(item.textContent) :
                        void 0;
                // Whether to ignore the AST filtering totally, #15345
                var bypassHTMLFiltering = AST.bypassHTMLFiltering;
                var node;
                if (tagName) {
                    if (tagName === '#text') {
                        node = textNode;
                    }
                    else if (AST.allowedTags.indexOf(tagName) !== -1 ||
                        bypassHTMLFiltering) {
                        var NS = tagName === 'svg' ?
                                SVG_NS :
                                (subParent.namespaceURI || SVG_NS);
                        var element = Core_Globals.doc.createElementNS(NS,
                            tagName);
                        var attributes_1 = item.attributes || {};
                        // Apply attributes from root of AST node, legacy from
                        // from before TextBuilder
                        AST_objectEach(item, function (val, key) {
                            if (key !== 'tagName' &&
                                key !== 'attributes' &&
                                key !== 'children' &&
                                key !== 'style' &&
                                key !== 'textContent') {
                                attributes_1[key] = val;
                            }
                        });
                        AST_attr(element, bypassHTMLFiltering ?
                            attributes_1 :
                            AST.filterUserAttributes(attributes_1));
                        if (item.style) {
                            AST_css(element, item.style);
                        }
                        // Add text content
                        if (textNode) {
                            element.appendChild(textNode);
                        }
                        // Recurse
                        recurse(item.children || [], element);
                        node = element;
                    }
                    else {
                        AST_error(33, false, void 0, {
                            'Invalid tagName in config': tagName
                        });
                    }
                }
                // Add to the tree
                if (node) {
                    subParent.appendChild(node);
                }
                ret = node;
            });
            // Return last node added (on top level it's the only one)
            return ret;
        }
        return recurse(this.nodes, parent);
    };
    /**
     * Parse HTML/SVG markup into AST Node objects. Used internally from the
     * constructor.
     *
     * @private
     *
     * @function Highcharts.AST#getNodesFromMarkup
     *
     * @param {string} markup The markup string.
     *
     * @return {Array<Highcharts.ASTNode>} The parsed nodes.
     */
    AST.prototype.parseMarkup = function (markup) {
        var nodes = [];
        markup = markup
            .trim()
            // The style attribute throws a warning when parsing when CSP is
            // enabled (#6884), so use an alias and pick it up below
            // Make all quotation marks parse correctly to DOM (#17627)
            .replace(/ style=(["'])/g, ' data-style=$1');
        var doc;
        try {
            doc = new DOMParser().parseFromString(trustedTypesPolicy ?
                trustedTypesPolicy.createHTML(markup) :
                markup, 'text/html');
        }
        catch (e) {
            // There are two cases where this fails:
            // 1. IE9 and PhantomJS, where the DOMParser only supports parsing
            //    XML
            // 2. Due to a Chromium issue where chart redraws are triggered by
            //    a `beforeprint` event (#16931),
            //    https://issues.chromium.org/issues/40222135
        }
        if (!doc) {
            var body = AST_createElement('div');
            body.innerHTML = markup;
            doc = { body: body };
        }
        var appendChildNodes = function (node,
            addTo) {
                var tagName = node.nodeName.toLowerCase();
            // Add allowed tags
            var astNode = {
                    tagName: tagName
                };
            if (tagName === '#text') {
                astNode.textContent = node.textContent || '';
            }
            var parsedAttributes = node.attributes;
            // Add attributes
            if (parsedAttributes) {
                var attributes_2 = {};
                [].forEach.call(parsedAttributes, function (attrib) {
                    if (attrib.name === 'data-style') {
                        astNode.style = AST.parseStyle(attrib.value);
                    }
                    else {
                        attributes_2[attrib.name] = attrib.value;
                    }
                });
                astNode.attributes = attributes_2;
            }
            // Handle children
            if (node.childNodes.length) {
                var children_1 = [];
                [].forEach.call(node.childNodes, function (childNode) {
                    appendChildNodes(childNode, children_1);
                });
                if (children_1.length) {
                    astNode.children = children_1;
                }
            }
            addTo.push(astNode);
        };
        [].forEach.call(doc.body.childNodes, function (childNode) { return appendChildNodes(childNode, nodes); });
        return nodes;
    };
    /* *
     *
     *  Static Properties
     *
     * */
    /**
     * The list of allowed SVG or HTML attributes, used for sanitizing
     * potentially harmful content from the chart configuration before adding to
     * the DOM.
     *
     * @see [Source code with default values](
     * https://github.com/highcharts/highcharts/blob/master/ts/Core/Renderer/HTML/AST.ts#:~:text=public%20static%20allowedAttributes)
     *
     * @example
     * // Allow a custom, trusted attribute
     * Highcharts.AST.allowedAttributes.push('data-value');
     *
     * @name Highcharts.AST.allowedAttributes
     * @type {Array<string>}
     */
    AST.allowedAttributes = [
        'alt',
        'aria-controls',
        'aria-describedby',
        'aria-expanded',
        'aria-haspopup',
        'aria-hidden',
        'aria-label',
        'aria-labelledby',
        'aria-live',
        'aria-pressed',
        'aria-readonly',
        'aria-roledescription',
        'aria-selected',
        'class',
        'clip-path',
        'color',
        'colspan',
        'cx',
        'cy',
        'd',
        'dx',
        'dy',
        'disabled',
        'fill',
        'filterUnits',
        'flood-color',
        'flood-opacity',
        'height',
        'href',
        'id',
        'in',
        'in2',
        'markerHeight',
        'markerWidth',
        'offset',
        'opacity',
        'operator',
        'orient',
        'padding',
        'paddingLeft',
        'paddingRight',
        'patternUnits',
        'r',
        'radius',
        'refX',
        'refY',
        'role',
        'scope',
        'slope',
        'src',
        'startOffset',
        'stdDeviation',
        'stroke',
        'stroke-linecap',
        'stroke-width',
        'style',
        'tableValues',
        'result',
        'rowspan',
        'summary',
        'target',
        'tabindex',
        'text-align',
        'text-anchor',
        'textAnchor',
        'textLength',
        'title',
        'type',
        'valign',
        'width',
        'x',
        'x1',
        'x2',
        'xlink:href',
        'y',
        'y1',
        'y2',
        'zIndex'
    ];
    /**
     * The list of allowed references for referring attributes like `href` and
     * `src`. Attribute values will only be allowed if they start with one of
     * these strings.
     *
     * @see [Source code with default values](
     * https://github.com/highcharts/highcharts/blob/master/ts/Core/Renderer/HTML/AST.ts#:~:text=public%20static%20allowedReferences)
     *
     * @example
     * // Allow tel:
     * Highcharts.AST.allowedReferences.push('tel:');
     *
     * @name    Highcharts.AST.allowedReferences
     * @type    {Array<string>}
     */
    AST.allowedReferences = [
        'https://',
        'http://',
        'mailto:',
        '/',
        '../',
        './',
        '#'
    ];
    /**
     * The list of allowed SVG or HTML tags, used for sanitizing potentially
     * harmful content from the chart configuration before adding to the DOM.
     *
     * @see [Source code with default values](
     * https://github.com/highcharts/highcharts/blob/master/ts/Core/Renderer/HTML/AST.ts#:~:text=public%20static%20allowedTags)
     *
     * @example
     * // Allow a custom, trusted tag
     * Highcharts.AST.allowedTags.push('blink'); // ;)
     *
     * @name    Highcharts.AST.allowedTags
     * @type    {Array<string>}
     */
    AST.allowedTags = [
        'a',
        'abbr',
        'b',
        'br',
        'button',
        'caption',
        'circle',
        'clipPath',
        'code',
        'dd',
        'defs',
        'div',
        'dl',
        'dt',
        'em',
        'feComponentTransfer',
        'feComposite',
        'feDropShadow',
        'feFlood',
        'feFuncA',
        'feFuncB',
        'feFuncG',
        'feFuncR',
        'feGaussianBlur',
        'feMorphology',
        'feOffset',
        'feMerge',
        'feMergeNode',
        'filter',
        'h1',
        'h2',
        'h3',
        'h4',
        'h5',
        'h6',
        'hr',
        'i',
        'img',
        'li',
        'linearGradient',
        'marker',
        'ol',
        'p',
        'path',
        'pattern',
        'pre',
        'rect',
        'small',
        'span',
        'stop',
        'strong',
        'style',
        'sub',
        'sup',
        'svg',
        'table',
        'text',
        'textPath',
        'thead',
        'title',
        'tbody',
        'tspan',
        'td',
        'th',
        'tr',
        'u',
        'ul',
        '#text'
    ];
    AST.emptyHTML = emptyHTML;
    /**
     * Allow all custom SVG and HTML attributes, references and tags (together
     * with potentially harmful ones) to be added to the DOM from the chart
     * configuration. In other words, disable the allow-listing which is the
     * primary functionality of the AST.
     *
     * WARNING: Setting this property to `true` while allowing untrusted user
     * data in the chart configuration will expose your application to XSS
     * security risks!
     *
     * Note that in case you want to allow a known set of tags or attributes,
     * you should allow-list them instead of disabling the filtering totally.
     * See [allowedAttributes](Highcharts.AST#.allowedAttributes),
     * [allowedReferences](Highcharts.AST#.allowedReferences) and
     * [allowedTags](Highcharts.AST#.allowedTags). The `bypassHTMLFiltering`
     * setting is intended only for those cases where allow-listing is not
     * practical, and the chart configuration already comes from a secure
     * source.
     *
     * @example
     * // Allow all custom attributes, references and tags (disable DOM XSS
     * // filtering)
     * Highcharts.AST.bypassHTMLFiltering = true;
     *
     * @name Highcharts.AST.bypassHTMLFiltering
     * @static
     */
    AST.bypassHTMLFiltering = false;
    return AST;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var HTML_AST = (AST);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Serialized form of an SVG/HTML definition, including children.
 *
 * @interface Highcharts.ASTNode
 */ /**
* @name Highcharts.ASTNode#attributes
* @type {Highcharts.SVGAttributes|undefined}
*/ /**
* @name Highcharts.ASTNode#children
* @type {Array<Highcharts.ASTNode>|undefined}
*/ /**
* @name Highcharts.ASTNode#tagName
* @type {string|undefined}
*/ /**
* @name Highcharts.ASTNode#textContent
* @type {string|undefined}
*/
(''); // Keeps doclets above in file

;// ./code/es5/es-modules/Core/Templating.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Templating_defaultOptions = Defaults.defaultOptions, Templating_defaultTime = Defaults.defaultTime;

var Templating_pageLang = Core_Globals.pageLang;

var Templating_extend = Core_Utilities.extend, Templating_getNestedProperty = Core_Utilities.getNestedProperty, Templating_isArray = Core_Utilities.isArray, Templating_isNumber = Core_Utilities.isNumber, Templating_isObject = Core_Utilities.isObject, Templating_isString = Core_Utilities.isString, Templating_pick = Core_Utilities.pick, Templating_ucfirst = Core_Utilities.ucfirst;
var helpers = {
    // Built-in helpers
    add: function (a, b) { return a + b; },
    divide: function (a, b) { return (b !== 0 ? a / b : ''); },
    // eslint-disable-next-line eqeqeq
    eq: function (a, b) { return a == b; },
    each: function (arr) {
        var match = arguments[arguments.length - 1];
        return Templating_isArray(arr) ?
            arr.map(function (item, i) { return format(match.body, Templating_extend(Templating_isObject(item) ? item : { '@this': item }, {
                '@index': i,
                '@first': i === 0,
                '@last': i === arr.length - 1
            })); }).join('') :
            false;
    },
    ge: function (a, b) { return a >= b; },
    gt: function (a, b) { return a > b; },
    'if': function (condition) { return !!condition; },
    le: function (a, b) { return a <= b; },
    lt: function (a, b) { return a < b; },
    multiply: function (a, b) { return a * b; },
    // eslint-disable-next-line eqeqeq
    ne: function (a, b) { return a != b; },
    subtract: function (a, b) { return a - b; },
    ucfirst: Templating_ucfirst,
    unless: function (condition) { return !condition; }
};
var numberFormatCache = {};
/* *
 *
 *  Functions
 *
 * */
// Internal convenience function
var isQuotedString = function (str) { return /^["'].+["']$/.test(str); };
/**
 * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a
 * human readable date string. The format is a subset of the formats for PHP's
 * [strftime](https://www.php.net/manual/en/function.strftime.php) function.
 * Additional formats can be given in the {@link Highcharts.dateFormats} hook.
 *
 * Since v6.0.5, all internal dates are formatted through the
 * {@link Highcharts.Chart#time} instance to respect chart-level time settings.
 * The `Highcharts.dateFormat` function only reflects global time settings set
 * with `setOptions`.
 *
 * Supported format keys:
 * - `%a`: Short weekday, like 'Mon'
 * - `%A`: Long weekday, like 'Monday'
 * - `%d`: Two digit day of the month, 01 to 31
 * - `%e`: Day of the month, 1 through 31
 * - `%w`: Day of the week, 0 through 6
 * - `%b`: Short month, like 'Jan'
 * - `%B`: Long month, like 'January'
 * - `%m`: Two digit month number, 01 through 12
 * - `%y`: Two digits year, like 09 for 2009
 * - `%Y`: Four digits year, like 2009
 * - `%H`: Two digits hours in 24h format, 00 through 23
 * - `%k`: Hours in 24h format, 0 through 23
 * - `%I`: Two digits hours in 12h format, 00 through 11
 * - `%l`: Hours in 12h format, 1 through 12
 * - `%M`: Two digits minutes, 00 through 59
 * - `%p`: Upper case AM or PM
 * - `%P`: Lower case AM or PM
 * - `%S`: Two digits seconds, 00 through 59
 * - `%L`: Milliseconds (naming from Ruby)
 *
 * @function Highcharts.dateFormat
 *
 * @param {string} format
 *        The desired format where various time representations are prefixed
 *        with `%`.
 *
 * @param {number} timestamp
 *        The JavaScript timestamp.
 *
 * @param {boolean} [upperCaseFirst=false]
 *        Upper case first letter in the return.
 *
 * @return {string}
 *         The formatted date.
 */
function dateFormat(format, timestamp, upperCaseFirst) {
    return Templating_defaultTime.dateFormat(format, timestamp, upperCaseFirst);
}
/**
 * Format a string according to a subset of the rules of Python's String.format
 * method.
 *
 * @example
 * let s = Highcharts.format(
 *     'The {color} fox was {len:.2f} feet long',
 *     { color: 'red', len: Math.PI }
 * );
 * // => The red fox was 3.14 feet long
 *
 * @function Highcharts.format
 *
 * @param {string} str
 *        The string to format.
 *
 * @param {Record<string, *>} ctx
 *        The context, a collection of key-value pairs where each key is
 *        replaced by its value.
 *
 * @param {Highcharts.Chart} [chart]
 *        A `Chart` instance used to get numberFormatter and time.
 *
 * @return {string}
 *         The formatted string.
 */
function format(str, ctx, chart) {
    if (str === void 0) { str = ''; }
    var regex = /\{([\p{L}\d:\.,;\-\/<>\[\]%_@+"'’= #\(\)]+)\}/gu, 
        // The sub expression regex is the same as the top expression regex,
        // but except parens and block helpers (#), and surrounded by parens
        // instead of curly brackets.
        subRegex = /\(([\p{L}\d:\.,;\-\/<>\[\]%_@+"'= ]+)\)/gu, matches = [], floatRegex = /f$/, decRegex = /\.(\d)/, lang = (chart === null || chart === void 0 ? void 0 : chart.options.lang) || Templating_defaultOptions.lang, time = chart && chart.time || Templating_defaultTime, numberFormatter = chart && chart.numberFormatter || numberFormat;
    /*
     * Get a literal or variable value inside a template expression. May be
     * extended with other types like string or null if needed, but keep it
     * small for now.
     */
    var resolveProperty = function (key) {
            if (key === void 0) { key = ''; }
            var n;
        // Literals
        if (key === 'true') {
            return true;
        }
        if (key === 'false') {
            return false;
        }
        if ((n = Number(key)).toString() === key) {
            return n;
        }
        if (isQuotedString(key)) {
            return key.slice(1, -1);
        }
        // Variables and constants
        return Templating_getNestedProperty(key, ctx);
    };
    var match,
        currentMatch,
        depth = 0,
        hasSub;
    // Parse and create tree
    while ((match = regex.exec(str)) !== null) {
        // When a sub expression is found, it is evaluated first, and the
        // results recursively evaluated until no subexpression exists.
        var mainMatch = match,
            subMatch = subRegex.exec(match[1]);
        if (subMatch) {
            match = subMatch;
            hasSub = true;
        }
        if (!currentMatch || !currentMatch.isBlock) {
            currentMatch = {
                ctx: ctx,
                expression: match[1],
                find: match[0],
                isBlock: match[1].charAt(0) === '#',
                start: match.index,
                startInner: match.index + match[0].length,
                length: match[0].length
            };
        }
        // Identify helpers
        var fn = (currentMatch.isBlock ? mainMatch : match)[1].split(' ')[0].replace('#', '');
        if (helpers[fn]) {
            // Block helper, only 0 level is handled
            if (currentMatch.isBlock && fn === currentMatch.fn) {
                depth++;
            }
            if (!currentMatch.fn) {
                currentMatch.fn = fn;
            }
        }
        // Closing a block helper
        var startingElseSection = match[1] === 'else';
        if (currentMatch.isBlock &&
            currentMatch.fn && (match[1] === "/".concat(currentMatch.fn) ||
            startingElseSection)) {
            if (!depth) { // === 0
                var start = currentMatch.startInner,
                    body = str.substr(start,
                    match.index - start);
                // Either closing without an else section, or when encountering
                // an else section
                if (currentMatch.body === void 0) {
                    currentMatch.body = body;
                    currentMatch.startInner = match.index + match[0].length;
                    // The body exists already, so this is the else section
                }
                else {
                    currentMatch.elseBody = body;
                }
                currentMatch.find += body + match[0];
                if (!startingElseSection) {
                    matches.push(currentMatch);
                    currentMatch = void 0;
                }
            }
            else if (!startingElseSection) {
                depth--;
            }
            // Common expression
        }
        else if (!currentMatch.isBlock) {
            matches.push(currentMatch);
        }
        // Evaluate sub-matches one by one to prevent orphaned block closers
        if (subMatch && !(currentMatch === null || currentMatch === void 0 ? void 0 : currentMatch.isBlock)) {
            break;
        }
    }
    // Execute
    matches.forEach(function (match) {
        var body = match.body,
            elseBody = match.elseBody,
            expression = match.expression,
            fn = match.fn;
        var replacement,
            i;
        // Helper function
        if (fn) {
            // Pass the helpers the amount of arguments defined by the function,
            // then the match as the last argument.
            var args = [match],
                parts = [],
                len = expression.length;
            var start = 0,
                startChar = void 0;
            for (i = 0; i <= len; i++) {
                var char = expression.charAt(i);
                // Start of string
                if (!startChar && (char === '"' || char === '\'')) {
                    startChar = char;
                    // End of string
                }
                else if (startChar === char) {
                    startChar = '';
                }
                if (!startChar &&
                    (char === ' ' || i === len)) {
                    parts.push(expression.substr(start, i - start));
                    start = i + 1;
                }
            }
            i = helpers[fn].length;
            while (i--) {
                args.unshift(resolveProperty(parts[i + 1]));
            }
            replacement = helpers[fn].apply(ctx, args);
            // Block helpers may return true or false. They may also return a
            // string, like the `each` helper.
            if (match.isBlock && typeof replacement === 'boolean') {
                replacement = format(replacement ? body : elseBody, ctx, chart);
            }
            // Simple variable replacement
        }
        else {
            var valueAndFormat = isQuotedString(expression) ?
                    [expression] : expression.split(':');
            replacement = resolveProperty(valueAndFormat.shift() || '');
            // Format the replacement
            if (valueAndFormat.length && typeof replacement === 'number') {
                var segment = valueAndFormat.join(':');
                if (floatRegex.test(segment)) { // Float
                    var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10);
                    if (replacement !== null) {
                        replacement = numberFormatter(replacement, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : '');
                    }
                }
                else {
                    replacement = time.dateFormat(segment, replacement);
                }
            }
            // Use string literal in order to be preserved in the outer
            // expression
            subRegex.lastIndex = 0;
            if (subRegex.test(match.find) && Templating_isString(replacement)) {
                replacement = "\"".concat(replacement, "\"");
            }
        }
        str = str.replace(match.find, Templating_pick(replacement, ''));
    });
    return hasSub ? format(str, ctx, chart) : str;
}
/**
 * Format a number and return a string based on input settings.
 *
 * @sample highcharts/members/highcharts-numberformat/
 *         Custom number format
 *
 * @function Highcharts.numberFormat
 *
 * @param {number} number
 *        The input number to format.
 *
 * @param {number} decimals
 *        The amount of decimals. A value of -1 preserves the amount in the
 *        input number.
 *
 * @param {string} [decimalPoint]
 *        The decimal point, defaults to the one given in the lang options, or
 *        a dot.
 *
 * @param {string} [thousandsSep]
 *        The thousands separator, defaults to the one given in the lang
 *        options, or a space character.
 *
 * @return {string}
 *         The formatted number.
 */
function numberFormat(number, decimals, decimalPoint, thousandsSep) {
    var _a,
        _b;
    number = +number || 0;
    decimals = +decimals;
    var ret,
        fractionDigits,
        _c = number.toString().split('e').map(Number),
        mantissa = _c[0],
        exp = _c[1];
    var lang = ((_a = this === null || this === void 0 ? void 0 : this.options) === null || _a === void 0 ? void 0 : _a.lang) || Templating_defaultOptions.lang,
        origDec = (number.toString().split('.')[1] || '').split('e')[0].length,
        firstDecimals = decimals,
        options = {};
    decimalPoint !== null && decimalPoint !== void 0 ? decimalPoint : (decimalPoint = lang.decimalPoint);
    thousandsSep !== null && thousandsSep !== void 0 ? thousandsSep : (thousandsSep = lang.thousandsSep);
    if (decimals === -1) {
        // Preserve decimals. Not huge numbers (#3793).
        decimals = Math.min(origDec, 20);
    }
    else if (!Templating_isNumber(decimals)) {
        decimals = 2;
    }
    else if (decimals && exp < 0) {
        // Expose decimals from exponential notation (#7042)
        fractionDigits = decimals + exp;
        if (fractionDigits >= 0) {
            // Remove too small part of the number while keeping the notation
            mantissa = +mantissa.toExponential(fractionDigits).split('e')[0];
            decimals = fractionDigits;
        }
        else {
            // `fractionDigits < 0`
            mantissa = Math.floor(mantissa);
            if (decimals < 20) {
                // Use number instead of exponential notation (#7405)
                number = +(mantissa * Math.pow(10, exp)).toFixed(decimals);
            }
            else {
                // Or zero
                number = 0;
            }
            exp = 0;
        }
    }
    if (exp) {
        decimals !== null && decimals !== void 0 ? decimals : (decimals = 2);
        number = mantissa;
    }
    if (Templating_isNumber(decimals) && decimals >= 0) {
        options.minimumFractionDigits = decimals;
        options.maximumFractionDigits = decimals;
    }
    if (thousandsSep === '') {
        options.useGrouping = false;
    }
    var hasSeparators = thousandsSep || decimalPoint,
        locale = hasSeparators ?
            'en' :
            ((this === null || this === void 0 ? void 0 : this.locale) || lang.locale || Templating_pageLang),
        cacheKey = JSON.stringify(options) + locale,
        nf = (_b = numberFormatCache[cacheKey]) !== null && _b !== void 0 ? _b : (numberFormatCache[cacheKey] = new Intl.NumberFormat(locale,
        options));
    ret = nf.format(number);
    // If thousandsSep or decimalPoint are set, fall back to using English
    // format with string replacement for the separators.
    if (hasSeparators) {
        ret = ret
            // Preliminary step to avoid re-swapping (#22402)
            .replace(/([,\.])/g, '_$1')
            .replace(/_\,/g, thousandsSep !== null && thousandsSep !== void 0 ? thousandsSep : ',')
            .replace('_.', decimalPoint !== null && decimalPoint !== void 0 ? decimalPoint : '.');
    }
    if (
    // Remove signed zero (#20564)
    (!decimals && +ret === 0) ||
        // Small numbers, no decimals (#14023)
        (exp < 0 && !firstDecimals)) {
        ret = '0';
    }
    if (exp && +ret !== 0) {
        ret += 'e' + (exp < 0 ? '' : '+') + exp;
    }
    return ret;
}
/* *
 *
 *  Default Export
 *
 * */
var Templating = {
    dateFormat: dateFormat,
    format: format,
    helpers: helpers,
    numberFormat: numberFormat
};
/* harmony default export */ var Core_Templating = (Templating);

;// ./code/es5/es-modules/Core/Renderer/RendererRegistry.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


/* *
 *
 *  Namespace
 *
 * */
var RendererRegistry;
(function (RendererRegistry) {
    /* *
     *
     *  Constants
     *
     * */
    RendererRegistry.rendererTypes = {};
    /* *
     *
     *  Variables
     *
     * */
    var defaultRenderer;
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Gets a registered renderer class. If no renderer type is provided or the
     * requested renderer was not founded, the default renderer is returned.
     *
     * @param {string} [rendererType]
     * Renderer type or the default renderer.
     *
     * @return {Highcharts.Class<Highcharts.SVGRenderer>}
     * Returns the requested renderer class or the default renderer class.
     */
    function getRendererType(rendererType) {
        if (rendererType === void 0) { rendererType = defaultRenderer; }
        return (RendererRegistry.rendererTypes[rendererType] || RendererRegistry.rendererTypes[defaultRenderer]);
    }
    RendererRegistry.getRendererType = getRendererType;
    /**
     * Register a renderer class.
     *
     * @param {string} rendererType
     * Renderer type to register.
     *
     * @param {Highcharts.Class<Highcharts.SVGRenderer>} rendererClass
     * Returns the requested renderer class or the default renderer class.
     *
     * @param {boolean} setAsDefault
     * Sets the renderer class as the default renderer.
     */
    function registerRendererType(rendererType, rendererClass, setAsDefault) {
        RendererRegistry.rendererTypes[rendererType] = rendererClass;
        if (!defaultRenderer || setAsDefault) {
            defaultRenderer = rendererType;
            Core_Globals.Renderer = rendererClass; // Compatibility
        }
    }
    RendererRegistry.registerRendererType = registerRendererType;
})(RendererRegistry || (RendererRegistry = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Renderer_RendererRegistry = (RendererRegistry);

;// ./code/es5/es-modules/Core/Renderer/RendererUtilities.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Imports
 *
 * */

var RendererUtilities_clamp = Core_Utilities.clamp, RendererUtilities_pick = Core_Utilities.pick, RendererUtilities_pushUnique = Core_Utilities.pushUnique, RendererUtilities_stableSort = Core_Utilities.stableSort;
/* *
 *
 *  Namespace
 *
 * */
var RendererUtilities;
(function (RendererUtilities) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * General distribution algorithm for distributing labels of differing size
     * along a confined length in two dimensions. The algorithm takes an array
     * of objects containing a size, a target and a rank. It will place the
     * labels as close as possible to their targets, skipping the lowest ranked
     * labels if necessary.
     * @private
     */
    function distribute(boxes, len, maxDistance) {
        // Original array will be altered with added .pos
        var origBoxes = boxes,
            reducedLen = origBoxes.reducedLen || len,
            sortByRank = function (a,
            b) {
                return (b.rank || 0) - (a.rank || 0);
        }, sortByTarget = function (a, b) {
            return a.target - b.target;
        }, restBoxes = [], // The outranked overshoot
        boxesLength = boxes.length, forDeletion = [], push = restBoxes.push;
        var i,
            cursor,
            step,
            overlapping = true,
            box,
            target,
            total = 0,
            equalRank;
        // If the total size exceeds the len, remove those boxes with the lowest
        // rank
        i = boxesLength;
        while (i--) {
            total += boxes[i].size;
        }
        // Sort by rank, then slice away overshoot
        if (total > reducedLen) {
            RendererUtilities_stableSort(boxes, sortByRank);
            equalRank = boxes[0].rank === boxes[boxes.length - 1].rank;
            step = equalRank ? boxesLength / 2 : -1;
            cursor = equalRank ? step : boxesLength - 1;
            // When the boxes have equal rank (pie data labels, flags - #10073),
            // decimate the boxes by starting in the middle and gradually remove
            // more items inside the array. When they are sorted by rank, just
            // remove the ones with the lowest rank from the end.
            while (step && total > reducedLen) {
                i = Math.floor(cursor);
                box = boxes[i];
                if (RendererUtilities_pushUnique(forDeletion, i)) {
                    total -= box.size;
                }
                cursor += step;
                // Start over the decimation with smaller steps
                if (equalRank && cursor >= boxes.length) {
                    step /= 2;
                    cursor = step;
                }
            }
            // Clean out the boxes marked for deletion
            forDeletion
                .sort(function (a, b) { return b - a; })
                .forEach(function (i) {
                return push.apply(restBoxes, boxes.splice(i, 1));
            });
        }
        // Order by target
        RendererUtilities_stableSort(boxes, sortByTarget);
        // So far we have been mutating the original array. Now
        // create a copy with target arrays
        boxes = boxes.map(function (box) { return ({
            size: box.size,
            targets: [box.target],
            align: RendererUtilities_pick(box.align, 0.5)
        }); });
        while (overlapping) {
            // Initial positions: target centered in box
            i = boxes.length;
            while (i--) {
                box = boxes[i];
                // Composite box, average of targets
                target = (Math.min.apply(0, box.targets) +
                    Math.max.apply(0, box.targets)) / 2;
                box.pos = RendererUtilities_clamp(target - box.size * box.align, 0, len - box.size);
            }
            // Detect overlap and join boxes
            i = boxes.length;
            overlapping = false;
            while (i--) {
                // Overlap
                if (i > 0 &&
                    boxes[i - 1].pos + boxes[i - 1].size >
                        boxes[i].pos) {
                    // Add this size to the previous box
                    boxes[i - 1].size += boxes[i].size;
                    boxes[i - 1].targets = boxes[i - 1]
                        .targets
                        .concat(boxes[i].targets);
                    boxes[i - 1].align = 0.5;
                    // Overlapping right, push left
                    if (boxes[i - 1].pos + boxes[i - 1].size > len) {
                        boxes[i - 1].pos = len - boxes[i - 1].size;
                    }
                    boxes.splice(i, 1); // Remove this item
                    overlapping = true;
                }
            }
        }
        // Add the rest (hidden boxes)
        push.apply(origBoxes, restBoxes);
        // Now the composite boxes are placed, we need to put the original boxes
        // within them
        i = 0;
        boxes.some(function (box) {
            var posInCompositeBox = 0;
            // Exceeded maxDistance => abort
            return (box.targets || []).some(function () {
                origBoxes[i].pos = box.pos + posInCompositeBox;
                // If the distance between the position and the target exceeds
                // maxDistance, abort the loop and decrease the length in
                // increments of 10% to recursively reduce the number of
                // visible boxes by rank. Once all boxes are within the
                // maxDistance, we're good.
                if (typeof maxDistance !== 'undefined' &&
                    Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance) {
                    // Reset the positions that are already set
                    origBoxes
                        .slice(0, i + 1)
                        .forEach(function (box) { return delete box.pos; });
                    // Try with a smaller length
                    origBoxes.reducedLen =
                        (origBoxes.reducedLen || len) - (len * 0.1);
                    // Recurse
                    if (origBoxes.reducedLen > len * 0.1) {
                        distribute(origBoxes, len, maxDistance);
                    }
                    // Exceeded maxDistance => abort
                    return true;
                }
                posInCompositeBox += origBoxes[i].size;
                i++;
                return false;
            });
        });
        // Add the rest (hidden) boxes and sort by target
        RendererUtilities_stableSort(origBoxes, sortByTarget);
        return origBoxes;
    }
    RendererUtilities.distribute = distribute;
})(RendererUtilities || (RendererUtilities = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Renderer_RendererUtilities = (RendererUtilities);

;// ./code/es5/es-modules/Core/Renderer/SVG/SVGElement.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var SVGElement_animate = AnimationUtilities.animate, SVGElement_animObject = AnimationUtilities.animObject, SVGElement_stop = AnimationUtilities.stop;


var deg2rad = Core_Globals.deg2rad, SVGElement_doc = Core_Globals.doc, svg = Core_Globals.svg, SVGElement_SVG_NS = Core_Globals.SVG_NS, SVGElement_win = Core_Globals.win, isFirefox = Core_Globals.isFirefox;

var SVGElement_addEvent = Core_Utilities.addEvent, SVGElement_attr = Core_Utilities.attr, SVGElement_createElement = Core_Utilities.createElement, SVGElement_crisp = Core_Utilities.crisp, SVGElement_css = Core_Utilities.css, SVGElement_defined = Core_Utilities.defined, SVGElement_erase = Core_Utilities.erase, SVGElement_extend = Core_Utilities.extend, SVGElement_fireEvent = Core_Utilities.fireEvent, SVGElement_getAlignFactor = Core_Utilities.getAlignFactor, SVGElement_isArray = Core_Utilities.isArray, SVGElement_isFunction = Core_Utilities.isFunction, SVGElement_isNumber = Core_Utilities.isNumber, SVGElement_isObject = Core_Utilities.isObject, SVGElement_isString = Core_Utilities.isString, SVGElement_merge = Core_Utilities.merge, SVGElement_objectEach = Core_Utilities.objectEach, SVGElement_pick = Core_Utilities.pick, SVGElement_pInt = Core_Utilities.pInt, SVGElement_pushUnique = Core_Utilities.pushUnique, SVGElement_replaceNested = Core_Utilities.replaceNested, SVGElement_syncTimeout = Core_Utilities.syncTimeout, SVGElement_uniqueKey = Core_Utilities.uniqueKey;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the
 * rendering layer of Highcharts. Combined with the
 * {@link Highcharts.SVGRenderer}
 * object, these prototypes allow freeform annotation in the charts or even in
 * HTML pages without instanciating a chart. The SVGElement can also wrap HTML
 * labels, when `text` or `label` elements are created with the `useHTML`
 * parameter.
 *
 * The SVGElement instances are created through factory functions on the
 * {@link Highcharts.SVGRenderer}
 * object, like
 * {@link Highcharts.SVGRenderer#rect|rect},
 * {@link Highcharts.SVGRenderer#path|path},
 * {@link Highcharts.SVGRenderer#text|text},
 * {@link Highcharts.SVGRenderer#label|label},
 * {@link Highcharts.SVGRenderer#g|g}
 * and more.
 *
 * See [How to use the SVG Renderer](
 * https://www.highcharts.com/docs/advanced-chart-features/renderer) for a
 * comprehensive tutorial on how to draw SVG elements on a chart.
 *
 * @class
 * @name Highcharts.SVGElement
 */
var SVGElement = /** @class */ (function () {
    /**
     * Initialize the SVG element. This function only exists to make the
     * initialization process overridable. It should not be called directly.
     *
     * @function Highcharts.SVGElement#init
     *
     * @param {Highcharts.SVGRenderer} renderer
     * The SVGRenderer instance to initialize to.
     *
     * @param {string} nodeName
     * The SVG node name.
     */
    function SVGElement(renderer, nodeName) {
        this.onEvents = {};
        this.opacity = 1; // Default base for animation
        this.SVG_NS = SVGElement_SVG_NS;
        /**
         * The primary DOM node. Each `SVGElement` instance wraps a main DOM
         * node, but may also represent more nodes.
         *
         * @name Highcharts.SVGElement#element
         * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement}
         */
        this.element = nodeName === 'span' || nodeName === 'body' ?
            SVGElement_createElement(nodeName) :
            SVGElement_doc.createElementNS(this.SVG_NS, nodeName);
        /**
         * The renderer that the SVGElement belongs to.
         *
         * @name Highcharts.SVGElement#renderer
         * @type {Highcharts.SVGRenderer}
         */
        this.renderer = renderer;
        this.styles = {};
        SVGElement_fireEvent(this, 'afterInit');
    }
    // @todo public zIndex?: number;
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Get the current value of an attribute or pseudo attribute,
     * used mainly for animation. Called internally from
     * the {@link Highcharts.SVGRenderer#attr} function.
     *
     * @private
     * @function Highcharts.SVGElement#_defaultGetter
     *
     * @param {string} key
     *        Property key.
     *
     * @return {number|string}
     *         Property value.
     */
    SVGElement.prototype._defaultGetter = function (key) {
        var ret = SVGElement_pick(this[key + 'Value'], // Align getter
            this[key],
            this.element ? this.element.getAttribute(key) : null, 0);
        if (/^-?[\d\.]+$/.test(ret)) { // Is numerical
            ret = parseFloat(ret);
        }
        return ret;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#_defaultSetter
     *
     * @param {string} value
     *
     * @param {string} key
     *
     * @param {Highcharts.SVGDOMElement} element
     *
     */
    SVGElement.prototype._defaultSetter = function (value, key, element) {
        element.setAttribute(key, value);
    };
    /**
     * Add the element to the DOM. All elements must be added this way.
     *
     * @sample highcharts/members/renderer-g
     *         Elements added to a group
     *
     * @function Highcharts.SVGElement#add
     *
     * @param {Highcharts.SVGElement} [parent]
     *        The parent item to add it to. If undefined, the element is added
     *        to the {@link Highcharts.SVGRenderer.box}.
     *
     * @return {Highcharts.SVGElement}
     *         Returns the SVGElement for chaining.
     */
    SVGElement.prototype.add = function (parent) {
        var renderer = this.renderer,
            element = this.element;
        var inserted;
        if (parent) {
            this.parentGroup = parent;
        }
        // Build formatted text
        if (typeof this.textStr !== 'undefined' &&
            this.element.nodeName === 'text' // Not for SVGLabel instances
        ) {
            renderer.buildText(this);
        }
        // Mark as added
        this.added = true;
        // If we're adding to renderer root, or other elements in the group
        // have a z index, we need to handle it
        if (!parent || parent.handleZ || this.zIndex) {
            inserted = this.zIndexSetter();
        }
        // If zIndex is not handled, append at the end
        if (!inserted) {
            (parent ?
                parent.element :
                renderer.box).appendChild(element);
        }
        // Fire an event for internal hooks
        if (this.onAdd) {
            this.onAdd();
        }
        return this;
    };
    /**
     * Add a class name to an element.
     *
     * @function Highcharts.SVGElement#addClass
     *
     * @param {string} className
     * The new class name to add.
     *
     * @param {boolean} [replace=false]
     * When true, the existing class name(s) will be overwritten with the new
     * one. When false, the new one is added.
     *
     * @return {Highcharts.SVGElement}
     * Return the SVG element for chainability.
     */
    SVGElement.prototype.addClass = function (className, replace) {
        var currentClassName = replace ? '' : (this.attr('class') || '');
        // Trim the string and remove duplicates
        className = (className || '')
            .split(/ /g)
            .reduce(function (newClassName, name) {
            if (currentClassName.indexOf(name) === -1) {
                newClassName.push(name);
            }
            return newClassName;
        }, (currentClassName ?
            [currentClassName] :
            []))
            .join(' ');
        if (className !== currentClassName) {
            this.attr('class', className);
        }
        return this;
    };
    /**
     * This method is executed in the end of `attr()`, after setting all
     * attributes in the hash. In can be used to efficiently consolidate
     * multiple attributes in one SVG property -- e.g., translate, rotate and
     * scale are merged in one "transform" attribute in the SVG node.
     *
     * @private
     * @function Highcharts.SVGElement#afterSetters
     */
    SVGElement.prototype.afterSetters = function () {
        // Update transform. Do this outside the loop to prevent redundant
        // updating for batch setting of attributes.
        if (this.doTransform) {
            this.updateTransform();
            this.doTransform = false;
        }
    };
    /**
     * Align the element relative to the chart or another box.
     *
     * @function Highcharts.SVGElement#align
     *
     * @param {Highcharts.AlignObject} [alignOptions]
     *        The alignment options. The function can be called without this
     *        parameter in order to re-align an element after the box has been
     *        updated.
     *
     * @param {boolean} [alignByTranslate]
     *        Align element by translation.
     *
     * @param {string|Highcharts.BBoxObject} [alignTo]
     *        The box to align to, needs a width and height. When the box is a
     *        string, it refers to an object in the Renderer. For example, when
     *        box is `spacingBox`, it refers to `Renderer.spacingBox` which
     *        holds `width`, `height`, `x` and `y` properties.
     *
     * @param {boolean} [redraw]
     *        Decide if SVGElement should be redrawn with new alignment or
     *        just change its attributes.
     *
     * @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
     */
    SVGElement.prototype.align = function (alignOptions, alignByTranslate, alignTo, redraw) {
        if (redraw === void 0) { redraw = true; }
        var renderer = this.renderer,
            alignedObjects = renderer.alignedObjects,
            initialAlignment = Boolean(alignOptions);
        // First call on instanciate
        if (alignOptions) {
            this.alignOptions = alignOptions;
            this.alignByTranslate = alignByTranslate;
            this.alignTo = alignTo;
            // When called on resize, no arguments are supplied
        }
        else {
            alignOptions = this.alignOptions || {};
            alignByTranslate = this.alignByTranslate;
            alignTo = this.alignTo;
        }
        var alignToKey = !alignTo || SVGElement_isString(alignTo) ?
                alignTo || 'renderer' :
                void 0;
        // When aligned to a key, automatically re-align on redraws
        if (alignToKey) {
            // Prevent duplicates, like legendGroup after resize
            if (initialAlignment) {
                SVGElement_pushUnique(alignedObjects, this);
            }
            alignTo = void 0; // Do not use the box
        }
        var alignToBox = SVGElement_pick(alignTo,
            renderer[alignToKey],
            renderer), 
            // Default: left align
            x = (alignToBox.x || 0) + (alignOptions.x || 0) +
                ((alignToBox.width || 0) - (alignOptions.width || 0)) *
                    SVGElement_getAlignFactor(alignOptions.align), 
            // Default: top align
            y = (alignToBox.y || 0) + (alignOptions.y || 0) +
                ((alignToBox.height || 0) - (alignOptions.height || 0)) *
                    SVGElement_getAlignFactor(alignOptions.verticalAlign),
            attribs = {
                'text-align': alignOptions === null || alignOptions === void 0 ? void 0 : alignOptions.align
            };
        attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x);
        attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y);
        // Animate only if already placed
        if (redraw) {
            this[this.placed ? 'animate' : 'attr'](attribs);
            this.placed = true;
        }
        this.alignAttr = attribs;
        return this;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#alignSetter
     * @param {"left"|"center"|"right"} value
     */
    SVGElement.prototype.alignSetter = function (value) {
        var convert = {
                left: 'start',
                center: 'middle',
                right: 'end'
            };
        if (convert[value]) {
            this.alignValue = value;
            this.element.setAttribute('text-anchor', convert[value]);
        }
    };
    /**
     * Animate to given attributes or CSS properties.
     *
     * @sample highcharts/members/element-on/
     *         Setting some attributes by animation
     *
     * @function Highcharts.SVGElement#animate
     *
     * @param {Highcharts.SVGAttributes} params
     *        SVG attributes or CSS to animate.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [options]
     *        Animation options.
     *
     * @param {Function} [complete]
     *        Function to perform at the end of animation.
     *
     * @return {Highcharts.SVGElement}
     *         Returns the SVGElement for chaining.
     */
    SVGElement.prototype.animate = function (params, options, complete) {
        var _this = this;
        var animOptions = SVGElement_animObject(SVGElement_pick(options,
            this.renderer.globalAnimation,
            true)),
            deferTime = animOptions.defer;
        // When the page is hidden save resources in the background by not
        // running animation at all (#9749).
        if (SVGElement_doc.hidden) {
            animOptions.duration = 0;
        }
        if (animOptions.duration !== 0) {
            // Allows using a callback with the global animation without
            // overwriting it
            if (complete) {
                animOptions.complete = complete;
            }
            // If defer option is defined delay the animation #12901
            SVGElement_syncTimeout(function () {
                if (_this.element) {
                    SVGElement_animate(_this, params, animOptions);
                }
            }, deferTime);
        }
        else {
            this.attr(params, void 0, complete || animOptions.complete);
            // Call the end step synchronously
            SVGElement_objectEach(params, function (val, prop) {
                if (animOptions.step) {
                    animOptions.step.call(this, val, { prop: prop, pos: 1, elem: this });
                }
            }, this);
        }
        return this;
    };
    /**
     * Apply a text outline through a custom CSS property, by copying the text
     * element and apply stroke to the copy. Used internally. Contrast checks at
     * [example](https://jsfiddle.net/highcharts/43soe9m1/2/).
     *
     * @example
     * // Specific color
     * text.css({
     *    textOutline: '1px black'
     * });
     * // Automatic contrast
     * text.css({
     *    color: '#000000', // black text
     *    textOutline: '1px contrast' // => white outline
     * });
     *
     * @private
     * @function Highcharts.SVGElement#applyTextOutline
     *
     * @param {string} textOutline
     *        A custom CSS `text-outline` setting, defined by `width color`.
     */
    SVGElement.prototype.applyTextOutline = function (textOutline) {
        var elem = this.element,
            hasContrast = textOutline.indexOf('contrast') !== -1,
            styles = {};
        // When the text shadow is set to contrast, use dark stroke for light
        // text and vice versa.
        if (hasContrast) {
            styles.textOutline = textOutline = textOutline.replace(/contrast/g, this.renderer.getContrast(elem.style.fill));
        }
        // Extract the stroke width and color
        var parts = textOutline.split(' ');
        var color = parts[parts.length - 1];
        var strokeWidth = parts[0];
        if (strokeWidth && strokeWidth !== 'none' && Core_Globals.svg) {
            this.fakeTS = true; // Fake text shadow
            // Since the stroke is applied on center of the actual outline, we
            // need to double it to get the correct stroke-width outside the
            // glyphs.
            strokeWidth = strokeWidth.replace(/(^[\d\.]+)(.*?)$/g, function (match, digit, unit) {
                return (2 * Number(digit)) + unit;
            });
            // Remove shadows from previous runs.
            this.removeTextOutline();
            var outline_1 = SVGElement_doc.createElementNS(SVGElement_SVG_NS, 'tspan');
            SVGElement_attr(outline_1, {
                'class': 'highcharts-text-outline',
                fill: color,
                stroke: color,
                'stroke-width': strokeWidth,
                'stroke-linejoin': 'round'
            });
            // For each of the tspans and text nodes, create a copy in the
            // outline.
            var parentElem = elem.querySelector('textPath') || elem;
            [].forEach.call(parentElem.childNodes, function (childNode) {
                var clone = childNode.cloneNode(true);
                if (clone.removeAttribute) {
                    ['fill', 'stroke', 'stroke-width', 'stroke'].forEach(function (prop) { return clone
                        .removeAttribute(prop); });
                }
                outline_1.appendChild(clone);
            });
            // Collect the sum of dy from all children, included nested ones
            var totalHeight_1 = 0;
            [].forEach.call(parentElem.querySelectorAll('text tspan'), function (element) {
                totalHeight_1 += Number(element.getAttribute('dy'));
            });
            // Insert an absolutely positioned break before the original text
            // to keep it in place
            var br = SVGElement_doc.createElementNS(SVGElement_SVG_NS, 'tspan');
            br.textContent = '\u200B';
            // Reset the position for the following text
            SVGElement_attr(br, {
                x: Number(elem.getAttribute('x')),
                dy: -totalHeight_1
            });
            // Insert the outline
            outline_1.appendChild(br);
            parentElem.insertBefore(outline_1, parentElem.firstChild);
        }
    };
    /**
     * @function Highcharts.SVGElement#attr
     * @param {string} key
     * @return {number|string}
     */ /**
    * Apply native and custom attributes to the SVG elements.
    *
    * In order to set the rotation center for rotation, set x and y to 0 and
    * use `translateX` and `translateY` attributes to position the element
    * instead.
    *
    * Attributes frequently used in Highcharts are `fill`, `stroke`,
    * `stroke-width`.
    *
    * @sample highcharts/members/renderer-rect/
    *         Setting some attributes
    *
    * @example
    * // Set multiple attributes
    * element.attr({
    *     stroke: 'red',
    *     fill: 'blue',
    *     x: 10,
    *     y: 10
    * });
    *
    * // Set a single attribute
    * element.attr('stroke', 'red');
    *
    * // Get an attribute
    * element.attr('stroke'); // => 'red'
    *
    * @function Highcharts.SVGElement#attr
    *
    * @param {string|Highcharts.SVGAttributes} [hash]
    *        The native and custom SVG attributes.
    *
    * @param {number|string|Highcharts.SVGPathArray} [val]
    *        If the type of the first argument is `string`, the second can be a
    *        value, which will serve as a single attribute setter. If the first
    *        argument is a string and the second is undefined, the function
    *        serves as a getter and the current value of the property is
    *        returned.
    *
    * @param {Function} [complete]
    *        A callback function to execute after setting the attributes. This
    *        makes the function compliant and interchangeable with the
    *        {@link SVGElement#animate} function.
    *
    * @param {boolean} [continueAnimation=true]
    *        Used internally when `.attr` is called as part of an animation
    *        step. Otherwise, calling `.attr` for an attribute will stop
    *        animation for that attribute.
    *
    * @return {Highcharts.SVGElement}
    *         If used as a setter, it returns the current
    *         {@link Highcharts.SVGElement} so the calls can be chained. If
    *         used as a getter, the current value of the attribute is returned.
    */
    SVGElement.prototype.attr = function (hash, val, complete, continueAnimation) {
        var element = this.element,
            symbolCustomAttribs = SVGElement.symbolCustomAttribs;
        var key,
            hasSetSymbolSize,
            ret = this,
            skipAttr,
            setter;
        // Single key-value pair
        if (typeof hash === 'string' && typeof val !== 'undefined') {
            key = hash;
            hash = {};
            hash[key] = val;
        }
        // Used as a getter: first argument is a string, second is undefined
        if (typeof hash === 'string') {
            ret = (this[hash + 'Getter'] ||
                this._defaultGetter).call(this, hash, element);
            // Setter
        }
        else {
            SVGElement_objectEach(hash, function eachAttribute(val, key) {
                skipAttr = false;
                // Unless .attr is from the animator update, stop current
                // running animation of this property
                if (!continueAnimation) {
                    SVGElement_stop(this, key);
                }
                // Special handling of symbol attributes
                if (this.symbolName &&
                    symbolCustomAttribs.indexOf(key) !== -1) {
                    if (!hasSetSymbolSize) {
                        this.symbolAttr(hash);
                        hasSetSymbolSize = true;
                    }
                    skipAttr = true;
                }
                if (this.rotation && (key === 'x' || key === 'y')) {
                    this.doTransform = true;
                }
                if (!skipAttr) {
                    setter = (this[key + 'Setter'] ||
                        this._defaultSetter);
                    setter.call(this, val, key, element);
                }
            }, this);
            this.afterSetters();
        }
        // In accordance with animate, run a complete callback
        if (complete) {
            complete.call(this);
        }
        return ret;
    };
    /**
     * Apply a clipping shape to this element.
     *
     * @function Highcharts.SVGElement#clip
     *
     * @param {SVGElement} [clipElem]
     *        The clipping shape. If skipped, the current clip is removed.
     *
     * @return {Highcharts.SVGElement}
     *         Returns the SVG element to allow chaining.
     */
    SVGElement.prototype.clip = function (clipElem) {
        if (clipElem && !clipElem.clipPath) {
            // Add a hyphen at the end to avoid confusion in testing indexes
            // -1 and -10, -11 etc (#6550)
            var id = SVGElement_uniqueKey() + '-', clipPath = this.renderer.createElement('clipPath')
                    .attr({ id: id })
                    .add(this.renderer.defs);
            SVGElement_extend(clipElem, { clipPath: clipPath, id: id, count: 0 });
            clipElem.add(clipPath);
        }
        return this.attr('clip-path', clipElem ?
            "url(".concat(this.renderer.url, "#").concat(clipElem.id, ")") :
            'none');
    };
    /**
     * Calculate the coordinates needed for drawing a rectangle crisply and
     * return the calculated attributes.
     *
     * @function Highcharts.SVGElement#crisp
     *
     * @param {Highcharts.RectangleObject} rect
     * Rectangle to crisp.
     *
     * @param {number} [strokeWidth]
     * The stroke width to consider when computing crisp positioning. It can
     * also be set directly on the rect parameter.
     *
     * @return {Highcharts.RectangleObject}
     * The modified rectangle arguments.
     */
    SVGElement.prototype.crisp = function (rect, strokeWidth) {
        // Math.round because strokeWidth can sometimes have roundoff errors
        strokeWidth = Math.round(strokeWidth || rect.strokeWidth || 0);
        var x1 = rect.x || this.x || 0,
            y1 = rect.y || this.y || 0,
            x2 = (rect.width || this.width || 0) + x1,
            y2 = (rect.height || this.height || 0) + y1, 
            // Find all the rounded coordinates for corners
            x = SVGElement_crisp(x1,
            strokeWidth),
            y = SVGElement_crisp(y1,
            strokeWidth),
            x2Crisp = SVGElement_crisp(x2,
            strokeWidth),
            y2Crisp = SVGElement_crisp(y2,
            strokeWidth);
        SVGElement_extend(rect, {
            x: x,
            y: y,
            width: x2Crisp - x,
            height: y2Crisp - y
        });
        if (SVGElement_defined(rect.strokeWidth)) {
            rect.strokeWidth = strokeWidth;
        }
        return rect;
    };
    /**
     * Build and apply an SVG gradient out of a common JavaScript configuration
     * object. This function is called from the attribute setters. An event
     * hook is added for supporting other complex color types.
     *
     * @private
     * @function Highcharts.SVGElement#complexColor
     *
     * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions
     * The gradient or pattern options structure.
     *
     * @param {string} prop
     * The property to apply, can either be `fill` or `stroke`.
     *
     * @param {Highcharts.SVGDOMElement} elem
     * SVG element to apply the gradient on.
     */
    SVGElement.prototype.complexColor = function (colorOptions, prop, elem) {
        var renderer = this.renderer;
        var colorObject,
            gradName,
            gradAttr,
            radAttr,
            gradients,
            stops,
            stopColor,
            stopOpacity,
            radialReference,
            id,
            key = [],
            value;
        SVGElement_fireEvent(this.renderer, 'complexColor', {
            args: arguments
        }, function () {
            // Apply linear or radial gradients
            if (colorOptions.radialGradient) {
                gradName = 'radialGradient';
            }
            else if (colorOptions.linearGradient) {
                gradName = 'linearGradient';
            }
            if (gradName) {
                gradAttr = colorOptions[gradName];
                gradients = renderer.gradients;
                stops = colorOptions.stops;
                radialReference = elem.radialReference;
                // Keep < 2.2 compatibility
                if (SVGElement_isArray(gradAttr)) {
                    colorOptions[gradName] = gradAttr = {
                        x1: gradAttr[0],
                        y1: gradAttr[1],
                        x2: gradAttr[2],
                        y2: gradAttr[3],
                        gradientUnits: 'userSpaceOnUse'
                    };
                }
                // Correct the radial gradient for the radial reference system
                if (gradName === 'radialGradient' &&
                    radialReference &&
                    !SVGElement_defined(gradAttr.gradientUnits)) {
                    // Save the radial attributes for updating
                    radAttr = gradAttr;
                    gradAttr = SVGElement_merge(gradAttr, renderer.getRadialAttr(radialReference, radAttr), { gradientUnits: 'userSpaceOnUse' });
                }
                // Build the unique key to detect whether we need to create a
                // new element (#1282)
                SVGElement_objectEach(gradAttr, function (value, n) {
                    if (n !== 'id') {
                        key.push(n, value);
                    }
                });
                SVGElement_objectEach(stops, function (val) {
                    key.push(val);
                });
                key = key.join(',');
                // Check if a gradient object with the same config object is
                // created within this renderer
                if (gradients[key]) {
                    id = gradients[key].attr('id');
                }
                else {
                    // Set the id and create the element
                    gradAttr.id = id = SVGElement_uniqueKey();
                    var gradientObject_1 = gradients[key] =
                            renderer.createElement(gradName)
                                .attr(gradAttr)
                                .add(renderer.defs);
                    gradientObject_1.radAttr = radAttr;
                    // The gradient needs to keep a list of stops to be able to
                    // destroy them
                    gradientObject_1.stops = [];
                    stops.forEach(function (stop) {
                        if (stop[1].indexOf('rgba') === 0) {
                            colorObject = Color_Color.parse(stop[1]);
                            stopColor = colorObject.get('rgb');
                            stopOpacity = colorObject.get('a');
                        }
                        else {
                            stopColor = stop[1];
                            stopOpacity = 1;
                        }
                        var stopObject = renderer.createElement('stop').attr({
                                offset: stop[0],
                                'stop-color': stopColor,
                                'stop-opacity': stopOpacity
                            }).add(gradientObject_1);
                        // Add the stop element to the gradient
                        gradientObject_1.stops.push(stopObject);
                    });
                }
                // Set the reference to the gradient object
                value = 'url(' + renderer.url + '#' + id + ')';
                elem.setAttribute(prop, value);
                elem.gradient = key;
                // Allow the color to be concatenated into tooltips formatters
                // etc. (#2995)
                colorOptions.toString = function () {
                    return value;
                };
            }
        });
    };
    /**
     * Set styles for the element. In addition to CSS styles supported by
     * native SVG and HTML elements, there are also some custom made for
     * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text
     * elements.
     *
     * @sample highcharts/members/renderer-text-on-chart/
     *         Styled text
     *
     * @function Highcharts.SVGElement#css
     *
     * @param {Highcharts.CSSObject} styles
     *        The new CSS styles.
     *
     * @return {Highcharts.SVGElement}
     *         Return the SVG element for chaining.
     */
    SVGElement.prototype.css = function (styles) {
        var oldStyles = this.styles,
            newStyles = {},
            elem = this.element;
        var textWidth,
            hasNew = !oldStyles;
        // Filter out existing styles to increase performance (#2640)
        if (oldStyles) {
            SVGElement_objectEach(styles, function (value, n) {
                if (oldStyles && oldStyles[n] !== value) {
                    newStyles[n] = value;
                    hasNew = true;
                }
            });
        }
        if (hasNew) {
            // Merge the new styles with the old ones
            if (oldStyles) {
                styles = SVGElement_extend(oldStyles, newStyles);
            }
            // Get the text width from style
            // Previously set, unset it (#8234)
            if (styles.width === null || styles.width === 'auto') {
                delete this.textWidth;
                // Apply new
            }
            else if (elem.nodeName.toLowerCase() === 'text' &&
                styles.width) {
                textWidth = this.textWidth = SVGElement_pInt(styles.width);
            }
            // Store object
            SVGElement_extend(this.styles, styles);
            if (textWidth && (!svg && this.renderer.forExport)) {
                delete styles.width;
            }
            var fontSize = isFirefox && styles.fontSize || null;
            // Necessary in firefox to be able to set font-size, #22124
            if (fontSize && (SVGElement_isNumber(fontSize) ||
                /^\d+$/.test(fontSize))) {
                styles.fontSize += 'px';
            }
            var stylesToApply_1 = SVGElement_merge(styles);
            if (elem.namespaceURI === this.SVG_NS) {
                // These CSS properties are interpreted internally by the SVG
                // renderer, but are not supported by SVG and should not be
                // added to the DOM. In styled mode, no CSS should find its way
                // to the DOM whatsoever (#6173, #6474).
                ['textOutline', 'textOverflow', 'whiteSpace', 'width'].forEach(function (key) { return (stylesToApply_1 &&
                    delete stylesToApply_1[key]); });
                // SVG requires fill for text
                if (stylesToApply_1.color) {
                    stylesToApply_1.fill = stylesToApply_1.color;
                }
            }
            SVGElement_css(elem, stylesToApply_1);
        }
        if (this.added) {
            // Rebuild text after added. Cache mechanisms in the buildText will
            // prevent building if there are no significant changes.
            if (this.element.nodeName === 'text') {
                this.renderer.buildText(this);
            }
            // Apply text outline after added
            if (styles.textOutline) {
                this.applyTextOutline(styles.textOutline);
            }
        }
        return this;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#dashstyleSetter
     * @param {string} value
     */
    SVGElement.prototype.dashstyleSetter = function (value) {
        var i,
            strokeWidth = this['stroke-width'];
        // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new
        // strokeWidth function, we should be able to use that instead.
        if (strokeWidth === 'inherit') {
            strokeWidth = 1;
        }
        value = value && value.toLowerCase();
        if (value) {
            var v = value
                    .replace('shortdashdotdot', '3,1,1,1,1,1,')
                    .replace('shortdashdot', '3,1,1,1')
                    .replace('shortdot', '1,1,')
                    .replace('shortdash', '3,1,')
                    .replace('longdash', '8,3,')
                    .replace(/dot/g, '1,3,')
                    .replace('dash', '4,3,')
                    .replace(/,$/, '')
                    .split(','); // Ending comma
                i = v.length;
            while (i--) {
                v[i] = '' + (SVGElement_pInt(v[i]) * SVGElement_pick(strokeWidth, NaN));
            }
            value = v.join(',').replace(/NaN/g, 'none'); // #3226
            this.element.setAttribute('stroke-dasharray', value);
        }
    };
    /**
     * Destroy the element and element wrapper and clear up the DOM and event
     * hooks.
     *
     * @function Highcharts.SVGElement#destroy
     */
    SVGElement.prototype.destroy = function () {
        var _a;
        var wrapper = this,
            element = wrapper.element || {},
            renderer = wrapper.renderer,
            ownerSVGElement = element.ownerSVGElement;
        var parentToClean = (element.nodeName === 'SPAN' &&
                wrapper.parentGroup ||
                void 0),
            grandParent,
            i;
        // Remove events
        element.onclick = element.onmouseout = element.onmouseover =
            element.onmousemove = element.point = null;
        SVGElement_stop(wrapper); // Stop running animations
        if (wrapper.clipPath && ownerSVGElement) {
            var clipPath_1 = wrapper.clipPath;
            // Look for existing references to this clipPath and remove them
            // before destroying the element (#6196).
            // The upper case version is for Edge
            [].forEach.call(ownerSVGElement.querySelectorAll('[clip-path],[CLIP-PATH]'), function (el) {
                if (el.getAttribute('clip-path').indexOf(clipPath_1.element.id) > -1) {
                    el.removeAttribute('clip-path');
                }
            });
            wrapper.clipPath = clipPath_1.destroy();
        }
        wrapper.connector = (_a = wrapper.connector) === null || _a === void 0 ? void 0 : _a.destroy();
        // Destroy stops in case this is a gradient object @todo old code?
        if (wrapper.stops) {
            for (i = 0; i < wrapper.stops.length; i++) {
                wrapper.stops[i].destroy();
            }
            wrapper.stops.length = 0;
            wrapper.stops = void 0;
        }
        // Remove element
        wrapper.safeRemoveChild(element);
        // In case of useHTML, clean up empty containers emulating SVG groups
        // (#1960, #2393, #2697).
        while (parentToClean &&
            parentToClean.div &&
            parentToClean.div.childNodes.length === 0) {
            grandParent = parentToClean.parentGroup;
            wrapper.safeRemoveChild(parentToClean.div);
            delete parentToClean.div;
            parentToClean = grandParent;
        }
        // Remove from alignObjects
        if (wrapper.alignOptions) {
            SVGElement_erase(renderer.alignedObjects, wrapper);
        }
        SVGElement_objectEach(wrapper, function (val, key) {
            // Destroy child elements of a group
            if (wrapper[key] &&
                wrapper[key].parentGroup === wrapper &&
                wrapper[key].destroy) {
                wrapper[key].destroy();
            }
            // Delete all properties
            delete wrapper[key];
        });
        return;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#dSettter
     * @param {number|string|Highcharts.SVGPathArray} value
     * @param {string} key
     * @param {Highcharts.SVGDOMElement} element
     */
    SVGElement.prototype.dSetter = function (value, key, element) {
        if (SVGElement_isArray(value)) {
            // Backwards compatibility, convert one-dimensional array into an
            // array of segments
            if (typeof value[0] === 'string') {
                value = this.renderer.pathToSegments(value);
            }
            this.pathArray = value;
            value = value.reduce(function (acc, seg, i) {
                if (!seg || !seg.join) {
                    return (seg || '').toString();
                }
                return (i ? acc + ' ' : '') + seg.join(' ');
            }, '');
        }
        if (/(NaN| {2}|^$)/.test(value)) {
            value = 'M 0 0';
        }
        // Check for cache before resetting. Resetting causes disturbance in the
        // DOM, causing flickering in some cases in Edge/IE (#6747). Also
        // possible performance gain.
        if (this[key] !== value) {
            element.setAttribute(key, value);
            this[key] = value;
        }
    };
    /**
     * @private
     * @function Highcharts.SVGElement#fillSetter
     * @param {Highcharts.ColorType} value
     * @param {string} key
     * @param {Highcharts.SVGDOMElement} element
     */
    SVGElement.prototype.fillSetter = function (value, key, element) {
        if (typeof value === 'string') {
            element.setAttribute(key, value);
        }
        else if (value) {
            this.complexColor(value, key, element);
        }
    };
    /**
     * @private
     * @function Highcharts.SVGElement#hrefSetter
     * @param {Highcharts.ColorType} value
     * @param {string} key
     * @param {Highcharts.SVGDOMElement} element
     */
    SVGElement.prototype.hrefSetter = function (value, key, element) {
        // Namespace is needed for offline export, #19106
        element.setAttributeNS('http://www.w3.org/1999/xlink', key, value);
    };
    /**
     * Get the bounding box (width, height, x and y) for the element. Generally
     * used to get rendered text size. Since this is called a lot in charts,
     * the results are cached based on text properties, in order to save DOM
     * traffic. The returned bounding box includes the rotation, so for example
     * a single text line of rotation 90 will report a greater height, and a
     * width corresponding to the line-height.
     *
     * @sample highcharts/members/renderer-on-chart/
     *         Draw a rectangle based on a text's bounding box
     *
     * @function Highcharts.SVGElement#getBBox
     *
     * @param {boolean} [reload]
     *        Skip the cache and get the updated DOM bounding box.
     *
     * @param {number} [rot]
     *        Override the element's rotation. This is internally used on axis
     *        labels with a value of 0 to find out what the bounding box would
     *        be have been if it were not rotated.
     *
     * @return {Highcharts.BBoxObject}
     *         The bounding box with `x`, `y`, `width` and `height` properties.
     */
    SVGElement.prototype.getBBox = function (reload, rot) {
        var wrapper = this,
            alignValue = wrapper.alignValue,
            element = wrapper.element,
            renderer = wrapper.renderer,
            styles = wrapper.styles,
            textStr = wrapper.textStr,
            cache = renderer.cache,
            cacheKeys = renderer.cacheKeys,
            isSVG = element.namespaceURI === wrapper.SVG_NS,
            rotation = SVGElement_pick(rot,
            wrapper.rotation, 0),
            fontSize = renderer.styledMode ? (element &&
                SVGElement.prototype.getStyle.call(element, 'font-size')) : (styles.fontSize);
        var bBox,
            height,
            toggleTextShadowShim,
            cacheKey;
        // Avoid undefined and null (#7316)
        if (SVGElement_defined(textStr)) {
            cacheKey = textStr.toString();
            // Since numbers are monospaced, and numerical labels appear a lot
            // in a chart, we assume that a label of n characters has the same
            // bounding box as others of the same length. Unless there is inner
            // HTML in the label. In that case, leave the numbers as is (#5899).
            if (cacheKey.indexOf('<') === -1) {
                cacheKey = cacheKey.replace(/\d/g, '0');
            }
            // Properties that affect bounding box
            cacheKey += [
                '',
                renderer.rootFontSize,
                fontSize,
                rotation,
                wrapper.textWidth, // #7874, also useHTML
                alignValue,
                styles.lineClamp,
                styles.textOverflow, // #5968
                styles.fontWeight // #12163
            ].join(',');
        }
        if (cacheKey && !reload) {
            bBox = cache[cacheKey];
        }
        // No cache found
        if (!bBox || bBox.polygon) {
            // SVG elements
            if (isSVG || renderer.forExport) {
                try { // Fails in Firefox if the container has display: none.
                    // When the text shadow shim is used, we need to hide the
                    // fake shadows to get the correct bounding box (#3872)
                    toggleTextShadowShim = this.fakeTS && function (display) {
                        var outline = element.querySelector('.highcharts-text-outline');
                        if (outline) {
                            SVGElement_css(outline, { display: display });
                        }
                    };
                    // Workaround for #3842, Firefox reporting wrong bounding
                    // box for shadows
                    if (SVGElement_isFunction(toggleTextShadowShim)) {
                        toggleTextShadowShim('none');
                    }
                    bBox = element.getBBox ?
                        // SVG: use extend because IE9 is not allowed to change
                        // width and height in case of rotation (below)
                        SVGElement_extend({}, element.getBBox()) : {
                        // HTML elements with `exporting.allowHTML` and
                        // legacy IE in export mode
                        width: element.offsetWidth,
                        height: element.offsetHeight,
                        x: 0,
                        y: 0
                    };
                    // #3842
                    if (SVGElement_isFunction(toggleTextShadowShim)) {
                        toggleTextShadowShim('');
                    }
                }
                catch (e) {
                    '';
                }
                // If the bBox is not set, the try-catch block above failed. The
                // other condition is for Opera that returns a width of
                // -Infinity on hidden elements.
                if (!bBox || bBox.width < 0) {
                    bBox = { x: 0, y: 0, width: 0, height: 0 };
                }
                // Use HTML within SVG
            }
            else {
                bBox = wrapper.htmlGetBBox();
            }
            // True SVG elements as well as HTML elements in modern browsers
            // using the .useHTML option need to compensated for rotation
            height = bBox.height;
            // Workaround for wrong bounding box in IE, Edge and Chrome on
            // Windows. With Highcharts' default font, IE and Edge report
            // a box height of 16.899 and Chrome rounds it to 17. If this
            // stands uncorrected, it results in more padding added below
            // the text than above when adding a label border or background.
            // Also vertical positioning is affected.
            // https://jsfiddle.net/highcharts/em37nvuj/
            // (#1101, #1505, #1669, #2568, #6213).
            if (isSVG) {
                bBox.height = height = ({
                    '11px,17': 14,
                    '13px,20': 16
                }["" + (fontSize || '') + ",".concat(Math.round(height))] ||
                    height);
            }
            // Adjust for rotated text
            if (rotation) {
                bBox = this.getRotatedBox(bBox, rotation);
            }
            // Create a reference to catch changes to bBox
            var e = { bBox: bBox };
            SVGElement_fireEvent(this, 'afterGetBBox', e);
            // Pick up any changes after the fired event
            bBox = e.bBox;
        }
        // Cache it. When loading a chart in a hidden iframe in Firefox and
        // IE/Edge, the bounding box height is 0, so don't cache it (#5620).
        if (cacheKey && (textStr === '' || bBox.height > 0)) {
            // Rotate (#4681)
            while (cacheKeys.length > 250) {
                delete cache[cacheKeys.shift()];
            }
            if (!cache[cacheKey]) {
                cacheKeys.push(cacheKey);
            }
            cache[cacheKey] = bBox;
        }
        return bBox;
    };
    /**
     * Get the rotated box.
     * @private
     */
    SVGElement.prototype.getRotatedBox = function (box, rotation) {
        var boxX = box.x,
            boxY = box.y,
            width = box.width,
            height = box.height,
            _a = this,
            alignValue = _a.alignValue,
            translateY = _a.translateY,
            _b = _a.rotationOriginX,
            rotationOriginX = _b === void 0 ? 0 : _b,
            _c = _a.rotationOriginY,
            rotationOriginY = _c === void 0 ? 0 : _c,
            alignFactor = SVGElement_getAlignFactor(alignValue),
            baseline = Number(this.element.getAttribute('y') || 0) -
                (translateY ? 0 : boxY),
            rad = rotation * deg2rad,
            rad90 = (rotation - 90) * deg2rad,
            cosRad = Math.cos(rad),
            sinRad = Math.sin(rad),
            wCosRad = width * cosRad,
            wSinRad = width * sinRad,
            cosRad90 = Math.cos(rad90),
            sinRad90 = Math.sin(rad90),
            _d = [
                rotationOriginX,
                rotationOriginY
            ].map(function (rotOrigin) { return [
                rotOrigin - (rotOrigin * cosRad),
                rotOrigin * sinRad
            ]; }),
            _e = _d[0],
            xOriginCosRad = _e[0],
            xOriginSinRad = _e[1],
            _f = _d[1],
            yOriginCosRad = _f[0],
            yOriginSinRad = _f[1], 
            // Find the starting point on the left side baseline of
            // the text
            pX = ((boxX + alignFactor * (width - wCosRad)) +
                xOriginCosRad + yOriginSinRad),
            pY = ((boxY + baseline - alignFactor * wSinRad) -
                xOriginSinRad + yOriginCosRad), 
            // Find all corners
            aX = pX + baseline * cosRad90,
            bX = aX + wCosRad,
            cX = bX - height * cosRad90,
            dX = cX - wCosRad,
            aY = pY + baseline * sinRad90,
            bY = aY + wSinRad,
            cY = bY - height * sinRad90,
            dY = cY - wSinRad;
        // Deduct the bounding box from the corners
        var x = Math.min(aX,
            bX,
            cX,
            dX),
            y = Math.min(aY,
            bY,
            cY,
            dY),
            boxWidth = Math.max(aX,
            bX,
            cX,
            dX) - x,
            boxHeight = Math.max(aY,
            bY,
            cY,
            dY) - y;
        /* Uncomment to debug boxes
        this.renderer.path([
            ['M', aX, aY],
            ['L', bX, bY],
            ['L', cX, cY],
            ['L', dX, dY],
            ['Z']
        ])
            .attr({
                stroke: 'red',
                'stroke-width': 1
            })
            .add();
        // */
        return {
            x: x,
            y: y,
            width: boxWidth,
            height: boxHeight,
            polygon: [
                [aX, aY],
                [bX, bY],
                [cX, cY],
                [dX, dY]
            ]
        };
    };
    /**
     * Get the computed style. Only in styled mode.
     *
     * @example
     * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px'
     *
     * @function Highcharts.SVGElement#getStyle
     *
     * @param {string} prop
     *        The property name to check for.
     *
     * @return {string}
     *         The current computed value.
     */
    SVGElement.prototype.getStyle = function (prop) {
        return SVGElement_win
            .getComputedStyle(this.element || this, '')
            .getPropertyValue(prop);
    };
    /**
     * Check if an element has the given class name.
     *
     * @function Highcharts.SVGElement#hasClass
     *
     * @param {string} className
     * The class name to check for.
     *
     * @return {boolean}
     * Whether the class name is found.
     */
    SVGElement.prototype.hasClass = function (className) {
        return ('' + this.attr('class'))
            .split(' ')
            .indexOf(className) !== -1;
    };
    /**
     * Hide the element, similar to setting the `visibility` attribute to
     * `hidden`.
     *
     * @function Highcharts.SVGElement#hide
     *
     * @return {Highcharts.SVGElement}
     *         Returns the SVGElement for chaining.
     */
    SVGElement.prototype.hide = function () {
        return this.attr({ visibility: 'hidden' });
    };
    /**
     * @private
     */
    SVGElement.prototype.htmlGetBBox = function () {
        return { height: 0, width: 0, x: 0, y: 0 };
    };
    /**
     * Add an event listener. This is a simple setter that replaces the
     * previous event of the same type added by this function, as opposed to
     * the {@link Highcharts#addEvent} function.
     *
     * @sample highcharts/members/element-on/
     *         A clickable rectangle
     *
     * @function Highcharts.SVGElement#on
     *
     * @param {string} eventType
     * The event type.
     *
     * @param {Function} handler
     * The handler callback.
     *
     * @return {Highcharts.SVGElement}
     * The SVGElement for chaining.
     */
    SVGElement.prototype.on = function (eventType, handler) {
        var onEvents = this.onEvents;
        if (onEvents[eventType]) {
            // Unbind existing event
            onEvents[eventType]();
        }
        onEvents[eventType] = SVGElement_addEvent(this.element, eventType, handler);
        return this;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#opacitySetter
     * @param {string} value
     * @param {string} key
     * @param {Highcharts.SVGDOMElement} element
     */
    SVGElement.prototype.opacitySetter = function (value, key, element) {
        // Round off to avoid float errors, like tests where opacity lands on
        // 9.86957e-06 instead of 0
        var opacity = Number(Number(value).toFixed(3));
        this.opacity = opacity;
        element.setAttribute(key, opacity);
    };
    /**
     * Re-align an aligned text or label after setting the text.
     *
     * @private
     * @function Highcharts.SVGElement#reAlign
     *
     */
    SVGElement.prototype.reAlign = function () {
        var _a;
        if (((_a = this.alignOptions) === null || _a === void 0 ? void 0 : _a.width) && this.alignOptions.align !== 'left') {
            this.alignOptions.width = this.getBBox().width;
            this.placed = false; // Block animation
            this.align();
        }
    };
    /**
     * Remove a class name from the element.
     *
     * @function Highcharts.SVGElement#removeClass
     *
     * @param {string|RegExp} className
     *        The class name to remove.
     *
     * @return {Highcharts.SVGElement} Returns the SVG element for chainability.
     */
    SVGElement.prototype.removeClass = function (className) {
        return this.attr('class', ('' + this.attr('class'))
            .replace(SVGElement_isString(className) ?
            new RegExp("(^| )".concat(className, "( |$)")) : // #12064, #13590
            className, ' ')
            .replace(/ +/g, ' ')
            .trim());
    };
    /**
     *
     * @private
     */
    SVGElement.prototype.removeTextOutline = function () {
        var outline = this.element
                .querySelector('tspan.highcharts-text-outline');
        if (outline) {
            this.safeRemoveChild(outline);
        }
    };
    /**
     * Removes an element from the DOM.
     *
     * @private
     * @function Highcharts.SVGElement#safeRemoveChild
     *
     * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
     * The DOM node to remove.
     */
    SVGElement.prototype.safeRemoveChild = function (element) {
        var parentNode = element.parentNode;
        if (parentNode) {
            parentNode.removeChild(element);
        }
    };
    /**
     * Set the coordinates needed to draw a consistent radial gradient across
     * a shape regardless of positioning inside the chart. Used on pie slices
     * to make all the slices have the same radial reference point.
     *
     * @function Highcharts.SVGElement#setRadialReference
     *
     * @param {Array<number>} coordinates
     * The center reference. The format is `[centerX, centerY, diameter]` in
     * pixels.
     *
     * @return {Highcharts.SVGElement}
     * Returns the SVGElement for chaining.
     */
    SVGElement.prototype.setRadialReference = function (coordinates) {
        var existingGradient = (this.element.gradient &&
                this.renderer.gradients[this.element.gradient]);
        this.element.radialReference = coordinates;
        // On redrawing objects with an existing gradient, the gradient needs
        // to be repositioned (#3801)
        if (existingGradient && existingGradient.radAttr) {
            existingGradient.animate(this.renderer.getRadialAttr(coordinates, existingGradient.radAttr));
        }
        return this;
    };
    /**
     * Add a shadow to the element. In styled mode, this method is not used,
     * instead use `defs` and filters.
     *
     * @example
     * renderer.rect(10, 100, 100, 100)
     *     .attr({ fill: 'red' })
     *     .shadow(true);
     *
     * @function Highcharts.SVGElement#shadow
     *
     * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions] The
     *        shadow options. If `true`, the default options are applied. If
     *        `false`, the current shadow will be removed.
     *
     * @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
     */
    SVGElement.prototype.shadow = function (shadowOptions) {
        var _a;
        var renderer = this.renderer,
            options = SVGElement_merge(((_a = this.parentGroup) === null || _a === void 0 ? void 0 : _a.rotation) === 90 ? {
                offsetX: -1,
                offsetY: -1
            } : {},
            SVGElement_isObject(shadowOptions) ? shadowOptions : {}),
            id = renderer.shadowDefinition(options);
        return this.attr({
            filter: shadowOptions ?
                "url(".concat(renderer.url, "#").concat(id, ")") :
                'none'
        });
    };
    /**
     * Show the element after it has been hidden.
     *
     * @function Highcharts.SVGElement#show
     *
     * @param {boolean} [inherit=true]
     *        Set the visibility attribute to `inherit` rather than `visible`.
     *        The difference is that an element with `visibility="visible"`
     *        will be visible even if the parent is hidden.
     *
     * @return {Highcharts.SVGElement}
     *         Returns the SVGElement for chaining.
     */
    SVGElement.prototype.show = function (inherit) {
        if (inherit === void 0) { inherit = true; }
        return this.attr({ visibility: inherit ? 'inherit' : 'visible' });
    };
    /**
     * Set the stroke-width and record it on the SVGElement
     *
     * @private
     * @function Highcharts.SVGElement#strokeSetter
     * @param {number|string|ColorType} value
     * @param {string} key
     * @param {Highcharts.SVGDOMElement} element
     */
    SVGElement.prototype['stroke-widthSetter'] = function (value, key, element) {
        // Record it for quick access in getter
        this[key] = value;
        element.setAttribute(key, value);
    };
    /**
     * Get the computed stroke width in pixel values. This is used extensively
     * when drawing shapes to ensure the shapes are rendered crisp and
     * positioned correctly relative to each other. Using
     * `shape-rendering: crispEdges` leaves us less control over positioning,
     * for example when we want to stack columns next to each other, or position
     * things pixel-perfectly within the plot box.
     *
     * The common pattern when placing a shape is:
     * - Create the SVGElement and add it to the DOM. In styled mode, it will
     *   now receive a stroke width from the style sheet. In classic mode we
     *   will add the `stroke-width` attribute.
     * - Read the computed `elem.strokeWidth()`.
     * - Place it based on the stroke width.
     *
     * @function Highcharts.SVGElement#strokeWidth
     *
     * @return {number}
     * The stroke width in pixels. Even if the given stroke width (in CSS or by
     * attributes) is based on `em` or other units, the pixel size is returned.
     */
    SVGElement.prototype.strokeWidth = function () {
        // In non-styled mode, read the stroke width as set by .attr
        if (!this.renderer.styledMode) {
            return this['stroke-width'] || 0;
        }
        // In styled mode, read computed stroke width
        var val = this.getStyle('stroke-width');
        var ret = 0,
            tempElement;
        // Read pixel values directly
        if (/px$/.test(val)) {
            ret = SVGElement_pInt(val);
            // Other values like em, pt etc need to be measured
        }
        else if (val !== '') {
            tempElement = SVGElement_doc.createElementNS(SVGElement_SVG_NS, 'rect');
            SVGElement_attr(tempElement, {
                width: val,
                'stroke-width': 0
            });
            this.element.parentNode.appendChild(tempElement);
            ret = tempElement.getBBox().width;
            tempElement.parentNode.removeChild(tempElement);
        }
        return ret;
    };
    /**
     * If one of the symbol size affecting parameters are changed,
     * check all the others only once for each call to an element's
     * .attr() method
     *
     * @private
     * @function Highcharts.SVGElement#symbolAttr
     *
     * @param {Highcharts.SVGAttributes} hash
     * The attributes to set.
     */
    SVGElement.prototype.symbolAttr = function (hash) {
        var wrapper = this;
        SVGElement.symbolCustomAttribs.forEach(function (key) {
            wrapper[key] = SVGElement_pick(hash[key], wrapper[key]);
        });
        wrapper.attr({
            d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper)
        });
    };
    /**
     * @private
     * @function Highcharts.SVGElement#textSetter
     * @param {string} value
     */
    SVGElement.prototype.textSetter = function (value) {
        if (value !== this.textStr) {
            // Delete size caches when the text changes
            // delete this.bBox; // old code in series-label
            delete this.textPxLength;
            this.textStr = value;
            if (this.added) {
                this.renderer.buildText(this);
            }
            this.reAlign();
        }
    };
    /**
     * @private
     * @function Highcharts.SVGElement#titleSetter
     * @param {string} value
     */
    SVGElement.prototype.titleSetter = function (value) {
        var el = this.element;
        var titleNode = el.getElementsByTagName('title')[0] ||
                SVGElement_doc.createElementNS(this.SVG_NS, 'title');
        // Move to first child
        if (el.insertBefore) {
            el.insertBefore(titleNode, el.firstChild);
        }
        else {
            el.appendChild(titleNode);
        }
        // Replace text content and escape markup
        titleNode.textContent = SVGElement_replaceNested(// Scan #[73]
        SVGElement_pick(value, ''), // #3276, #3895
        [/<[^>]*>/g, '']).replace(/&lt;/g, '<').replace(/&gt;/g, '>');
    };
    /**
     * Bring the element to the front. Alternatively, a new zIndex can be set.
     *
     * @sample highcharts/members/element-tofront/
     *         Click an element to bring it to front
     *
     * @function Highcharts.SVGElement#toFront
     *
     * @return {Highcharts.SVGElement}
     * Returns the SVGElement for chaining.
     */
    SVGElement.prototype.toFront = function () {
        var element = this.element;
        element.parentNode.appendChild(element);
        return this;
    };
    /**
     * Move an object and its children by x and y values.
     *
     * @function Highcharts.SVGElement#translate
     *
     * @param {number} x
     * The x value.
     *
     * @param {number} y
     * The y value.
     *
     * @return {Highcharts.SVGElement}
     * Translated element.
     */
    SVGElement.prototype.translate = function (x, y) {
        return this.attr({
            translateX: x,
            translateY: y
        });
    };
    /**
     * Update the transform attribute based on internal properties. Deals with
     * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY`
     * attributes and updates the SVG `transform` attribute.
     *
     * @private
     * @function Highcharts.SVGElement#updateTransform
     */
    SVGElement.prototype.updateTransform = function (attrib) {
        var _a;
        if (attrib === void 0) { attrib = 'transform'; }
        var _b = this,
            element = _b.element,
            matrix = _b.matrix,
            _c = _b.rotation,
            rotation = _c === void 0 ? 0 : _c,
            rotationOriginX = _b.rotationOriginX,
            rotationOriginY = _b.rotationOriginY,
            scaleX = _b.scaleX,
            scaleY = _b.scaleY,
            _d = _b.translateX,
            translateX = _d === void 0 ? 0 : _d,
            _e = _b.translateY,
            translateY = _e === void 0 ? 0 : _e;
        // Apply translate. Nearly all transformed elements have translation,
        // so instead of checking for translate = 0, do it always (#1767,
        // #1846).
        var transform = ['translate(' + translateX + ',' + translateY + ')'];
        // Apply matrix
        if (SVGElement_defined(matrix)) {
            transform.push('matrix(' + matrix.join(',') + ')');
        }
        // Apply rotation
        if (rotation) {
            transform.push('rotate(' + rotation + ' ' +
                SVGElement_pick(rotationOriginX, element.getAttribute('x'), 0) +
                ' ' +
                SVGElement_pick(rotationOriginY, element.getAttribute('y') || 0) + ')');
            // HTML labels rotation (#20685)
            if (((_a = this.text) === null || _a === void 0 ? void 0 : _a.element.tagName) === 'SPAN') {
                this.text.attr({
                    rotation: rotation,
                    rotationOriginX: (rotationOriginX || 0) - this.padding,
                    rotationOriginY: (rotationOriginY || 0) - this.padding
                });
            }
        }
        // Apply scale
        if (SVGElement_defined(scaleX) || SVGElement_defined(scaleY)) {
            transform.push('scale(' + SVGElement_pick(scaleX, 1) + ' ' + SVGElement_pick(scaleY, 1) + ')');
        }
        if (transform.length && !(this.text || this).textPath) {
            element.setAttribute(attrib, transform.join(' '));
        }
    };
    /**
     * @private
     * @function Highcharts.SVGElement#visibilitySetter
     *
     * @param {string} value
     *
     * @param {string} key
     *
     * @param {Highcharts.SVGDOMElement} element
     *
     */
    SVGElement.prototype.visibilitySetter = function (value, key, element) {
        // IE9-11 doesn't handle visibility:inherit well, so we remove the
        // attribute instead (#2881, #3909)
        if (value === 'inherit') {
            element.removeAttribute(key);
        }
        else if (this[key] !== value) { // #6747
            element.setAttribute(key, value);
        }
        this[key] = value;
    };
    /**
     * @private
     * @function Highcharts.SVGElement#xGetter
     */
    SVGElement.prototype.xGetter = function (key) {
        if (this.element.nodeName === 'circle') {
            if (key === 'x') {
                key = 'cx';
            }
            else if (key === 'y') {
                key = 'cy';
            }
        }
        return this._defaultGetter(key);
    };
    /**
     * @private
     * @function Highcharts.SVGElement#zIndexSetter
     */
    SVGElement.prototype.zIndexSetter = function (value, key) {
        var renderer = this.renderer,
            parentGroup = this.parentGroup,
            parentWrapper = parentGroup || renderer,
            parentNode = parentWrapper.element || renderer.box,
            element = this.element,
            svgParent = parentNode === renderer.box;
        var childNodes,
            otherElement,
            otherZIndex,
            inserted = false,
            undefinedOtherZIndex,
            run = this.added,
            i;
        if (SVGElement_defined(value)) {
            // So we can read it for other elements in the group
            element.setAttribute('data-z-index', value);
            value = +value;
            if (this[key] === value) {
                // Only update when needed (#3865)
                run = false;
            }
        }
        else if (SVGElement_defined(this[key])) {
            element.removeAttribute('data-z-index');
        }
        this[key] = value;
        // Insert according to this and other elements' zIndex. Before .add() is
        // called, nothing is done. Then on add, or by later calls to
        // zIndexSetter, the node is placed on the right place in the DOM.
        if (run) {
            value = this.zIndex;
            if (value && parentGroup) {
                parentGroup.handleZ = true;
            }
            childNodes = parentNode.childNodes;
            for (i = childNodes.length - 1; i >= 0 && !inserted; i--) {
                otherElement = childNodes[i];
                otherZIndex = otherElement.getAttribute('data-z-index');
                undefinedOtherZIndex = !SVGElement_defined(otherZIndex);
                if (otherElement !== element) {
                    if (
                    // Negative zIndex versus no zIndex:
                    // On all levels except the highest. If the parent is
                    // <svg>, then we don't want to put items before <desc>
                    // or <defs>
                    value < 0 &&
                        undefinedOtherZIndex &&
                        !svgParent &&
                        !i) {
                        parentNode.insertBefore(element, childNodes[i]);
                        inserted = true;
                    }
                    else if (
                    // Insert after the first element with a lower zIndex
                    SVGElement_pInt(otherZIndex) <= value ||
                        // If negative zIndex, add this before first undefined
                        // zIndex element
                        (undefinedOtherZIndex &&
                            (!SVGElement_defined(value) || value >= 0))) {
                        parentNode.insertBefore(element, childNodes[i + 1]);
                        inserted = true;
                    }
                }
            }
            if (!inserted) {
                parentNode.insertBefore(element, childNodes[svgParent ? 3 : 0]);
                inserted = true;
            }
        }
        return inserted;
    };
    /* *
     *
     *  Properties
     *
     * */
    // Custom attributes used for symbols, these should be filtered out when
    // setting SVGElement attributes (#9375).
    SVGElement.symbolCustomAttribs = [
        'anchorX',
        'anchorY',
        'clockwise',
        'end',
        'height',
        'innerR',
        'r',
        'start',
        'width',
        'x',
        'y'
    ];
    return SVGElement;
}());
// Some shared setters and getters
SVGElement.prototype.strokeSetter = SVGElement.prototype.fillSetter;
SVGElement.prototype.yGetter = SVGElement.prototype.xGetter;
SVGElement.prototype.matrixSetter =
    SVGElement.prototype.rotationOriginXSetter =
        SVGElement.prototype.rotationOriginYSetter =
            SVGElement.prototype.rotationSetter =
                SVGElement.prototype.scaleXSetter =
                    SVGElement.prototype.scaleYSetter =
                        SVGElement.prototype.translateXSetter =
                            SVGElement.prototype.translateYSetter =
                                SVGElement.prototype.verticalAlignSetter = function (value, key) {
                                    this[key] = value;
                                    this.doTransform = true;
                                };
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var SVG_SVGElement = (SVGElement);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Reference to the global SVGElement class as a workaround for a name conflict
 * in the Highcharts namespace.
 *
 * @global
 * @typedef {global.SVGElement} GlobalSVGElement
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
 */
/**
 * The horizontal alignment of an element.
 *
 * @typedef {"center"|"left"|"right"} Highcharts.AlignValue
 */
/**
 * Options to align the element relative to the chart or another box.
 *
 * @interface Highcharts.AlignObject
 */ /**
* Horizontal alignment. Can be one of `left`, `center` and `right`.
*
* @name Highcharts.AlignObject#align
* @type {Highcharts.AlignValue|undefined}
*
* @default left
*/ /**
* Vertical alignment. Can be one of `top`, `middle` and `bottom`.
*
* @name Highcharts.AlignObject#verticalAlign
* @type {Highcharts.VerticalAlignValue|undefined}
*
* @default top
*/ /**
* Horizontal pixel offset from alignment.
*
* @name Highcharts.AlignObject#x
* @type {number|undefined}
*
* @default 0
*/ /**
* Vertical pixel offset from alignment.
*
* @name Highcharts.AlignObject#y
* @type {number|undefined}
*
* @default 0
*/ /**
* Use the `transform` attribute with translateX and translateY custom
* attributes to align this elements rather than `x` and `y` attributes.
*
* @name Highcharts.AlignObject#alignByTranslate
* @type {boolean|undefined}
*
* @default false
*/
/**
 * Bounding box of an element.
 *
 * @interface Highcharts.BBoxObject
 * @extends Highcharts.PositionObject
 */ /**
* Height of the bounding box.
*
* @name Highcharts.BBoxObject#height
* @type {number}
*/ /**
* Width of the bounding box.
*
* @name Highcharts.BBoxObject#width
* @type {number}
*/ /**
* Horizontal position of the bounding box.
*
* @name Highcharts.BBoxObject#x
* @type {number}
*/ /**
* Vertical position of the bounding box.
*
* @name Highcharts.BBoxObject#y
* @type {number}
*/
/**
 * An object of key-value pairs for SVG attributes. Attributes in Highcharts
 * elements for the most parts correspond to SVG, but some are specific to
 * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`,
 * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG
 * attributes containing a hyphen are _not_ camel-cased, they should be
 * quoted to preserve the hyphen.
 *
 * @example
 * {
 *     'stroke': '#ff0000', // basic
 *     'stroke-width': 2, // hyphenated
 *     'rotation': 45 // custom
 *     'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format
 * }
 *
 * @interface Highcharts.SVGAttributes
 */ /**
* @name Highcharts.SVGAttributes#[key:string]
* @type {*}
*/ /**
* @name Highcharts.SVGAttributes#d
* @type {string|Highcharts.SVGPathArray|undefined}
*/ /**
* @name Highcharts.SVGAttributes#dx
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#dy
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#fill
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
*/ /**
* @name Highcharts.SVGAttributes#inverted
* @type {boolean|undefined}
*/ /**
* @name Highcharts.SVGAttributes#matrix
* @type {Array<number>|undefined}
*/ /**
* @name Highcharts.SVGAttributes#rotation
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#rotationOriginX
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#rotationOriginY
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#scaleX
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#scaleY
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#stroke
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
*/ /**
* @name Highcharts.SVGAttributes#style
* @type {string|Highcharts.CSSObject|undefined}
*/ /**
* @name Highcharts.SVGAttributes#translateX
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#translateY
* @type {number|undefined}
*/ /**
* @name Highcharts.SVGAttributes#zIndex
* @type {number|undefined}
*/
/**
 * An SVG DOM element. The type is a reference to the regular SVGElement in the
 * global scope.
 *
 * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
 */
/**
 * The vertical alignment of an element.
 *
 * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Renderer/SVG/SVGLabel.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */
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 SVGLabel_defined = Core_Utilities.defined, SVGLabel_extend = Core_Utilities.extend, SVGLabel_getAlignFactor = Core_Utilities.getAlignFactor, SVGLabel_isNumber = Core_Utilities.isNumber, SVGLabel_merge = Core_Utilities.merge, SVGLabel_pick = Core_Utilities.pick, SVGLabel_removeEvent = Core_Utilities.removeEvent;
/* *
 *
 *  Class
 *
 * */
/**
 * SVG label to render text.
 * @private
 * @class
 * @name Highcharts.SVGLabel
 * @augments Highcharts.SVGElement
 */
var SVGLabel = /** @class */ (function (_super) {
    __extends(SVGLabel, _super);
    /* *
     *
     *  Constructor
     *
     * */
    function SVGLabel(renderer, str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
        var _this = _super.call(this,
            renderer, 'g') || this;
        _this.paddingLeftSetter = _this.paddingSetter;
        _this.paddingRightSetter = _this.paddingSetter;
        _this.doUpdate = false;
        _this.textStr = str;
        _this.x = x;
        _this.y = y;
        _this.anchorX = anchorX;
        _this.anchorY = anchorY;
        _this.baseline = baseline;
        _this.className = className;
        _this.addClass(className === 'button' ?
            'highcharts-no-tooltip' :
            'highcharts-label');
        if (className) {
            _this.addClass('highcharts-' + className);
        }
        // Create the text element. An undefined text content prevents redundant
        // box calculation (#16121)
        _this.text = renderer.text(void 0, 0, 0, useHTML).attr({ zIndex: 1 });
        // Validate the shape argument
        var hasBGImage;
        if (typeof shape === 'string') {
            hasBGImage = /^url\((.*?)\)$/.test(shape);
            if (hasBGImage || _this.renderer.symbols[shape]) {
                _this.symbolKey = shape;
            }
        }
        _this.bBox = SVGLabel.emptyBBox;
        _this.padding = 3;
        _this.baselineOffset = 0;
        _this.needsBox = renderer.styledMode || hasBGImage;
        _this.deferredAttr = {};
        _this.alignFactor = 0;
        return _this;
    }
    /* *
     *
     *  Functions
     *
     * */
    SVGLabel.prototype.alignSetter = function (value) {
        var alignFactor = SVGLabel_getAlignFactor(value);
        this.textAlign = value;
        if (alignFactor !== this.alignFactor) {
            this.alignFactor = alignFactor;
            // Bounding box exists, means we're dynamically changing
            if (this.bBox && SVGLabel_isNumber(this.xSetting)) {
                this.attr({ x: this.xSetting }); // #5134
            }
        }
    };
    SVGLabel.prototype.anchorXSetter = function (value, key) {
        this.anchorX = value;
        this.boxAttr(key, Math.round(value) - this.getCrispAdjust() - this.xSetting);
    };
    SVGLabel.prototype.anchorYSetter = function (value, key) {
        this.anchorY = value;
        this.boxAttr(key, value - this.ySetting);
    };
    /*
     * Set a box attribute, or defer it if the box is not yet created
     */
    SVGLabel.prototype.boxAttr = function (key, value) {
        if (this.box) {
            this.box.attr(key, value);
        }
        else {
            this.deferredAttr[key] = value;
        }
    };
    /*
     * Pick up some properties and apply them to the text instead of the
     * wrapper.
     */
    SVGLabel.prototype.css = function (styles) {
        if (styles) {
            var textStyles_1 = {};
            // Create a copy to avoid altering the original object
            // (#537)
            styles = SVGLabel_merge(styles);
            SVGLabel.textProps.forEach(function (prop) {
                if (typeof styles[prop] !== 'undefined') {
                    textStyles_1[prop] = styles[prop];
                    delete styles[prop];
                }
            });
            this.text.css(textStyles_1);
            // Update existing text, box (#9400, #12163, #18212)
            if ('fontSize' in textStyles_1 || 'fontWeight' in textStyles_1) {
                this.updateTextPadding();
            }
            else if ('width' in textStyles_1 || 'textOverflow' in textStyles_1) {
                this.updateBoxSize();
            }
        }
        return SVG_SVGElement.prototype.css.call(this, styles);
    };
    /*
     * Destroy and release memory.
     */
    SVGLabel.prototype.destroy = function () {
        // Added by button implementation
        SVGLabel_removeEvent(this.element, 'mouseenter');
        SVGLabel_removeEvent(this.element, 'mouseleave');
        if (this.text) {
            this.text.destroy();
        }
        if (this.box) {
            this.box = this.box.destroy();
        }
        // Call base implementation to destroy the rest
        SVG_SVGElement.prototype.destroy.call(this);
        return void 0;
    };
    SVGLabel.prototype.fillSetter = function (value, key) {
        if (value) {
            this.needsBox = true;
        }
        // For animation getter (#6776)
        this.fill = value;
        this.boxAttr(key, value);
    };
    /*
     * Return the bounding box of the box, not the group.
     */
    SVGLabel.prototype.getBBox = function (reload, rot) {
        // If we have a text string and the DOM bBox was 0, it typically means
        // that the label was first rendered hidden, so we need to update the
        // bBox (#15246)
        if (this.textStr && this.bBox.width === 0 && this.bBox.height === 0) {
            this.updateBoxSize();
        }
        var _a = this,
            padding = _a.padding,
            _b = _a.height,
            height = _b === void 0 ? 0 : _b,
            _c = _a.translateX,
            translateX = _c === void 0 ? 0 : _c,
            _d = _a.translateY,
            translateY = _d === void 0 ? 0 : _d,
            _e = _a.width,
            width = _e === void 0 ? 0 : _e,
            paddingLeft = SVGLabel_pick(this.paddingLeft,
            padding),
            rotation = rot !== null && rot !== void 0 ? rot : (this.rotation || 0);
        var bBox = {
                width: width,
                height: height,
                x: translateX + this.bBox.x - paddingLeft,
                y: translateY + this.bBox.y - padding + this.baselineOffset
            };
        if (rotation) {
            bBox = this.getRotatedBox(bBox, rotation);
        }
        return bBox;
    };
    SVGLabel.prototype.getCrispAdjust = function () {
        return (this.renderer.styledMode && this.box ?
            this.box.strokeWidth() :
            (this['stroke-width'] ?
                parseInt(this['stroke-width'], 10) :
                0)) % 2 / 2;
    };
    SVGLabel.prototype.heightSetter = function (value) {
        this.heightSetting = value;
        this.doUpdate = true;
    };
    /**
     * This method is executed in the end of `attr()`, after setting all
     * attributes in the hash. In can be used to efficiently consolidate
     * multiple attributes in one SVG property -- e.g., translate, rotate and
     * scale are merged in one "transform" attribute in the SVG node.
     * Also updating height or width should trigger update of the box size.
     *
     * @private
     * @function Highcharts.SVGLabel#afterSetters
     */
    SVGLabel.prototype.afterSetters = function () {
        _super.prototype.afterSetters.call(this);
        if (this.doUpdate) {
            this.updateBoxSize();
            this.doUpdate = false;
        }
    };
    /*
     * After the text element is added, get the desired size of the border
     * box and add it before the text in the DOM.
     */
    SVGLabel.prototype.onAdd = function () {
        this.text.add(this);
        this.attr({
            // Alignment is available now  (#3295, 0 not rendered if given
            // as a value)
            text: SVGLabel_pick(this.textStr, ''),
            x: this.x || 0,
            y: this.y || 0
        });
        if (this.box && SVGLabel_defined(this.anchorX)) {
            this.attr({
                anchorX: this.anchorX,
                anchorY: this.anchorY
            });
        }
    };
    SVGLabel.prototype.paddingSetter = function (value, key) {
        if (!SVGLabel_isNumber(value)) {
            this[key] = void 0;
        }
        else if (value !== this[key]) {
            this[key] = value;
            this.updateTextPadding();
        }
    };
    SVGLabel.prototype.rSetter = function (value, key) {
        this.boxAttr(key, value);
    };
    SVGLabel.prototype.strokeSetter = function (value, key) {
        // For animation getter (#6776)
        this.stroke = value;
        this.boxAttr(key, value);
    };
    SVGLabel.prototype['stroke-widthSetter'] = function (value, key) {
        if (value) {
            this.needsBox = true;
        }
        this['stroke-width'] = value;
        this.boxAttr(key, value);
    };
    SVGLabel.prototype['text-alignSetter'] = function (value) {
        // The text-align variety is for the pre-animation getter. The code
        // should be unified to either textAlign or text-align.
        this.textAlign = this['text-align'] = value;
        this.updateTextPadding();
    };
    SVGLabel.prototype.textSetter = function (text) {
        if (typeof text !== 'undefined') {
            // Must use .attr to ensure transforms are done (#10009)
            this.text.attr({ text: text });
        }
        this.updateTextPadding();
        this.reAlign();
    };
    /*
     * This function runs after the label is added to the DOM (when the bounding
     * box is available), and after the text of the label is updated to detect
     * the new bounding box and reflect it in the border box.
     */
    SVGLabel.prototype.updateBoxSize = function () {
        var text = this.text,
            attribs = {},
            padding = this.padding, 
            // #12165 error when width is null (auto)
            // #12163 when fontweight: bold, recalculate bBox without cache
            // #3295 && 3514 box failure when string equals 0
            bBox = this.bBox = (((!SVGLabel_isNumber(this.widthSetting) ||
                !SVGLabel_isNumber(this.heightSetting) ||
                this.textAlign) && SVGLabel_defined(text.textStr)) ?
                text.getBBox(void 0, 0) :
                SVGLabel.emptyBBox);
        var crispAdjust;
        this.width = this.getPaddedWidth();
        this.height = (this.heightSetting || bBox.height || 0) + 2 * padding;
        var metrics = this.renderer.fontMetrics(text);
        // Update the label-scoped y offset. Math.min because of inline
        // style (#9400)
        this.baselineOffset = padding + Math.min(
        // When applicable, use the font size of the first line (#15707)
        (this.text.firstLineMetrics || metrics).b, 
        // When the height is 0, there is no bBox, so go with the font
        // metrics. Highmaps CSS demos.
        bBox.height || Infinity);
        // #15491: Vertical centering
        if (this.heightSetting) {
            this.baselineOffset += (this.heightSetting - metrics.h) / 2;
        }
        if (this.needsBox && !text.textPath) {
            // Create the border box if it is not already present
            if (!this.box) {
                // Symbol definition exists (#5324)
                var box = this.box = this.symbolKey ?
                        this.renderer.symbol(this.symbolKey) :
                        this.renderer.rect();
                box.addClass(// Don't use label className for buttons
                (this.className === 'button' ?
                    '' : 'highcharts-label-box') +
                    (this.className ?
                        ' highcharts-' + this.className + '-box' : ''));
                box.add(this);
            }
            crispAdjust = this.getCrispAdjust();
            attribs.x = crispAdjust;
            attribs.y = ((this.baseline ? -this.baselineOffset : 0) + crispAdjust);
            // Apply the box attributes
            attribs.width = Math.round(this.width);
            attribs.height = Math.round(this.height);
            this.box.attr(SVGLabel_extend(attribs, this.deferredAttr));
            this.deferredAttr = {};
        }
    };
    /*
     * This function runs after setting text or padding, but only if padding
     * is changed.
     */
    SVGLabel.prototype.updateTextPadding = function () {
        var _a,
            _b;
        var text = this.text,
            textAlign = text.styles.textAlign || this.textAlign;
        if (!text.textPath) {
            this.updateBoxSize();
            // Determine y based on the baseline
            var textY = this.baseline ? 0 : this.baselineOffset,
                textX = ((_a = this.paddingLeft) !== null && _a !== void 0 ? _a : this.padding) +
                    // Compensate for alignment
                    SVGLabel_getAlignFactor(textAlign) * ((_b = this.widthSetting) !== null && _b !== void 0 ? _b : this.bBox.width);
            // Update if anything changed
            if (textX !== text.x || textY !== text.y) {
                text.attr({
                    align: textAlign,
                    x: textX
                });
                if (typeof textY !== 'undefined') {
                    text.attr('y', textY);
                }
            }
            // Record current values
            text.x = textX;
            text.y = textY;
        }
    };
    SVGLabel.prototype.widthSetter = function (value) {
        // `width:auto` => null
        this.widthSetting = SVGLabel_isNumber(value) ? value : void 0;
        this.doUpdate = true;
    };
    SVGLabel.prototype.getPaddedWidth = function () {
        var padding = this.padding;
        var paddingLeft = SVGLabel_pick(this.paddingLeft,
            padding);
        var paddingRight = SVGLabel_pick(this.paddingRight,
            padding);
        return ((this.widthSetting || this.bBox.width || 0) +
            paddingLeft +
            paddingRight);
    };
    SVGLabel.prototype.xSetter = function (value) {
        this.x = value; // For animation getter
        if (this.alignFactor) {
            value -= this.alignFactor * this.getPaddedWidth();
            // Force animation even when setting to the same value (#7898)
            this['forceAnimate:x'] = true;
        }
        this.xSetting = Math.round(value);
        this.attr('translateX', this.xSetting);
    };
    SVGLabel.prototype.ySetter = function (value) {
        this.ySetting = this.y = Math.round(value);
        this.attr('translateY', this.ySetting);
    };
    /* *
     *
     *  Static Properties
     *
     * */
    SVGLabel.emptyBBox = {
        width: 0,
        height: 0,
        x: 0,
        y: 0
    };
    /**
     * For labels, these CSS properties are applied to the `text` node directly.
     *
     * @private
     * @name Highcharts.SVGLabel#textProps
     * @type {Array<string>}
     */
    SVGLabel.textProps = [
        'color', 'direction', 'fontFamily', 'fontSize', 'fontStyle',
        'fontWeight', 'lineClamp', 'lineHeight', 'textAlign', 'textDecoration',
        'textOutline', 'textOverflow', 'whiteSpace', 'width'
    ];
    return SVGLabel;
}(SVG_SVGElement));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var SVG_SVGLabel = (SVGLabel);

;// ./code/es5/es-modules/Core/Renderer/SVG/Symbols.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Symbols_defined = Core_Utilities.defined, Symbols_isNumber = Core_Utilities.isNumber, Symbols_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/* eslint-disable require-jsdoc, valid-jsdoc */
/**
 *
 */
function arc(cx, cy, w, h, options) {
    var arc = [];
    if (options) {
        var start = options.start || 0,
            rx = Symbols_pick(options.r,
            w),
            ry = Symbols_pick(options.r,
            h || w), 
            // Subtract a small number to prevent cos and sin of start and end
            // from becoming equal on 360 arcs (#1561). The size of the circle
            // affects the constant, therefore the division by `rx`. If the
            // proximity is too small, the arc disappears. If it is too great, a
            // gap appears. This can be seen in the animation of the official
            // bubble demo (#20586).
            proximity = 0.0002 / (options.borderRadius ? 1 : Math.max(rx, 1)),
            fullCircle = (Math.abs((options.end || 0) - start - 2 * Math.PI) <
                proximity),
            end = (options.end || 0) - (fullCircle ? proximity : 0),
            innerRadius = options.innerR,
            open_1 = Symbols_pick(options.open,
            fullCircle),
            cosStart = Math.cos(start),
            sinStart = Math.sin(start),
            cosEnd = Math.cos(end),
            sinEnd = Math.sin(end), 
            // Proximity takes care of rounding errors around PI (#6971)
            longArc = Symbols_pick(options.longArc,
            end - start - Math.PI < proximity ? 0 : 1);
        var arcSegment = [
                'A', // ArcTo
                rx, // X radius
                ry, // Y radius
                0, // Slanting
                longArc, // Long or short arc
                Symbols_pick(options.clockwise, 1), // Clockwise
                cx + rx * cosEnd,
                cy + ry * sinEnd
            ];
        arcSegment.params = { start: start, end: end, cx: cx, cy: cy }; // Memo for border radius
        arc.push([
            'M',
            cx + rx * cosStart,
            cy + ry * sinStart
        ], arcSegment);
        if (Symbols_defined(innerRadius)) {
            arcSegment = [
                'A', // ArcTo
                innerRadius, // X radius
                innerRadius, // Y radius
                0, // Slanting
                longArc, // Long or short arc
                // Clockwise - opposite to the outer arc clockwise
                Symbols_defined(options.clockwise) ? 1 - options.clockwise : 0,
                cx + innerRadius * cosStart,
                cy + innerRadius * sinStart
            ];
            // Memo for border radius
            arcSegment.params = {
                start: end,
                end: start,
                cx: cx,
                cy: cy
            };
            arc.push(open_1 ?
                [
                    'M',
                    cx + innerRadius * cosEnd,
                    cy + innerRadius * sinEnd
                ] : [
                'L',
                cx + innerRadius * cosEnd,
                cy + innerRadius * sinEnd
            ], arcSegment);
        }
        if (!open_1) {
            arc.push(['Z']);
        }
    }
    return arc;
}
/**
 * Callout shape used for default tooltips.
 */
function callout(x, y, w, h, options) {
    var arrowLength = 6,
        halfDistance = 6,
        r = Math.min((options && options.r) || 0,
        w,
        h),
        safeDistance = r + halfDistance,
        anchorX = options && options.anchorX,
        anchorY = options && options.anchorY || 0;
    var path = roundedRect(x,
        y,
        w,
        h, { r: r });
    if (!Symbols_isNumber(anchorX)) {
        return path;
    }
    // Do not render a connector, if anchor starts inside the label
    if (anchorX < w && anchorX > 0 && anchorY < h && anchorY > 0) {
        return path;
    }
    // Anchor on right side
    if (x + anchorX > w - safeDistance) {
        // Chevron
        if (anchorY > y + safeDistance &&
            anchorY < y + h - safeDistance) {
            path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]);
            // Simple connector
        }
        else {
            if (anchorX < w) { // Corner connector
                var isTopCorner = anchorY < y + safeDistance,
                    cornerY = isTopCorner ? y : y + h,
                    sliceStart = isTopCorner ? 2 : 5;
                path.splice(sliceStart, 0, ['L', anchorX, anchorY], ['L', x + w - r, cornerY]);
            }
            else { // Side connector
                path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]);
            }
        }
        // Anchor on left side
    }
    else if (x + anchorX < safeDistance) {
        // Chevron
        if (anchorY > y + safeDistance &&
            anchorY < y + h - safeDistance) {
            path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]);
            // Simple connector
        }
        else {
            if (anchorX > 0) { // Corner connector
                var isTopCorner = anchorY < y + safeDistance,
                    cornerY = isTopCorner ? y : y + h,
                    sliceStart = isTopCorner ? 1 : 6;
                path.splice(sliceStart, 0, ['L', anchorX, anchorY], ['L', x + r, cornerY]);
            }
            else { // Side connector
                path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]);
            }
        }
    }
    else if ( // Replace bottom
    anchorY > h &&
        anchorX < w - safeDistance) {
        path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]);
    }
    else if ( // Replace top
    anchorY < 0 &&
        anchorX > safeDistance) {
        path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]);
    }
    return path;
}
/**
 *
 */
function circle(x, y, w, h) {
    // Return a full arc
    return arc(x + w / 2, y + h / 2, w / 2, h / 2, {
        start: Math.PI * 0.5,
        end: Math.PI * 2.5,
        open: false
    });
}
/**
 *
 */
function diamond(x, y, w, h) {
    return [
        ['M', x + w / 2, y],
        ['L', x + w, y + h / 2],
        ['L', x + w / 2, y + h],
        ['L', x, y + h / 2],
        ['Z']
    ];
}
// #15291
/**
 *
 */
function rect(x, y, w, h, options) {
    if (options && options.r) {
        return roundedRect(x, y, w, h, options);
    }
    return [
        ['M', x, y],
        ['L', x + w, y],
        ['L', x + w, y + h],
        ['L', x, y + h],
        ['Z']
    ];
}
/**
 *
 */
function roundedRect(x, y, w, h, options) {
    var r = (options === null || options === void 0 ? void 0 : options.r) || 0;
    return [
        ['M', x + r, y],
        ['L', x + w - r, y], // Top side
        ['A', r, r, 0, 0, 1, x + w, y + r], // Top-right corner
        ['L', x + w, y + h - r], // Right side
        ['A', r, r, 0, 0, 1, x + w - r, y + h], // Bottom-right corner
        ['L', x + r, y + h], // Bottom side
        ['A', r, r, 0, 0, 1, x, y + h - r], // Bottom-left corner
        ['L', x, y + r], // Left side
        ['A', r, r, 0, 0, 1, x + r, y],
        ['Z'] // Top-left corner
    ];
}
/**
 *
 */
function triangle(x, y, w, h) {
    return [
        ['M', x + w / 2, y],
        ['L', x + w, y + h],
        ['L', x, y + h],
        ['Z']
    ];
}
/**
 *
 */
function triangleDown(x, y, w, h) {
    return [
        ['M', x, y],
        ['L', x + w, y],
        ['L', x + w / 2, y + h],
        ['Z']
    ];
}
var Symbols = {
    arc: arc,
    callout: callout,
    circle: circle,
    diamond: diamond,
    rect: rect,
    roundedRect: roundedRect,
    square: rect,
    triangle: triangle,
    'triangle-down': triangleDown
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var SVG_Symbols = (Symbols);

;// ./code/es5/es-modules/Core/Renderer/SVG/TextBuilder.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var TextBuilder_doc = Core_Globals.doc, TextBuilder_SVG_NS = Core_Globals.SVG_NS, TextBuilder_win = Core_Globals.win;

var TextBuilder_attr = Core_Utilities.attr, TextBuilder_extend = Core_Utilities.extend, TextBuilder_fireEvent = Core_Utilities.fireEvent, TextBuilder_isString = Core_Utilities.isString, TextBuilder_objectEach = Core_Utilities.objectEach, TextBuilder_pick = Core_Utilities.pick;
// Function used to test string length including an ellipsis
var stringWithEllipsis = function (text, currentIndex) {
    return text.substring(0, currentIndex) + '\u2026';
};
/* *
 *
 *  Class
 *
 * */
/**
 * SVG Text Builder
 * @private
 * @class
 * @name Highcharts.TextBuilder
 */
var TextBuilder = /** @class */ (function () {
    function TextBuilder(svgElement) {
        var textStyles = svgElement.styles;
        this.renderer = svgElement.renderer;
        this.svgElement = svgElement;
        this.width = svgElement.textWidth;
        this.textLineHeight = textStyles && textStyles.lineHeight;
        this.textOutline = textStyles && textStyles.textOutline;
        this.ellipsis = Boolean(textStyles && textStyles.textOverflow === 'ellipsis');
        this.lineClamp = textStyles === null || textStyles === void 0 ? void 0 : textStyles.lineClamp;
        this.noWrap = Boolean(textStyles && textStyles.whiteSpace === 'nowrap');
    }
    /**
     * Build an SVG representation of the pseudo HTML given in the object's
     * svgElement.
     *
     * @private
     *
     * @return {void}.
     */
    TextBuilder.prototype.buildSVG = function () {
        var wrapper = this.svgElement, textNode = wrapper.element, renderer = wrapper.renderer, textStr = TextBuilder_pick(wrapper.textStr, '').toString(), hasMarkup = textStr.indexOf('<') !== -1, childNodes = textNode.childNodes, tempParent = !wrapper.added && renderer.box, regexMatchBreaks = /<br.*?>/g, 
            // The buildText code is quite heavy, so if we're not changing
            // something that affects the text, skip it (#6113).
            textCache = [
                textStr,
                this.ellipsis,
                this.noWrap,
                this.textLineHeight,
                this.textOutline,
                wrapper.getStyle('font-size'),
                wrapper.styles.lineClamp,
                this.width
            ].join(',');
        if (textCache === wrapper.textCache) {
            return;
        }
        wrapper.textCache = textCache;
        delete wrapper.actualWidth;
        // Remove old text
        for (var i = childNodes.length; i--;) {
            textNode.removeChild(childNodes[i]);
        }
        // Simple strings, add text directly and return
        if (!hasMarkup &&
            !this.ellipsis &&
            !this.width &&
            !wrapper.textPath &&
            (textStr.indexOf(' ') === -1 ||
                (this.noWrap && !regexMatchBreaks.test(textStr)))) {
            textNode.appendChild(TextBuilder_doc.createTextNode(this.unescapeEntities(textStr)));
            // Complex strings, add more logic
        }
        else if (textStr !== '') {
            if (tempParent) {
                // Attach it to the DOM to read offset width and font size
                tempParent.appendChild(textNode);
            }
            // Step 1. Parse the markup safely and directly into a tree
            // structure.
            var ast = new HTML_AST(textStr);
            // Step 2. Do as many as we can of the modifications to the tree
            // structure before it is added to the DOM
            this.modifyTree(ast.nodes);
            ast.addToDOM(textNode);
            // Step 3. Some modifications can't be done until the structure is
            // in the DOM, because we need to read computed metrics.
            this.modifyDOM();
            // Add title if an ellipsis was added
            if (this.ellipsis &&
                (textNode.textContent || '').indexOf('\u2026') !== -1) {
                wrapper.attr('title', this.unescapeEntities(wrapper.textStr || '', ['&lt;', '&gt;']) // #7179
                );
            }
            if (tempParent) {
                tempParent.removeChild(textNode);
            }
        }
        // Apply the text outline
        if (TextBuilder_isString(this.textOutline) && wrapper.applyTextOutline) {
            wrapper.applyTextOutline(this.textOutline);
        }
    };
    /**
     * Modify the DOM of the generated SVG structure. This function only does
     * operations that cannot be done until the elements are attached to the
     * DOM, like doing layout based on rendered metrics of the added elements.
     *
     * @private
     *
     */
    TextBuilder.prototype.modifyDOM = function () {
        var _this = this;
        var wrapper = this.svgElement;
        var x = TextBuilder_attr(wrapper.element, 'x');
        wrapper.firstLineMetrics = void 0;
        // Remove empty tspans (including breaks) from the beginning because
        // SVG's getBBox doesn't count empty lines. The use case is tooltip
        // where the header is empty. By doing this in the DOM rather than in
        // the AST, we can inspect the textContent directly and don't have to
        // recurse down to look for valid content.
        var firstChild;
        while ((firstChild = wrapper.element.firstChild)) {
            if (/^[\s\u200B]*$/.test(firstChild.textContent || ' ')) {
                wrapper.element.removeChild(firstChild);
            }
            else {
                break;
            }
        }
        // Modify hard line breaks by applying the rendered line height
        [].forEach.call(wrapper.element.querySelectorAll('tspan.highcharts-br'), function (br, i) {
            if (br.nextSibling && br.previousSibling) { // #5261
                if (i === 0 && br.previousSibling.nodeType === 1) {
                    wrapper.firstLineMetrics = wrapper.renderer
                        .fontMetrics(br.previousSibling);
                }
                TextBuilder_attr(br, {
                    // Since the break is inserted in front of the next
                    // line, we need to use the next sibling for the line
                    // height
                    dy: _this.getLineHeight(br.nextSibling),
                    x: x
                });
            }
        });
        // Constrain the line width, either by ellipsis or wrapping
        var width = this.width || 0;
        if (!width) {
            return;
        }
        // Insert soft line breaks into each text node
        var modifyTextNode = function (textNode,
            parentElement) {
                var _a;
            var text = textNode.textContent || '';
            var words = text
                    .replace(/([^\^])-/g, '$1- ') // Split on hyphens
                    // .trim()
                    .split(' '); // #1273
                var hasWhiteSpace = !_this.noWrap && (words.length > 1 || wrapper.element.childNodes.length > 1);
            var dy = _this.getLineHeight(parentElement),
                ellipsisWidth = Math.max(0, 
                // Subtract the font face to make room for
                // the ellipsis itself
                width - 0.8 * dy);
            var lineNo = 0;
            var startAt = wrapper.actualWidth;
            if (hasWhiteSpace) {
                var lines = [];
                // Remove preceding siblings in order to make the text length
                // calculation correct in the truncate function
                var precedingSiblings = [];
                while (parentElement.firstChild &&
                    parentElement.firstChild !== textNode) {
                    precedingSiblings.push(parentElement.firstChild);
                    parentElement.removeChild(parentElement.firstChild);
                }
                while (words.length) {
                    // Apply the previous line
                    if (words.length && !_this.noWrap && lineNo > 0) {
                        lines.push(textNode.textContent || '');
                        textNode.textContent = words.join(' ')
                            .replace(/- /g, '-');
                    }
                    // For each line, truncate the remaining
                    // words into the line length.
                    _this.truncate(textNode, void 0, words, lineNo === 0 ? (startAt || 0) : 0, width, ellipsisWidth, 
                    // Build the text to test for
                    function (t, currentIndex) {
                        return words
                            .slice(0, currentIndex)
                            .join(' ')
                            .replace(/- /g, '-');
                    });
                    startAt = wrapper.actualWidth;
                    lineNo++;
                    // Line clamp. Break out after n lines and append an
                    // ellipsis regardless of the text length.
                    if (_this.lineClamp && lineNo >= _this.lineClamp) {
                        // Only if there are remaining words that should have
                        // been rendered.
                        if (words.length) {
                            _this.truncate(textNode, textNode.textContent || '', void 0, 0, 
                            // Target width
                            width, ellipsisWidth, stringWithEllipsis);
                            textNode.textContent = ((_a = textNode.textContent) === null || _a === void 0 ? void 0 : _a.replace('\u2026', '')) + '\u2026';
                        }
                        break;
                    }
                }
                // Reinsert the preceding child nodes
                precedingSiblings.forEach(function (childNode) {
                    parentElement.insertBefore(childNode, textNode);
                });
                // Insert the previous lines before the original text node
                lines.forEach(function (line) {
                    // Insert the line
                    parentElement.insertBefore(TextBuilder_doc.createTextNode(line), textNode);
                    // Insert a break
                    var br = TextBuilder_doc.createElementNS(TextBuilder_SVG_NS, 'tspan');
                    br.textContent = '\u200B'; // Zero-width space
                    TextBuilder_attr(br, { dy: dy, x: x });
                    parentElement.insertBefore(br, textNode);
                });
            }
            else if (_this.ellipsis) {
                if (text) {
                    _this.truncate(textNode, text, void 0, 0, 
                    // Target width
                    width, ellipsisWidth, stringWithEllipsis);
                }
            }
        };
        // Recurse down the DOM tree and handle line breaks for each text node
        var modifyChildren = (function (node) {
                var childNodes = [].slice.call(node.childNodes);
            childNodes.forEach(function (childNode) {
                if (childNode.nodeType === TextBuilder_win.Node.TEXT_NODE) {
                    modifyTextNode(childNode, node);
                }
                else {
                    // Reset word-wrap width readings after hard breaks
                    if (childNode.className.baseVal
                        .indexOf('highcharts-br') !== -1) {
                        wrapper.actualWidth = 0;
                    }
                    // Recurse down to child node
                    modifyChildren(childNode);
                }
            });
        });
        modifyChildren(wrapper.element);
    };
    /**
     * Get the rendered line height of a <text>, <tspan> or pure text node.
     * @private
     * @param {DOMElementType|Text} node The node to check for
     * @return {number} The rendered line height
     */
    TextBuilder.prototype.getLineHeight = function (node) {
        // If the node is a text node, use its parent
        var element = (node.nodeType === TextBuilder_win.Node.TEXT_NODE) ?
                node.parentElement :
                node;
        return this.textLineHeight ?
            parseInt(this.textLineHeight.toString(), 10) :
            this.renderer.fontMetrics(element || this.svgElement.element).h;
    };
    /**
     * Transform a pseudo HTML AST node tree into an SVG structure. We do as
     * much heavy lifting as we can here, before doing the final processing in
     * the modifyDOM function. The original data is mutated.
     *
     * @private
     *
     * @param {ASTNode[]} nodes The AST nodes
     *
     */
    TextBuilder.prototype.modifyTree = function (nodes) {
        var _this = this;
        var modifyChild = function (node,
            i) {
                var _a = node.attributes,
            attributes = _a === void 0 ? {} : _a,
            children = node.children,
            _b = node.style,
            style = _b === void 0 ? {} : _b,
            tagName = node.tagName,
            styledMode = _this.renderer.styledMode;
            // Apply styling to text tags
            if (tagName === 'b' || tagName === 'strong') {
                if (styledMode) {
                    // eslint-disable-next-line dot-notation
                    attributes['class'] = 'highcharts-strong';
                }
                else {
                    style.fontWeight = 'bold';
                }
            }
            else if (tagName === 'i' || tagName === 'em') {
                if (styledMode) {
                    // eslint-disable-next-line dot-notation
                    attributes['class'] = 'highcharts-emphasized';
                }
                else {
                    style.fontStyle = 'italic';
                }
            }
            // Modify styling
            if (style && style.color) {
                style.fill = style.color;
            }
            // Handle breaks
            if (tagName === 'br') {
                attributes['class'] = 'highcharts-br'; // eslint-disable-line dot-notation
                node.textContent = '\u200B'; // Zero-width space
                // Trim whitespace off the beginning of new lines
                var nextNode = nodes[i + 1];
                if (nextNode && nextNode.textContent) {
                    nextNode.textContent =
                        nextNode.textContent.replace(/^ +/gm, '');
                }
                // If an anchor has direct text node children, the text is unable to
                // wrap because there is no `getSubStringLength` function on the
                // element. Therefore we need to wrap the child text node or nodes
                // in a tspan. #16173.
            }
            else if (tagName === 'a' &&
                children &&
                children.some(function (child) { return child.tagName === '#text'; })) {
                node.children = [{ children: children, tagName: 'tspan' }];
            }
            if (tagName !== '#text' && tagName !== 'a') {
                node.tagName = 'tspan';
            }
            TextBuilder_extend(node, { attributes: attributes, style: style });
            // Recurse
            if (children) {
                children
                    .filter(function (c) { return c.tagName !== '#text'; })
                    .forEach(modifyChild);
            }
        };
        nodes.forEach(modifyChild);
        TextBuilder_fireEvent(this.svgElement, 'afterModifyTree', { nodes: nodes });
    };
    /*
     * Truncate the text node contents to a given length. Used when the css
     * width is set. If the `textOverflow` is `ellipsis`, the text is truncated
     * character by character to the given length. If not, the text is
     * word-wrapped line by line.
     */
    TextBuilder.prototype.truncate = function (textNode, text, words, startAt, width, ellipsisWidth, getString) {
        var svgElement = this.svgElement;
        var rotation = svgElement.rotation;
        // Cache the lengths to avoid checking the same twice
        var lengths = [];
        // Word wrap cannot be truncated to shorter than one word, ellipsis
        // text can be completely blank.
        var minIndex = words && !startAt ? 1 : 0;
        var maxIndex = (text || words || '').length;
        var currentIndex = maxIndex;
        var str;
        var actualWidth;
        if (!words) {
            width = ellipsisWidth;
        }
        var getSubStringLength = function (charEnd,
            concatenatedEnd) {
                // `charEnd` is used when finding the character-by-character
                // break for ellipsis, concatenatedEnd is used for word-by-word
                // break for word wrapping.
                var end = concatenatedEnd || charEnd;
            var parentNode = textNode.parentNode;
            if (parentNode && typeof lengths[end] === 'undefined') {
                // Modern browsers
                if (parentNode.getSubStringLength) {
                    // Fails with DOM exception on unit-tests/legend/members
                    // of unknown reason. Desired width is 0, text content
                    // is "5" and end is 1.
                    try {
                        lengths[end] = startAt +
                            parentNode.getSubStringLength(0, words ? end + 1 : end);
                    }
                    catch (e) {
                        '';
                    }
                }
            }
            return lengths[end];
        };
        svgElement.rotation = 0; // Discard rotation when computing box
        actualWidth = getSubStringLength(textNode.textContent.length);
        if (startAt + actualWidth > width) {
            // Do a binary search for the index where to truncate the text
            while (minIndex <= maxIndex) {
                currentIndex = Math.ceil((minIndex + maxIndex) / 2);
                // When checking words for word-wrap, we need to build the
                // string and measure the subStringLength at the concatenated
                // word length.
                if (words) {
                    str = getString(words, currentIndex);
                }
                actualWidth = getSubStringLength(currentIndex, str && str.length - 1);
                if (minIndex === maxIndex) {
                    // Complete
                    minIndex = maxIndex + 1;
                }
                else if (actualWidth > width) {
                    // Too large. Set max index to current.
                    maxIndex = currentIndex - 1;
                }
                else {
                    // Within width. Set min index to current.
                    minIndex = currentIndex;
                }
            }
            // If max index was 0 it means the shortest possible text was also
            // too large. For ellipsis that means only the ellipsis, while for
            // word wrap it means the whole first word.
            if (maxIndex === 0) {
                // Remove ellipsis
                textNode.textContent = '';
                // If the new text length is one less than the original, we don't
                // need the ellipsis
            }
            else if (!(text && maxIndex === text.length - 1)) {
                textNode.textContent = str || getString(text || words, currentIndex);
            }
            // Add ellipsis on individual lines
            if (this.ellipsis && actualWidth > width) {
                this.truncate(textNode, textNode.textContent || '', void 0, 0, width, ellipsisWidth, stringWithEllipsis);
            }
        }
        // When doing line wrapping, prepare for the next line by removing the
        // items from this line.
        if (words) {
            words.splice(0, currentIndex);
        }
        svgElement.actualWidth = actualWidth;
        svgElement.rotation = rotation; // Apply rotation again.
    };
    /*
     * Un-escape HTML entities based on the public `renderer.escapes` list
     *
     * @private
     *
     * @param {string} inputStr The string to unescape
     * @param {Array<string>} [except] Exceptions
     *
     * @return {string} The processed string
     */
    TextBuilder.prototype.unescapeEntities = function (inputStr, except) {
        TextBuilder_objectEach(this.renderer.escapes, function (value, key) {
            if (!except || except.indexOf(value) === -1) {
                inputStr = inputStr.toString().replace(new RegExp(value, 'g'), key);
            }
        });
        return inputStr;
    };
    return TextBuilder;
}());
/* harmony default export */ var SVG_TextBuilder = (TextBuilder);

;// ./code/es5/es-modules/Core/Renderer/SVG/SVGRenderer.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var SVGRenderer_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};


var SVGRenderer_defaultOptions = Defaults.defaultOptions;


var SVGRenderer_charts = Core_Globals.charts, SVGRenderer_deg2rad = Core_Globals.deg2rad, SVGRenderer_doc = Core_Globals.doc, SVGRenderer_isFirefox = Core_Globals.isFirefox, isMS = Core_Globals.isMS, isWebKit = Core_Globals.isWebKit, noop = Core_Globals.noop, SVGRenderer_SVG_NS = Core_Globals.SVG_NS, symbolSizes = Core_Globals.symbolSizes, SVGRenderer_win = Core_Globals.win;






var SVGRenderer_addEvent = Core_Utilities.addEvent, SVGRenderer_attr = Core_Utilities.attr, SVGRenderer_createElement = Core_Utilities.createElement, SVGRenderer_crisp = Core_Utilities.crisp, SVGRenderer_css = Core_Utilities.css, SVGRenderer_defined = Core_Utilities.defined, SVGRenderer_destroyObjectProperties = Core_Utilities.destroyObjectProperties, SVGRenderer_extend = Core_Utilities.extend, SVGRenderer_isArray = Core_Utilities.isArray, SVGRenderer_isNumber = Core_Utilities.isNumber, SVGRenderer_isObject = Core_Utilities.isObject, SVGRenderer_isString = Core_Utilities.isString, SVGRenderer_merge = Core_Utilities.merge, SVGRenderer_pick = Core_Utilities.pick, SVGRenderer_pInt = Core_Utilities.pInt, SVGRenderer_replaceNested = Core_Utilities.replaceNested, SVGRenderer_uniqueKey = Core_Utilities.uniqueKey;
/* *
 *
 *  Variables
 *
 * */
var hasInternalReferenceBug;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * Allows direct access to the Highcharts rendering layer in order to draw
 * primitive shapes like circles, rectangles, paths or text directly on a chart,
 * or independent from any chart. The SVGRenderer represents a wrapper object
 * for SVG in modern browsers.
 *
 * An existing chart's renderer can be accessed through {@link Chart.renderer}.
 * The renderer can also be used completely decoupled from a chart.
 *
 * See [How to use the SVG Renderer](
 * https://www.highcharts.com/docs/advanced-chart-features/renderer) for a
 * comprehensive tutorial.
 *
 * @sample highcharts/members/renderer-on-chart
 *         Annotating a chart programmatically.
 * @sample highcharts/members/renderer-basic
 *         Independent SVG drawing.
 *
 * @example
 * // Use directly without a chart object.
 * let renderer = new Highcharts.Renderer(parentNode, 600, 400);
 *
 * @class
 * @name Highcharts.SVGRenderer
 *
 * @param {Highcharts.HTMLDOMElement} container
 *        Where to put the SVG in the web page.
 *
 * @param {number} width
 *        The width of the SVG.
 *
 * @param {number} height
 *        The height of the SVG.
 *
 * @param {Highcharts.CSSObject} [style]
 *        The box style, if not in styleMode
 *
 * @param {boolean} [forExport=false]
 *        Whether the rendered content is intended for export.
 *
 * @param {boolean} [allowHTML=true]
 *        Whether the renderer is allowed to include HTML text, which will be
 *        projected on top of the SVG.
 *
 * @param {boolean} [styledMode=false]
 *        Whether the renderer belongs to a chart that is in styled mode.
 *        If it does, it will avoid setting presentational attributes in
 *        some cases, but not when set explicitly through `.attr` and `.css`
 *        etc.
 */
var SVGRenderer = /** @class */ (function () {
    /**
     * The root `svg` node of the renderer.
     *
     * @name Highcharts.SVGRenderer#box
     * @type {Highcharts.SVGDOMElement}
     */
    /**
     * The wrapper for the root `svg` node of the renderer.
     *
     * @name Highcharts.SVGRenderer#boxWrapper
     * @type {Highcharts.SVGElement}
     */
    /**
     * A pointer to the `defs` node of the root SVG.
     *
     * @name Highcharts.SVGRenderer#defs
     * @type {Highcharts.SVGElement}
     */
    /**
     * Whether the rendered content is intended for export.
     *
     * @name Highcharts.SVGRenderer#forExport
     * @type {boolean | undefined}
     */
    /**
     * Page url used for internal references.
     *
     * @private
     * @name Highcharts.SVGRenderer#url
     * @type {string}
     */
    /**
     * Initialize the SVGRenderer. Overridable initializer function that takes
     * the same parameters as the constructor.
     *
     * @function Highcharts.SVGRenderer#init
     *
     * @param {Highcharts.HTMLDOMElement} container
     * Where to put the SVG in the web page.
     *
     * @param {number} width
     * The width of the SVG.
     *
     * @param {number} height
     * The height of the SVG.
     *
     * @param {Highcharts.CSSObject} [style]
     * The box style, if not in styleMode
     *
     * @param {boolean} [forExport=false]
     * Whether the rendered content is intended for export.
     *
     * @param {boolean} [allowHTML=true]
     * Whether the renderer is allowed to include HTML text, which will be
     * projected on top of the SVG.
     *
     * @param {boolean} [styledMode=false]
     * Whether the renderer belongs to a chart that is in styled mode. If it
     * does, it will avoid setting presentational attributes in some cases, but
     * not when set explicitly through `.attr` and `.css` etc.
     */
    function SVGRenderer(container, width, height, style, forExport, allowHTML, styledMode) {
        var renderer = this,
            boxWrapper = renderer
                .createElement('svg')
                .attr({
                version: '1.1',
                'class': 'highcharts-root'
            }),
            element = boxWrapper.element;
        if (!styledMode) {
            boxWrapper.css(this.getStyle(style || {}));
        }
        container.appendChild(element);
        // Always use ltr on the container, otherwise text-anchor will be
        // flipped and text appear outside labels, buttons, tooltip etc (#3482)
        SVGRenderer_attr(container, 'dir', 'ltr');
        // For browsers other than IE, add the namespace attribute (#1978)
        if (container.innerHTML.indexOf('xmlns') === -1) {
            SVGRenderer_attr(element, 'xmlns', this.SVG_NS);
        }
        this.box = element;
        this.boxWrapper = boxWrapper;
        this.alignedObjects = [];
        this.url = this.getReferenceURL();
        // Add description
        var desc = this.createElement('desc').add();
        desc.element.appendChild(SVGRenderer_doc.createTextNode('Created with Highcharts 12.1.2'));
        this.defs = this.createElement('defs').add();
        this.allowHTML = allowHTML;
        this.forExport = forExport;
        this.styledMode = styledMode;
        this.gradients = {}; // Object where gradient SvgElements are stored
        this.cache = {}; // Cache for numerical bounding boxes
        this.cacheKeys = [];
        this.imgCount = 0;
        this.rootFontSize = boxWrapper.getStyle('font-size');
        renderer.setSize(width, height, false);
        // Issue 110 workaround:
        // In Firefox, if a div is positioned by percentage, its pixel position
        // may land between pixels. The container itself doesn't display this,
        // but an SVG element inside this container will be drawn at subpixel
        // precision. In order to draw sharp lines, this must be compensated
        // for. This doesn't seem to work inside iframes though (like in
        // jsFiddle).
        var subPixelFix,
            rect;
        if (SVGRenderer_isFirefox && container.getBoundingClientRect) {
            subPixelFix = function () {
                SVGRenderer_css(container, { left: 0, top: 0 });
                rect = container.getBoundingClientRect();
                SVGRenderer_css(container, {
                    left: (Math.ceil(rect.left) - rect.left) + 'px',
                    top: (Math.ceil(rect.top) - rect.top) + 'px'
                });
            };
            // Run the fix now
            subPixelFix();
            // Run it on resize
            renderer.unSubPixelFix = SVGRenderer_addEvent(SVGRenderer_win, 'resize', subPixelFix);
        }
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * General method for adding a definition to the SVG `defs` tag. Can be used
     * for gradients, fills, filters etc. Styled mode only. A hook for adding
     * general definitions to the SVG's defs tag. Definitions can be referenced
     * from the CSS by its `id`. Read more in
     * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns).
     * Styled mode only.
     *
     * @function Highcharts.SVGRenderer#definition
     *
     * @param {Highcharts.ASTNode} def
     * A serialized form of an SVG definition, including children.
     *
     * @return {Highcharts.SVGElement}
     * The inserted node.
     */
    SVGRenderer.prototype.definition = function (def) {
        var ast = new HTML_AST([def]);
        return ast.addToDOM(this.defs.element);
    };
    /**
     * Get the prefix needed for internal URL references to work in certain
     * cases. Some older browser versions had a bug where internal url
     * references in SVG attributes, on the form `url(#some-id)`, would fail if
     * a base tag was present in the page. There were also issues with
     * `history.pushState` related to this prefix.
     *
     * Related issues: #24, #672, #1070, #5244.
     *
     * The affected browsers are:
     * - Chrome <= 53 (May 2018)
     * - Firefox <= 51 (January 2017)
     * - Safari/Mac <= 12.1 (2018 or 2019)
     * - Safari/iOS <= 13
     *
     * @todo Remove this hack when time has passed. All the affected browsers
     * are evergreens, so it is increasingly unlikely that users are affected by
     * the bug.
     *
     * @return {string}
     * The prefix to use. An empty string for modern browsers.
     */
    SVGRenderer.prototype.getReferenceURL = function () {
        if ((SVGRenderer_isFirefox || isWebKit) &&
            SVGRenderer_doc.getElementsByTagName('base').length) {
            // Detect if a clip path is taking effect by performing a hit test
            // outside the clipped area. If the hit element is the rectangle
            // that was supposed to be clipped, the bug is present. This only
            // has to be performed once per page load, so we store the result
            // locally in the module.
            if (!SVGRenderer_defined(hasInternalReferenceBug)) {
                var id = SVGRenderer_uniqueKey();
                var ast = new HTML_AST([{
                            tagName: 'svg',
                            attributes: {
                                width: 8,
                                height: 8
                            },
                            children: [{
                                    tagName: 'defs',
                                    children: [{
                                            tagName: 'clipPath',
                                            attributes: {
                                                id: id
                                            },
                                            children: [{
                                                    tagName: 'rect',
                                                    attributes: {
                                                        width: 4,
                                                        height: 4
                                                    }
                                                }]
                                        }]
                                }, {
                                    tagName: 'rect',
                                    attributes: {
                                        id: 'hitme',
                                        width: 8,
                                        height: 8,
                                        'clip-path': "url(#".concat(id, ")"),
                                        fill: 'rgba(0,0,0,0.001)'
                                    }
                                }]
                        }]);
                var svg = ast.addToDOM(SVGRenderer_doc.body);
                SVGRenderer_css(svg, {
                    position: 'fixed',
                    top: 0,
                    left: 0,
                    zIndex: 9e5
                });
                var hitElement = SVGRenderer_doc.elementFromPoint(6, 6);
                hasInternalReferenceBug = (hitElement && hitElement.id) === 'hitme';
                SVGRenderer_doc.body.removeChild(svg);
            }
            if (hasInternalReferenceBug) {
                // Scan alert #[72]: Loop for nested patterns
                return SVGRenderer_replaceNested(SVGRenderer_win.location.href.split('#')[0], // Remove hash
                [/<[^>]*>/g, ''], // Wing cut HTML
                [/([\('\)])/g, '\\$1'], // Escape parantheses and quotes
                [/ /g, '%20'] // Replace spaces (needed for Safari only)
                );
            }
        }
        return '';
    };
    /**
     * Get the global style setting for the renderer.
     *
     * @private
     * @function Highcharts.SVGRenderer#getStyle
     *
     * @param {Highcharts.CSSObject} style
     * Style settings.
     *
     * @return {Highcharts.CSSObject}
     * The style settings mixed with defaults.
     */
    SVGRenderer.prototype.getStyle = function (style) {
        this.style = SVGRenderer_extend({
            fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", ' +
                'Roboto, Helvetica, Arial, "Apple Color Emoji", ' +
                '"Segoe UI Emoji", "Segoe UI Symbol", sans-serif',
            fontSize: '1rem'
        }, style);
        return this.style;
    };
    /**
     * Apply the global style on the renderer, mixed with the default styles.
     *
     * @function Highcharts.SVGRenderer#setStyle
     *
     * @param {Highcharts.CSSObject} style
     * CSS to apply.
     */
    SVGRenderer.prototype.setStyle = function (style) {
        this.boxWrapper.css(this.getStyle(style));
    };
    /**
     * Detect whether the renderer is hidden. This happens when one of the
     * parent elements has `display: none`. Used internally to detect when we
     * need to render preliminarily in another div to get the text bounding
     * boxes right.
     *
     * @function Highcharts.SVGRenderer#isHidden
     *
     * @return {boolean}
     * True if it is hidden.
     */
    SVGRenderer.prototype.isHidden = function () {
        return !this.boxWrapper.getBBox().width;
    };
    /**
     * Destroys the renderer and its allocated members.
     *
     * @function Highcharts.SVGRenderer#destroy
     *
     * @return {null}
     * Pass through value.
     */
    SVGRenderer.prototype.destroy = function () {
        var renderer = this,
            rendererDefs = renderer.defs;
        renderer.box = null;
        renderer.boxWrapper = renderer.boxWrapper.destroy();
        // Call destroy on all gradient elements
        SVGRenderer_destroyObjectProperties(renderer.gradients || {});
        renderer.gradients = null;
        renderer.defs = rendererDefs.destroy();
        // Remove sub pixel fix handler (#982)
        if (renderer.unSubPixelFix) {
            renderer.unSubPixelFix();
        }
        renderer.alignedObjects = null;
        return null;
    };
    /**
     * Create a wrapper for an SVG element. Serves as a factory for
     * {@link SVGElement}, but this function is itself mostly called from
     * primitive factories like {@link SVGRenderer#path}, {@link
     * SVGRenderer#rect} or {@link SVGRenderer#text}.
     *
     * @function Highcharts.SVGRenderer#createElement
     *
     * @param {string} nodeName
     * The node name, for example `rect`, `g` etc.
     *
     * @return {Highcharts.SVGElement}
     * The generated SVGElement.
     */
    SVGRenderer.prototype.createElement = function (nodeName) {
        return new this.Element(this, nodeName);
    };
    /**
     * Get converted radial gradient attributes according to the radial
     * reference. Used internally from the {@link SVGElement#colorGradient}
     * function.
     *
     * @private
     * @function Highcharts.SVGRenderer#getRadialAttr
     */
    SVGRenderer.prototype.getRadialAttr = function (radialReference, gradAttr) {
        return {
            cx: (radialReference[0] - radialReference[2] / 2) +
                (gradAttr.cx || 0) * radialReference[2],
            cy: (radialReference[1] - radialReference[2] / 2) +
                (gradAttr.cy || 0) * radialReference[2],
            r: (gradAttr.r || 0) * radialReference[2]
        };
    };
    /**
     * Create a drop shadow definition and return its id
     *
     * @private
     * @function Highcharts.SVGRenderer#shadowDefinition
     *
     * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions] The
     *        shadow options. If `true`, the default options are applied
     */
    SVGRenderer.prototype.shadowDefinition = function (shadowOptions) {
        var id = SVGRenderer_spreadArray([
                "highcharts-drop-shadow-".concat(this.chartIndex)
            ],
            Object.keys(shadowOptions)
                .map(function (key) {
                return "" + key + "-".concat(shadowOptions[key]);
        }), true).join('-').toLowerCase().replace(/[^a-z\d\-]/g, ''), options = SVGRenderer_merge({
            color: '#000000',
            offsetX: 1,
            offsetY: 1,
            opacity: 0.15,
            width: 5
        }, shadowOptions);
        if (!this.defs.element.querySelector("#".concat(id))) {
            this.definition({
                tagName: 'filter',
                attributes: {
                    id: id,
                    filterUnits: options.filterUnits
                },
                children: this.getShadowFilterContent(options)
            });
        }
        return id;
    };
    /**
     * Get shadow filter content.
     * NOTE! Overridden in es5 module for IE11 compatibility.
     *
     * @private
     * @function Highcharts.SVGRenderer#getShadowFilterContent
     *
     * @param {ShadowOptionsObject} options
     * The shadow options.
     * @return {Array<AST.Node>}
     * The shadow filter content.
     */
    SVGRenderer.prototype.getShadowFilterContent = function (options) {
        return [{
                tagName: 'feDropShadow',
                attributes: {
                    dx: options.offsetX,
                    dy: options.offsetY,
                    'flood-color': options.color,
                    // Tuned and modified to keep a preserve compatibility
                    // with the old settings
                    'flood-opacity': Math.min(options.opacity * 5, 1),
                    stdDeviation: options.width / 2
                }
            }];
    };
    /**
     * Parse a simple HTML string into SVG tspans. Called internally when text
     * is set on an SVGElement. The function supports a subset of HTML tags, CSS
     * text features like `width`, `text-overflow`, `white-space`, and also
     * attributes like `href` and `style`.
     *
     * @private
     * @function Highcharts.SVGRenderer#buildText
     *
     * @param {Highcharts.SVGElement} wrapper
     * The parent SVGElement.
     */
    SVGRenderer.prototype.buildText = function (wrapper) {
        new SVG_TextBuilder(wrapper).buildSVG();
    };
    /**
     * Returns white for dark colors and black for bright colors, based on W3C's
     * definition of [Relative luminance](
     * https://www.w3.org/WAI/GL/wiki/Relative_luminance).
     *
     * @function Highcharts.SVGRenderer#getContrast
     *
     * @param {Highcharts.ColorString} color
     * The color to get the contrast for.
     *
     * @return {Highcharts.ColorString}
     * The contrast color, either `#000000` or `#FFFFFF`.
     */
    SVGRenderer.prototype.getContrast = function (color) {
        // #6216, #17273
        var rgba = Color_Color.parse(color).rgba
                .map(function (b8) {
                var c = b8 / 255;
            return c <= 0.03928 ?
                c / 12.92 :
                Math.pow((c + 0.055) / 1.055, 2.4);
        });
        // Relative luminance
        var l = 0.2126 * rgba[0] + 0.7152 * rgba[1] + 0.0722 * rgba[2];
        // Use white or black based on which provides more contrast
        return 1.05 / (l + 0.05) > (l + 0.05) / 0.05 ? '#FFFFFF' : '#000000';
    };
    /**
     * Create a button with preset states. Styles for the button can either be
     * set as arguments, or a general theme for all buttons can be set by the
     * `global.buttonTheme` option.
     *
     * @function Highcharts.SVGRenderer#button
     *
     * @param {string} text
     * The text or HTML to draw.
     *
     * @param {number} x
     * The x position of the button's left side.
     *
     * @param {number} y
     * The y position of the button's top side.
     *
     * @param {Highcharts.EventCallbackFunction<Highcharts.SVGElement>} callback
     * The function to execute on button click or touch.
     *
     * @param {Highcharts.SVGAttributes} [theme]
     * SVG attributes for the normal state.
     *
     * @param {Highcharts.SVGAttributes} [hoverState]
     * SVG attributes for the hover state.
     *
     * @param {Highcharts.SVGAttributes} [selectState]
     * SVG attributes for the pressed state.
     *
     * @param {Highcharts.SVGAttributes} [disabledState]
     * SVG attributes for the disabled state.
     *
     * @param {Highcharts.SymbolKeyValue} [shape=rect]
     * The shape type.
     *
     * @param {boolean} [useHTML=false]
     * Whether to use HTML to render the label.
     *
     * @return {Highcharts.SVGElement}
     * The button element.
     */
    SVGRenderer.prototype.button = function (text, x, y, callback, theme, hoverState, selectState, disabledState, shape, useHTML) {
        if (theme === void 0) { theme = {}; }
        var label = this.label(text,
            x,
            y,
            shape,
            void 0,
            void 0,
            useHTML,
            void 0, 'button'),
            styledMode = this.styledMode,
            args = arguments;
        var curState = 0;
        theme = SVGRenderer_merge(SVGRenderer_defaultOptions.global.buttonTheme, theme);
        // @todo Consider moving this to a lower level, like .attr
        if (styledMode) {
            delete theme.fill;
            delete theme.stroke;
            delete theme['stroke-width'];
        }
        var states = theme.states || {},
            normalStyle = theme.style || {};
        delete theme.states;
        delete theme.style;
        // Presentational
        var stateAttribs = [
                HTML_AST.filterUserAttributes(theme)
            ], 
            // The string type is a mistake, it is just for compliance with
            // SVGAttribute and is not used in button theme.
            stateStyles = [normalStyle];
        if (!styledMode) {
            ['hover', 'select', 'disabled'].forEach(function (stateName, i) {
                stateAttribs.push(SVGRenderer_merge(stateAttribs[0], HTML_AST.filterUserAttributes(args[i + 5] || states[stateName] || {})));
                stateStyles.push(stateAttribs[i + 1].style);
                delete stateAttribs[i + 1].style;
            });
        }
        // Add the events. IE9 and IE10 need mouseover and mouseout to function
        // (#667).
        SVGRenderer_addEvent(label.element, isMS ? 'mouseover' : 'mouseenter', function () {
            if (curState !== 3) {
                label.setState(1);
            }
        });
        SVGRenderer_addEvent(label.element, isMS ? 'mouseout' : 'mouseleave', function () {
            if (curState !== 3) {
                label.setState(curState);
            }
        });
        label.setState = function (state) {
            if (state === void 0) { state = 0; }
            // Hover state is temporary, don't record it
            if (state !== 1) {
                label.state = curState = state;
            }
            // Update visuals
            label
                .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/)
                .addClass('highcharts-button-' +
                ['normal', 'hover', 'pressed', 'disabled'][state]);
            if (!styledMode) {
                label.attr(stateAttribs[state]);
                var css_1 = stateStyles[state];
                if (SVGRenderer_isObject(css_1)) {
                    label.css(css_1);
                }
            }
        };
        label.attr(stateAttribs[0]);
        // Presentational attributes
        if (!styledMode) {
            label.css(SVGRenderer_extend({ cursor: 'default' }, normalStyle));
            // HTML labels don't need to handle pointer events because click and
            // mouseenter/mouseleave is bound to the underlying <g> element.
            // Should this be reconsidered, we need more complex logic to share
            // events between the <g> and its <div> counterpart, and avoid
            // triggering mouseenter/mouseleave when hovering from one to the
            // other (#17440).
            if (useHTML) {
                label.text.css({ pointerEvents: 'none' });
            }
        }
        return label
            .on('touchstart', function (e) { return e.stopPropagation(); })
            .on('click', function (e) {
            if (curState !== 3) {
                callback.call(label, e);
            }
        });
    };
    /**
     * Make a straight line crisper by not spilling out to neighbour pixels.
     *
     * @function Highcharts.SVGRenderer#crispLine
     *
     * @param {Highcharts.SVGPathArray} points
     *        The original points on the format `[['M', 0, 0], ['L', 100, 0]]`.
     *
     * @param {number} width
     *        The width of the line.
     *
     * @return {Highcharts.SVGPathArray}
     *         The original points array, but modified to render crisply.
     */
    SVGRenderer.prototype.crispLine = function (points, width) {
        var start = points[0],
            end = points[1];
        // Normalize to a crisp line
        if (SVGRenderer_defined(start[1]) && start[1] === end[1]) {
            start[1] = end[1] = SVGRenderer_crisp(start[1], width);
        }
        if (SVGRenderer_defined(start[2]) && start[2] === end[2]) {
            start[2] = end[2] = SVGRenderer_crisp(start[2], width);
        }
        return points;
    };
    /**
     * Draw a path, wraps the SVG `path` element.
     *
     * @sample highcharts/members/renderer-path-on-chart/
     *         Draw a path in a chart
     * @sample highcharts/members/renderer-path/
     *         Draw a path independent from a chart
     *
     * @example
     * let path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z'])
     *     .attr({ stroke: '#ff00ff' })
     *     .add();
     *
     * @function Highcharts.SVGRenderer#path
     *
     * @param {Highcharts.SVGPathArray} [path]
     * An SVG path definition in array form.
     *
     * @return {Highcharts.SVGElement}
     * The generated wrapper element.
     *
     */ /**
    * Draw a path, wraps the SVG `path` element.
    *
    * @function Highcharts.SVGRenderer#path
    *
    * @param {Highcharts.SVGAttributes} [attribs]
    * The initial attributes.
    *
    * @return {Highcharts.SVGElement}
    * The generated wrapper element.
    */
    SVGRenderer.prototype.path = function (path) {
        var attribs = (this.styledMode ? {} : {
                fill: 'none'
            });
        if (SVGRenderer_isArray(path)) {
            attribs.d = path;
        }
        else if (SVGRenderer_isObject(path)) { // Attributes
            SVGRenderer_extend(attribs, path);
        }
        return this.createElement('path').attr(attribs);
    };
    /**
     * Draw a circle, wraps the SVG `circle` element.
     *
     * @sample highcharts/members/renderer-circle/
     *         Drawing a circle
     *
     * @function Highcharts.SVGRenderer#circle
     *
     * @param {number} [x]
     * The center x position.
     *
     * @param {number} [y]
     * The center y position.
     *
     * @param {number} [r]
     * The radius.
     *
     * @return {Highcharts.SVGElement}
     * The generated wrapper element.
     */ /**
    * Draw a circle, wraps the SVG `circle` element.
    *
    * @function Highcharts.SVGRenderer#circle
    *
    * @param {Highcharts.SVGAttributes} [attribs]
    * The initial attributes.
    *
    * @return {Highcharts.SVGElement}
    * The generated wrapper element.
    */
    SVGRenderer.prototype.circle = function (x, y, r) {
        var attribs = (SVGRenderer_isObject(x) ?
                x :
                typeof x === 'undefined' ? {} : { x: x, y: y, r: r }), wrapper = this.createElement('circle');
        // Setting x or y translates to cx and cy
        wrapper.xSetter = wrapper.ySetter = function (value, key, element) {
            element.setAttribute('c' + key, value);
        };
        return wrapper.attr(attribs);
    };
    /**
     * Draw and return an arc.
     *
     * @sample highcharts/members/renderer-arc/
     *         Drawing an arc
     *
     * @function Highcharts.SVGRenderer#arc
     *
     * @param {number} [x=0]
     * Center X position.
     *
     * @param {number} [y=0]
     * Center Y position.
     *
     * @param {number} [r=0]
     * The outer radius' of the arc.
     *
     * @param {number} [innerR=0]
     * Inner radius like used in donut charts.
     *
     * @param {number} [start=0]
     * The starting angle of the arc in radians, where 0 is to the right and
     * `-Math.PI/2` is up.
     *
     * @param {number} [end=0]
     * The ending angle of the arc in radians, where 0 is to the right and
     * `-Math.PI/2` is up.
     *
     * @return {Highcharts.SVGElement}
     * The generated wrapper element.
     */ /**
    * Draw and return an arc. Overloaded function that takes arguments object.
    *
    * @function Highcharts.SVGRenderer#arc
    *
    * @param {Highcharts.SVGAttributes} attribs
    * Initial SVG attributes.
    *
    * @return {Highcharts.SVGElement}
    * The generated wrapper element.
    */
    SVGRenderer.prototype.arc = function (x, y, r, innerR, start, end) {
        var options;
        if (SVGRenderer_isObject(x)) {
            options = x;
            y = options.y;
            r = options.r;
            innerR = options.innerR;
            start = options.start;
            end = options.end;
            x = options.x;
        }
        else {
            options = { innerR: innerR, start: start, end: end };
        }
        // Arcs are defined as symbols for the ability to set
        // attributes in attr and animate
        var arc = this.symbol('arc',
            x,
            y,
            r,
            r,
            options);
        arc.r = r; // #959
        return arc;
    };
    /**
     * Draw and return a rectangle.
     *
     * @function Highcharts.SVGRenderer#rect
     *
     * @param {number} [x]
     * Left position.
     *
     * @param {number} [y]
     * Top position.
     *
     * @param {number} [width]
     * Width of the rectangle.
     *
     * @param {number} [height]
     * Height of the rectangle.
     *
     * @param {number} [r]
     * Border corner radius.
     *
     * @param {number} [strokeWidth]
     * A stroke width can be supplied to allow crisp drawing.
     *
     * @return {Highcharts.SVGElement}
     * The generated wrapper element.
     */ /**
    * Draw and return a rectangle.
    *
    * @sample highcharts/members/renderer-rect-on-chart/
    *         Draw a rectangle in a chart
    * @sample highcharts/members/renderer-rect/
    *         Draw a rectangle independent from a chart
    *
    * @function Highcharts.SVGRenderer#rect
    *
    * @param {Highcharts.SVGAttributes} [attributes]
    * General SVG attributes for the rectangle.
    *
    * @return {Highcharts.SVGElement}
    * The generated wrapper element.
    */
    SVGRenderer.prototype.rect = function (x, y, width, height, r, strokeWidth) {
        var attribs = (SVGRenderer_isObject(x) ?
                x :
                typeof x === 'undefined' ?
                    {} :
                    {
                        x: x,
                        y: y,
                        r: r,
                        width: Math.max(width || 0, 0),
                        height: Math.max(height || 0, 0)
                    }),
            wrapper = this.createElement('rect');
        if (!this.styledMode) {
            if (typeof strokeWidth !== 'undefined') {
                attribs['stroke-width'] = strokeWidth;
                SVGRenderer_extend(attribs, wrapper.crisp(attribs));
            }
            attribs.fill = 'none';
        }
        wrapper.rSetter = function (value, _key, element) {
            wrapper.r = value;
            SVGRenderer_attr(element, {
                rx: value,
                ry: value
            });
        };
        wrapper.rGetter = function () {
            return wrapper.r || 0;
        };
        return wrapper.attr(attribs);
    };
    /**
     * Draw and return a rectangle with advanced corner rounding options.
     *
     * @function Highcharts.SVGRenderer#roundedRect
     *
     * @param {Highcharts.SVGAttributes} attribs
     *      Attributes
     * @return {Highcharts.SVGElement}
     * The generated wrapper element.
     */
    SVGRenderer.prototype.roundedRect = function (attribs) {
        return this.symbol('roundedRect').attr(attribs);
    };
    /**
     * Resize the {@link SVGRenderer#box} and re-align all aligned child
     * elements.
     *
     * @sample highcharts/members/renderer-g/
     *         Show and hide grouped objects
     *
     * @function Highcharts.SVGRenderer#setSize
     *
     * @param {number} width
     * The new pixel width.
     *
     * @param {number} height
     * The new pixel height.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animate=true]
     * Whether and how to animate.
     */
    SVGRenderer.prototype.setSize = function (width, height, animate) {
        var renderer = this;
        renderer.width = width;
        renderer.height = height;
        renderer.boxWrapper.animate({
            width: width,
            height: height
        }, {
            step: function () {
                this.attr({
                    viewBox: '0 0 ' + this.attr('width') + ' ' +
                        this.attr('height')
                });
            },
            duration: SVGRenderer_pick(animate, true) ? void 0 : 0
        });
        renderer.alignElements();
    };
    /**
     * Create and return an svg group element. Child
     * {@link Highcharts.SVGElement} objects are added to the group by using the
     * group as the first parameter in {@link Highcharts.SVGElement#add|add()}.
     *
     * @function Highcharts.SVGRenderer#g
     *
     * @param {string} [name]
     *        The group will be given a class name of `highcharts-{name}`. This
     *        can be used for styling and scripting.
     *
     * @return {Highcharts.SVGElement}
     *         The generated wrapper element.
     */
    SVGRenderer.prototype.g = function (name) {
        var elem = this.createElement('g');
        return name ?
            elem.attr({ 'class': 'highcharts-' + name }) :
            elem;
    };
    /**
     * Display an image.
     *
     * @sample highcharts/members/renderer-image-on-chart/
     *         Add an image in a chart
     * @sample highcharts/members/renderer-image/
     *         Add an image independent of a chart
     *
     * @function Highcharts.SVGRenderer#image
     *
     * @param {string} href
     *        The image source.
     *
     * @param {number} [x]
     *        The X position.
     *
     * @param {number} [y]
     *        The Y position.
     *
     * @param {number} [width]
     *        The image width. If omitted, it defaults to the image file width.
     *
     * @param {number} [height]
     *        The image height. If omitted it defaults to the image file
     *        height.
     *
     * @param {Function} [onload]
     *        Event handler for image load.
     *
     * @return {Highcharts.SVGElement}
     *         The generated wrapper element.
     */
    SVGRenderer.prototype.image = function (href, x, y, width, height, onload) {
        var attribs = { preserveAspectRatio: 'none' };
        // Optional properties (#11756)
        if (SVGRenderer_isNumber(x)) {
            attribs.x = x;
        }
        if (SVGRenderer_isNumber(y)) {
            attribs.y = y;
        }
        if (SVGRenderer_isNumber(width)) {
            attribs.width = width;
        }
        if (SVGRenderer_isNumber(height)) {
            attribs.height = height;
        }
        var elemWrapper = this.createElement('image').attr(attribs),
            onDummyLoad = function (e) {
                elemWrapper.attr({ href: href });
            onload.call(elemWrapper, e);
        };
        // Add load event if supplied
        if (onload) {
            // We have to use a dummy HTML image since IE support for SVG image
            // load events is very buggy. First set a transparent src, wait for
            // dummy to load, and then add the real src to the SVG image.
            elemWrapper.attr({
                /* eslint-disable-next-line max-len */
                href: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
            });
            var dummy = new SVGRenderer_win.Image();
            SVGRenderer_addEvent(dummy, 'load', onDummyLoad);
            dummy.src = href;
            if (dummy.complete) {
                onDummyLoad({});
            }
        }
        else {
            elemWrapper.attr({ href: href });
        }
        return elemWrapper;
    };
    /**
     * Draw a symbol out of pre-defined shape paths from
     * {@link SVGRenderer#symbols}.
     * It is used in Highcharts for point makers, which cake a `symbol` option,
     * and label and button backgrounds like in the tooltip and stock flags.
     *
     * @function Highcharts.SVGRenderer#symbol
     *
     * @param {string} symbol
     * The symbol name.
     *
     * @param {number} [x]
     * The X coordinate for the top left position.
     *
     * @param {number} [y]
     * The Y coordinate for the top left position.
     *
     * @param {number} [width]
     * The pixel width.
     *
     * @param {number} [height]
     * The pixel height.
     *
     * @param {Highcharts.SymbolOptionsObject} [options]
     * Additional options, depending on the actual symbol drawn.
     *
     * @return {Highcharts.SVGElement}
     * SVG symbol.
     */
    SVGRenderer.prototype.symbol = function (symbol, x, y, width, height, options) {
        var ren = this, imageRegex = /^url\((.*?)\)$/, isImage = imageRegex.test(symbol), sym = (!isImage && (this.symbols[symbol] ? symbol : 'circle')), 
            // Get the symbol definition function
            symbolFn = (sym && this.symbols[sym]);
        var obj,
            path,
            imageSrc,
            centerImage;
        if (symbolFn) {
            // Check if there's a path defined for this symbol
            if (typeof x === 'number') {
                path = symbolFn.call(this.symbols, x || 0, y || 0, width || 0, height || 0, options);
            }
            obj = this.path(path);
            if (!ren.styledMode) {
                obj.attr('fill', 'none');
            }
            // Expando properties for use in animate and attr
            SVGRenderer_extend(obj, {
                symbolName: (sym || void 0),
                x: x,
                y: y,
                width: width,
                height: height
            });
            if (options) {
                SVGRenderer_extend(obj, options);
            }
            // Image symbols
        }
        else if (isImage) {
            imageSrc = symbol.match(imageRegex)[1];
            // Create the image synchronously, add attribs async
            var img_1 = obj = this.image(imageSrc);
            // The image width is not always the same as the symbol width. The
            // image may be centered within the symbol, as is the case when
            // image shapes are used as label backgrounds, for example in flags.
            img_1.imgwidth = SVGRenderer_pick(options && options.width, symbolSizes[imageSrc] && symbolSizes[imageSrc].width);
            img_1.imgheight = SVGRenderer_pick(options && options.height, symbolSizes[imageSrc] && symbolSizes[imageSrc].height);
            /**
             * Set the size and position
             */
            centerImage = function (obj) { return obj.attr({
                width: obj.width,
                height: obj.height
            }); };
            /**
             * Width and height setters that take both the image's physical size
             * and the label size into consideration, and translates the image
             * to center within the label.
             */
            ['width', 'height'].forEach(function (key) {
                img_1["" + key + "Setter"] = function (value, key) {
                    this[key] = value;
                    var _a = this,
                        alignByTranslate = _a.alignByTranslate,
                        element = _a.element,
                        width = _a.width,
                        height = _a.height,
                        imgwidth = _a.imgwidth,
                        imgheight = _a.imgheight,
                        imgSize = key === 'width' ? imgwidth : imgheight;
                    var scale = 1;
                    // Scale and center the image within its container. The name
                    // `backgroundSize` is taken from the CSS spec, but the
                    // value `within` is made up. Other possible values in the
                    // spec, `cover` and `contain`, can be implemented if
                    // needed.
                    if (options &&
                        options.backgroundSize === 'within' &&
                        width &&
                        height &&
                        imgwidth &&
                        imgheight) {
                        scale = Math.min(width / imgwidth, height / imgheight);
                        // Update both width and height to keep the ratio
                        // correct (#17315)
                        SVGRenderer_attr(element, {
                            width: Math.round(imgwidth * scale),
                            height: Math.round(imgheight * scale)
                        });
                    }
                    else if (element && imgSize) {
                        element.setAttribute(key, imgSize);
                    }
                    if (!alignByTranslate && imgwidth && imgheight) {
                        this.translate(((width || 0) - (imgwidth * scale)) / 2, ((height || 0) - (imgheight * scale)) / 2);
                    }
                };
            });
            if (SVGRenderer_defined(x)) {
                img_1.attr({
                    x: x,
                    y: y
                });
            }
            img_1.isImg = true;
            img_1.symbolUrl = symbol;
            if (SVGRenderer_defined(img_1.imgwidth) && SVGRenderer_defined(img_1.imgheight)) {
                centerImage(img_1);
            }
            else {
                // Initialize image to be 0 size so export will still function
                // if there's no cached sizes.
                img_1.attr({ width: 0, height: 0 });
                // Create a dummy JavaScript image to get the width and height.
                SVGRenderer_createElement('img', {
                    onload: function () {
                        var chart = SVGRenderer_charts[ren.chartIndex];
                        // Special case for SVGs on IE11, the width is not
                        // accessible until the image is part of the DOM
                        // (#2854).
                        if (this.width === 0) {
                            SVGRenderer_css(this, {
                                position: 'absolute',
                                top: '-999em'
                            });
                            SVGRenderer_doc.body.appendChild(this);
                        }
                        // Center the image
                        symbolSizes[imageSrc] = {
                            width: this.width,
                            height: this.height
                        };
                        img_1.imgwidth = this.width;
                        img_1.imgheight = this.height;
                        if (img_1.element) {
                            centerImage(img_1);
                        }
                        // Clean up after #2854 workaround.
                        if (this.parentNode) {
                            this.parentNode.removeChild(this);
                        }
                        // Fire the load event when all external images are
                        // loaded
                        ren.imgCount--;
                        if (!ren.imgCount && chart && !chart.hasLoaded) {
                            chart.onload();
                        }
                    },
                    src: imageSrc
                });
                this.imgCount++;
            }
        }
        return obj;
    };
    /**
     * Define a clipping rectangle. The clipping rectangle is later applied
     * to {@link SVGElement} objects through the {@link SVGElement#clip}
     * function.
     *
     * This function is deprecated as of v11.2. Instead, use a regular shape
     * (`rect`, `path` etc), and the `SVGElement.clipTo` function.
     *
     * @example
     * let circle = renderer.circle(100, 100, 100)
     *     .attr({ fill: 'red' })
     *     .add();
     * let clipRect = renderer.clipRect(100, 100, 100, 100);
     *
     * // Leave only the lower right quarter visible
     * circle.clip(clipRect);
     *
     * @deprecated
     *
     * @function Highcharts.SVGRenderer#clipRect
     *
     * @param {number} [x]
     *
     * @param {number} [y]
     *
     * @param {number} [width]
     *
     * @param {number} [height]
     *
     * @return {Highcharts.ClipRectElement}
     *         A clipping rectangle.
     */
    SVGRenderer.prototype.clipRect = function (x, y, width, height) {
        return this.rect(x, y, width, height, 0);
    };
    /**
     * Draw text. The text can contain a subset of HTML, like spans and anchors
     * and some basic text styling of these. For more advanced features like
     * border and background, use {@link Highcharts.SVGRenderer#label} instead.
     * To update the text after render, run `text.attr({ text: 'New text' })`.
     *
     * @sample highcharts/members/renderer-text-on-chart/
     *         Annotate the chart freely
     * @sample highcharts/members/renderer-on-chart/
     *         Annotate with a border and in response to the data
     * @sample highcharts/members/renderer-text/
     *         Formatted text
     *
     * @function Highcharts.SVGRenderer#text
     *
     * @param {string} [str]
     * The text of (subset) HTML to draw.
     *
     * @param {number} [x]
     * The x position of the text's lower left corner.
     *
     * @param {number} [y]
     * The y position of the text's lower left corner.
     *
     * @param {boolean} [useHTML=false]
     * Use HTML to render the text.
     *
     * @return {Highcharts.SVGElement}
     * The text object.
     */
    SVGRenderer.prototype.text = function (str, x, y, useHTML) {
        var renderer = this,
            attribs = {};
        if (useHTML && (renderer.allowHTML || !renderer.forExport)) {
            return renderer.html(str, x, y);
        }
        attribs.x = Math.round(x || 0); // X always needed for line-wrap logic
        if (y) {
            attribs.y = Math.round(y);
        }
        if (SVGRenderer_defined(str)) {
            attribs.text = str;
        }
        var wrapper = renderer.createElement('text').attr(attribs);
        if (!useHTML || (renderer.forExport && !renderer.allowHTML)) {
            wrapper.xSetter = function (value, key, element) {
                var tspans = element.getElementsByTagName('tspan'),
                    parentVal = element.getAttribute(key);
                for (var i = 0, tspan = void 0; i < tspans.length; i++) {
                    tspan = tspans[i];
                    // If the x values are equal, the tspan represents a line
                    // break
                    if (tspan.getAttribute(key) === parentVal) {
                        tspan.setAttribute(key, value);
                    }
                }
                element.setAttribute(key, value);
            };
        }
        return wrapper;
    };
    /**
     * Utility to return the baseline offset and total line height from the font
     * size.
     *
     * @function Highcharts.SVGRenderer#fontMetrics
     *
     * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement|number} [element]
     *        The element to inspect for a current font size. If a number is
     *        given, it's used as a fall back for direct font size in pixels.
     *
     * @return {Highcharts.FontMetricsObject}
     *         The font metrics.
     */
    SVGRenderer.prototype.fontMetrics = function (element) {
        var f = SVGRenderer_pInt(SVG_SVGElement.prototype.getStyle.call(element, 'font-size') || 0);
        // Empirical values found by comparing font size and bounding box
        // height. Applies to the default font family.
        // https://jsfiddle.net/highcharts/7xvn7/
        var h = f < 24 ? f + 3 : Math.round(f * 1.2),
            b = Math.round(h * 0.8);
        return {
            // Line height
            h: h,
            // Baseline
            b: b,
            // Font size
            f: f
        };
    };
    /**
     * Correct X and Y positioning of a label for rotation (#1764).
     *
     * @private
     * @function Highcharts.SVGRenderer#rotCorr
     */
    SVGRenderer.prototype.rotCorr = function (baseline, rotation, alterY) {
        var y = baseline;
        if (rotation && alterY) {
            y = Math.max(y * Math.cos(rotation * SVGRenderer_deg2rad), 4);
        }
        return {
            x: (-baseline / 3) * Math.sin(rotation * SVGRenderer_deg2rad),
            y: y
        };
    };
    /**
     * Compatibility function to convert the legacy one-dimensional path array
     * into an array of segments.
     *
     * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter
     * to support legacy paths from demos.
     *
     * @private
     * @function Highcharts.SVGRenderer#pathToSegments
     */
    SVGRenderer.prototype.pathToSegments = function (path) {
        var ret = [];
        var segment = [];
        var commandLength = {
                A: 8,
                C: 7,
                H: 2,
                L: 3,
                M: 3,
                Q: 5,
                S: 5,
                T: 3,
                V: 2
            };
        // Short, non-typesafe parsing of the one-dimensional array. It splits
        // the path on any string. This is not type checked against the tuple
        // types, but is shorter, and doesn't require specific checks for any
        // command type in SVG.
        for (var i = 0; i < path.length; i++) {
            // Command skipped, repeat previous or insert L/l for M/m
            if (SVGRenderer_isString(segment[0]) &&
                SVGRenderer_isNumber(path[i]) &&
                segment.length === commandLength[(segment[0].toUpperCase())]) {
                path.splice(i, 0, segment[0].replace('M', 'L').replace('m', 'l'));
            }
            // Split on string
            if (typeof path[i] === 'string') {
                if (segment.length) {
                    ret.push(segment.slice(0));
                }
                segment.length = 0;
            }
            segment.push(path[i]);
        }
        ret.push(segment.slice(0));
        return ret;
        /*
        // Fully type-safe version where each tuple type is checked. The
        // downside is filesize and a lack of flexibility for unsupported
        // commands
        const ret: SVGPath = [],
            commands = {
                A: 7,
                C: 6,
                H: 1,
                L: 2,
                M: 2,
                Q: 4,
                S: 4,
                T: 2,
                V: 1,
                Z: 0
            };

        let i = 0,
            lastI = 0,
            lastCommand;

        while (i < path.length) {
            const item = path[i];

            let command;

            if (typeof item === 'string') {
                command = item;
                i += 1;
            } else {
                command = lastCommand || 'M';
            }

            // Upper case
            const commandUC = command.toUpperCase();

            if (commandUC in commands) {

                // No numeric parameters
                if (command === 'Z' || command === 'z') {
                    ret.push([command]);

                // One numeric parameter
                } else {
                    const val0 = path[i];
                    if (typeof val0 === 'number') {

                        // Horizontal line to
                        if (command === 'H' || command === 'h') {
                            ret.push([command, val0]);
                            i += 1;

                        // Vertical line to
                        } else if (command === 'V' || command === 'v') {
                            ret.push([command, val0]);
                            i += 1;

                        // Two numeric parameters
                        } else {
                            const val1 = path[i + 1];
                            if (typeof val1 === 'number') {
                                // lineTo
                                if (command === 'L' || command === 'l') {
                                    ret.push([command, val0, val1]);
                                    i += 2;

                                // moveTo
                                } else if (command === 'M' || command === 'm') {
                                    ret.push([command, val0, val1]);
                                    i += 2;

                                // Smooth quadratic bezier
                                } else if (command === 'T' || command === 't') {
                                    ret.push([command, val0, val1]);
                                    i += 2;

                                // Four numeric parameters
                                } else {
                                    const val2 = path[i + 2],
                                        val3 = path[i + 3];
                                    if (
                                        typeof val2 === 'number' &&
                                        typeof val3 === 'number'
                                    ) {
                                        // Quadratic bezier to
                                        if (
                                            command === 'Q' ||
                                            command === 'q'
                                        ) {
                                            ret.push([
                                                command,
                                                val0,
                                                val1,
                                                val2,
                                                val3
                                            ]);
                                            i += 4;

                                        // Smooth cubic bezier to
                                        } else if (
                                            command === 'S' ||
                                            command === 's'
                                        ) {
                                            ret.push([
                                                command,
                                                val0,
                                                val1,
                                                val2,
                                                val3
                                            ]);
                                            i += 4;

                                        // Six numeric parameters
                                        } else {
                                            const val4 = path[i + 4],
                                                val5 = path[i + 5];

                                            if (
                                                typeof val4 === 'number' &&
                                                typeof val5 === 'number'
                                            ) {
                                                // Curve to
                                                if (
                                                    command === 'C' ||
                                                    command === 'c'
                                                ) {
                                                    ret.push([
                                                        command,
                                                        val0,
                                                        val1,
                                                        val2,
                                                        val3,
                                                        val4,
                                                        val5
                                                    ]);
                                                    i += 6;

                                                // Seven numeric parameters
                                                } else {
                                                    const val6 = path[i + 6];

                                                    // Arc to
                                                    if (
                                                        typeof val6 ===
                                                        'number' &&
                                                        (
                                                            command === 'A' ||
                                                            command === 'a'
                                                        )
                                                    ) {
                                                        ret.push([
                                                            command,
                                                            val0,
                                                            val1,
                                                            val2,
                                                            val3,
                                                            val4,
                                                            val5,
                                                            val6
                                                        ]);
                                                        i += 7;

                                                    }

                                                }
                                            }
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }

            // An unmarked command following a moveTo is a lineTo
            lastCommand = command === 'M' ? 'L' : command;

            if (i === lastI) {
                break;
            }
            lastI = i;
        }
        return ret;
        */
    };
    /**
     * Draw a label, which is an extended text element with support for border
     * and background. Highcharts creates a `g` element with a text and a `path`
     * or `rect` inside, to make it behave somewhat like a HTML div. Border and
     * background are set through `stroke`, `stroke-width` and `fill` attributes
     * using the {@link Highcharts.SVGElement#attr|attr} method. To update the
     * text after render, run `label.attr({ text: 'New text' })`.
     *
     * @sample highcharts/members/renderer-label-on-chart/
     *         A label on the chart
     *
     * @function Highcharts.SVGRenderer#label
     *
     * @param {string} str
     *        The initial text string or (subset) HTML to render.
     *
     * @param {number} x
     *        The x position of the label's left side.
     *
     * @param {number} [y]
     *        The y position of the label's top side or baseline, depending on
     *        the `baseline` parameter.
     *
     * @param {string} [shape='rect']
     *        The shape of the label's border/background, if any. Defaults to
     *        `rect`. Other possible values are `callout` or other shapes
     *        defined in {@link Highcharts.SVGRenderer#symbols}.
     *
     * @param {number} [anchorX]
     *        In case the `shape` has a pointer, like a flag, this is the
     *        coordinates it should be pinned to.
     *
     * @param {number} [anchorY]
     *        In case the `shape` has a pointer, like a flag, this is the
     *        coordinates it should be pinned to.
     *
     * @param {boolean} [useHTML=false]
     *        Whether to use HTML to render the label.
     *
     * @param {boolean} [baseline=false]
     *        Whether to position the label relative to the text baseline,
     *        like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the
     *        upper border of the rectangle.
     *
     * @param {string} [className]
     *        Class name for the group.
     *
     * @return {Highcharts.SVGElement}
     *         The generated label.
     */
    SVGRenderer.prototype.label = function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
        return new SVG_SVGLabel(this, str, x, y, shape, anchorX, anchorY, useHTML, baseline, className);
    };
    /**
     * Re-align all aligned elements.
     *
     * @private
     * @function Highcharts.SVGRenderer#alignElements
     */
    SVGRenderer.prototype.alignElements = function () {
        this.alignedObjects.forEach(function (el) { return el.align(); });
    };
    return SVGRenderer;
}());
SVGRenderer_extend(SVGRenderer.prototype, {
    /**
     * A pointer to the renderer's associated Element class.
     *
     * @name Highcharts.SVGRenderer#Element
     * @type {Highcharts.SVGElement}
     */
    Element: SVG_SVGElement,
    SVG_NS: SVGRenderer_SVG_NS,
    /**
     * A collection of characters mapped to HTML entities. When `useHTML` on an
     * element is true, these entities will be rendered correctly by HTML. In
     * the SVG pseudo-HTML, they need to be unescaped back to simple characters,
     * so for example `&lt;` will render as `<`.
     *
     * @example
     * // Add support for unescaping quotes
     * Highcharts.SVGRenderer.prototype.escapes['"'] = '&quot;';
     *
     * @name Highcharts.SVGRenderer#escapes
     * @type {Highcharts.Dictionary<string>}
     */
    escapes: {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;', // eslint-disable-line quotes
        '"': '&quot;'
    },
    /**
     * An extendable collection of functions for defining symbol paths.
     *
     * @name Highcharts.SVGRenderer#symbols
     * @type {Highcharts.SymbolDictionary}
     */
    symbols: SVG_Symbols,
    /**
     * Dummy function for plugins, called every time the renderer is updated.
     * Prior to Highcharts 5, this was used for the canvg renderer.
     *
     * @deprecated
     * @function Highcharts.SVGRenderer#draw
     */
    draw: noop
});
/* *
 *
 *  Registry
 *
 * */
Renderer_RendererRegistry.registerRendererType('svg', SVGRenderer, true);
/* *
 *
 *  Export Default
 *
 * */
/* harmony default export */ var SVG_SVGRenderer = (SVGRenderer);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * A clipping rectangle that can be applied to one or more {@link SVGElement}
 * instances. It is instantiated with the {@link SVGRenderer#clipRect} function
 * and applied with the {@link SVGElement#clip} function.
 *
 * @example
 * let circle = renderer.circle(100, 100, 100)
 *     .attr({ fill: 'red' })
 *     .add();
 * let clipRect = renderer.clipRect(100, 100, 100, 100);
 *
 * // Leave only the lower right quarter visible
 * circle.clip(clipRect);
 *
 * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement
 */
/**
 * The font metrics.
 *
 * @interface Highcharts.FontMetricsObject
 */ /**
* The baseline relative to the top of the box.
*
* @name Highcharts.FontMetricsObject#b
* @type {number}
*/ /**
* The font size.
*
* @name Highcharts.FontMetricsObject#f
* @type {number}
*/ /**
* The line height.
*
* @name Highcharts.FontMetricsObject#h
* @type {number}
*/
/**
 * An object containing `x` and `y` properties for the position of an element.
 *
 * @interface Highcharts.PositionObject
 */ /**
* X position of the element.
* @name Highcharts.PositionObject#x
* @type {number}
*/ /**
* Y position of the element.
* @name Highcharts.PositionObject#y
* @type {number}
*/
/**
 * A rectangle.
 *
 * @interface Highcharts.RectangleObject
 */ /**
* Height of the rectangle.
* @name Highcharts.RectangleObject#height
* @type {number}
*/ /**
* Width of the rectangle.
* @name Highcharts.RectangleObject#width
* @type {number}
*/ /**
* Horizontal position of the rectangle.
* @name Highcharts.RectangleObject#x
* @type {number}
*/ /**
* Vertical position of the rectangle.
* @name Highcharts.RectangleObject#y
* @type {number}
*/
/**
 * The shadow options.
 *
 * @interface Highcharts.ShadowOptionsObject
 */ /**
* The shadow color.
* @name    Highcharts.ShadowOptionsObject#color
* @type    {Highcharts.ColorString|undefined}
* @default ${palette.neutralColor100}
*/ /**
* The horizontal offset from the element.
*
* @name    Highcharts.ShadowOptionsObject#offsetX
* @type    {number|undefined}
* @default 1
*/ /**
* The vertical offset from the element.
* @name    Highcharts.ShadowOptionsObject#offsetY
* @type    {number|undefined}
* @default 1
*/ /**
* The shadow opacity.
*
* @name    Highcharts.ShadowOptionsObject#opacity
* @type    {number|undefined}
* @default 0.15
*/ /**
* The shadow width or distance from the element.
* @name    Highcharts.ShadowOptionsObject#width
* @type    {number|undefined}
* @default 3
*/
/**
 * @interface Highcharts.SizeObject
 */ /**
* @name Highcharts.SizeObject#height
* @type {number}
*/ /**
* @name Highcharts.SizeObject#width
* @type {number}
*/
/**
 * Array of path commands, that will go into the `d` attribute of an SVG
 * element.
 *
 * @typedef {Array<(Array<Highcharts.SVGPathCommand>|Array<Highcharts.SVGPathCommand,number>|Array<Highcharts.SVGPathCommand,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number,number>)>} Highcharts.SVGPathArray
 */
/**
 * Possible path commands in an SVG path array. Valid values are `A`, `C`, `H`,
 * `L`, `M`, `Q`, `S`, `T`, `V`, `Z`.
 *
 * @typedef {string} Highcharts.SVGPathCommand
 * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"]
 */
/**
 * An extendable collection of functions for defining symbol paths. Symbols are
 * used internally for point markers, button and label borders and backgrounds,
 * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}.
 *
 * @interface Highcharts.SymbolDictionary
 */ /**
* @name Highcharts.SymbolDictionary#[key:string]
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#arc
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#callout
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#circle
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#diamond
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#square
* @type {Function|undefined}
*/ /**
* @name Highcharts.SymbolDictionary#triangle
* @type {Function|undefined}
*/
/**
 * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`,
 * and `triangle-down`. Symbols are used internally for point markers, button
 * and label borders and backgrounds, or custom shapes. Extendable by adding to
 * {@link SVGRenderer#symbols}.
 *
 * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue
 */
/**
 * Additional options, depending on the actual symbol drawn.
 *
 * @interface Highcharts.SymbolOptionsObject
 */ /**
* The anchor X position for the `callout` symbol. This is where the chevron
* points to.
*
* @name Highcharts.SymbolOptionsObject#anchorX
* @type {number|undefined}
*/ /**
* The anchor Y position for the `callout` symbol. This is where the chevron
* points to.
*
* @name Highcharts.SymbolOptionsObject#anchorY
* @type {number|undefined}
*/ /**
* The end angle of an `arc` symbol.
*
* @name Highcharts.SymbolOptionsObject#end
* @type {number|undefined}
*/ /**
* Whether to draw `arc` symbol open or closed.
*
* @name Highcharts.SymbolOptionsObject#open
* @type {boolean|undefined}
*/ /**
* The radius of an `arc` symbol, or the border radius for the `callout` symbol.
*
* @name Highcharts.SymbolOptionsObject#r
* @type {number|undefined}
*/ /**
* The start angle of an `arc` symbol.
*
* @name Highcharts.SymbolOptionsObject#start
* @type {number|undefined}
*/
(''); // Keeps doclets above in transpiled file

;// ./code/es5/es-modules/Core/Renderer/HTML/HTMLElement.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var HTMLElement_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (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 composed = Core_Globals.composed;


var HTMLElement_attr = Core_Utilities.attr, HTMLElement_css = Core_Utilities.css, HTMLElement_createElement = Core_Utilities.createElement, HTMLElement_defined = Core_Utilities.defined, HTMLElement_extend = Core_Utilities.extend, HTMLElement_getAlignFactor = Core_Utilities.getAlignFactor, HTMLElement_isNumber = Core_Utilities.isNumber, HTMLElement_pInt = Core_Utilities.pInt, HTMLElement_pushUnique = Core_Utilities.pushUnique;
/**
 * The opacity and visibility properties are set as attributes on the main
 * element and SVG groups, and as identical CSS properties on the HTML element
 * and the ancestry divs. (#3542)
 *
 * @private
 */
function commonSetter(value, key, elem) {
    var _a;
    var style = ((_a = this.div) === null || _a === void 0 ? void 0 : _a.style) || elem.style;
    SVG_SVGElement.prototype["" + key + "Setter"].call(this, value, key, elem);
    if (style) {
        style[key] = value;
    }
}
/**
 * Decorate each SVG group in the ancestry line. Each SVG `g` element that
 * contains children with useHTML, will receive a `div` element counterpart to
 * contain the HTML span. These div elements are translated and styled like
 * original `g` counterparts.
 *
 * @private
 */
var decorateSVGGroup = function (g, container) {
    var _a;
    if (!g.div) {
        var className = HTMLElement_attr(g.element, 'class'),
            cssProto_1 = g.css;
        // Create the parallel HTML group
        var div_1 = HTMLElement_createElement('div', className ? { className: className } : void 0, __assign(__assign({ 
                // Add HTML specific styles
                position: 'absolute', left: "" + (g.translateX || 0) + "px", top: "" + (g.translateY || 0) + "px" }, g.styles), { 
                // Add g attributes that correspond to CSS
                display: g.display, opacity: g.opacity, visibility: g.visibility }), 
            // The top group is appended to container
            ((_a = g.parentGroup) === null || _a === void 0 ? void 0 : _a.div) || container);
        g.classSetter = function (value, key, element) {
            element.setAttribute('class', value);
            div_1.className = value;
        };
        /**
         * Common translate setter for X and Y on the HTML group.
         *
         * Reverted the fix for #6957 due to positioning problems and offline
         * export (#7254, #7280, #7529)
         * @private
         */
        g.translateXSetter = g.translateYSetter = function (value, key) {
            g[key] = value;
            div_1.style[key === 'translateX' ? 'left' : 'top'] = "" + value + "px";
            g.doTransform = true;
        };
        g.opacitySetter = g.visibilitySetter = commonSetter;
        // Extend the parent group's css function by updating the parallel div
        // counterpart with the same style.
        g.css = function (styles) {
            // Call the base css method. The `parentGroup` can be either an
            // SVGElement or an SVGLabel, in which the css method is extended
            // (#19200).
            cssProto_1.call(g, styles);
            // #6794
            if (styles.cursor) {
                div_1.style.cursor = styles.cursor;
            }
            // #18821
            if (styles.pointerEvents) {
                div_1.style.pointerEvents = styles.pointerEvents;
            }
            return g;
        };
        // Event handling
        g.on = function () {
            SVG_SVGElement.prototype.on.apply({
                element: div_1,
                onEvents: g.onEvents
            }, arguments);
            return g;
        };
        g.div = div_1;
    }
    return g.div;
};
/* *
 *
 *  Class
 *
 * */
var HTMLElement = /** @class */ (function (_super) {
    HTMLElement_extends(HTMLElement, _super);
    /* *
     *
     *  Functions
     *
     * */
    function HTMLElement(renderer, nodeName) {
        var _this = _super.call(this,
            renderer,
            nodeName) || this;
        _this.css(__assign({ position: 'absolute' }, (renderer.styledMode ? {} : {
            fontFamily: renderer.style.fontFamily,
            fontSize: renderer.style.fontSize
        })));
        return _this;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * Compose
     * @private
     */
    HTMLElement.compose = function (SVGRendererClass) {
        if (HTMLElement_pushUnique(composed, this.compose)) {
            /**
             * Create a HTML text node. This is used by the SVG renderer `text`
             * and `label` functions through the `useHTML` parameter.
             *
             * @private
             */
            SVGRendererClass.prototype.html = function (str, x, y) {
                return new HTMLElement(this, 'span')
                    // Set the default attributes
                    .attr({
                    text: str,
                    x: Math.round(x),
                    y: Math.round(y)
                });
            };
        }
    };
    /**
     * Get the correction in X and Y positioning as the element is rotated.
     * @private
     */
    HTMLElement.prototype.getSpanCorrection = function (width, baseline, alignCorrection) {
        this.xCorr = -width * alignCorrection;
        this.yCorr = -baseline;
    };
    /**
     * Apply CSS to HTML elements. This is used in text within SVG rendering.
     * @private
     */
    HTMLElement.prototype.css = function (styles) {
        var element = this.element, 
            // When setting or unsetting the width style, we need to update
            // transform (#8809)
            isSettingWidth = (element.tagName === 'SPAN' &&
                styles &&
                'width' in styles),
            textWidth = isSettingWidth && styles.width;
        var doTransform;
        if (isSettingWidth) {
            delete styles.width;
            this.textWidth = HTMLElement_pInt(textWidth) || void 0;
            doTransform = true;
        }
        // Some properties require other properties to be set
        if ((styles === null || styles === void 0 ? void 0 : styles.textOverflow) === 'ellipsis') {
            styles.overflow = 'hidden';
        }
        if (styles === null || styles === void 0 ? void 0 : styles.lineClamp) {
            styles.display = '-webkit-box';
            styles.WebkitLineClamp = styles.lineClamp;
            styles.WebkitBoxOrient = 'vertical';
            styles.overflow = 'hidden';
        }
        // SVG natively supports setting font size as numbers. With HTML, the
        // font size should behave in the same way (#21624).
        if (HTMLElement_isNumber(Number(styles === null || styles === void 0 ? void 0 : styles.fontSize))) {
            styles.fontSize = styles.fontSize + 'px';
        }
        HTMLElement_extend(this.styles, styles);
        HTMLElement_css(element, styles);
        // Now that all styles are applied, to the transform
        if (doTransform) {
            this.updateTransform();
        }
        return this;
    };
    /**
     * The useHTML method for calculating the bounding box based on offsets.
     * Called internally from the `SVGElement.getBBox` function and subsequently
     * rotated.
     *
     * @private
     */
    HTMLElement.prototype.htmlGetBBox = function () {
        var element = this.element;
        return {
            x: element.offsetLeft,
            y: element.offsetTop,
            width: element.offsetWidth,
            height: element.offsetHeight
        };
    };
    /**
     * Batch update styles and attributes related to transform
     *
     * @private
     */
    HTMLElement.prototype.updateTransform = function () {
        var _this = this;
        var _a;
        // Aligning non added elements is expensive
        if (!this.added) {
            this.alignOnAdd = true;
            return;
        }
        var _b = this, element = _b.element, renderer = _b.renderer, rotation = _b.rotation, rotationOriginX = _b.rotationOriginX, rotationOriginY = _b.rotationOriginY, scaleX = _b.scaleX, scaleY = _b.scaleY, styles = _b.styles, _c = _b.textAlign, textAlign = _c === void 0 ? 'left' : _c, textWidth = _b.textWidth, _d = _b.translateX, translateX = _d === void 0 ? 0 : _d, _e = _b.translateY, translateY = _e === void 0 ? 0 : _e, _f = _b.x, x = _f === void 0 ? 0 : _f, _g = _b.y, y = _g === void 0 ? 0 : _g, _h = styles.display, display = _h === void 0 ? 'block' : _h, whiteSpace = styles.whiteSpace;
        // Get the pixel length of the text
        var getTextPxLength = function () {
                if (_this.textPxLength) {
                    return _this.textPxLength;
            }
            // Reset multiline/ellipsis in order to read width (#4928,
            // #5417)
            HTMLElement_css(element, {
                width: '',
                whiteSpace: whiteSpace || 'nowrap'
            });
            return element.offsetWidth;
        };
        // Apply translate
        HTMLElement_css(element, {
            marginLeft: "" + translateX + "px",
            marginTop: "" + translateY + "px"
        });
        if (element.tagName === 'SPAN') {
            var currentTextTransform = [
                    rotation,
                    textAlign,
                    element.innerHTML,
                    textWidth,
                    this.textAlign
                ].join(','), parentPadding = (((_a = this.parentGroup) === null || _a === void 0 ? void 0 : _a.padding) * -1) || 0;
            var baseline = void 0;
            // Update textWidth. Use the memoized textPxLength if possible, to
            // avoid the getTextPxLength function using elem.offsetWidth.
            // Calling offsetWidth affects rendering time as it forces layout
            // (#7656).
            if (textWidth !== this.oldTextWidth) { // #983, #1254
                var textPxLength = getTextPxLength(),
                    textWidthNum = textWidth || 0;
                if (((textWidthNum > this.oldTextWidth) ||
                    textPxLength > textWidthNum) && (
                // Only set the width if the text is able to word-wrap,
                // or text-overflow is ellipsis (#9537)
                /[ \-]/.test(element.textContent || element.innerText) ||
                    element.style.textOverflow === 'ellipsis')) {
                    HTMLElement_css(element, {
                        width: ((textPxLength > textWidthNum) ||
                            rotation ||
                            scaleX) ?
                            textWidth + 'px' :
                            'auto', // #16261
                        display: display,
                        whiteSpace: whiteSpace || 'normal' // #3331
                    });
                    this.oldTextWidth = textWidth;
                }
            }
            // Do the calculations and DOM access only if properties changed
            if (currentTextTransform !== this.cTT) {
                baseline = renderer.fontMetrics(element).b;
                // Renderer specific handling of span rotation, but only if we
                // have something to update.
                if (HTMLElement_defined(rotation) &&
                    ((rotation !== (this.oldRotation || 0)) ||
                        (textAlign !== this.oldAlign))) {
                    this.setSpanRotation(rotation, parentPadding, parentPadding);
                }
                this.getSpanCorrection(
                // Avoid elem.offsetWidth if we can, it affects rendering
                // time heavily (#7656)
                ((!HTMLElement_defined(rotation) &&
                    !this.textWidth &&
                    this.textPxLength) || // #7920
                    element.offsetWidth), baseline, HTMLElement_getAlignFactor(textAlign));
            }
            // Apply position with correction and rotation origin
            var _j = this,
                _k = _j.xCorr,
                xCorr = _k === void 0 ? 0 : _k,
                _l = _j.yCorr,
                yCorr = _l === void 0 ? 0 : _l,
                rotOriginX = (rotationOriginX !== null && rotationOriginX !== void 0 ? rotationOriginX : x) - xCorr - x - parentPadding,
                rotOriginY = (rotationOriginY !== null && rotationOriginY !== void 0 ? rotationOriginY : y) - yCorr - y - parentPadding,
                styles_1 = {
                    left: "" + (x + xCorr) + "px",
                    top: "" + (y + yCorr) + "px",
                    textAlign: textAlign,
                    transformOrigin: "" + rotOriginX + "px " + rotOriginY + "px"
                };
            if (scaleX || scaleY) {
                styles_1.transform = "scale(".concat(scaleX !== null && scaleX !== void 0 ? scaleX : 1, ",").concat(scaleY !== null && scaleY !== void 0 ? scaleY : 1, ")");
            }
            HTMLElement_css(element, styles_1);
            // Record current text transform
            this.cTT = currentTextTransform;
            this.oldRotation = rotation;
            this.oldAlign = textAlign;
        }
    };
    /**
     * Set the rotation of an individual HTML span.
     * @private
     */
    HTMLElement.prototype.setSpanRotation = function (rotation, originX, originY) {
        // CSS transform and transform-origin both supported without prefix
        // since Firefox 16 (2012), IE 10 (2012), Chrome 36 (2014), Safari 9
        // (2015).;
        HTMLElement_css(this.element, {
            transform: "rotate(".concat(rotation, "deg)"),
            transformOrigin: "" + originX + "% " + originY + "px"
        });
    };
    /**
     * Add the element to a group wrapper. For HTML elements, a parallel div
     * will be created for each ancenstor SVG `g` element.
     *
     * @private
     */
    HTMLElement.prototype.add = function (parentGroup) {
        var container = this.renderer.box
                .parentNode,
            parents = [];
        var div;
        this.parentGroup = parentGroup;
        // Create a parallel divs to hold the HTML elements
        if (parentGroup) {
            div = parentGroup.div;
            if (!div) {
                // Read the parent chain into an array and read from top
                // down
                var svgGroup = parentGroup;
                while (svgGroup) {
                    parents.push(svgGroup);
                    // Move up to the next parent group
                    svgGroup = svgGroup.parentGroup;
                }
                // Decorate each of the ancestor group elements with a parallel
                // div that reflects translation and styling
                for (var _i = 0, _a = parents.reverse(); _i < _a.length; _i++) {
                    var parentGroup_1 = _a[_i];
                    div = decorateSVGGroup(parentGroup_1, container);
                }
            }
        }
        (div || container).appendChild(this.element);
        this.added = true;
        if (this.alignOnAdd) {
            this.updateTransform();
        }
        return this;
    };
    /**
     * Text setter
     * @private
     */
    HTMLElement.prototype.textSetter = function (value) {
        if (value !== this.textStr) {
            delete this.bBox;
            delete this.oldTextWidth;
            HTML_AST.setElementHTML(this.element, value !== null && value !== void 0 ? value : '');
            this.textStr = value;
            this.doTransform = true;
        }
    };
    /**
     * Align setter
     *
     * @private
     */
    HTMLElement.prototype.alignSetter = function (value) {
        this.alignValue = this.textAlign = value;
        this.doTransform = true;
    };
    /**
     * Various setters which rely on update transform
     * @private
     */
    HTMLElement.prototype.xSetter = function (value, key) {
        this[key] = value;
        this.doTransform = true;
    };
    return HTMLElement;
}(SVG_SVGElement));
// Some shared setters
var proto = HTMLElement.prototype;
proto.visibilitySetter = proto.opacitySetter = commonSetter;
proto.ySetter =
    proto.rotationSetter =
        proto.rotationOriginXSetter =
            proto.rotationOriginYSetter = proto.xSetter;
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var HTML_HTMLElement = (HTMLElement);

;// ./code/es5/es-modules/Core/Axis/AxisDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Namespace
 *
 * */
var AxisDefaults;
(function (AxisDefaults) {
    /* *
     *
     *  Constants
     *
     * */
    /**
     * The X axis or category axis. Normally this is the horizontal axis,
     * though if the chart is inverted this is the vertical axis. In case of
     * multiple axes, the xAxis node is an array of configuration objects.
     *
     * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
     * access to the axis.
     *
     * @productdesc {highmaps}
     * In Highmaps, the axis is hidden, but it is used behind the scenes to
     * control features like zooming and panning. Zooming is in effect the same
     * as setting the extremes of one of the exes.
     *
     * @type         {*|Array<*>}
     * @optionparent xAxis
     */
    AxisDefaults.xAxis = {
        /**
         * When using multiple axis, the ticks of two or more opposite axes
         * will automatically be aligned by adding ticks to the axis or axes
         * with the least ticks, as if `tickAmount` were specified.
         *
         * This can be prevented by setting `alignTicks` to false. If the grid
         * lines look messy, it's a good idea to hide them for the secondary
         * axis by setting `gridLineWidth` to 0.
         *
         * If `startOnTick` or `endOnTick` in an Axis options are set to false,
         * then the `alignTicks ` will be disabled for the Axis.
         *
         * Disabled for logarithmic axes.
         *
         * @product   highcharts highstock gantt
         */
        alignTicks: true,
        /**
         * Whether to allow decimals in this axis' ticks. When counting
         * integers, like persons or hits on a web page, decimals should
         * be avoided in the labels. By default, decimals are allowed on small
         * scale axes.
         *
         * @see [minTickInterval](#xAxis.minTickInterval)
         *
         * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/
         *         True by default
         * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/
         *         False
         *
         * @type      {boolean|undefined}
         * @default   undefined
         * @since     2.0
         */
        allowDecimals: void 0,
        /**
         * When using an alternate grid color, a band is painted across the
         * plot area between every other grid line.
         *
         * @sample {highcharts} highcharts/yaxis/alternategridcolor/
         *         Alternate grid color on the Y axis
         * @sample {highstock} stock/xaxis/alternategridcolor/
         *         Alternate grid color on the Y axis
         *
         * @type      {Highcharts.ColorType}
         * @apioption xAxis.alternateGridColor
         */
        /**
         * An array defining breaks in the axis, the sections defined will be
         * left out and all the points shifted closer to each other.
         *
         * @productdesc {highcharts}
         * Requires that the broken-axis.js module is loaded.
         *
         * @sample {highcharts} highcharts/axisbreak/break-simple/
         *         Simple break
         * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/
         *         Advanced with callback
         * @sample {highstock} stock/demo/intraday-breaks/
         *         Break on nights and weekends
         *
         * @type      {Array<*>}
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.breaks
         */
        /**
         * A number indicating how much space should be left between the start
         * and the end of the break. The break size is given in axis units,
         * so for instance on a `datetime` axis, a break size of 3600000 would
         * indicate the equivalent of an hour.
         *
         * @type      {number}
         * @default   0
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.breaks.breakSize
         */
        /**
         * The axis value where the break starts. On datetime axes, this may be
         * a date string.
         *
         * @type      {number|string}
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.breaks.from
         */
        /**
         * Defines an interval after which the break appears again. By default
         * the breaks do not repeat.
         *
         * @type      {number}
         * @default   0
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.breaks.repeat
         */
        /**
         * The axis value where the break ends. On datetime axes, this may be
         * a date string.
         *
         * @type      {number|string}
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.breaks.to
         */
        /**
         * If categories are present for the xAxis, names are used instead of
         * numbers for that axis.
         *
         * Since Highcharts 3.0, categories can also
         * be extracted by giving each point a [name](#series.data) and setting
         * axis [type](#xAxis.type) to `category`. However, if you have multiple
         * series, best practice remains defining the `categories` array.
         *
         * Example: `categories: ['Apples', 'Bananas', 'Oranges']`
         *
         * @sample {highcharts} highcharts/demo/line-labels/
         *         With
         * @sample {highcharts} highcharts/xaxis/categories/
         *         Without
         *
         * @type      {Array<string>}
         * @product   highcharts gantt
         * @apioption xAxis.categories
         */
        /**
         * The highest allowed value for automatically computed axis extremes.
         *
         * @see [floor](#xAxis.floor)
         *
         * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/
         *         Floor and ceiling
         *
         * @type       {number}
         * @since      4.0
         * @product    highcharts highstock gantt
         * @apioption  xAxis.ceiling
         */
        /**
         * A class name that opens for styling the axis by CSS, especially in
         * Highcharts styled mode. The class name is applied to group elements
         * for the grid, axis elements and labels.
         *
         * @sample {highcharts|highstock|highmaps} highcharts/css/axis/
         *         Multiple axes with separate styling
         *
         * @type      {string}
         * @since     5.0.0
         * @apioption xAxis.className
         */
        /**
         * Configure a crosshair that follows either the mouse pointer or the
         * hovered point.
         *
         * In styled mode, the crosshairs are styled in the
         * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or
         * `.highcharts-xaxis-category` classes.
         *
         * @productdesc {highstock}
         * In Highcharts stock, by default, the crosshair is enabled on the
         * X axis and disabled on the Y axis.
         *
         * @sample {highcharts} highcharts/xaxis/crosshair-both/
         *         Crosshair on both axes
         * @sample {highstock} stock/xaxis/crosshairs-xy/
         *         Crosshair on both axes, with y axis label
         * @sample {highmaps} highcharts/xaxis/crosshair-both/
         *         Crosshair on both axes
         *
         * @declare   Highcharts.AxisCrosshairOptions
         * @type      {boolean|*}
         * @default   false
         * @since     4.1
         * @apioption xAxis.crosshair
         */
        /**
         * The value on a perpendicular axis where this axis should cross. This
         * is typically used on mathematical plots where the axes cross at 0.
         * When `crossing` is set, space will not be reserved at the sides of
         * the chart for axis labels and title, so those may be clipped. In this
         * case it is better to place the axes without the `crossing` option.
         *
         * @type      {number}
         * @sample    highcharts/xaxis/crossing
         *            Function plot with axes crossing at 0
         * @since 11.0.1
         * @apioption xAxis.crossing
         */
        /**
         * A class name for the crosshair, especially as a hook for styling.
         *
         * @type      {string}
         * @since     5.0.0
         * @apioption xAxis.crosshair.className
         */
        /**
         * The color of the crosshair. Defaults to `#cccccc` for numeric and
         * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where
         * the crosshair by default highlights the whole category.
         *
         * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/
         *         Customized crosshairs
         *
         * @type      {Highcharts.ColorType}
         * @default   #cccccc
         * @since     4.1
         * @apioption xAxis.crosshair.color
         */
        /**
         * The dash style for the crosshair. See
         * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
         * for possible values.
         *
         * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/
         *         Dotted crosshair
         * @sample {highstock} stock/xaxis/crosshair-dashed/
         *         Dashed X axis crosshair
         *
         * @type      {Highcharts.DashStyleValue}
         * @default   Solid
         * @since     4.1
         * @apioption xAxis.crosshair.dashStyle
         */
        /**
         * A label on the axis next to the crosshair.
         *
         * In styled mode, the label is styled with the
         * `.highcharts-crosshair-label` class.
         *
         * @sample {highstock} stock/xaxis/crosshair-label/
         *         Crosshair labels
         * @sample {highstock} highcharts/css/crosshair-label/
         *         Style mode
         *
         * @declare   Highcharts.AxisCrosshairLabelOptions
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label
         */
        /**
         * Alignment of the label compared to the axis. Defaults to `"left"` for
         * right-side axes, `"right"` for left-side axes and `"center"` for
         * horizontal axes.
         *
         * @type      {Highcharts.AlignValue}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.align
         */
        /**
         * The background color for the label. Defaults to the related series
         * color, or `#666666` if that is not available.
         *
         * @type      {Highcharts.ColorType}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.backgroundColor
         */
        /**
         * The border color for the crosshair label
         *
         * @type      {Highcharts.ColorType}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.borderColor
         */
        /**
         * The border corner radius of the crosshair label.
         *
         * @type      {number}
         * @default   3
         * @since     2.1.10
         * @product   highstock
         * @apioption xAxis.crosshair.label.borderRadius
         */
        /**
         * The border width for the crosshair label.
         *
         * @type      {number}
         * @default   0
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.borderWidth
         */
        /**
         * Flag to enable crosshair's label.
         *
         * @sample {highstock} stock/xaxis/crosshairs-xy/
         *         Enabled label for yAxis' crosshair
         *
         * @type      {boolean}
         * @default   false
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.enabled
         */
        /**
         * A format string for the crosshair label. Defaults to `{value}` for
         * numeric axes and `{value:%b %d, %Y}` for datetime axes.
         *
         * @type      {string}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.format
         */
        /**
         * Formatter function for the label text.
         *
         * @type      {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.formatter
         */
        /**
         * Padding inside the crosshair label.
         *
         * @type      {number}
         * @default   8
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.padding
         */
        /**
         * The shape to use for the label box.
         *
         * @type      {string}
         * @default   callout
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.shape
         */
        /**
         * Text styles for the crosshair label.
         *
         * @type      {Highcharts.CSSObject}
         * @default   {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"}
         * @since     2.1
         * @product   highstock
         * @apioption xAxis.crosshair.label.style
         */
        /**
         * Whether the crosshair should snap to the point or follow the pointer
         * independent of points.
         *
         * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/
         *         True by default
         * @sample {highmaps} maps/demo/latlon-advanced/
         *         Snap is false
         *
         * @type      {boolean}
         * @default   true
         * @since     4.1
         * @apioption xAxis.crosshair.snap
         */
        /**
         * The pixel width of the crosshair. Defaults to 1 for numeric or
         * datetime axes, and for one category width for category axes.
         *
         * @sample {highcharts} highcharts/xaxis/crosshair-customized/
         *         Customized crosshairs
         * @sample {highstock} highcharts/xaxis/crosshair-customized/
         *         Customized crosshairs
         * @sample {highmaps} highcharts/xaxis/crosshair-customized/
         *         Customized crosshairs
         *
         * @type      {number}
         * @default   1
         * @since     4.1
         * @apioption xAxis.crosshair.width
         */
        /**
         * The Z index of the crosshair. Higher Z indices allow drawing the
         * crosshair on top of the series or behind the grid lines.
         *
         * @type      {number}
         * @default   2
         * @since     4.1
         * @apioption xAxis.crosshair.zIndex
         */
        /**
         * Whether to pan axis. If `chart.panning` is enabled, the option
         * allows to disable panning on an individual axis.
         */
        panningEnabled: true,
        /**
         * The Z index for the axis group.
         *
         * @see [axis.gridZIndex](#xAxis.gridZIndex)
         * @see [axis.labels.zIndex](#xAxis.labels.zIndex)
         */
        zIndex: 2,
        /**
         * Whether to zoom axis. If `chart.zoomType` is set, the option allows
         * to disable zooming on an individual axis.
         *
         * @sample {highcharts} highcharts/xaxis/zoomenabled/
         *         Zoom enabled is false
         */
        zoomEnabled: true,
        /**
         * For a datetime axis, the scale will automatically adjust to the
         * appropriate unit. This member gives the default string
         * representations used for each unit. For intermediate values,
         * different units may be used, for example the `day` unit can be used
         * on midnight and `hour` unit be used for intermediate values on the
         * same axis.
         *
         * For an overview of the string or object configuration, see
         * [dateFormat](/class-reference/Highcharts.Time#dateFormat).
         *
         * Defaults to:
         * ```js
         * {
         *     millisecond: '%[HMSL]',
         *     second: '%[HMS]',
         *     minute: '%[HM]',
         *     hour: '%[HM]',
         *     day: '%[eb]',
         *     week: '%[eb]',
         *     month: '%[bY]',
         *     year: '%Y'
         * }
         * ```
         *
         * @sample {highcharts} highcharts/xaxis/datetimelabelformats-object/
         *         Object day format on X axis
         * @sample {highcharts} highcharts/xaxis/datetimelabelformats/
         *         String day format on X axis
         * @sample {highstock} stock/xaxis/datetimelabelformats/
         *         More information in x axis labels
         *
         * @declare Highcharts.AxisDateTimeLabelFormatsOptions
         * @product highcharts highstock gantt
         */
        dateTimeLabelFormats: {
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            millisecond: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.millisecond.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.millisecond.main
                 */
                main: '%[HMSL]',
                range: false
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            second: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.second.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.second.main
                 */
                main: '%[HMS]',
                range: false
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            minute: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.minute.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.minute.main
                 */
                main: '%[HM]',
                range: false
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            hour: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.hour.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.hour.main
                 */
                main: '%[HM]',
                range: false
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            day: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.day.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.day.main
                 */
                main: '%[eb]'
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            week: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.week.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.week.main
                 */
                main: '%[eb]'
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            month: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.month.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.month.main
                 */
                main: '%[bY]'
            },
            /**
             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
             * @type {string|*}
             */
            year: {
                /**
                 * @type {Array<string|Highcharts.DateTimeFormatOptions>}
                 * @default undefined
                 * @apioption xAxis.dateTimeLabelFormats.year.list
                 */
                /**
                 * @type {string|Highcharts.DateTimeFormatOptions}
                 * @apioption xAxis.dateTimeLabelFormats.year.main
                 */
                main: '%Y'
            }
        },
        /**
         * Whether to force the axis to end on a tick. Use this option with
         * the `maxPadding` option to control the axis end.
         *
         * @productdesc {highstock}
         * In Highcharts Stock, `endOnTick` is always `false` when the navigator
         * is enabled, to prevent jumpy scrolling. With disabled navigator
         * enabling `endOnTick` may lead to extending the xAxis to show the last
         * tick, therefore range selector buttons may not have an active state
         * if the axis gets extended.
         *
         * @sample {highcharts} highcharts/yaxis/endontick/
         *         True by default
         * @sample {highcharts} highcharts/yaxis/endontick-false/
         *         False
         * @sample {highstock} stock/demo/basic-line/
         *         True by default
         * @sample {highstock} stock/xaxis/endontick/
         *         False
         *
         * @since 1.2.0
         */
        endOnTick: false,
        /**
         * Event handlers for the axis.
         *
         * @type      {*}
         * @apioption xAxis.events
         */
        /**
         * An event fired after the breaks have rendered.
         *
         * @see [breaks](#xAxis.breaks)
         *
         * @sample {highcharts} highcharts/axisbreak/break-event/
         *         AfterBreak Event
         *
         * @type      {Highcharts.AxisEventCallbackFunction}
         * @since     4.1.0
         * @product   highcharts gantt
         * @apioption xAxis.events.afterBreaks
         */
        /**
         * As opposed to the `setExtremes` event, this event fires after the
         * final min and max values are computed and corrected for `minRange`.
         *
         * Fires when the minimum and maximum is set for the axis, either by
         * calling the `.setExtremes()` method or by selecting an area in the
         * chart. One parameter, `event`, is passed to the function, containing
         * common event information.
         *
         * The new user set minimum and maximum values can be found by
         * `event.min` and `event.max`. These reflect the axis minimum and
         * maximum in axis values. The actual data extremes are found in
         * `event.dataMin` and `event.dataMax`.
         *
         * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
         * @since     2.3
         * @context   Highcharts.Axis
         * @apioption xAxis.events.afterSetExtremes
         */
        /**
         * An event fired when a break from this axis occurs on a point.
         *
         * @see [breaks](#xAxis.breaks)
         *
         * @sample {highcharts} highcharts/axisbreak/break-visualized/
         *         Visualization of a Break
         *
         * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
         * @since     4.1.0
         * @product   highcharts gantt
         * @context   Highcharts.Axis
         * @apioption xAxis.events.pointBreak
         */
        /**
         * An event fired when a point falls inside a break from this axis.
         *
         * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
         * @product   highcharts highstock gantt
         * @context   Highcharts.Axis
         * @apioption xAxis.events.pointInBreak
         */
        /**
         * An event fired when a point is outside a break after zoom.
         *
         * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
         * @product   highcharts highstock gantt
         * @context   Highcharts.Axis
         * @apioption xAxis.events.pointBreakOut
         */
        /**
         * Fires when the minimum and maximum is set for the axis, either by
         * calling the `.setExtremes()` method or by selecting an area in the
         * chart. One parameter, `event`, is passed to the function,
         * containing common event information.
         *
         * The new user set minimum and maximum values can be found by
         * `event.min` and `event.max`. These reflect the axis minimum and
         * maximum in data values. When an axis is zoomed all the way out from
         * the "Reset zoom" button, `event.min` and `event.max` are null, and
         * the new extremes are set based on `this.dataMin` and `this.dataMax`.
         *
         * @sample {highstock} stock/xaxis/events-setextremes/
         *         Log new extremes on x axis
         *
         * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
         * @since     1.2.0
         * @context   Highcharts.Axis
         * @apioption xAxis.events.setExtremes
         */
        /**
         * The lowest allowed value for automatically computed axis extremes.
         *
         * @see [ceiling](#yAxis.ceiling)
         *
         * @sample {highcharts} highcharts/yaxis/floor-ceiling/
         *         Floor and ceiling
         * @sample {highstock} stock/demo/lazy-loading/
         *         Prevent negative stock price on Y axis
         *
         * @type      {number}
         * @since     4.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.floor
         */
        /**
         * The dash or dot style of the grid lines. For possible values, see
         * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
         *
         * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/
         *         Long dashes
         * @sample {highstock} stock/xaxis/gridlinedashstyle/
         *         Long dashes
         *
         * @type      {Highcharts.DashStyleValue}
         * @since     1.2
         */
        gridLineDashStyle: 'Solid',
        /**
         * The Z index of the grid lines.
         *
         * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/
         *         A Z index of 4 renders the grid above the graph
         *
         * @product   highcharts highstock gantt
         *
         * @see [axis.zIndex](#xAxis.zIndex)
         * @see [axis.labels.zIndex](#xAxis.labels.zIndex)
         */
        gridZIndex: 1,
        /**
         * An id for the axis. This can be used after render time to get
         * a pointer to the axis object through `chart.get()`.
         *
         * @sample {highcharts} highcharts/xaxis/id/
         *         Get the object
         * @sample {highstock} stock/xaxis/id/
         *         Get the object
         *
         * @type      {string}
         * @since     1.2.0
         * @apioption xAxis.id
         */
        /**
         * The axis labels show the number or category for each tick.
         *
         * Since v8.0.0: Labels are animated in categorized x-axis with
         * updating data if `tickInterval` and `step` is set to 1.
         *
         * @productdesc {highmaps}
         * X and Y axis labels are by default disabled in Highmaps, but the
         * functionality is inherited from Highcharts and used on `colorAxis`,
         * and can be enabled on X and Y axes too.
         */
        labels: {
            /**
             * What part of the string the given position is anchored to.
             * If `left`, the left side of the string is at the axis position.
             * Can be one of `"left"`, `"center"` or `"right"`. Defaults to
             * an intelligent guess based on which side of the chart the axis
             * is on and the rotation of the label.
             *
             * @see [reserveSpace](#xAxis.labels.reserveSpace)
             *
             * @sample {highcharts} highcharts/xaxis/labels-align-left/
             *         Left
             * @sample {highcharts} highcharts/xaxis/labels-align-right/
             *         Right
             * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
             *         Left-aligned labels on a vertical category axis
             *
             * @type      {Highcharts.AlignValue}
             * @apioption xAxis.labels.align
             */
            /**
             * Whether to allow the axis labels to overlap. When false,
             * overlapping labels are hidden.
             *
             * @sample {highcharts} highcharts/xaxis/labels-allowoverlap-true/
             *         X axis labels overlap enabled
             *
             * @type      {boolean}
             * @default   false
             * @apioption xAxis.labels.allowOverlap
             */
            /**
             * For horizontal axes, the allowed degrees of label rotation
             * to prevent overlapping labels. If there is enough space,
             * labels are not rotated. As the chart gets narrower, it
             * will start rotating the labels -45 degrees, then remove
             * every second label and try again with rotations 0 and -45 etc.
             * Set it to `undefined` to disable rotation, which will
             * cause the labels to word-wrap if possible. Defaults to `[-45]``
             * on bottom and top axes, `undefined` on left and right axes.
             *
             * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/
             *         Default auto rotation of 0 or -45
             * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/
             *         Custom graded auto rotation
             *
             * @type      {Array<number>}
             * @default   undefined
             * @since     4.1.0
             * @product   highcharts highstock gantt
             * @apioption xAxis.labels.autoRotation
             */
            /**
             * When each category width is more than this many pixels, we don't
             * apply auto rotation. Instead, we lay out the axis label with word
             * wrap. A lower limit makes sense when the label contains multiple
             * short words that don't extend the available horizontal space for
             * each label.
             *
             * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/
             *         Lower limit
             *
             * @since     4.1.5
             * @product   highcharts gantt
             */
            autoRotationLimit: 80,
            /**
             * The label's pixel distance from the perimeter of the plot area.
             * On cartesian charts, this is overridden if the `labels.y` setting
             * is set.
             *
             * @sample {highcharts} highcharts/yaxis/labels-distance/
             *         Polar chart, labels centered under the arc
             *
             * @type      {number}
             * @product   highcharts gantt
             */
            distance: 15,
            /**
             * Enable or disable the axis labels.
             *
             * @sample {highcharts} highcharts/xaxis/labels-enabled/
             *         X axis labels disabled
             * @sample {highstock} stock/xaxis/labels-enabled/
             *         X axis labels disabled
             *
             */
            enabled: true,
            /**
             * A format string for the axis label. The context is available as
             * format string variables. For example, you can use `{text}` to
             * insert the default formatted text. The recommended way of adding
             * units for the label is using `text`, for example `{text} km`.
             *
             * To add custom numeric or datetime formatting, use `{value}` with
             * formatting, for example `{value:.1f}` or `{value:%Y-%m-%d}`.
             *
             * See
             * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
             * for more examples of formatting.
             *
             * The default value is not specified due to the dynamic
             * nature of the default implementation.
             *
             * @sample {highcharts|highstock} highcharts/yaxis/labels-format/
             *         Add units to Y axis label
             * @sample {highcharts} highcharts/xaxis/labels-format-linked/
             *         Linked category names
             * @sample {highcharts} highcharts/xaxis/labels-format-custom/
             *         Custom number format
             *
             * @type      {string}
             * @since     3.0
             * @apioption xAxis.labels.format
             */
            /**
             * Callback JavaScript function to format the label. The value
             * is given by `this.value`. Additional properties for `this` are
             * `axis`, `chart`, `isFirst`, `isLast` and `text` which holds the
             * value of the default formatter.
             *
             * Defaults to a built in function returning a formatted string
             * depending on whether the axis is `category`, `datetime`,
             * `numeric` or other.
             *
             * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/
             *         Linked category names
             * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/
             *         Modified numeric labels
             * @sample {highstock} stock/xaxis/labels-formatter/
             *         Added units on Y axis
             *
             * @type      {Highcharts.AxisLabelsFormatterCallbackFunction}
             * @apioption xAxis.labels.formatter
             */
            /**
             * The number of pixels to indent the labels per level in a treegrid
             * axis.
             *
             * @sample gantt/treegrid-axis/demo
             *         Indentation 10px by default.
             * @sample gantt/treegrid-axis/indentation-0px
             *         Indentation set to 0px.
             *
             * @product gantt
             */
            indentation: 10,
            /**
             * Horizontal axis only. When `staggerLines` is not set,
             * `maxStaggerLines` defines how many lines the axis is allowed to
             * add to automatically avoid overlapping X labels. Set to `1` to
             * disable overlap detection.
             *
             * @deprecated
             * @type      {number}
             * @default   5
             * @since     1.3.3
             * @apioption xAxis.labels.maxStaggerLines
             */
            /**
             * How to handle overflowing labels on horizontal axis. If set to
             * `"allow"`, it will not be aligned at all. By default it
             * `"justify"` labels inside the chart area. If there is room to
             * move it, it will be aligned to the edge, else it will be removed.
             *
             * @since      2.2.5
             * @validvalue ["allow", "justify"]
             */
            overflow: 'justify',
            /**
             * The pixel padding for axis labels, to ensure white space between
             * them. Defaults to 4 for horizontal axes, 1 for vertical.
             *
             * @type      {number}
             * @default   undefined
             * @product   highcharts gantt
             * @apioption xAxis.labels.padding
             */
            /**
             * Whether to reserve space for the labels. By default, space is
             * reserved for the labels in these cases:
             *
             * * On all horizontal axes.
             * * On vertical axes if `label.align` is `right` on a left-side
             * axis or `left` on a right-side axis.
             * * On vertical axes if `label.align` is `center`.
             *
             * This can be turned off when for example the labels are rendered
             * inside the plot area instead of outside.
             *
             * @see [labels.align](#xAxis.labels.align)
             *
             * @sample {highcharts} highcharts/xaxis/labels-reservespace/
             *         No reserved space, labels inside plot
             * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
             *         Left-aligned labels on a vertical category axis
             *
             * @type      {boolean}
             * @since     4.1.10
             * @product   highcharts highstock gantt
             * @apioption xAxis.labels.reserveSpace
             */
            reserveSpace: void 0,
            /**
             * Rotation of the labels in degrees. When `undefined`, the
             * `autoRotation` option takes precedence.
             *
             * @sample {highcharts} highcharts/xaxis/labels-rotation/
             *         X axis labels rotated 90°
             *
             * @type      {number}
             * @default   0
             * @apioption xAxis.labels.rotation
             */
            rotation: void 0,
            /**
             * Horizontal axes only. The number of lines to spread the labels
             * over to make room or tighter labels. 0 disables staggering.
             *
             * @sample {highcharts} highcharts/xaxis/labels-staggerlines/
             *         Show labels over two lines
             * @sample {highstock} stock/xaxis/labels-staggerlines/
             *         Show labels over two lines
             *
             * @since     2.1
             */
            staggerLines: 0,
            /**
             * To show only every _n_'th label on the axis, set the step to _n_.
             * Setting the step to 2 shows every other label.
             *
             * By default, when 0, the step is calculated automatically to avoid
             * overlap. To prevent this, set it to 1\. This usually only
             * happens on a category axis, and is often a sign that you have
             * chosen the wrong axis type.
             *
             * Read more at
             * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes)
             * => What axis should I use?
             *
             * @sample {highcharts} highcharts/xaxis/labels-step/
             *         Showing only every other axis label on a categorized
             *         x-axis
             * @sample {highcharts} highcharts/xaxis/labels-step-auto/
             *         Auto steps on a category axis
             *
             * @since     2.1
             */
            step: 0,
            /**
             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
             * to render the labels.
             */
            useHTML: false,
            /**
             * The x position offset of all labels relative to the tick
             * positions on the axis. Overrides the `labels.distance` option.
             *
             * @type      {number}
             * @apioption xAxis.labels.x
             */
            /**
             * The y position offset of all labels relative to the tick
             * positions on the axis. Overrides the `labels.distance` option.
             *
             * @sample {highcharts} highcharts/xaxis/labels-x/
             *         X axis labels placed on grid lines
             *
             * @type      {number}
             * @apioption xAxis.labels.y
             */
            /**
             * The Z index for the axis labels.
             *
             * @see [axis.zIndex](#xAxis.zIndex)
             * @see [axis.gridZIndex](#xAxis.gridZIndex)
             */
            zIndex: 7,
            /**
             * CSS styles for the label. Use `lineClamp` to control wrapping of
             * category labels. Use `textOverflow: 'none'` to prevent ellipsis
             * (dots).
             *
             * In styled mode, the labels are styled with the
             * `.highcharts-axis-labels` class.
             *
             * @sample {highcharts} highcharts/xaxis/labels-style/
             *         Red X axis labels
             *
             * @type      {Highcharts.CSSObject}
             */
            style: {
                /** @internal */
                color: "#333333" /* Palette.neutralColor80 */,
                /** @internal */
                cursor: 'default',
                /**
                 * @type {number|string}
                 */
                fontSize: '0.8em',
                /** @internal */
                textOverflow: 'ellipsis'
            }
        },
        /**
         * The left position as the horizontal axis. If it's a number, it is
         * interpreted as pixel position relative to the chart.
         *
         * Since Highcharts v5.0.13: If it's a percentage string, it is
         * interpreted as percentages of the plot width, offset from plot area
         * left.
         *
         * @sample {highcharts} highcharts/xaxis/axis-position-properties
         *         Different axis position properties
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption xAxis.left
         */
        /**
         * The top position as the vertical axis. If it's a number, it is
         * interpreted as pixel position relative to the chart.
         *
         * Since Highcharts 2: If it's a percentage string, it is interpreted
         * as percentages of the plot height, offset from plot area top.
         *
         * @sample {highcharts} highcharts/xaxis/axis-position-properties
         *         Different axis position properties
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption xAxis.top
         */
        /**
         * Index of another axis that this axis is linked to. When an axis is
         * linked to a master axis, it will take the same extremes as
         * the master, but as assigned by min or max or by setExtremes.
         * It can be used to show additional info, or to ease reading the
         * chart by duplicating the scales.
         *
         * @sample {highcharts} highcharts/xaxis/linkedto/
         *         Different string formats of the same date
         * @sample {highcharts} highcharts/yaxis/linkedto/
         *         Y values on both sides
         *
         * @type      {number}
         * @since     2.0.2
         * @product   highcharts highstock gantt
         * @apioption xAxis.linkedTo
         */
        /**
         * The maximum value of the axis. If `undefined`, the max value is
         * automatically calculated.
         *
         * If a datetime string is passed, it is parsed into epoch time
         * according to the time zone given in [time.timezone](#time.timezone).
         *
         * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value
         * might be rounded up.
         *
         * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended
         * beyond the set max in order to reach the given number of ticks. The
         * same may happen in a chart with multiple axes, determined by [chart.
         * alignTicks](#chart), where a `tickAmount` is applied internally.
         *
         * @sample {highcharts} highcharts/yaxis/max-200/
         *         Y axis max of 200
         * @sample {highcharts} highcharts/yaxis/max-logarithmic/
         *         Y axis max on logarithmic axis
         * @sample {highstock} stock/xaxis/min-max/
         *         Fixed min and max on X axis
         *
         * @type      {number|string|null}
         * @apioption xAxis.max
         */
        /**
         * Padding of the max value relative to the length of the axis. A
         * padding of 0.05 will make a 100px axis 5px longer. This is useful
         * when you don't want the highest data value to appear on the edge
         * of the plot area. When the axis' `max` option is set or a max extreme
         * is set using `axis.setExtremes()`, the maxPadding will be ignored.
         *
         * @productdesc {highstock}
         * For an [ordinal](#xAxis.ordinal) axis, `minPadding` and `maxPadding`
         * are ignored. Use [overscroll](#xAxis.overscroll) instead.
         *
         * @sample {highcharts} highcharts/yaxis/maxpadding/
         *         Max padding of 0.25 on y axis
         * @sample {highstock} stock/xaxis/minpadding-maxpadding/
         *         Greater min- and maxPadding
         * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
         *         Add some padding
         *
         * @default   {highcharts} 0.01
         * @default   {highstock|highmaps} 0
         * @since     1.2.0
         */
        maxPadding: 0.01,
        /**
         * Deprecated. Use `minRange` instead.
         *
         * @deprecated
         * @type      {number}
         * @product   highcharts highstock
         * @apioption xAxis.maxZoom
         */
        /**
         * The minimum value of the axis. If `undefined`, the min value is
         * automatically calculated.
         *
         * If a datetime string is passed, it is parsed into epoch time
         * according to the time zone given in [time.timezone](#time.timezone).
         *
         * If the [startOnTick](#yAxis.startOnTick) option is true (default),
         * the `min` value might be rounded down.
         *
         * The automatically calculated minimum value is also affected by
         * [floor](#yAxis.floor), [softMin](#yAxis.softMin),
         * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange)
         * as well as [series.threshold](#plotOptions.series.threshold)
         * and [series.softThreshold](#plotOptions.series.softThreshold).
         *
         * @sample {highcharts} highcharts/yaxis/min-startontick-false/
         *         -50 with startOnTick to false
         * @sample {highcharts} highcharts/yaxis/min-startontick-true/
         *         -50 with startOnTick true by default
         * @sample {highstock} stock/xaxis/min-max/
         *         Set min and max on X axis
         *
         * @type      {number|string|null}
         * @apioption xAxis.min
         */
        /**
         * The dash or dot style of the minor grid lines. For possible values,
         * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
         *
         * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/
         *         Long dashes on minor grid lines
         * @sample {highstock} stock/xaxis/minorgridlinedashstyle/
         *         Long dashes on minor grid lines
         *
         * @type      {Highcharts.DashStyleValue}
         * @since     1.2
         */
        minorGridLineDashStyle: 'Solid',
        /**
         * Specific tick interval in axis units for the minor ticks. On a linear
         * axis, if `"auto"`, the minor tick interval is calculated as a fifth
         * of the tickInterval. If `undefined`, minor ticks are not shown.
         *
         * On logarithmic axes, the unit is the power of the value. For example,
         * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1,
         * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks
         * between 1 and 10, 10 and 100 etc.
         *
         * If user settings dictate minor ticks to become too dense, they don't
         * make sense, and will be ignored to prevent performance problems.
         *
         * @sample {highcharts} highcharts/yaxis/minortickinterval-null/
         *         Undefined by default
         * @sample {highcharts} highcharts/yaxis/minortickinterval-5/ 5 units
         * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/
         *         "auto"
         * @sample {highcharts} highcharts/yaxis/minortickinterval-log/ 0.1
         * @sample {highstock} stock/demo/basic-line/ Null by default
         * @sample {highstock} stock/xaxis/minortickinterval-auto/ "auto"
         *
         * @type      {number|'auto'}
         * @apioption xAxis.minorTickInterval
         */
        /**
         * The pixel length of the minor tick marks.
         *
         * @sample {highcharts} highcharts/yaxis/minorticklength/
         *         10px on Y axis
         * @sample {highstock} stock/xaxis/minorticks/
         *         10px on Y axis
         */
        minorTickLength: 2,
        /**
         * The position of the minor tick marks relative to the axis line.
         *  Can be one of `inside` and `outside`.
         *
         * @sample {highcharts} highcharts/yaxis/minortickposition-outside/
         *         Outside by default
         * @sample {highcharts} highcharts/yaxis/minortickposition-inside/
         *         Inside
         * @sample {highstock} stock/xaxis/minorticks/
         *         Inside
         *
         * @validvalue ["inside", "outside"]
         */
        minorTickPosition: 'outside',
        /**
         * Enable or disable minor ticks. The interval between the minor ticks
         * can be controlled either by the
         * [minorTicksPerMajor](#xAxis.minorTicksPerMajor) setting, or as an
         * absolute [minorTickInterval](#xAxis.minorTickInterval) value.
         *
         * On a logarithmic axis, minor ticks are laid out based on a best
         * guess, attempting to enter an approximate number of minor ticks
         * between each major tick based on
         * [minorTicksPerMajor](#xAxis.minorTicksPerMajor).
         *
         * Prior to v6.0.0, ticks were enabled in auto layout by setting
         * `minorTickInterval` to `"auto"`.
         *
         * @productdesc {highcharts} On axes using
         * [categories](#xAxis.categories), minor ticks are not supported.
         *
         * @sample {highcharts} highcharts/yaxis/minorticks-true/ Enabled on
         *         linear Y axis
         *
         * @type      {boolean}
         * @default   false
         * @since     6.0.0
         * @apioption xAxis.minorTicks
         */
        /**
         * The number of minor ticks per major tick. Works for `linear`,
         * `logarithmic` and `datetime` axes.
         *
         * @sample {highcharts} highcharts/yaxis/minortickspermajor/
         *         2 minor ticks per major tick on Y axis
         *
         * @since  11.0.0
         *
         * @type {number}
         */
        minorTicksPerMajor: 5,
        /**
         * The pixel width of the minor tick mark.
         *
         * @sample {highcharts} highcharts/yaxis/minortickwidth/
         *         3px width
         * @sample {highstock} stock/xaxis/minorticks/
         *         1px width
         *
         * @type      {number}
         * @default   0
         * @apioption xAxis.minorTickWidth
         */
        /**
         * Padding of the min value relative to the length of the axis. A
         * padding of 0.05 will make a 100px axis 5px longer. This is useful
         * when you don't want the lowest data value to appear on the edge
         * of the plot area. When the axis' `min` option is set or a min extreme
         * is set using `axis.setExtremes()`, the minPadding will be ignored.
         *
         * @productdesc {highstock}
         * For an [ordinal](#xAxis.ordinal) axis, `minPadding` and `maxPadding`
         * are ignored. Use [overscroll](#xAxis.overscroll) instead.
         *
         * @sample {highcharts} highcharts/yaxis/minpadding/
         *         Min padding of 0.2
         * @sample {highstock} stock/xaxis/minpadding-maxpadding/
         *         Greater min- and maxPadding
         * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
         *         Add some padding
         *
         * @default    {highcharts} 0.01
         * @default    {highstock|highmaps} 0
         * @since      1.2.0
         * @product    highcharts highstock gantt
         */
        minPadding: 0.01,
        /**
         * The minimum range to display on this axis. The entire axis will not
         * be allowed to span over a smaller interval than this. For example,
         * for a datetime axis the main unit is milliseconds. If minRange is
         * set to 3600000, you can't zoom in more than to one hour.
         *
         * The default minRange for the x axis is five times the smallest
         * interval between any of the data points.
         *
         * On a logarithmic axis, the unit for the minimum range is the power.
         * So a minRange of 1 means that the axis can be zoomed to 10-100,
         * 100-1000, 1000-10000 etc.
         *
         * **Note**: The `minPadding`, `maxPadding`, `startOnTick` and
         * `endOnTick` settings also affect how the extremes of the axis
         * are computed.
         *
         * @sample {highcharts} highcharts/xaxis/minrange/
         *         Minimum range of 5
         * @sample {highstock} stock/xaxis/minrange/
         *         Max zoom of 6 months overrides user selections
         *
         * @type      {number}
         * @apioption xAxis.minRange
         */
        /**
         * The minimum tick interval allowed in axis values. For example on
         * zooming in on an axis with daily data, this can be used to prevent
         * the axis from showing hours. Defaults to the closest distance between
         * two points on the axis.
         *
         * @type      {number}
         * @since     2.3.0
         * @apioption xAxis.minTickInterval
         */
        /**
         * The distance in pixels from the plot area to the axis line.
         * A positive offset moves the axis with it's line, labels and ticks
         * away from the plot area. This is typically used when two or more
         * axes are displayed on the same side of the plot. With multiple
         * axes the offset is dynamically adjusted to avoid collision, this
         * can be overridden by setting offset explicitly.
         *
         * @sample {highcharts} highcharts/yaxis/offset/
         *         Y axis offset of 70
         * @sample {highcharts} highcharts/yaxis/offset-centered/
         *         Axes positioned in the center of the plot
         * @sample {highstock} stock/xaxis/offset/
         *         Y axis offset by 70 px
         *
         * @type {number}
         */
        offset: void 0,
        /**
         * Whether to display the axis on the opposite side of the normal. The
         * normal is on the left side for vertical axes and bottom for
         * horizontal, so the opposite sides will be right and top respectively.
         * This is typically used with dual or multiple axes.
         *
         * @sample {highcharts} highcharts/yaxis/opposite/
         *         Secondary Y axis opposite
         * @sample {highstock} stock/xaxis/opposite/
         *         Y axis on left side
         *
         * @default   {highcharts|highstock|highmaps} false
         * @default   {gantt} true
         * @type      Boolean
         * @apioption xAxis.opposite
         */
        /**
         * In an ordinal axis, the points are equally spaced in the chart
         * regardless of the actual time or x distance between them. This means
         * that missing data periods (e.g. nights or weekends for a stock chart)
         * will not take up space in the chart.
         * Having `ordinal: false` will show any gaps created by the `gapSize`
         * setting proportionate to their duration.
         *
         * In stock charts the X axis is ordinal by default, unless
         * the boost module is used and at least one of the series' data length
         * exceeds the [boostThreshold](#series.line.boostThreshold).
         *
         * For an ordinal axis, `minPadding` and `maxPadding` are ignored. Use
         * [overscroll](#xAxis.overscroll) instead.
         *
         * @sample {highstock} stock/xaxis/ordinal-true/
         *         True by default
         * @sample {highstock} stock/xaxis/ordinal-false/
         *         False
         *
         * @see [overscroll](#xAxis.overscroll)
         *
         * @type      {boolean}
         * @default   true
         * @since     1.1
         * @product   highstock
         * @apioption xAxis.ordinal
         */
        /**
         * Additional range on the right side of the xAxis. Works similar to
         * `xAxis.maxPadding`, but the value is set in terms of axis values,
         * percentage or pixels.
         *
         * If it's a number, it is interpreted as axis values, which in a
         * datetime axis equals milliseconds.
         *
         * If it's a percentage string, is interpreted as percentages of axis
         * length. An overscroll of 50% will make a 100px axis 50px longer.
         *
         * If it's a pixel string, it is interpreted as a fixed pixel value, but
         * limited to 90% of the axis length.
         *
         * @sample {highstock} stock/xaxis/overscroll/ One minute overscroll
         *         with live data
         * @sample {highstock} stock/xaxis/overscroll-percent/ Overscroll set in
         *         percentage
         * @sample {highstock} stock/xaxis/overscroll-pixel/ Overscroll set in
         *         pixels
         *
         * @type      {number | string}
         * @default   0
         * @since     6.0.0
         * @product   highstock
         * @apioption xAxis.overscroll
         */
        /**
         * Refers to the index in the [panes](#panes) array. Used for circular
         * gauges and polar charts. When the option is not set then first pane
         * will be used.
         *
         * @sample highcharts/demo/gauge-vu-meter
         *         Two gauges with different center
         *
         * @type      {number}
         * @product   highcharts
         * @apioption xAxis.pane
         */
        /**
         * The zoomed range to display when only defining one or none of `min`
         * or `max`. For example, to show the latest month, a range of one month
         * can be set.
         *
         * @sample {highstock} stock/xaxis/range/
         *         Setting a zoomed range when the rangeSelector is disabled
         *
         * @type      {number}
         * @product   highstock
         * @apioption xAxis.range
         */
        /**
         * Whether to reverse the axis so that the highest number is closest
         * to the origin. If the chart is inverted, the x axis is reversed by
         * default.
         *
         * @sample {highcharts} highcharts/yaxis/reversed/
         *         Reversed Y axis
         * @sample {highstock} stock/xaxis/reversed/
         *         Reversed Y axis
         *
         * @type      {boolean}
         * @default   undefined
         * @apioption xAxis.reversed
         */
        reversed: void 0,
        /**
         * This option determines how stacks should be ordered within a group.
         * For example reversed xAxis also reverses stacks, so first series
         * comes last in a group. To keep order like for non-reversed xAxis
         * enable this option.
         *
         * @sample {highcharts} highcharts/xaxis/reversedstacks/
         *         Reversed stacks comparison
         * @sample {highstock} highcharts/xaxis/reversedstacks/
         *         Reversed stacks comparison
         *
         * @since     6.1.1
         * @product   highcharts highstock
         */
        reversedStacks: false,
        /**
         * An optional scrollbar to display on the X axis in response to
         * limiting the minimum and maximum of the axis values.
         *
         * In styled mode, all the presentational options for the scrollbar are
         * replaced by the classes `.highcharts-scrollbar-thumb`,
         * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
         * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
         *
         * @sample {highstock} stock/yaxis/heatmap-scrollbars/
         *         Heatmap with both scrollbars
         *
         * @extends   scrollbar
         * @since     4.2.6
         * @product   highstock
         * @apioption xAxis.scrollbar
         */
        /**
         * Whether to show the axis line and title when the axis has no data.
         *
         * @sample {highcharts} highcharts/yaxis/showempty/
         *         When clicking the legend to hide series, one axis preserves
         *         line and title, the other doesn't
         * @sample {highstock} highcharts/yaxis/showempty/
         *         When clicking the legend to hide series, one axis preserves
         *         line and title, the other doesn't
         *
         * @since     1.1
         */
        showEmpty: true,
        /**
         * Whether to show the first tick label.
         *
         * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/
         *         Set to false on X axis
         * @sample {highstock} stock/xaxis/showfirstlabel/
         *         Labels below plot lines on Y axis
         */
        showFirstLabel: true,
        /**
         * Whether to show the last tick label. Defaults to `true` on cartesian
         * charts, and `false` on polar charts.
         *
         * @sample {highcharts} highcharts/xaxis/showlastlabel-true/
         *         Set to true on X axis
         * @sample {highstock} stock/xaxis/showfirstlabel/
         *         Labels below plot lines on Y axis
         *
         * @type    {boolean}
         * @default undefined
         * @product highcharts highstock gantt
         */
        showLastLabel: true,
        /**
         * A soft maximum for the axis. If the series data maximum is less than
         * this, the axis will stay at this maximum, but if the series data
         * maximum is higher, the axis will flex to show all data.
         *
         * @sample highcharts/yaxis/softmin-softmax/
         *         Soft min and max
         *
         * @type      {number}
         * @since     5.0.1
         * @product   highcharts highstock gantt
         * @apioption xAxis.softMax
         */
        /**
         * A soft minimum for the axis. If the series data minimum is greater
         * than this, the axis will stay at this minimum, but if the series
         * data minimum is lower, the axis will flex to show all data.
         *
         * @sample highcharts/yaxis/softmin-softmax/
         *         Soft min and max
         *
         * @type      {number}
         * @since     5.0.1
         * @product   highcharts highstock gantt
         * @apioption xAxis.softMin
         */
        /**
         * For datetime axes, this decides where to put the tick between weeks.
         *  0 = Sunday, 1 = Monday.
         *
         * @sample {highcharts} highcharts/xaxis/startofweek-monday/
         *         Monday by default
         * @sample {highcharts} highcharts/xaxis/startofweek-sunday/
         *         Sunday
         * @sample {highstock} stock/xaxis/startofweek-1
         *         Monday by default
         * @sample {highstock} stock/xaxis/startofweek-0
         *         Sunday
         *
         * @product highcharts highstock gantt
         */
        startOfWeek: 1,
        /**
         * Whether to force the axis to start on a tick. Use this option with
         * the `minPadding` option to control the axis start.
         *
         * @productdesc {highstock}
         * In Highcharts Stock, `startOnTick` is always `false` when
         * the navigator is enabled, to prevent jumpy scrolling.
         *
         * @sample {highcharts} highcharts/xaxis/startontick-false/
         *         False by default
         * @sample {highcharts} highcharts/xaxis/startontick-true/
         *         True
         *
         * @since 1.2.0
         */
        startOnTick: false,
        /**
         * The amount of ticks to draw on the axis. This opens up for aligning
         * the ticks of multiple charts or panes within a chart. This option
         * overrides the `tickPixelInterval` option.
         *
         * This option only has an effect on linear axes. Datetime, logarithmic
         * or category axes are not affected.
         *
         * @sample {highcharts} highcharts/yaxis/tickamount/
         *         8 ticks on Y axis
         * @sample {highstock} highcharts/yaxis/tickamount/
         *         8 ticks on Y axis
         *
         * @type      {number}
         * @since     4.1.0
         * @product   highcharts highstock gantt
         * @apioption xAxis.tickAmount
         */
        /**
         * The interval of the tick marks in axis units. When `undefined`, the
         * tick interval is computed to approximately follow the
         * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime
         * axes. On categorized axes, a `undefined` tickInterval will default to
         * 1, one category. Note that datetime axes are based on milliseconds,
         * so for example an interval of one day is expressed as
         * `24 * 3600 * 1000`.
         *
         * On logarithmic axes, the tickInterval is based on powers, so a
         * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A
         * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval
         * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20,
         * 40 etc.
         *
         *
         * If the tickInterval is too dense for labels to be drawn, Highcharts
         * may remove ticks.
         *
         * If the chart has multiple axes, the [alignTicks](#chart.alignTicks)
         * option may interfere with the `tickInterval` setting.
         *
         * @see [tickPixelInterval](#xAxis.tickPixelInterval)
         * @see [tickPositions](#xAxis.tickPositions)
         * @see [tickPositioner](#xAxis.tickPositioner)
         *
         * @sample {highcharts} highcharts/xaxis/tickinterval-5/
         *         Tick interval of 5 on a linear axis
         * @sample {highstock} stock/xaxis/tickinterval/
         *         Tick interval of 0.01 on Y axis
         *
         * @type      {number}
         * @apioption xAxis.tickInterval
         */
        /**
         * The pixel length of the main tick marks.
         *
         * @sample {highcharts} highcharts/xaxis/ticklength/
         *         20 px tick length on the X axis
         * @sample {highstock} stock/xaxis/ticks/
         *         Formatted ticks on X axis
         */
        tickLength: 10,
        /**
         * If tickInterval is `null` this option sets the approximate pixel
         * interval of the tick marks. Not applicable to categorized axis.
         *
         * The tick interval is also influenced by the [minTickInterval](
         * #xAxis.minTickInterval) option, that, by default prevents ticks from
         * being denser than the data points.
         *
         * @see [tickInterval](#xAxis.tickInterval)
         * @see [tickPositioner](#xAxis.tickPositioner)
         * @see [tickPositions](#xAxis.tickPositions)
         *
         * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/
         *         50 px on X axis
         * @sample {highstock} stock/xaxis/tickpixelinterval/
         *         200 px on X axis
         */
        tickPixelInterval: 100,
        /**
         * For categorized axes only. If `on` the tick mark is placed in the
         * center of the category, if `between` the tick mark is placed between
         * categories. The default is `between` if the `tickInterval` is 1, else
         * `on`. In order to render tick marks on a category axis it is necessary
         * to provide a [tickWidth](#xAxis.tickWidth).
         *
         * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/
         *         "between" by default
         * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/
         *         "on"
         *
         * @product    highcharts gantt
         * @validvalue ["on", "between"]
         */
        tickmarkPlacement: 'between',
        /**
         * The position of the major tick marks relative to the axis line.
         * Can be one of `inside` and `outside`.
         *
         * @sample {highcharts} highcharts/xaxis/tickposition-outside/
         *         "outside" by default
         * @sample {highcharts} highcharts/xaxis/tickposition-inside/
         *         "inside"
         * @sample {highstock} stock/xaxis/ticks/
         *         Formatted ticks on X axis
         *
         * @validvalue ["inside", "outside"]
         */
        tickPosition: 'outside',
        /**
         * A callback function returning array defining where the ticks are
         * laid out on the axis. This overrides the default behaviour of
         * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval](
         * #xAxis.tickInterval). The automatic tick positions are accessible
         * through `this.tickPositions` and can be modified by the callback.
         *
         * @see [tickPositions](#xAxis.tickPositions)
         *
         * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
         *         Demo of tickPositions and tickPositioner
         * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
         *         Demo of tickPositions and tickPositioner
         *
         * @type      {Highcharts.AxisTickPositionerCallbackFunction}
         * @apioption xAxis.tickPositioner
         */
        /**
         * An array defining where the ticks are laid out on the axis. This
         * overrides the default behaviour of [tickPixelInterval](
         * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval).
         *
         * @see [tickPositioner](#xAxis.tickPositioner)
         *
         * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
         *         Demo of tickPositions and tickPositioner
         * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
         *         Demo of tickPositions and tickPositioner
         *
         * @type      {Array<number>}
         * @apioption xAxis.tickPositions
         */
        /**
         * The pixel width of the major tick marks. Defaults to 0 on category
         * axes, otherwise 1.
         *
         * In styled mode, the stroke width is given in the `.highcharts-tick`
         * class, but in order for the element to be generated on category axes,
         * the option must be explicitly set to 1.
         *
         * @sample {highcharts} highcharts/xaxis/tickwidth/
         *         10 px width
         * @sample {highcharts} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/ticks/
         *         Formatted ticks on X axis
         * @sample {highstock} highcharts/css/axis-grid/
         *         Styled mode
         *
         * @type      {undefined|number}
         * @default   {highstock} 1
         * @default   {highmaps} 0
         * @apioption xAxis.tickWidth
         */
        /**
         * The axis title, showing next to the axis line.
         *
         * @productdesc {highmaps}
         * In Highmaps, the axis is hidden by default, but adding an axis title
         * is still possible. X axis and Y axis titles will appear at the bottom
         * and left by default.
         */
        title: {
            /**
             * Alignment of the title relative to the axis values. Possible
             * values are "low", "middle" or "high".
             *
             * @sample {highcharts} highcharts/xaxis/title-align-low/
             *         "low"
             * @sample {highcharts} highcharts/xaxis/title-align-center/
             *         "middle" by default
             * @sample {highcharts} highcharts/xaxis/title-align-high/
             *         "high"
             * @sample {highcharts} highcharts/yaxis/title-offset/
             *         Place the Y axis title on top of the axis
             * @sample {highstock} stock/xaxis/title-align/
             *         Aligned to "high" value
             *
             * @type {Highcharts.AxisTitleAlignValue}
             */
            align: 'middle',
            /**
             * Deprecated. Set the `text` to `undefined` to disable the title.
             *
             * @deprecated
             * @type      {boolean}
             * @product   highcharts
             * @apioption xAxis.title.enabled
             */
            /**
             * The pixel distance between the axis labels or line and the title.
             * Defaults to 0 for horizontal axes, 10 for vertical
             *
             * @sample {highcharts} highcharts/xaxis/title-margin/
             *         Y axis title margin of 60
             *
             * @type      {number}
             * @apioption xAxis.title.margin
             */
            /**
             * The distance of the axis title from the axis line. By default,
             * this distance is computed from the offset width of the labels,
             * the labels' distance from the axis and the title's margin.
             * However when the offset option is set, it overrides all this.
             *
             * @sample {highcharts} highcharts/yaxis/title-offset/
             *         Place the axis title on top of the axis
             * @sample {highstock} highcharts/yaxis/title-offset/
             *         Place the axis title on top of the Y axis
             *
             * @type      {number}
             * @since     2.2.0
             * @apioption xAxis.title.offset
             */
            /**
             * Whether to reserve space for the title when laying out the axis.
             *
             * @type      {boolean}
             * @default   true
             * @since     5.0.11
             * @product   highcharts highstock gantt
             * @apioption xAxis.title.reserveSpace
             */
            /**
             * The rotation of the text in degrees. 0 is horizontal, 270 is
             * vertical reading from bottom to top. Defaults to 0 for horizontal
             * axes, 270 for left-side axes and 90 for right-side axes.
             *
             * @sample    {highcharts} highcharts/yaxis/title-offset/
             *            Horizontal
             *
             * @type      {number}
             * @default   undefined
             * @apioption xAxis.title.rotation
             */
            /**
             * The actual text of the axis title. It can contain basic HTML tags
             * like `b`, `i` and `span` with style.
             *
             * @sample {highcharts} highcharts/xaxis/title-text/
             *         Custom HTML
             * @sample {highstock} stock/xaxis/title-text/
             *         Titles for both axes
             *
             * @type      {string|null}
             * @apioption xAxis.title.text
             */
            /**
             * Alignment of the text, can be `"left"`, `"right"` or `"center"`.
             * Default alignment depends on the
             * [title.align](xAxis.title.align):
             *
             * Horizontal axes:
             * - for `align` = `"low"`, `textAlign` is set to `left`
             * - for `align` = `"middle"`, `textAlign` is set to `center`
             * - for `align` = `"high"`, `textAlign` is set to `right`
             *
             * Vertical axes:
             * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is
             *   set to `right`
             * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is
             *   set to `left`
             * - for `align` = `"middle"`, `textAlign` is set to `center`
             * - for `align` = `"high"` and `opposite` = `true` `textAlign` is
             *   set to `left`
             * - for `align` = `"high"` and `opposite` = `false` `textAlign` is
             *   set to `right`
             *
             * @type      {Highcharts.AlignValue}
             * @apioption xAxis.title.textAlign
             */
            /**
             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
             * to render the axis title.
             *
             * @product   highcharts highstock gantt
             */
            useHTML: false,
            /**
             * Horizontal pixel offset of the title position.
             *
             * @since     4.1.6
             * @product   highcharts highstock gantt
             */
            x: 0,
            /**
             * Vertical pixel offset of the title position.
             *
             * @product   highcharts highstock gantt
             */
            y: 0,
            /**
             * CSS styles for the title. If the title text is longer than the
             * axis length, it will wrap to multiple lines by default. This can
             * be customized by setting the `lineClamp` property, by setting a
             * specific `width` or by setting `whiteSpace: 'nowrap'`.
             *
             * In styled mode, the stroke width is given in the
             * `.highcharts-axis-title` class.
             *
             * @sample {highcharts} highcharts/xaxis/title-style/
             *         Red
             * @sample {highcharts} highcharts/css/axis/
             *         Styled mode
             *
             * @type    {Highcharts.CSSObject}
             */
            style: {
                /** @internal */
                color: "#666666" /* Palette.neutralColor60 */,
                /**
                 * @type {number|string}
                 */
                fontSize: '0.8em'
            }
        },
        /**
         * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`
         * or `category`. In a datetime axis, the numbers are given in
         * milliseconds, and tick marks are placed on appropriate values like
         * full hours or days. In a category axis, the
         * [point names](#series.line.data.name) of the chart's series are used
         * for categories, if not a [categories](#xAxis.categories) array is
         * defined.
         *
         * @sample {highcharts} highcharts/xaxis/type-linear/
         *         Linear
         * @sample {highcharts} highcharts/yaxis/type-log/
         *         Logarithmic
         * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
         *         Logarithmic with minor grid lines
         * @sample {highcharts} highcharts/xaxis/type-log-both/
         *         Logarithmic on two axes
         * @sample {highcharts} highcharts/yaxis/type-log-negative/
         *         Logarithmic with extension to emulate negative values
         *
         * @type    {Highcharts.AxisTypeValue}
         * @default linear
         * @product highcharts gantt
         * @apioption xAxis.type
         */
        /**
         * If there are multiple axes on the same side of the chart, the pixel
         * margin between the axes. Defaults to 0 on vertical axes, 15 on
         * horizontal axes.
         *
         * @type      {number}
         * @since     7.0.3
         * @apioption xAxis.margin
         */
        /**
         * Applies only when the axis `type` is `category`. When `uniqueNames`
         * is true, points are placed on the X axis according to their names.
         * If the same point name is repeated in the same or another series,
         * the point is placed on the same X position as other points of the
         * same name. When `uniqueNames` is false, the points are laid out in
         * increasing X positions regardless of their names, and the X axis
         * category will take the name of the last point in each position.
         *
         * @sample {highcharts} highcharts/xaxis/uniquenames-true/
         *         True by default
         * @sample {highcharts} highcharts/xaxis/uniquenames-false/
         *         False
         *
         * @since     4.2.7
         * @product   highcharts gantt
         * @type      {boolean}
         * @default   true
         * @apioption xAxis.uniqueNames
         */
        /**
         * Datetime axis only. An array determining what time intervals the
         * ticks are allowed to fall on. Each array item is an array where the
         * first value is the time unit and the second value another array of
         * allowed multiples.
         *
         * Defaults to:
         * ```js
         * units: [[
         *     'millisecond', // unit name
         *     [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples
         * ], [
         *     'second',
         *     [1, 2, 5, 10, 15, 30]
         * ], [
         *     'minute',
         *     [1, 2, 5, 10, 15, 30]
         * ], [
         *     'hour',
         *     [1, 2, 3, 4, 6, 8, 12]
         * ], [
         *     'day',
         *     [1, 2]
         * ], [
         *     'week',
         *     [1, 2]
         * ], [
         *     'month',
         *     [1, 2, 3, 4, 6]
         * ], [
         *     'year',
         *     null
         * ]]
         * ```
         *
         * @sample {highcharts} highcharts/xaxis/units/
         *         Axis units demonstrated
         *
         * @type      {Array<Array<string,(Array<number>|null)>>}
         * @product   highcharts highstock gantt
         * @apioption xAxis.units
         */
        /**
         * Whether axis, including axis title, line, ticks and labels, should
         * be visible.
         *
         * @since     4.1.9
         * @product   highcharts highstock gantt
         */
        visible: true,
        /**
         * Color of the minor, secondary grid lines.
         *
         * In styled mode, the stroke width is given in the
         * `.highcharts-minor-grid-line` class.
         *
         * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/
         *         Bright grey lines from Y axis
         * @sample {highcharts|highstock} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/minorgridlinecolor/
         *         Bright grey lines from Y axis
         *
         * @type    {Highcharts.ColorType}
         * @default #f2f2f2
         */
        minorGridLineColor: "#f2f2f2" /* Palette.neutralColor5 */,
        /**
         * Width of the minor, secondary grid lines.
         *
         * In styled mode, the stroke width is given in the
         * `.highcharts-grid-line` class.
         *
         * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/
         *         2px lines from Y axis
         * @sample {highcharts|highstock} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/minorgridlinewidth/
         *         2px lines from Y axis
         */
        minorGridLineWidth: 1,
        /**
         * Color for the minor tick marks.
         *
         * @sample {highcharts} highcharts/yaxis/minortickcolor/
         *         Black tick marks on Y axis
         * @sample {highstock} stock/xaxis/minorticks/
         *         Black tick marks on Y axis
         *
         * @type    {Highcharts.ColorType}
         * @default #999999
         */
        minorTickColor: "#999999" /* Palette.neutralColor40 */,
        /**
         * The color of the line marking the axis itself.
         *
         * In styled mode, the line stroke is given in the
         * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
         *
         * @sample {highcharts} highcharts/yaxis/linecolor/
         *         A red line on Y axis
         * @sample {highcharts|highstock} highcharts/css/axis/
         *         Axes in styled mode
         * @sample {highstock} stock/xaxis/linecolor/
         *         A red line on X axis
         *
         * @type    {Highcharts.ColorType}
         */
        lineColor: "#333333" /* Palette.neutralColor80 */,
        /**
         * The width of the line marking the axis itself.
         *
         * In styled mode, the stroke width is given in the
         * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
         *
         * @sample {highcharts} highcharts/yaxis/linecolor/
         *         A 1px line on Y axis
         * @sample {highcharts|highstock} highcharts/css/axis/
         *         Axes in styled mode
         * @sample {highstock} stock/xaxis/linewidth/
         *         A 2px line on X axis
         *
         * @default {highcharts|highstock} 1
         * @default {highmaps} 0
         */
        lineWidth: 1,
        /**
         * Color of the grid lines extending the ticks across the plot area.
         *
         * In styled mode, the stroke is given in the `.highcharts-grid-line`
         * class.
         *
         * @productdesc {highmaps}
         * In Highmaps, the grid lines are hidden by default.
         *
         * @sample {highcharts} highcharts/yaxis/gridlinecolor/
         *         Green lines
         * @sample {highcharts|highstock} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/gridlinecolor/
         *         Green lines
         *
         * @type    {Highcharts.ColorType}
         * @default #e6e6e6
         */
        gridLineColor: "#e6e6e6" /* Palette.neutralColor10 */,
        /**
         * The width of the grid lines extending the ticks across the plot area.
         * Defaults to 1 on the Y axis and 0 on the X axis, except for 3d
         * charts.
         *
         * In styled mode, the stroke width is given in the
         * `.highcharts-grid-line` class.
         *
         * @sample {highcharts} highcharts/yaxis/gridlinewidth/
         *         2px lines
         * @sample {highcharts|highstock} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/gridlinewidth/
         *         2px lines
         *
         * @type      {number}
         * @apioption xAxis.gridLineWidth
         */
        gridLineWidth: void 0,
        /**
         * The height as the vertical axis. If it's a number, it is
         * interpreted as pixels.
         *
         * Since Highcharts 2: If it's a percentage string, it is interpreted
         * as percentages of the total plot height.
         *
         * @sample {highcharts} highcharts/xaxis/axis-position-properties
         *         Different axis position properties
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption xAxis.height
         */
        /**
         * The width as the horizontal axis. If it's a number, it is interpreted
         * as pixels.
         *
         * Since Highcharts v5.0.13: If it's a percentage string, it is
         * interpreted as percentages of the total plot width.
         *
         * @sample {highcharts} highcharts/xaxis/axis-position-properties
         *         Different axis position properties
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption xAxis.width
         */
        /**
         * Color for the main tick marks.
         *
         * In styled mode, the stroke is given in the `.highcharts-tick`
         * class.
         *
         * @sample {highcharts} highcharts/xaxis/tickcolor/
         *         Red ticks on X axis
         * @sample {highcharts|highstock} highcharts/css/axis-grid/
         *         Styled mode
         * @sample {highstock} stock/xaxis/ticks/
         *         Formatted ticks on X axis
         *
         * @type    {Highcharts.ColorType}
         */
        tickColor: "#333333" /* Palette.neutralColor80 */
        // `tickWidth: 1`
    };
    /**
     * The Z axis or depth axis for 3D plots.
     *
     * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
     * access to the axis.
     *
     * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/
     *         Z-Axis with Categories
     * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/
     *         Z-Axis with styling
     *
     * @type      {*|Array<*>}
     * @extends   xAxis
     * @since     5.0.0
     * @product   highcharts
     * @excluding breaks, crosshair, height, left, lineColor, lineWidth,
     *            nameToX, showEmpty, top, width
     * @apioption zAxis
     */
    /**
     * The Y axis or value axis. Normally this is the vertical axis,
     * though if the chart is inverted this is the horizontal axis.
     * In case of multiple axes, the yAxis node is an array of
     * configuration objects.
     *
     * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic
     * access to the axis.
     *
     * @type         {*|Array<*>}
     * @extends      xAxis
     * @excluding    currentDateIndicator,ordinal,overscroll
     * @optionparent yAxis
     */
    AxisDefaults.yAxis = {
        /**
         * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`,
         * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts,
         * `linear` for other chart types.
         *
         * In a datetime axis, the numbers are given in milliseconds, and tick
         * marks are placed on appropriate values, like full hours or days. In a
         * category or treegrid axis, the [point names](#series.line.data.name)
         * of the chart's series are used for categories, if a
         * [categories](#xAxis.categories) array is not defined.
         *
         * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
         *         Logarithmic with minor grid lines
         * @sample {highcharts} highcharts/yaxis/type-log-negative/
         *         Logarithmic with extension to emulate negative values
         * @sample {gantt} gantt/treegrid-axis/demo
         *         Treegrid axis
         *
         * @type      {Highcharts.AxisTypeValue}
         * @default   {highcharts} linear
         * @default   {gantt} treegrid
         * @product   highcharts gantt
         * @apioption yAxis.type
         */
        /**
         * The height of the Y axis. If it's a number, it is interpreted as
         * pixels.
         *
         * Since Highcharts 2: If it's a percentage string, it is interpreted as
         * percentages of the total plot height.
         *
         * @see [yAxis.top](#yAxis.top)
         *
         * @sample {highstock} stock/demo/candlestick-and-volume/
         *         Percentage height panes
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption yAxis.height
         */
        /**
         * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
         * to represent the maximum value of the Y axis.
         *
         * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
         *         Min and max colors
         *
         * @type      {Highcharts.ColorType}
         * @default   #003399
         * @since     4.0
         * @product   highcharts
         * @apioption yAxis.maxColor
         */
        /**
         * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
         * to represent the minimum value of the Y axis.
         *
         * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
         *         Min and max color
         *
         * @type      {Highcharts.ColorType}
         * @default   #e6ebf5
         * @since     4.0
         * @product   highcharts
         * @apioption yAxis.minColor
         */
        /**
         * Whether to reverse the axis so that the highest number is closest
         * to the origin.
         *
         * @sample {highcharts} highcharts/yaxis/reversed/
         *         Reversed Y axis
         * @sample {highstock} stock/xaxis/reversed/
         *         Reversed Y axis
         *
         * @type      {boolean}
         * @default   {highcharts} false
         * @default   {highstock} false
         * @default   {highmaps} true
         * @default   {gantt} true
         * @apioption yAxis.reversed
         */
        /**
         * If `true`, the first series in a stack will be drawn on top in a
         * positive, non-reversed Y axis. If `false`, the first series is in
         * the base of the stack.
         *
         * @sample {highcharts} highcharts/yaxis/reversedstacks-false/
         *         Non-reversed stacks
         * @sample {highstock} highcharts/yaxis/reversedstacks-false/
         *         Non-reversed stacks
         *
         * @type      {boolean}
         * @default   true
         * @since     3.0.10
         * @product   highcharts highstock
         * @apioption yAxis.reversedStacks
         */
        reversedStacks: true,
        /**
         * Solid gauge series only. Color stops for the solid gauge. Use this
         * in cases where a linear gradient between a `minColor` and `maxColor`
         * is not sufficient. The stops is an array of tuples, where the first
         * item is a float between 0 and 1 assigning the relative position in
         * the gradient, and the second item is the color.
         *
         * For solid gauges, the Y axis also inherits the concept of
         * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses)
         * from the Highmaps color axis.
         *
         * @sample {highcharts} highcharts/demo/gauge-solid/
         *         Gauge with stops
         *
         * @see [minColor](#yAxis.minColor)
         * @see [maxColor](#yAxis.maxColor)
         *
         * @type      {Array<Array<number,Highcharts.ColorType>>}
         * @since     4.0
         * @product   highcharts
         * @apioption yAxis.stops
         */
        /**
         * The pixel width of the major tick marks.
         *
         * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width
         * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis
         *
         * @type      {number}
         * @default   0
         * @product   highcharts highstock gantt
         * @apioption yAxis.tickWidth
         */
        /**
         * Whether to force the axis to end on a tick. Use this option with
         * the `maxPadding` option to control the axis end.
         *
         * This option is always disabled, when panning type is
         * either `y` or `xy`.
         *
         * @see [type](#chart.panning.type)
         *
         *
         * @sample {highcharts} highcharts/yaxis/endontick/
         *         True by default
         * @sample {highcharts} highcharts/yaxis/endontick-false/
         *         False
         * @sample {highstock} stock/demo/basic-line/
         *         True by default
         * @sample {highstock} stock/xaxis/endontick/
         *         False for Y axis
         *
         * @since 1.2.0
         */
        endOnTick: true,
        /**
         * Padding of the max value relative to the length of the axis. A
         * padding of 0.05 will make a 100px axis 5px longer. This is useful
         * when you don't want the highest data value to appear on the edge
         * of the plot area. When the axis' `max` option is set or a max extreme
         * is set using `axis.setExtremes()`, the maxPadding will be ignored.
         *
         * Also the `softThreshold` option takes precedence over `maxPadding`,
         * so if the data is tangent to the threshold, `maxPadding` may not
         * apply unless `softThreshold` is set to false.
         *
         * @sample {highcharts} highcharts/yaxis/maxpadding-02/
         *         Max padding of 0.2
         * @sample {highstock} stock/xaxis/minpadding-maxpadding/
         *         Greater min- and maxPadding
         *
         * @since   1.2.0
         * @product highcharts highstock gantt
         */
        maxPadding: 0.05,
        /**
         * Padding of the min value relative to the length of the axis. A
         * padding of 0.05 will make a 100px axis 5px longer. This is useful
         * when you don't want the lowest data value to appear on the edge
         * of the plot area. When the axis' `min` option is set or a max extreme
         * is set using `axis.setExtremes()`, the maxPadding will be ignored.
         *
         * Also the `softThreshold` option takes precedence over `minPadding`,
         * so if the data is tangent to the threshold, `minPadding` may not
         * apply unless `softThreshold` is set to false.
         *
         * @sample {highcharts} highcharts/yaxis/minpadding/
         *         Min padding of 0.2
         * @sample {highstock} stock/xaxis/minpadding-maxpadding/
         *         Greater min- and maxPadding
         *
         * @since   1.2.0
         * @product highcharts highstock gantt
         */
        minPadding: 0.05,
        /**
         * @productdesc {highstock}
         * In Highcharts Stock 1.x, the Y axis was placed
         * on the left side by default.
         *
         * @sample {highcharts} highcharts/yaxis/opposite/
         *         Secondary Y axis opposite
         * @sample {highstock} stock/xaxis/opposite/
         *         Y axis on left side
         *
         * @type      {boolean}
         * @default   {highstock} true
         * @default   {highcharts} false
         * @product   highstock highcharts gantt
         * @apioption yAxis.opposite
         */
        /**
         * @see [tickInterval](#xAxis.tickInterval)
         * @see [tickPositioner](#xAxis.tickPositioner)
         * @see [tickPositions](#xAxis.tickPositions)
         */
        tickPixelInterval: 72,
        /**
         * Whether to show the last tick label.
         *
         * @productdesc {highcharts|gantt}
         * Defaults to `true` on cartesian charts, and `false` on polar charts.
         *
         * @productdesc {highstock}
         * Defaults to `true` for categorized yAxis and `false` for other types
         * of yAxis.
         *
         * @default undefined
         */
        showLastLabel: true,
        /**
         * @extends xAxis.labels
         */
        labels: {
            /**
             * The label's pixel distance from the perimeter of the plot area.
             * On cartesian charts, this is overridden if the `labels.y` setting
             * is set.
             *
             * On polar charts, if it's a percentage string, it is interpreted
             * the same as [series.radius](#plotOptions.gauge.radius), so the
             * label can be aligned under the gauge's shape.
             *
             * @sample {highcharts} highcharts/yaxis/labels-distance/
             *         Polar chart, labels centered under the arc
             *
             * @type      {number|string}
             * @product   highcharts
             * @apioption yAxis.labels.distance
             */
            /**
             * The y position offset of all labels relative to the tick
             * positions on the axis. For polar and radial axis consider the use
             * of the [distance](#yAxis.labels.distance) option.
             *
             * @sample {highcharts} highcharts/xaxis/labels-x/
             *         Y axis labels placed on grid lines
             *
             * @type      {number}
             * @default   {highcharts} 3
             * @default   {highstock} -2
             * @default   {highmaps} 3
             * @apioption yAxis.labels.y
             */
            /**
             * What part of the string the given position is anchored to. Can
             * be one of `"left"`, `"center"` or `"right"`. The exact position
             * also depends on the `labels.x` setting.
             *
             * Angular gauges and solid gauges defaults to `"center"`.
             * Solid gauges with two labels have additional option `"auto"`
             * for automatic horizontal and vertical alignment.
             *
             * @sample {highcharts} highcharts/yaxis/labels-align-left/
             *         Left
             * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
             *         Solid gauge labels auto aligned
             *
             * @type       {Highcharts.AlignValue}
             * @default    {highstock} right
             * @apioption  yAxis.labels.align
             */
            /**
             * The x position offset of all labels relative to the tick
             * positions on the axis. Defaults to -15 for left axis, 15 for
             * right axis.
             *
             * @sample {highcharts} highcharts/xaxis/labels-x/
             *         Y axis labels placed on grid lines
             *
             * @type {number}
             */
            x: void 0
        },
        /**
         * @sample {highcharts} highcharts/yaxis/max-200/
         *         Y axis max of 200
         * @sample {highcharts} highcharts/yaxis/max-logarithmic/
         *         Y axis max on logarithmic axis
         * @sample {highstock} stock/yaxis/min-max/
         *         Fixed min and max on Y axis
         *
         * @apioption yAxis.max
         */
        /**
         * @sample {highcharts} highcharts/yaxis/min-startontick-false/
         *         -50 with startOnTick to false
         * @sample {highcharts} highcharts/yaxis/min-startontick-true/
         *         -50 with startOnTick true by default
         * @sample {highstock} stock/yaxis/min-max/
         *         Fixed min and max on Y axis
         *
         * @apioption yAxis.min
         */
        /**
         * An optional scrollbar to display on the Y axis in response to
         * limiting the minimum an maximum of the axis values.
         *
         * In styled mode, all the presentational options for the scrollbar
         * are replaced by the classes `.highcharts-scrollbar-thumb`,
         * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
         * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
         *
         * @sample {highstock} stock/yaxis/scrollbar/
         *         Scrollbar on the Y axis
         *
         * @extends   scrollbar
         * @since     4.2.6
         * @product   highstock
         * @excluding height
         * @apioption yAxis.scrollbar
         */
        /**
         * Enable the scrollbar on the Y axis.
         *
         * @sample {highstock} stock/yaxis/scrollbar/
         *         Enabled on Y axis
         *
         * @type      {boolean}
         * @default   false
         * @since     4.2.6
         * @product   highstock
         * @apioption yAxis.scrollbar.enabled
         */
        /**
         * Pixel margin between the scrollbar and the axis elements.
         *
         * @type      {number}
         * @default   10
         * @since     4.2.6
         * @product   highstock
         * @apioption yAxis.scrollbar.margin
         */
        /* eslint-disable highcharts/doclet-apioption-last */
        /**
         * Defines the position of the scrollbar. By default, it is positioned
         * on the opposite of the main axis (right side of the chart).
         * However, in the case of RTL languages could be set to `false`
         * which positions the scrollbar on the left.
         *
         * Works only for vertical axes.
         * This means yAxis in a non-inverted chart and xAxis in the inverted.
         *
         * @sample stock/yaxis/scrollbar-opposite/
         *         A scrollbar not on the opposite side
         *
         * @type      {boolean}
         * @default   true
         * @since 9.3.0
         *
         * @apioption yAxis.scrollbar.opposite
         * @apioption xAxis.scrollbar.opposite
         *
         */
        /* eslint-enable highcharts/doclet-apioption-last */
        /**
         * Whether to show the scrollbar when it is fully zoomed out at max
         * range. Setting it to `false` on the Y axis makes the scrollbar stay
         * hidden until the user zooms in, like common in browsers.
         *
         * @type      {boolean}
         * @default   true
         * @since     4.2.6
         * @product   highstock
         * @apioption yAxis.scrollbar.showFull
         */
        /**
         * The width of a vertical scrollbar or height of a horizontal
         * scrollbar. Defaults to 20 on touch devices.
         *
         * @type      {number}
         * @default   14
         * @since     4.2.6
         * @product   highstock
         * @apioption yAxis.scrollbar.size
         */
        /**
         * Z index of the scrollbar elements.
         *
         * @type      {number}
         * @default   3
         * @since     4.2.6
         * @product   highstock
         * @apioption yAxis.scrollbar.zIndex
         */
        /**
         * A soft maximum for the axis. If the series data maximum is less
         * than this, the axis will stay at this maximum, but if the series
         * data maximum is higher, the axis will flex to show all data.
         *
         * **Note**: The [series.softThreshold](
         * #plotOptions.series.softThreshold) option takes precedence over this
         * option.
         *
         * @sample highcharts/yaxis/softmin-softmax/
         *         Soft min and max
         *
         * @type      {number}
         * @since     5.0.1
         * @product   highcharts highstock gantt
         * @apioption yAxis.softMax
         */
        /**
         * A soft minimum for the axis. If the series data minimum is greater
         * than this, the axis will stay at this minimum, but if the series
         * data minimum is lower, the axis will flex to show all data.
         *
         * **Note**: The [series.softThreshold](
         * #plotOptions.series.softThreshold) option takes precedence over this
         * option.
         *
         * @sample highcharts/yaxis/softmin-softmax/
         *         Soft min and max
         *
         * @type      {number}
         * @since     5.0.1
         * @product   highcharts highstock gantt
         * @apioption yAxis.softMin
         */
        /**
         * Defines the horizontal alignment of the stack total label. Can be one
         * of `"left"`, `"center"` or `"right"`. The default value is calculated
         * at runtime and depends on orientation and whether the stack is
         * positive or negative.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/
         *         Aligned to the left
         * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/
         *         Aligned in center
         * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/
         *         Aligned to the right
         *
         * @type      {Highcharts.AlignValue}
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.align
         */
        /**
         * A format string for the data label. Available variables are the same
         * as for `formatter`.
         *
         * @type      {string}
         * @default   {total}
         * @since     3.0.2
         * @product   highcharts highstock
         * @apioption yAxis.stackLabels.format
         */
        /**
         * Rotation of the labels in degrees.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/
         *         Labels rotated 45°
         *
         * @type      {number}
         * @default   0
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.rotation
         */
        /**
         * The text alignment for the label. While `align` determines where the
         * texts anchor point is placed with regards to the stack, `textAlign`
         * determines how the text is aligned against its anchor point. Possible
         * values are `"left"`, `"center"` and `"right"`. The default value is
         * calculated at runtime and depends on orientation and whether the
         * stack is positive or negative.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/
         *         Label in center position but text-aligned left
         *
         * @type      {Highcharts.AlignValue}
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.textAlign
         */
        /**
         * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the labels.
         *
         * @type      {boolean}
         * @default   false
         * @since     3.0
         * @product   highcharts highstock
         * @apioption yAxis.stackLabels.useHTML
         */
        /**
         * Defines the vertical alignment of the stack total label. Can be one
         * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated
         * at runtime and depends on orientation and whether the stack is
         * positive or negative.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/
         *         Vertically aligned top
         * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/
         *         Vertically aligned middle
         * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/
         *         Vertically aligned bottom
         *
         * @type      {Highcharts.VerticalAlignValue}
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.verticalAlign
         */
        /**
         * The x position offset of the label relative to the left of the
         * stacked bar. The default value is calculated at runtime and depends
         * on orientation and whether the stack is positive or negative.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-x/
         *         Stack total labels with x offset
         *
         * @type      {number}
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.x
         */
        /**
         * The y position offset of the label relative to the tick position
         * on the axis. The default value is calculated at runtime and depends
         * on orientation and whether the stack is positive or negative.
         *
         * @sample {highcharts} highcharts/yaxis/stacklabels-y/
         *         Stack total labels with y offset
         *
         * @type      {number}
         * @since     2.1.5
         * @product   highcharts
         * @apioption yAxis.stackLabels.y
         */
        /**
         * Whether to force the axis to start on a tick. Use this option with
         * the `maxPadding` option to control the axis start.
         *
         * This option is always disabled, when panning type is
         * either `y` or `xy`.
         *
         * @see [type](#chart.panning.type)
         *
         * @sample {highcharts} highcharts/xaxis/startontick-false/
         *         False by default
         * @sample {highcharts} highcharts/xaxis/startontick-true/
         *         True
         * @sample {highstock} stock/xaxis/endontick/
         *         False for Y axis
         *
         * @since   1.2.0
         * @product highcharts highstock gantt
         */
        startOnTick: true,
        title: {
            /**
             * The pixel distance between the axis labels and the title.
             * Positive values are outside the axis line, negative are inside.
             *
             * @sample {highcharts} highcharts/xaxis/title-margin/
             *         Y axis title margin of 60
             *
             * @type      {number}
             * @default   40
             * @apioption yAxis.title.margin
             */
            /**
             * The actual text of the axis title. Horizontal texts can contain
             * HTML, but rotated texts are painted using vector techniques and
             * must be clean text. The Y axis title is disabled by setting the
             * `text` option to `undefined`.
             *
             * @sample {highcharts} highcharts/xaxis/title-text/
             *         Custom HTML
             *
             * @type    {string|null}
             * @default {highcharts} Values
             * @default {highstock} undefined
             * @product highcharts highstock gantt
             */
            text: 'Values'
        },
        /**
         * The top position of the Y axis. If it's a number, it is interpreted
         * as pixel position relative to the chart.
         *
         * Since Highcharts 2: If it's a percentage string, it is interpreted as
         * percentages of the plot height, offset from plot area top.
         *
         * @see [yAxis.height](#yAxis.height)
         *
         * @sample {highstock} stock/demo/candlestick-and-volume/
         *         Percentage height panes
         *
         * @type      {number|string}
         * @product   highcharts highstock
         * @apioption yAxis.top
         */
        /**
         * The stack labels show the total value for each bar in a stacked
         * column or bar chart. The label will be placed on top of positive
         * columns and below negative columns. In case of an inverted column
         * chart or a bar chart the label is placed to the right of positive
         * bars and to the left of negative bars.
         *
         * @product highcharts
         */
        stackLabels: {
            /**
             * Enable or disable the initial animation when a series is
             * displayed for the `stackLabels`. The animation can also be set as
             * a configuration object. Please note that this option only
             * applies to the initial animation.
             * For other animations, see [chart.animation](#chart.animation)
             * and the animation parameter under the API methods.
             * The following properties are supported:
             *
             * - `defer`: The animation delay time in milliseconds.
             *
             * @sample {highcharts} highcharts/plotoptions/animation-defer/
             *          Animation defer settings
             * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
             * @since 8.2.0
             * @apioption yAxis.stackLabels.animation
             */
            animation: {},
            /**
             * The animation delay time in milliseconds.
             * Set to `0` renders stackLabel immediately.
             * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer).
             *
             * @type      {number}
             * @since 8.2.0
             * @apioption yAxis.stackLabels.animation.defer
             */
            /**
             * Allow the stack labels to overlap.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/
             *         Default false
             *
             * @since   5.0.13
             * @product highcharts
             */
            allowOverlap: false,
            /**
             * The background color or gradient for the stack label.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
             *          Stack labels box options
             * @type      {Highcharts.ColorType}
             * @since 8.1.0
             * @apioption yAxis.stackLabels.backgroundColor
             */
            /**
             * The border color for the stack label. Defaults to `undefined`.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
             *          Stack labels box options
             * @type      {Highcharts.ColorType}
             * @since 8.1.0
             * @apioption yAxis.stackLabels.borderColor
             */
            /**
             * The border radius in pixels for the stack label.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
             *          Stack labels box options
             * @type      {number}
             * @default   0
             * @since 8.1.0
             * @apioption yAxis.stackLabels.borderRadius
             */
            /**
             * The border width in pixels for the stack label.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
             *          Stack labels box options
             * @type      {number}
             * @default   0
             * @since 8.1.0
             * @apioption yAxis.stackLabels.borderWidth
             */
            /**
             * Enable or disable the stack total labels.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/
             *         Enabled stack total labels
             * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/
             *         Enabled stack labels in waterfall chart
             *
             * @since   2.1.5
             * @product highcharts
             */
            enabled: false,
            /**
             * Whether to hide stack labels that are outside the plot area.
             * By default, the stack label is moved
             * inside the plot area according to the
             * [overflow](/highcharts/#yAxis/stackLabels/overflow)
             * option.
             *
             * @type  {boolean}
             * @since 7.1.3
             */
            crop: true,
            /**
             * How to handle stack total labels that flow outside the plot area.
             * The default is set to `"justify"`,
             * which aligns them inside the plot area.
             * For columns and bars, this means it will be moved inside the bar.
             * To display stack labels outside the plot area,
             * set `crop` to `false` and `overflow` to `"allow"`.
             *
             * @sample highcharts/yaxis/stacklabels-overflow/
             *         Stack labels flows outside the plot area.
             *
             * @type  {Highcharts.DataLabelsOverflowValue}
             * @since 7.1.3
             */
            overflow: 'justify',
            /* eslint-disable valid-jsdoc */
            /**
             * Callback JavaScript function to format the label. The value is
             * given by `this.total`.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/
             *         Added units to stack total value
             *
             * @type    {Highcharts.FormatterCallbackFunction<Highcharts.StackItemObject>}
             * @since   2.1.5
             * @product highcharts
             */
            formatter: function () {
                var numberFormatter = this.axis.chart.numberFormatter;
                /* eslint-enable valid-jsdoc */
                return numberFormatter(this.total || 0, -1);
            },
            /**
             * CSS styles for the label.
             *
             * In styled mode, the styles are set in the
             * `.highcharts-stack-label` class.
             *
             * @sample {highcharts} highcharts/yaxis/stacklabels-style/
             *         Red stack total labels
             *
             * @type    {Highcharts.CSSObject}
             * @since   2.1.5
             * @product highcharts
             */
            style: {
                /** @internal */
                color: "#000000" /* Palette.neutralColor100 */,
                /**
                 * @type {number|string}
                 */
                fontSize: '0.7em',
                /** @internal */
                fontWeight: 'bold',
                /** @internal */
                textOutline: '1px contrast'
            }
        },
        gridLineWidth: 1,
        lineWidth: 0
    };
})(AxisDefaults || (AxisDefaults = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_AxisDefaults = (AxisDefaults);

;// ./code/es5/es-modules/Core/Foundation.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Foundation_addEvent = Core_Utilities.addEvent, Foundation_isFunction = Core_Utilities.isFunction, Foundation_objectEach = Core_Utilities.objectEach, Foundation_removeEvent = Core_Utilities.removeEvent;
/* *
 *
 *  Class Namespace
 *
 * */
var Foundation;
(function (Foundation) {
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Register event options. If an event handler is set on the options, it
     * should be subject to Chart.update, Axis.update and Series.update. This is
     * contrary to general handlers that are set directly using addEvent either
     * on the class or on the instance. #6538, #6943, #10861.
     * @private
     */
    function registerEventOptions(component, options) {
        // A lookup over those events that are added by _options_ (not
        // programmatically). These are updated through .update()
        component.eventOptions = component.eventOptions || {};
        // Register event listeners
        Foundation_objectEach(options.events, function (event, eventType) {
            // If event does not exist, or is changed by the .update()
            // function
            if (component.eventOptions[eventType] !== event) {
                // Remove existing if set by option
                if (component.eventOptions[eventType]) {
                    Foundation_removeEvent(component, eventType, component.eventOptions[eventType]);
                    delete component.eventOptions[eventType];
                }
                if (Foundation_isFunction(event)) {
                    component.eventOptions[eventType] = event;
                    Foundation_addEvent(component, eventType, event, {
                        order: 0 // #14080 fire those events as firsts
                    });
                }
            }
        });
    }
    Foundation.registerEventOptions = registerEventOptions;
})(Foundation || (Foundation = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Core_Foundation = (Foundation);

;// ./code/es5/es-modules/Core/Axis/Tick.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var Tick_deg2rad = Core_Globals.deg2rad;

var Tick_clamp = Core_Utilities.clamp, Tick_correctFloat = Core_Utilities.correctFloat, Tick_defined = Core_Utilities.defined, Tick_destroyObjectProperties = Core_Utilities.destroyObjectProperties, Tick_extend = Core_Utilities.extend, Tick_fireEvent = Core_Utilities.fireEvent, Tick_getAlignFactor = Core_Utilities.getAlignFactor, Tick_isNumber = Core_Utilities.isNumber, Tick_merge = Core_Utilities.merge, Tick_objectEach = Core_Utilities.objectEach, Tick_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * The Tick class.
 *
 * @class
 * @name Highcharts.Tick
 *
 * @param {Highcharts.Axis} axis
 * The axis of the tick.
 *
 * @param {number} pos
 * The position of the tick on the axis in terms of axis values.
 *
 * @param {string} [type]
 * The type of tick, either 'minor' or an empty string
 *
 * @param {boolean} [noLabel=false]
 * Whether to disable the label or not. Defaults to false.
 *
 * @param {Object} [parameters]
 * Optional parameters for the tick.
 */
var Tick = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Tick(axis, pos, type, noLabel, parameters) {
        this.isNew = true;
        this.isNewLabel = true;
        /**
         * The related axis of the tick.
         * @name Highcharts.Tick#axis
         * @type {Highcharts.Axis}
         */
        this.axis = axis;
        /**
         * The logical position of the tick on the axis in terms of axis values.
         * @name Highcharts.Tick#pos
         * @type {number}
         */
        this.pos = pos;
        /**
         * The tick type, which can be `"minor"`, or an empty string.
         * @name Highcharts.Tick#type
         * @type {string}
         */
        this.type = type || '';
        this.parameters = parameters || {};
        /**
         * The mark offset of the tick on the axis. Usually `undefined`, numeric
         * for grid axes.
         * @name Highcharts.Tick#tickmarkOffset
         * @type {number|undefined}
         */
        this.tickmarkOffset = this.parameters.tickmarkOffset;
        this.options = this.parameters.options;
        Tick_fireEvent(this, 'init');
        if (!type && !noLabel) {
            this.addLabel();
        }
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Write the tick label.
     *
     * @private
     * @function Highcharts.Tick#addLabel
     */
    Tick.prototype.addLabel = function () {
        var tick = this,
            axis = tick.axis,
            options = axis.options,
            chart = axis.chart,
            categories = axis.categories,
            log = axis.logarithmic,
            names = axis.names,
            pos = tick.pos,
            labelOptions = Tick_pick(tick.options && tick.options.labels,
            options.labels),
            tickPositions = axis.tickPositions,
            isFirst = pos === tickPositions[0],
            isLast = pos === tickPositions[tickPositions.length - 1],
            animateLabels = (!labelOptions.step || labelOptions.step === 1) &&
                axis.tickInterval === 1,
            tickPositionInfo = tickPositions.info;
        var label = tick.label,
            dateTimeLabelFormat,
            dateTimeLabelFormats,
            i;
        // The context value
        var value = this.parameters.category || (categories ?
                Tick_pick(categories[pos],
            names[pos],
            pos) :
                pos);
        if (log && Tick_isNumber(value)) {
            value = Tick_correctFloat(log.lin2log(value));
        }
        // Set the datetime label format. If a higher rank is set for this
        // position, use that. If not, use the general format.
        if (axis.dateTime) {
            if (tickPositionInfo) {
                dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid &&
                    tickPositionInfo.higherRanks[pos]) ||
                    tickPositionInfo.unitName]);
                dateTimeLabelFormat = dateTimeLabelFormats.main;
            }
            else if (Tick_isNumber(value)) { // #1441
                dateTimeLabelFormat = axis.dateTime.getXDateFormat(value, options.dateTimeLabelFormats ||
                    {});
            }
        }
        // Set properties for access in render method
        /**
         * True if the tick is the first one on the axis.
         * @name Highcharts.Tick#isFirst
         * @readonly
         * @type {boolean|undefined}
         */
        tick.isFirst = isFirst;
        /**
         * True if the tick is the last one on the axis.
         * @name Highcharts.Tick#isLast
         * @readonly
         * @type {boolean|undefined}
         */
        tick.isLast = isLast;
        // Get the string
        var ctx = {
                axis: axis,
                chart: chart,
                dateTimeLabelFormat: dateTimeLabelFormat,
                isFirst: isFirst,
                isLast: isLast,
                pos: pos,
                tick: tick,
                tickPositionInfo: tickPositionInfo,
                value: value
            };
        // Fire an event that allows modifying the context for use in
        // `labels.format` and `labels.formatter`.
        Tick_fireEvent(this, 'labelFormat', ctx);
        // Label formatting. When `labels.format` is given, we first run the
        // defaultFormatter and append the result to the context as `text`.
        // Handy for adding prefix or suffix while keeping default number
        // formatting.
        var labelFormatter = function (ctx) {
                if (labelOptions.formatter) {
                    return labelOptions.formatter.call(ctx,
            ctx);
            }
            if (labelOptions.format) {
                ctx.text = axis.defaultLabelFormatter.call(ctx);
                return Core_Templating.format(labelOptions.format, ctx, chart);
            }
            return axis.defaultLabelFormatter.call(ctx);
        };
        var str = labelFormatter.call(ctx,
            ctx);
        // Set up conditional formatting based on the format list if existing.
        var list = dateTimeLabelFormats && dateTimeLabelFormats.list;
        if (list) {
            tick.shortenLabel = function () {
                for (i = 0; i < list.length; i++) {
                    Tick_extend(ctx, { dateTimeLabelFormat: list[i] });
                    label.attr({
                        text: labelFormatter.call(ctx, ctx)
                    });
                    if (label.getBBox().width <
                        axis.getSlotWidth(tick) - 2 *
                            (labelOptions.padding || 0)) {
                        return;
                    }
                }
                label.attr({
                    text: ''
                });
            };
        }
        else {
            // #15692
            tick.shortenLabel = void 0;
        }
        // Call only after first render
        if (animateLabels && axis._addedPlotLB) {
            tick.moveLabel(str, labelOptions);
        }
        // First call
        if (!Tick_defined(label) && !tick.movedLabel) {
            /**
             * The rendered text label of the tick.
             * @name Highcharts.Tick#label
             * @type {Highcharts.SVGElement|undefined}
             */
            tick.label = label = tick.createLabel(str, labelOptions);
            // Base value to detect change for new calls to getBBox
            tick.rotation = 0;
            // Update
        }
        else if (label && label.textStr !== str && !animateLabels) {
            // When resetting text, also reset the width if dynamically set
            // (#8809)
            if (label.textWidth &&
                !labelOptions.style.width &&
                !label.styles.width) {
                label.css({ width: null });
            }
            label.attr({ text: str });
            label.textPxLength = label.getBBox().width;
        }
    };
    /**
     * Render and return the label of the tick.
     *
     * @private
     * @function Highcharts.Tick#createLabel
     */
    Tick.prototype.createLabel = function (str, labelOptions, xy) {
        var axis = this.axis,
            _a = axis.chart,
            renderer = _a.renderer,
            styledMode = _a.styledMode,
            label = Tick_defined(str) && labelOptions.enabled ?
                renderer
                    .text(str,
            xy === null || xy === void 0 ? void 0 : xy.x,
            xy === null || xy === void 0 ? void 0 : xy.y,
            labelOptions.useHTML)
                    .add(axis.labelGroup) :
                void 0;
        // Un-rotated length
        if (label) {
            var whiteSpace = labelOptions.style.whiteSpace || 'normal';
            // Without position absolute, IE export sometimes is wrong
            if (!styledMode) {
                label.css(Tick_merge(labelOptions.style, { whiteSpace: 'nowrap' }));
            }
            label.textPxLength = label.getBBox().width;
            if (!styledMode) {
                label.css({ whiteSpace: whiteSpace });
            }
        }
        return label;
    };
    /**
     * Destructor for the tick prototype
     *
     * @private
     * @function Highcharts.Tick#destroy
     */
    Tick.prototype.destroy = function () {
        Tick_destroyObjectProperties(this, this.axis);
    };
    /**
     * Gets the x and y positions for ticks in terms of pixels.
     *
     * @private
     * @function Highcharts.Tick#getPosition
     *
     * @param {boolean} horiz
     * Whether the tick is on an horizontal axis or not.
     *
     * @param {number} tickPos
     * Position of the tick.
     *
     * @param {number} tickmarkOffset
     * Tickmark offset for all ticks.
     *
     * @param {boolean} [old]
     * Whether the axis has changed or not.
     *
     * @return {Highcharts.PositionObject}
     * The tick position.
     *
     * @emits Highcharts.Tick#event:afterGetPosition
     */
    Tick.prototype.getPosition = function (horiz, tickPos, tickmarkOffset, old) {
        var axis = this.axis,
            chart = axis.chart,
            cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
            pos = {
                x: horiz ?
                    Tick_correctFloat(axis.translate(tickPos + tickmarkOffset,
            void 0,
            void 0,
            old) +
                        axis.transB) :
                    (axis.left +
                        axis.offset +
                        (axis.opposite ?
                            (((old && chart.oldChartWidth) ||
                                chart.chartWidth) -
                                axis.right -
                                axis.left) :
                            0)),
                y: horiz ?
                    (cHeight -
                        axis.bottom +
                        axis.offset -
                        (axis.opposite ? axis.height : 0)) :
                    Tick_correctFloat(cHeight -
                        axis.translate(tickPos + tickmarkOffset,
            void 0,
            void 0,
            old) -
                        axis.transB)
            };
        // Chrome workaround for #10516
        pos.y = Tick_clamp(pos.y, -1e9, 1e9);
        Tick_fireEvent(this, 'afterGetPosition', { pos: pos });
        return pos;
    };
    /**
     * Get the x, y position of the tick label
     * @private
     */
    Tick.prototype.getLabelPosition = function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
        var axis = this.axis,
            transA = axis.transA,
            reversed = ( // #7911
            axis.isLinked && axis.linkedParent ?
                axis.linkedParent.reversed :
                axis.reversed),
            staggerLines = axis.staggerLines,
            rotCorr = axis.tickRotCorr || { x: 0,
            y: 0 }, 
            // Adjust for label alignment if we use reserveSpace: true (#5286)
            labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ?
                -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) :
                0),
            distance = labelOptions.distance,
            pos = {};
        var yOffset,
            line;
        if (axis.side === 0) {
            yOffset = label.rotation ? -distance : -label.getBBox().height;
        }
        else if (axis.side === 2) {
            yOffset = rotCorr.y + distance;
        }
        else {
            // #3140, #3140
            yOffset = Math.cos(label.rotation * Tick_deg2rad) *
                (rotCorr.y - label.getBBox(false, 0).height / 2);
        }
        if (Tick_defined(labelOptions.y)) {
            yOffset = axis.side === 0 && axis.horiz ?
                labelOptions.y + yOffset :
                labelOptions.y;
        }
        x = x +
            Tick_pick(labelOptions.x, [0, 1, 0, -1][axis.side] * distance) +
            labelOffsetCorrection +
            rotCorr.x -
            (tickmarkOffset && horiz ?
                tickmarkOffset * transA * (reversed ? -1 : 1) :
                0);
        y = y + yOffset - (tickmarkOffset && !horiz ?
            tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
        // Correct for staggered labels
        if (staggerLines) {
            line = (index / (step || 1) % staggerLines);
            if (axis.opposite) {
                line = staggerLines - line - 1;
            }
            y += line * (axis.labelOffset / staggerLines);
        }
        pos.x = x;
        pos.y = Math.round(y);
        Tick_fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index });
        return pos;
    };
    /**
     * Get the offset height or width of the label
     *
     * @private
     * @function Highcharts.Tick#getLabelSize
     */
    Tick.prototype.getLabelSize = function () {
        return this.label ?
            this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] :
            0;
    };
    /**
     * Extendible method to return the path of the marker
     * @private
     */
    Tick.prototype.getMarkPath = function (x, y, tickLength, tickWidth, horiz, renderer) {
        if (horiz === void 0) { horiz = false; }
        return renderer.crispLine([[
                'M',
                x,
                y
            ], [
                'L',
                x + (horiz ? 0 : -tickLength),
                y + (horiz ? tickLength : 0)
            ]], tickWidth);
    };
    /**
     * Handle the label overflow by adjusting the labels to the left and right
     * edge, or hide them if they collide into the neighbour label.
     *
     * @private
     * @function Highcharts.Tick#handleOverflow
     */
    Tick.prototype.handleOverflow = function (xy) {
        var tick = this,
            axis = this.axis,
            labelOptions = axis.options.labels,
            pxPos = xy.x,
            chartWidth = axis.chart.chartWidth,
            spacing = axis.chart.spacing,
            leftBound = Tick_pick(axis.labelLeft,
            Math.min(axis.pos,
            spacing[3])),
            rightBound = Tick_pick(axis.labelRight,
            Math.max(!axis.isRadial ? axis.pos + axis.len : 0,
            chartWidth - spacing[1])),
            label = this.label,
            rotation = this.rotation,
            factor = Tick_getAlignFactor(axis.labelAlign || label.attr('align')),
            labelWidth = label.getBBox().width,
            slotWidth = axis.getSlotWidth(tick),
            xCorrection = factor,
            css = {};
        var modifiedSlotWidth = slotWidth,
            goRight = 1,
            leftPos,
            rightPos,
            textWidth;
        // Check if the label overshoots the chart spacing box. If it does, move
        // it. If it now overshoots the slotWidth, add ellipsis.
        if (!rotation && labelOptions.overflow === 'justify') {
            leftPos = pxPos - factor * labelWidth;
            rightPos = pxPos + (1 - factor) * labelWidth;
            if (leftPos < leftBound) {
                modifiedSlotWidth =
                    xy.x + modifiedSlotWidth * (1 - factor) - leftBound;
            }
            else if (rightPos > rightBound) {
                modifiedSlotWidth =
                    rightBound - xy.x + modifiedSlotWidth * factor;
                goRight = -1;
            }
            modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177
            if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') {
                xy.x += (goRight *
                    (slotWidth -
                        modifiedSlotWidth -
                        xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth))));
            }
            // If the label width exceeds the available space, set a text width
            // to be picked up below. Also, if a width has been set before, we
            // need to set a new one because the reported labelWidth will be
            // limited by the box (#3938).
            if (labelWidth > modifiedSlotWidth ||
                (axis.autoRotation && (label.styles || {}).width)) {
                textWidth = modifiedSlotWidth;
            }
            // Add ellipsis to prevent rotated labels to be clipped against the edge
            // of the chart
        }
        else if (rotation < 0 &&
            pxPos - factor * labelWidth < leftBound) {
            textWidth = Math.round(pxPos / Math.cos(rotation * Tick_deg2rad) - leftBound);
        }
        else if (rotation > 0 &&
            pxPos + factor * labelWidth > rightBound) {
            textWidth = Math.round((chartWidth - pxPos) /
                Math.cos(rotation * Tick_deg2rad));
        }
        if (textWidth && label) {
            if (tick.shortenLabel) {
                tick.shortenLabel();
            }
            else {
                label.css(Tick_extend(css, {
                    width: Math.floor(textWidth) + 'px',
                    lineClamp: axis.isRadial ? 0 : 1
                }));
            }
        }
    };
    /**
     * Try to replace the label if the same one already exists.
     *
     * @private
     * @function Highcharts.Tick#moveLabel
     */
    Tick.prototype.moveLabel = function (str, labelOptions) {
        var tick = this,
            label = tick.label,
            axis = tick.axis;
        var moved = false,
            labelPos;
        if (label && label.textStr === str) {
            tick.movedLabel = label;
            moved = true;
            delete tick.label;
        }
        else { // Find a label with the same string
            Tick_objectEach(axis.ticks, function (currentTick) {
                if (!moved &&
                    !currentTick.isNew &&
                    currentTick !== tick &&
                    currentTick.label &&
                    currentTick.label.textStr === str) {
                    tick.movedLabel = currentTick.label;
                    moved = true;
                    currentTick.labelPos = tick.movedLabel.xy;
                    delete currentTick.label;
                }
            });
        }
        // Create new label if the actual one is moved
        if (!moved && (tick.labelPos || label)) {
            labelPos = tick.labelPos || label.xy;
            tick.movedLabel = tick.createLabel(str, labelOptions, labelPos);
            if (tick.movedLabel) {
                tick.movedLabel.attr({ opacity: 0 });
            }
        }
    };
    /**
     * Put everything in place
     *
     * @private
     * @param {number} index
     *
     * @param {boolean} [old]
     * Use old coordinates to prepare an animation into new position
     *
     * @param {number} [opacity]
     */
    Tick.prototype.render = function (index, old, opacity) {
        var tick = this,
            axis = tick.axis,
            horiz = axis.horiz,
            pos = tick.pos,
            tickmarkOffset = Tick_pick(tick.tickmarkOffset,
            axis.tickmarkOffset),
            xy = tick.getPosition(horiz,
            pos,
            tickmarkOffset,
            old),
            x = xy.x,
            y = xy.y,
            axisStart = axis.pos,
            axisEnd = axisStart + axis.len,
            pxPos = horiz ? x : y;
        // Anything that is not between `axis.pos` and `axis.pos + axis.length`
        // should not be visible (#20166). The `correctFloat` is for reversed
        // axes in Safari.
        if (!axis.chart.polar &&
            tick.isNew &&
            (Tick_correctFloat(pxPos) < axisStart || pxPos > axisEnd)) {
            opacity = 0;
        }
        var labelOpacity = Tick_pick(opacity,
            tick.label && tick.label.newOpacity, // #15528
            1);
        opacity = Tick_pick(opacity, 1);
        this.isActive = true;
        // Create the grid line
        this.renderGridLine(old, opacity);
        // Create the tick mark
        this.renderMark(xy, opacity);
        // The label is created on init - now move it into place
        this.renderLabel(xy, old, labelOpacity, index);
        tick.isNew = false;
        Tick_fireEvent(this, 'afterRender');
    };
    /**
     * Renders the gridLine.
     *
     * @private
     * @function Highcharts.Tick#renderGridLine
     * @param {boolean} old  Whether or not the tick is old
     * @param {number} opacity  The opacity of the grid line
     */
    Tick.prototype.renderGridLine = function (old, opacity) {
        var tick = this,
            axis = tick.axis,
            options = axis.options,
            attribs = {},
            pos = tick.pos,
            type = tick.type,
            tickmarkOffset = Tick_pick(tick.tickmarkOffset,
            axis.tickmarkOffset),
            renderer = axis.chart.renderer;
        var gridLine = tick.gridLine,
            gridLinePath,
            gridLineWidth = options.gridLineWidth,
            gridLineColor = options.gridLineColor,
            dashStyle = options.gridLineDashStyle;
        if (tick.type === 'minor') {
            gridLineWidth = options.minorGridLineWidth;
            gridLineColor = options.minorGridLineColor;
            dashStyle = options.minorGridLineDashStyle;
        }
        if (!gridLine) {
            if (!axis.chart.styledMode) {
                attribs.stroke = gridLineColor;
                attribs['stroke-width'] = gridLineWidth || 0;
                attribs.dashstyle = dashStyle;
            }
            if (!type) {
                attribs.zIndex = 1;
            }
            if (old) {
                opacity = 0;
            }
            /**
             * The rendered grid line of the tick.
             * @name Highcharts.Tick#gridLine
             * @type {Highcharts.SVGElement|undefined}
             */
            tick.gridLine = gridLine = renderer.path()
                .attr(attribs)
                .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line')
                .add(axis.gridGroup);
        }
        if (gridLine) {
            gridLinePath = axis.getPlotLinePath({
                value: pos + tickmarkOffset,
                lineWidth: gridLine.strokeWidth(),
                force: 'pass',
                old: old,
                acrossPanes: false // #18025
            });
            // If the parameter 'old' is set, the current call will be followed
            // by another call, therefore do not do any animations this time
            if (gridLinePath) {
                gridLine[old || tick.isNew ? 'attr' : 'animate']({
                    d: gridLinePath,
                    opacity: opacity
                });
            }
        }
    };
    /**
     * Renders the tick mark.
     *
     * @private
     * @function Highcharts.Tick#renderMark
     * @param {Highcharts.PositionObject} xy  The position vector of the mark
     * @param {number} opacity  The opacity of the mark
     */
    Tick.prototype.renderMark = function (xy, opacity) {
        var tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickSize = axis.tickSize(type ? type + 'Tick' : 'tick'), x = xy.x, y = xy.y, tickWidth = Tick_pick(options[type !== 'minor' ? 'tickWidth' : 'minorTickWidth'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1
            tickColor = options[type !== 'minor' ? 'tickColor' : 'minorTickColor'];
        var mark = tick.mark;
        var isNewMark = !mark;
        if (tickSize) {
            // Negate the length
            if (axis.opposite) {
                tickSize[0] = -tickSize[0];
            }
            // First time, create it
            if (!mark) {
                /**
                 * The rendered mark of the tick.
                 * @name Highcharts.Tick#mark
                 * @type {Highcharts.SVGElement|undefined}
                 */
                tick.mark = mark = renderer.path()
                    .addClass('highcharts-' + (type ? type + '-' : '') + 'tick')
                    .add(axis.axisGroup);
                if (!axis.chart.styledMode) {
                    mark.attr({
                        stroke: tickColor,
                        'stroke-width': tickWidth
                    });
                }
            }
            mark[isNewMark ? 'attr' : 'animate']({
                d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth(), axis.horiz, renderer),
                opacity: opacity
            });
        }
    };
    /**
     * Renders the tick label.
     * Note: The label should already be created in init(), so it should only
     * have to be moved into place.
     *
     * @private
     * @function Highcharts.Tick#renderLabel
     * @param {Highcharts.PositionObject} xy  The position vector of the label
     * @param {boolean} old  Whether or not the tick is old
     * @param {number} opacity  The opacity of the label
     * @param {number} index  The index of the tick
     */
    Tick.prototype.renderLabel = function (xy, old, opacity, index) {
        var tick = this,
            axis = tick.axis,
            horiz = axis.horiz,
            options = axis.options,
            label = tick.label,
            labelOptions = options.labels,
            step = labelOptions.step,
            tickmarkOffset = Tick_pick(tick.tickmarkOffset,
            axis.tickmarkOffset),
            x = xy.x,
            y = xy.y;
        var show = true;
        if (label && Tick_isNumber(x)) {
            label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
            // Apply show first and show last. If the tick is both first and
            // last, it is a single centered tick, in which case we show the
            // label anyway (#2100).
            if ((tick.isFirst &&
                !tick.isLast &&
                !options.showFirstLabel) ||
                (tick.isLast &&
                    !tick.isFirst &&
                    !options.showLastLabel)) {
                show = false;
                // Handle label overflow and show or hide accordingly
            }
            else if (horiz &&
                !labelOptions.step &&
                !labelOptions.rotation &&
                !old &&
                opacity !== 0) {
                tick.handleOverflow(xy);
            }
            // Apply step
            if (step && index % step) {
                // Show those indices dividable by step
                show = false;
            }
            // Set the new position, and show or hide
            if (show && Tick_isNumber(xy.y)) {
                xy.opacity = opacity;
                label[tick.isNewLabel ? 'attr' : 'animate'](xy).show(true);
                tick.isNewLabel = false;
            }
            else {
                label.hide(); // #1338, #15863
                tick.isNewLabel = true;
            }
        }
    };
    /**
     * Replace labels with the moved ones to perform animation. Additionally
     * destroy unused labels.
     *
     * @private
     * @function Highcharts.Tick#replaceMovedLabel
     */
    Tick.prototype.replaceMovedLabel = function () {
        var tick = this,
            label = tick.label,
            axis = tick.axis;
        // Animate and destroy
        if (label && !tick.isNew) {
            label.animate({ opacity: 0 }, void 0, label.destroy);
            delete tick.label;
        }
        axis.isDirty = true;
        tick.label = tick.movedLabel;
        delete tick.movedLabel;
    };
    return Tick;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_Tick = (Tick);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Optional parameters for the tick.
 * @private
 * @interface Highcharts.TickParametersObject
 */ /**
* Set category for the tick.
* @name Highcharts.TickParametersObject#category
* @type {string|undefined}
*/ /**
* @name Highcharts.TickParametersObject#options
* @type {Highcharts.Dictionary<any>|undefined}
*/ /**
* Set tickmarkOffset for the tick.
* @name Highcharts.TickParametersObject#tickmarkOffset
* @type {number|undefined}
*/
/**
 * Additional time tick information.
 *
 * @interface Highcharts.TimeTicksInfoObject
 * @extends Highcharts.TimeNormalizedObject
 */ /**
* @name Highcharts.TimeTicksInfoObject#higherRanks
* @type {Array<string>}
*/ /**
* @name Highcharts.TimeTicksInfoObject#totalRange
* @type {number}
*/
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Axis/Axis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Axis_animObject = AnimationUtilities.animObject;

var xAxis = Axis_AxisDefaults.xAxis, yAxis = Axis_AxisDefaults.yAxis;


var Axis_defaultOptions = Defaults.defaultOptions;

var registerEventOptions = Core_Foundation.registerEventOptions;

var Axis_deg2rad = Core_Globals.deg2rad;


var Axis_arrayMax = Core_Utilities.arrayMax, Axis_arrayMin = Core_Utilities.arrayMin, Axis_clamp = Core_Utilities.clamp, Axis_correctFloat = Core_Utilities.correctFloat, Axis_defined = Core_Utilities.defined, Axis_destroyObjectProperties = Core_Utilities.destroyObjectProperties, Axis_erase = Core_Utilities.erase, Axis_error = Core_Utilities.error, Axis_extend = Core_Utilities.extend, Axis_fireEvent = Core_Utilities.fireEvent, Axis_getClosestDistance = Core_Utilities.getClosestDistance, Axis_insertItem = Core_Utilities.insertItem, Axis_isArray = Core_Utilities.isArray, Axis_isNumber = Core_Utilities.isNumber, Axis_isString = Core_Utilities.isString, Axis_merge = Core_Utilities.merge, Axis_normalizeTickInterval = Core_Utilities.normalizeTickInterval, Axis_objectEach = Core_Utilities.objectEach, Axis_pick = Core_Utilities.pick, Axis_relativeLength = Core_Utilities.relativeLength, Axis_removeEvent = Core_Utilities.removeEvent, Axis_splat = Core_Utilities.splat, Axis_syncTimeout = Core_Utilities.syncTimeout;
var getNormalizedTickInterval = function (axis, tickInterval) { return Axis_normalizeTickInterval(tickInterval, void 0, void 0, Axis_pick(axis.options.allowDecimals, 
// If the tick interval is greater than 0.5, avoid decimals, as
// linear axes are often used to render discrete values (#3363). If
// a tick amount is set, allow decimals by default, as it increases
// the chances for a good fit.
tickInterval < 0.5 || axis.tickAmount !== void 0), !!axis.tickAmount); };
Axis_extend(Axis_defaultOptions, { xAxis: xAxis, yAxis: Axis_merge(xAxis, yAxis) });
/* *
 *
 *  Class
 *
 * */
/**
 * Create a new axis object. Called internally when instantiating a new chart or
 * adding axes by {@link Highcharts.Chart#addAxis}.
 *
 * A chart can have from 0 axes (pie chart) to multiples. In a normal, single
 * series cartesian chart, there is one X axis and one Y axis.
 *
 * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is
 * an array of Axis objects. If there is only one axis, it can be referenced
 * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same
 * pattern goes for Y axes.
 *
 * If you need to get the axes from a series object, use the `series.xAxis` and
 * `series.yAxis` properties. These are not arrays, as one series can only be
 * associated to one X and one Y axis.
 *
 * A third way to reference the axis programmatically is by `id`. Add an `id` in
 * the axis configuration options, and get the axis by
 * {@link Highcharts.Chart#get}.
 *
 * Configuration options for the axes are given in options.xAxis and
 * options.yAxis.
 *
 * @class
 * @name Highcharts.Axis
 *
 * @param {Highcharts.Chart} chart
 * The Chart instance to apply the axis on.
 *
 * @param {Highcharts.AxisOptions} userOptions
 * Axis options
 */
var Axis = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Axis(chart, userOptions, coll) {
        this.init(chart, userOptions, coll);
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Overrideable function to initialize the axis.
     *
     * @see {@link Axis}
     *
     * @function Highcharts.Axis#init
     *
     * @param {Highcharts.Chart} chart
     * The Chart instance to apply the axis on.
     *
     * @param {AxisOptions} userOptions
     * Axis options.
     *
     * @emits Highcharts.Axis#event:afterInit
     * @emits Highcharts.Axis#event:init
     */
    Axis.prototype.init = function (chart, userOptions, coll) {
        var _a,
            _b,
            _c,
            _d;
        if (coll === void 0) { coll = this.coll; }
        var isXAxis = coll === 'xAxis',
            axis = this,
            horiz = axis.isZAxis || (chart.inverted ? !isXAxis : isXAxis);
        /**
         * The Chart that the axis belongs to.
         *
         * @name Highcharts.Axis#chart
         * @type {Highcharts.Chart}
         */
        axis.chart = chart;
        /**
         * Whether the axis is horizontal.
         *
         * @name Highcharts.Axis#horiz
         * @type {boolean|undefined}
         */
        axis.horiz = horiz;
        /**
         * Whether the axis is the x-axis.
         *
         * @name Highcharts.Axis#isXAxis
         * @type {boolean|undefined}
         */
        axis.isXAxis = isXAxis;
        /**
         * The collection where the axis belongs, for example `xAxis`, `yAxis`
         * or `colorAxis`. Corresponds to properties on Chart, for example
         * {@link Chart.xAxis}.
         *
         * @name Highcharts.Axis#coll
         * @type {string}
         */
        axis.coll = coll;
        Axis_fireEvent(this, 'init', { userOptions: userOptions });
        // Needed in setOptions
        axis.opposite = Axis_pick(userOptions.opposite, axis.opposite);
        /**
         * The side on which the axis is rendered. 0 is top, 1 is right, 2
         * is bottom and 3 is left.
         *
         * @name Highcharts.Axis#side
         * @type {number}
         */
        axis.side = Axis_pick(userOptions.side, axis.side, (horiz ?
            (axis.opposite ? 0 : 2) : // Top : bottom
            (axis.opposite ? 1 : 3)) // Right : left
        );
        /**
         * Current options for the axis after merge of defaults and user's
         * options.
         *
         * @name Highcharts.Axis#options
         * @type {Highcharts.AxisOptions}
         */
        axis.setOptions(userOptions);
        var options = axis.options,
            labelsOptions = options.labels;
        // Set the type and fire an event
        (_a = axis.type) !== null && _a !== void 0 ? _a : (axis.type = options.type || 'linear');
        (_b = axis.uniqueNames) !== null && _b !== void 0 ? _b : (axis.uniqueNames = (_c = options.uniqueNames) !== null && _c !== void 0 ? _c : true);
        Axis_fireEvent(axis, 'afterSetType');
        /**
         * User's options for this axis without defaults.
         *
         * @name Highcharts.Axis#userOptions
         * @type {Highcharts.AxisOptions}
         */
        axis.userOptions = userOptions;
        axis.minPixelPadding = 0;
        /**
         * Whether the axis is reversed. Based on the `axis.reversed`,
         * option, but inverted charts have reversed xAxis by default.
         *
         * @name Highcharts.Axis#reversed
         * @type {boolean}
         */
        axis.reversed = Axis_pick(options.reversed, axis.reversed);
        axis.visible = options.visible;
        axis.zoomEnabled = options.zoomEnabled;
        // Initial categories
        axis.hasNames = this.type === 'category' || options.categories === true;
        /**
         * If categories are present for the axis, names are used instead of
         * numbers for that axis.
         *
         * Since Highcharts 3.0, categories can also be extracted by giving each
         * point a name and setting axis type to `category`. However, if you
         * have multiple series, best practice remains defining the `categories`
         * array.
         *
         * @see [xAxis.categories](/highcharts/xAxis.categories)
         *
         * @name Highcharts.Axis#categories
         * @type {Array<string>}
         * @readonly
         */
        axis.categories = (Axis_isArray(options.categories) && options.categories) ||
            (axis.hasNames ? [] : void 0);
        if (!axis.names) { // Preserve on update (#3830)
            axis.names = [];
            axis.names.keys = {};
        }
        // Placeholder for plotlines and plotbands groups
        axis.plotLinesAndBandsGroups = {};
        // Shorthand types
        axis.positiveValuesOnly = !!axis.logarithmic;
        // Flag, if axis is linked to another axis
        axis.isLinked = Axis_defined(options.linkedTo);
        /**
         * List of major ticks mapped by position on axis.
         *
         * @see {@link Highcharts.Tick}
         *
         * @name Highcharts.Axis#ticks
         * @type {Highcharts.Dictionary<Highcharts.Tick>}
         */
        axis.ticks = {};
        axis.labelEdge = [];
        /**
         * List of minor ticks mapped by position on the axis.
         *
         * @see {@link Highcharts.Tick}
         *
         * @name Highcharts.Axis#minorTicks
         * @type {Highcharts.Dictionary<Highcharts.Tick>}
         */
        axis.minorTicks = {};
        // List of plotLines/Bands
        axis.plotLinesAndBands = [];
        // Alternate bands
        axis.alternateBands = {};
        /**
         * The length of the axis in terms of pixels.
         *
         * @name Highcharts.Axis#len
         * @type {number}
         */
        (_d = axis.len) !== null && _d !== void 0 ? _d : (axis.len = 0);
        axis.minRange = axis.userMinRange = options.minRange || options.maxZoom;
        axis.range = options.range;
        axis.offset = options.offset || 0;
        /**
         * The maximum value of the axis. In a logarithmic axis, this is the
         * logarithm of the real value, and the real value can be obtained from
         * {@link Axis#getExtremes}.
         *
         * @name Highcharts.Axis#max
         * @type {number|undefined}
         */
        axis.max = void 0;
        /**
         * The minimum value of the axis. In a logarithmic axis, this is the
         * logarithm of the real value, and the real value can be obtained from
         * {@link Axis#getExtremes}.
         *
         * @name Highcharts.Axis#min
         * @type {number|undefined}
         */
        axis.min = void 0;
        /**
         * The processed crosshair options.
         *
         * @name Highcharts.Axis#crosshair
         * @type {boolean|Highcharts.AxisCrosshairOptions}
         */
        var crosshair = Axis_pick(options.crosshair,
            Axis_splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1]);
        axis.crosshair = crosshair === true ? {} : crosshair;
        // Register. Don't add it again on Axis.update().
        if (chart.axes.indexOf(axis) === -1) { //
            if (isXAxis) { // #2713
                chart.axes.splice(chart.xAxis.length, 0, axis);
            }
            else {
                chart.axes.push(axis);
            }
            Axis_insertItem(this, chart[this.coll]);
        }
        chart.orderItems(axis.coll);
        /**
         * All series associated to the axis.
         *
         * @name Highcharts.Axis#series
         * @type {Array<Highcharts.Series>}
         */
        axis.series = axis.series || []; // Populated by Series
        // Reversed axis
        if (chart.inverted &&
            !axis.isZAxis &&
            isXAxis &&
            !Axis_defined(axis.reversed)) {
            axis.reversed = true;
        }
        axis.labelRotation = Axis_isNumber(labelsOptions.rotation) ?
            labelsOptions.rotation :
            void 0;
        // Register event listeners
        registerEventOptions(axis, options);
        Axis_fireEvent(this, 'afterInit');
    };
    /**
     * Merge and set options.
     *
     * @private
     * @function Highcharts.Axis#setOptions
     *
     * @param {Highcharts.AxisOptions} userOptions
     * Axis options.
     *
     * @emits Highcharts.Axis#event:afterSetOptions
     */
    Axis.prototype.setOptions = function (userOptions) {
        var sideSpecific = this.horiz ?
                // Top and bottom axis defaults
                {
                    labels: {
                        autoRotation: [-45],
                        padding: 3
                    },
                    margin: 15
                } :
                // Left and right axis, title rotated 90 or 270 degrees
                // respectively
                {
                    labels: {
                        padding: 1
                    },
                    title: {
                        rotation: 90 * this.side
                    }
                };
        this.options = Axis_merge(sideSpecific, Axis_defaultOptions[this.coll], userOptions);
        Axis_fireEvent(this, 'afterSetOptions', { userOptions: userOptions });
    };
    /**
     * The default label formatter. The context is a special config object for
     * the label. In apps, use the
     * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter)
     * instead, except when a modification is needed.
     *
     * @function Highcharts.Axis#defaultLabelFormatter
     *
     * @param {Highcharts.AxisLabelsFormatterContextObject} this
     * Formatter context of axis label.
     *
     * @param {Highcharts.AxisLabelsFormatterContextObject} [ctx]
     * Formatter context of axis label.
     *
     * @return {string}
     * The formatted label content.
     */
    Axis.prototype.defaultLabelFormatter = function () {
        var axis = this.axis,
            chart = this.chart,
            numberFormatter = chart.numberFormatter,
            value = Axis_isNumber(this.value) ? this.value : NaN,
            time = axis.chart.time,
            categories = axis.categories,
            dateTimeLabelFormat = this.dateTimeLabelFormat,
            lang = Axis_defaultOptions.lang,
            numericSymbols = lang.numericSymbols,
            numSymMagnitude = lang.numericSymbolMagnitude || 1000, 
            // Make sure the same symbol is added for all labels on a linear
            // axis
            numericSymbolDetector = axis.logarithmic ?
                Math.abs(value) :
                axis.tickInterval;
        var i = numericSymbols && numericSymbols.length,
            multi,
            ret;
        if (categories) {
            ret = "".concat(this.value);
        }
        else if (dateTimeLabelFormat) { // Datetime axis
            ret = time.dateFormat(dateTimeLabelFormat, value, true);
        }
        else if (i &&
            numericSymbols &&
            numericSymbolDetector >= 1000) {
            // Decide whether we should add a numeric symbol like k (thousands)
            // or M (millions). If we are to enable this in tooltip or other
            // places as well, we can move this logic to the numberFormatter and
            // enable it by a parameter.
            while (i-- && typeof ret === 'undefined') {
                multi = Math.pow(numSymMagnitude, i + 1);
                if (
                // Only accept a numeric symbol when the distance is more
                // than a full unit. So for example if the symbol is k, we
                // don't accept numbers like 0.5k.
                numericSymbolDetector >= multi &&
                    // Accept one decimal before the symbol. Accepts 0.5k but
                    // not 0.25k. How does this work with the previous?
                    (value * 10) % multi === 0 &&
                    numericSymbols[i] !== null &&
                    value !== 0) { // #5480
                    ret = numberFormatter(value / multi, -1) + numericSymbols[i];
                }
            }
        }
        if (typeof ret === 'undefined') {
            if (Math.abs(value) >= 10000) { // Add thousands separators
                ret = numberFormatter(value, -1);
            }
            else { // Small numbers
                ret = numberFormatter(value, -1, void 0, ''); // #2466
            }
        }
        return ret;
    };
    /**
     * Get the minimum and maximum for the series of each axis. The function
     * analyzes the axis series and updates `this.dataMin` and `this.dataMax`.
     *
     * @private
     * @function Highcharts.Axis#getSeriesExtremes
     *
     * @emits Highcharts.Axis#event:afterGetSeriesExtremes
     * @emits Highcharts.Axis#event:getSeriesExtremes
     */
    Axis.prototype.getSeriesExtremes = function () {
        var axis = this;
        var xExtremes;
        Axis_fireEvent(this, 'getSeriesExtremes', null, function () {
            axis.hasVisibleSeries = false;
            // Reset properties in case we're redrawing (#3353)
            axis.dataMin = axis.dataMax = axis.threshold = void 0;
            axis.softThreshold = !axis.isXAxis;
            // Loop through this axis' series
            axis.series.forEach(function (series) {
                if (series.reserveSpace()) {
                    var seriesOptions = series.options;
                    var xData = void 0,
                        threshold = seriesOptions.threshold,
                        seriesDataMin = void 0,
                        seriesDataMax = void 0;
                    axis.hasVisibleSeries = true;
                    // Validate threshold in logarithmic axes
                    if (axis.positiveValuesOnly && (threshold || 0) <= 0) {
                        threshold = void 0;
                    }
                    // Get dataMin and dataMax for X axes
                    if (axis.isXAxis) {
                        xData = series.getColumn('x');
                        if (xData.length) {
                            xData = axis.logarithmic ?
                                xData.filter(function (x) { return x > 0; }) :
                                xData;
                            xExtremes = series.getXExtremes(xData);
                            // If xData contains values which is not numbers,
                            // then filter them out. To prevent performance hit,
                            // we only do this after we have already found
                            // seriesDataMin because in most cases all data is
                            // valid. #5234.
                            seriesDataMin = xExtremes.min;
                            seriesDataMax = xExtremes.max;
                            if (!Axis_isNumber(seriesDataMin) &&
                                // #5010:
                                !(seriesDataMin instanceof Date)) {
                                xData = xData.filter(Axis_isNumber);
                                xExtremes = series.getXExtremes(xData);
                                // Do it again with valid data
                                seriesDataMin = xExtremes.min;
                                seriesDataMax = xExtremes.max;
                            }
                            if (xData.length) {
                                axis.dataMin = Math.min(Axis_pick(axis.dataMin, seriesDataMin), seriesDataMin);
                                axis.dataMax = Math.max(Axis_pick(axis.dataMax, seriesDataMax), seriesDataMax);
                            }
                        }
                        // Get dataMin and dataMax for Y axes, as well as handle
                        // stacking and processed data
                    }
                    else {
                        // Get this particular series extremes
                        var dataExtremes = series.applyExtremes();
                        // Get the dataMin and dataMax so far. If percentage is
                        // used, the min and max are always 0 and 100. If
                        // seriesDataMin and seriesDataMax is null, then series
                        // doesn't have active y data, we continue with nulls
                        if (Axis_isNumber(dataExtremes.dataMin)) {
                            seriesDataMin = dataExtremes.dataMin;
                            axis.dataMin = Math.min(Axis_pick(axis.dataMin, seriesDataMin), seriesDataMin);
                        }
                        if (Axis_isNumber(dataExtremes.dataMax)) {
                            seriesDataMax = dataExtremes.dataMax;
                            axis.dataMax = Math.max(Axis_pick(axis.dataMax, seriesDataMax), seriesDataMax);
                        }
                        // Adjust to threshold
                        if (Axis_defined(threshold)) {
                            axis.threshold = threshold;
                        }
                        // If any series has a hard threshold, it takes
                        // precedence
                        if (!seriesOptions.softThreshold ||
                            axis.positiveValuesOnly) {
                            axis.softThreshold = false;
                        }
                    }
                }
            });
        });
        Axis_fireEvent(this, 'afterGetSeriesExtremes');
    };
    /**
     * Translate from axis value to pixel position on the chart, or back. Use
     * the `toPixels` and `toValue` functions in applications.
     *
     * @private
     * @function Highcharts.Axis#translate
     */
    Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) {
        var _a;
        var axis = (this.linkedParent || this), // #1417
            localMin = (old && axis.old ? axis.old.min : axis.min);
        if (!Axis_isNumber(localMin)) {
            return NaN;
        }
        var minPixelPadding = axis.minPixelPadding,
            doPostTranslate = (axis.isOrdinal ||
                ((_a = axis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks) ||
                (axis.logarithmic && handleLog)) && axis.lin2val;
        var sign = 1,
            cvsOffset = 0,
            localA = old && axis.old ? axis.old.transA : axis.transA,
            returnValue = 0;
        if (!localA) {
            localA = axis.transA;
        }
        // In vertical axes, the canvas coordinates start from 0 at the top like
        // in SVG.
        if (cvsCoord) {
            sign *= -1; // Canvas coordinates inverts the value
            cvsOffset = axis.len;
        }
        // Handle reversed axis
        if (axis.reversed) {
            sign *= -1;
            cvsOffset -= sign * (axis.sector || axis.len);
        }
        // From pixels to value
        if (backwards) { // Reverse translation
            val = val * sign + cvsOffset;
            val -= minPixelPadding;
            // From chart pixel to value:
            returnValue = val / localA + localMin;
            if (doPostTranslate) { // Log, ordinal and broken axis
                returnValue = axis.lin2val(returnValue);
            }
            // From value to pixels
        }
        else {
            if (doPostTranslate) { // Log, ordinal and broken axis
                val = axis.val2lin(val);
            }
            var value = sign * (val - localMin) * localA;
            returnValue = value +
                cvsOffset +
                (sign * minPixelPadding) +
                (Axis_isNumber(pointPlacement) ? localA * pointPlacement : 0);
            if (!axis.isRadial) {
                returnValue = Axis_correctFloat(returnValue);
            }
        }
        return returnValue;
    };
    /**
     * Translate a value in terms of axis units into pixels within the chart.
     *
     * @function Highcharts.Axis#toPixels
     *
     * @param {number|string} value
     * A value in terms of axis units. For datetime axes, a timestamp or
     * date/time string is accepted.
     *
     * @param {boolean} [paneCoordinates=false]
     * Whether to return the pixel coordinate relative to the chart or just the
     * axis/pane itself.
     *
     * @return {number}
     * Pixel position of the value on the chart or axis.
     */
    Axis.prototype.toPixels = function (value, paneCoordinates) {
        var _a,
            _b;
        return this.translate((_b = (_a = this.chart) === null || _a === void 0 ? void 0 : _a.time.parse(value)) !== null && _b !== void 0 ? _b : NaN, false, !this.horiz, void 0, true) + (paneCoordinates ? 0 : this.pos);
    };
    /**
     * Translate a pixel position along the axis to a value in terms of axis
     * units.
     *
     * @function Highcharts.Axis#toValue
     *
     * @param {number} pixel
     * The pixel value coordinate.
     *
     * @param {boolean} [paneCoordinates=false]
     * Whether the input pixel is relative to the chart or just the axis/pane
     * itself.
     *
     * @return {number}
     * The axis value.
     */
    Axis.prototype.toValue = function (pixel, paneCoordinates) {
        return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, void 0, true);
    };
    /**
     * Create the path for a plot line that goes from the given value on
     * this axis, across the plot to the opposite side. Also used internally for
     * grid lines and crosshairs.
     *
     * @function Highcharts.Axis#getPlotLinePath
     *
     * @param {Highcharts.AxisPlotLinePathOptionsObject} options
     * Options for the path.
     *
     * @return {Highcharts.SVGPathArray|null}
     * The SVG path definition for the plot line.
     */
    Axis.prototype.getPlotLinePath = function (options) {
        var axis = this,
            chart = axis.chart,
            axisLeft = axis.left,
            axisTop = axis.top,
            old = options.old,
            value = options.value,
            lineWidth = options.lineWidth,
            cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
            cWidth = (old && chart.oldChartWidth) || chart.chartWidth,
            transB = axis.transB;
        var translatedValue = options.translatedValue,
            force = options.force,
            x1,
            y1,
            x2,
            y2,
            skip;
        // eslint-disable-next-line valid-jsdoc
        /**
         * Check if x is between a and b. If not, either move to a/b
         * or skip, depending on the force parameter.
         * @private
         */
        function between(x, a, b) {
            if (force !== 'pass' && (x < a || x > b)) {
                if (force) {
                    x = Axis_clamp(x, a, b);
                }
                else {
                    skip = true;
                }
            }
            return x;
        }
        var evt = {
                value: value,
                lineWidth: lineWidth,
                old: old,
                force: force,
                acrossPanes: options.acrossPanes,
                translatedValue: translatedValue
            };
        Axis_fireEvent(this, 'getPlotLinePath', evt, function (e) {
            translatedValue = Axis_pick(translatedValue, axis.translate(value, void 0, void 0, old));
            // Keep the translated value within sane bounds, and avoid Infinity
            // to fail the isNumber test (#7709).
            translatedValue = Axis_clamp(translatedValue, -1e9, 1e9);
            x1 = x2 = translatedValue + transB;
            y1 = y2 = cHeight - translatedValue - transB;
            if (!Axis_isNumber(translatedValue)) { // No min or max
                skip = true;
                force = false; // #7175, don't force it when path is invalid
            }
            else if (axis.horiz) {
                y1 = axisTop;
                y2 = cHeight - axis.bottom + (axis.options.isInternal ?
                    0 :
                    (chart.scrollablePixelsY || 0)); // #20354, scrollablePixelsY shouldn't be used for navigator
                x1 = x2 = between(x1, axisLeft, axisLeft + axis.width);
            }
            else {
                x1 = axisLeft;
                x2 = cWidth - axis.right + (chart.scrollablePixelsX || 0);
                y1 = y2 = between(y1, axisTop, axisTop + axis.height);
            }
            e.path = skip && !force ?
                void 0 :
                chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1);
        });
        return evt.path;
    };
    /**
     * Internal function to get the tick positions of a linear axis to round
     * values like whole tens or every five.
     *
     * @function Highcharts.Axis#getLinearTickPositions
     *
     * @param {number} tickInterval
     * The normalized tick interval.
     *
     * @param {number} min
     * Axis minimum.
     *
     * @param {number} max
     * Axis maximum.
     *
     * @return {Array<number>}
     * An array of axis values where ticks should be placed.
     */
    Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) {
        var roundedMin = Axis_correctFloat(Math.floor(min / tickInterval) * tickInterval), roundedMax = Axis_correctFloat(Math.ceil(max / tickInterval) * tickInterval), tickPositions = [];
        var pos,
            lastPos,
            precision;
        // When the precision is higher than what we filter out in
        // correctFloat, skip it (#6183).
        if (Axis_correctFloat(roundedMin + tickInterval) === roundedMin) {
            precision = 20;
        }
        // For single points, add a tick regardless of the relative position
        // (#2662, #6274)
        if (this.single) {
            return [min];
        }
        // Populate the intermediate values
        pos = roundedMin;
        while (pos <= roundedMax) {
            // Place the tick on the rounded value
            tickPositions.push(pos);
            // Always add the raw tickInterval, not the corrected one.
            pos = Axis_correctFloat(pos + tickInterval, precision);
            // If the interval is not big enough in the current min - max range
            // to actually increase the loop variable, we need to break out to
            // prevent endless loop. Issue #619
            if (pos === lastPos) {
                break;
            }
            // Record the last value
            lastPos = pos;
        }
        return tickPositions;
    };
    /**
     * Resolve the new minorTicks/minorTickInterval options into the legacy
     * loosely typed minorTickInterval option.
     *
     * @function Highcharts.Axis#getMinorTickInterval
     *
     * @return {number|"auto"|null}
     * Legacy option
     */
    Axis.prototype.getMinorTickInterval = function () {
        var _a = this.options,
            minorTicks = _a.minorTicks,
            minorTickInterval = _a.minorTickInterval;
        if (minorTicks === true) {
            return Axis_pick(minorTickInterval, 'auto');
        }
        if (minorTicks === false) {
            return;
        }
        return minorTickInterval;
    };
    /**
     * Internal function to return the minor tick positions. For logarithmic
     * axes, the same logic as for major ticks is reused.
     *
     * @function Highcharts.Axis#getMinorTickPositions
     *
     * @return {Array<number>}
     * An array of axis values where ticks should be placed.
     */
    Axis.prototype.getMinorTickPositions = function () {
        var _a;
        var axis = this,
            options = axis.options,
            tickPositions = axis.tickPositions,
            minorTickInterval = axis.minorTickInterval,
            pointRangePadding = axis.pointRangePadding || 0,
            min = (axis.min || 0) - pointRangePadding, // #1498
            max = (axis.max || 0) + pointRangePadding, // #1498
            range = ((_a = axis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks) ?
                axis.brokenAxis.unitLength : max - min;
        var minorTickPositions = [],
            pos;
        // If minor ticks get too dense, they are hard to read, and may cause
        // long running script. So we don't draw them.
        if (range && range / minorTickInterval < axis.len / 3) { // #3875
            var logarithmic_1 = axis.logarithmic;
            if (logarithmic_1) {
                // For each interval in the major ticks, compute the minor ticks
                // separately.
                this.paddedTicks.forEach(function (_pos, i, paddedTicks) {
                    if (i) {
                        minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true));
                    }
                });
            }
            else if (axis.dateTime &&
                this.getMinorTickInterval() === 'auto') { // #1314
                minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek));
            }
            else {
                for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) {
                    // Very, very, tight grid lines (#5771)
                    if (pos === minorTickPositions[0]) {
                        break;
                    }
                    minorTickPositions.push(pos);
                }
            }
        }
        if (minorTickPositions.length !== 0) {
            axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330
        }
        return minorTickPositions;
    };
    /**
     * Adjust the min and max for the minimum range. Keep in mind that the
     * series data is not yet processed, so we don't have information on data
     * cropping and grouping, or updated `axis.pointRange` or
     * `series.pointRange`. The data can't be processed until we have finally
     * established min and max.
     *
     * @private
     * @function Highcharts.Axis#adjustForMinRange
     */
    Axis.prototype.adjustForMinRange = function () {
        var _a,
            _b,
            _c;
        var axis = this,
            options = axis.options,
            logarithmic = axis.logarithmic,
            time = axis.chart.time;
        var max = axis.max,
            min = axis.min,
            minRange = axis.minRange,
            zoomOffset,
            spaceAvailable,
            closestDataRange,
            minArgs,
            maxArgs;
        // Set the automatic minimum range based on the closest point distance
        if (axis.isXAxis &&
            typeof minRange === 'undefined' &&
            !logarithmic) {
            if (Axis_defined(options.min) ||
                Axis_defined(options.max) ||
                Axis_defined(options.floor) ||
                Axis_defined(options.ceiling)) {
                // Setting it to null, as opposed to undefined, signals we don't
                // run this block again as per the condition above.
                minRange = null;
            }
            else {
                // Find the closest distance between raw data points, as opposed
                // to closestPointRange that applies to processed points
                // (cropped and grouped)
                closestDataRange = Axis_getClosestDistance(axis.series.map(function (s) {
                    var xData = s.getColumn('x');
                    // If xIncrement, we only need to measure the two first
                    // points to get the distance. Saves processing time.
                    return s.xIncrement ? xData.slice(0, 2) : xData;
                })) || 0;
                minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin);
            }
        }
        // If minRange is exceeded, adjust
        if (Axis_isNumber(max) &&
            Axis_isNumber(min) &&
            Axis_isNumber(minRange) &&
            max - min < minRange) {
            spaceAvailable =
                axis.dataMax - axis.dataMin >=
                    minRange;
            zoomOffset = (minRange - max + min) / 2;
            // If min and max options have been set, don't go beyond it
            minArgs = [
                min - zoomOffset,
                (_a = time.parse(options.min)) !== null && _a !== void 0 ? _a : (min - zoomOffset)
            ];
            // If space is available, stay within the data range
            if (spaceAvailable) {
                minArgs[2] = logarithmic ?
                    logarithmic.log2lin(axis.dataMin) :
                    axis.dataMin;
            }
            min = Axis_arrayMax(minArgs);
            maxArgs = [
                min + minRange,
                (_b = time.parse(options.max)) !== null && _b !== void 0 ? _b : (min + minRange)
            ];
            // If space is available, stay within the data range
            if (spaceAvailable) {
                maxArgs[2] = logarithmic ?
                    logarithmic.log2lin(axis.dataMax) :
                    axis.dataMax;
            }
            max = Axis_arrayMin(maxArgs);
            // Now if the max is adjusted, adjust the min back
            if (max - min < minRange) {
                minArgs[0] = max - minRange;
                minArgs[1] = (_c = time.parse(options.min)) !== null && _c !== void 0 ? _c : (max - minRange);
                min = Axis_arrayMax(minArgs);
            }
        }
        // Record modified extremes
        axis.minRange = minRange;
        axis.min = min;
        axis.max = max;
    };
    /**
     * Find the closestPointRange across all series, including the single data
     * series.
     *
     * @private
     * @function Highcharts.Axis#getClosest
     */
    Axis.prototype.getClosest = function () {
        var closestSingleDistance,
            closestDistance;
        if (this.categories) {
            closestDistance = 1;
        }
        else {
            var singleXs_1 = [];
            this.series.forEach(function (series) {
                var seriesClosest = series.closestPointRange,
                    xData = series.getColumn('x');
                if (xData.length === 1) {
                    singleXs_1.push(xData[0]);
                }
                else if (series.sorted &&
                    Axis_defined(seriesClosest) &&
                    series.reserveSpace()) {
                    closestDistance = Axis_defined(closestDistance) ?
                        Math.min(closestDistance, seriesClosest) :
                        seriesClosest;
                }
            });
            if (singleXs_1.length) {
                singleXs_1.sort(function (a, b) { return a - b; });
                closestSingleDistance = Axis_getClosestDistance([singleXs_1]);
            }
        }
        if (closestSingleDistance && closestDistance) {
            return Math.min(closestSingleDistance, closestDistance);
        }
        return closestSingleDistance || closestDistance;
    };
    /**
     * When a point name is given and no x, search for the name in the existing
     * categories, or if categories aren't provided, search names or create a
     * new category (#2522).
     *
     * @private
     * @function Highcharts.Axis#nameToX
     *
     * @param {Highcharts.Point} point
     * The point to inspect.
     *
     * @return {number}
     * The X value that the point is given.
     */
    Axis.prototype.nameToX = function (point) {
        var explicitCategories = Axis_isArray(this.options.categories),
            names = explicitCategories ? this.categories : this.names;
        var nameX = point.options.x,
            x;
        point.series.requireSorting = false;
        if (!Axis_defined(nameX)) {
            nameX = this.uniqueNames && names ?
                (explicitCategories ?
                    names.indexOf(point.name) :
                    Axis_pick(names.keys[point.name], -1)) :
                point.series.autoIncrement();
        }
        if (nameX === -1) { // Not found in current categories
            if (!explicitCategories && names) {
                x = names.length;
            }
        }
        else if (Axis_isNumber(nameX)) {
            x = nameX;
        }
        // Write the last point's name to the names array
        if (typeof x !== 'undefined') {
            this.names[x] = point.name;
            // Backwards mapping is much faster than array searching (#7725)
            this.names.keys[point.name] = x;
        }
        else if (point.x) {
            x = point.x; // #17438
        }
        return x;
    };
    /**
     * When changes have been done to series data, update the axis.names.
     *
     * @private
     * @function Highcharts.Axis#updateNames
     */
    Axis.prototype.updateNames = function () {
        var axis = this,
            names = this.names,
            i = names.length;
        if (i > 0) {
            Object.keys(names.keys).forEach(function (key) {
                delete (names.keys)[key];
            });
            names.length = 0;
            this.minRange = this.userMinRange; // Reset
            (this.series || []).forEach(function (series) {
                // Reset incrementer (#5928)
                series.xIncrement = null;
                // When adding a series, points are not yet generated
                if (!series.points || series.isDirtyData) {
                    // When we're updating the series with data that is longer
                    // than it was, and cropThreshold is passed, we need to make
                    // sure that the axis.max is increased _before_ running the
                    // premature processData. Otherwise this early iteration of
                    // processData will crop the points to axis.max, and the
                    // names array will be too short (#5857).
                    axis.max = Math.max(axis.max || 0, series.dataTable.rowCount - 1);
                    series.processData();
                    series.generatePoints();
                }
                var xData = series.getColumn('x').slice();
                series.data.forEach(function (point, i) {
                    var x = xData[i];
                    if ((point === null || point === void 0 ? void 0 : point.options) &&
                        typeof point.name !== 'undefined' // #9562
                    ) {
                        x = axis.nameToX(point);
                        if (typeof x !== 'undefined' && x !== point.x) {
                            xData[i] = point.x = x;
                        }
                    }
                });
                series.dataTable.setColumn('x', xData);
            });
        }
    };
    /**
     * Update translation information.
     *
     * @private
     * @function Highcharts.Axis#setAxisTranslation
     *
     * @emits Highcharts.Axis#event:afterSetAxisTranslation
     */
    Axis.prototype.setAxisTranslation = function () {
        var axis = this,
            range = axis.max - axis.min,
            linkedParent = axis.linkedParent,
            hasCategories = !!axis.categories,
            isXAxis = axis.isXAxis;
        var pointRange = axis.axisPointRange || 0,
            closestPointRange,
            minPointOffset = 0,
            pointRangePadding = 0,
            ordinalCorrection,
            transA = axis.transA;
        // Adjust translation for padding. Y axis with categories need to go
        // through the same (#1784).
        if (isXAxis || hasCategories || pointRange) {
            // Get the closest points
            closestPointRange = axis.getClosest();
            if (linkedParent) {
                minPointOffset = linkedParent.minPointOffset;
                pointRangePadding = linkedParent.pointRangePadding;
            }
            else {
                axis.series.forEach(function (series) {
                    var seriesPointRange = hasCategories ?
                            1 :
                            (isXAxis ?
                                Axis_pick(series.options.pointRange,
                        closestPointRange, 0) :
                                (axis.axisPointRange || 0)), // #2806
                        pointPlacement = series.options.pointPlacement;
                    pointRange = Math.max(pointRange, seriesPointRange);
                    if (!axis.single || hasCategories) {
                        // TODO: series should internally set x- and y-
                        // pointPlacement to simplify this logic.
                        var isPointPlacementAxis = series.is('xrange') ?
                                !isXAxis :
                                isXAxis;
                        // The `minPointOffset` is the value padding to the left
                        // of the axis in order to make room for points with a
                        // pointRange, typically columns, or line/scatter points
                        // on a category axis. When the `pointPlacement` option
                        // is 'between' or 'on', this padding does not apply.
                        minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && Axis_isString(pointPlacement) ?
                            0 :
                            seriesPointRange / 2);
                        // Determine the total padding needed to the length of
                        // the axis to make room for the pointRange. If the
                        // series' pointPlacement is 'on', no padding is added.
                        pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ?
                            0 :
                            seriesPointRange);
                    }
                });
            }
            // Record minPointOffset and pointRangePadding
            ordinalCorrection = (axis.ordinal && axis.ordinal.slope && closestPointRange) ?
                axis.ordinal.slope / closestPointRange :
                1; // #988, #1853
            axis.minPointOffset = minPointOffset =
                minPointOffset * ordinalCorrection;
            axis.pointRangePadding =
                pointRangePadding = pointRangePadding * ordinalCorrection;
            // The `pointRange` is the width reserved for each point, like in a
            // column chart
            axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range);
            // The `closestPointRange` is the closest distance between points.
            // In columns it is mostly equal to pointRange, but in lines
            // pointRange is 0 while closestPointRange is some other value
            if (isXAxis && closestPointRange) {
                axis.closestPointRange = closestPointRange;
            }
        }
        // Secondary values
        axis.translationSlope = axis.transA = transA =
            axis.staticScale ||
                axis.len / ((range + pointRangePadding) || 1);
        // Translation addend
        axis.transB = axis.horiz ? axis.left : axis.bottom;
        axis.minPixelPadding = transA * minPointOffset;
        Axis_fireEvent(this, 'afterSetAxisTranslation');
    };
    /**
     * @private
     * @function Highcharts.Axis#minFromRange
     */
    Axis.prototype.minFromRange = function () {
        var _a = this,
            max = _a.max,
            min = _a.min;
        return Axis_isNumber(max) && Axis_isNumber(min) && max - min || void 0;
    };
    /**
     * Set the tick positions to round values and optionally extend the extremes
     * to the nearest tick.
     *
     * @private
     * @function Highcharts.Axis#setTickInterval
     *
     * @param {boolean} secondPass
     * TO-DO: parameter description
     *
     * @emits Highcharts.Axis#event:foundExtremes
     */
    Axis.prototype.setTickInterval = function (secondPass) {
        var _a,
            _b,
            _c,
            _d;
        var axis = this,
            categories = axis.categories,
            chart = axis.chart,
            dataMax = axis.dataMax,
            dataMin = axis.dataMin,
            dateTime = axis.dateTime,
            isXAxis = axis.isXAxis,
            logarithmic = axis.logarithmic,
            options = axis.options,
            softThreshold = axis.softThreshold,
            time = chart.time,
            threshold = Axis_isNumber(axis.threshold) ? axis.threshold : void 0,
            minRange = axis.minRange || 0,
            ceiling = options.ceiling,
            floor = options.floor,
            linkedTo = options.linkedTo,
            softMax = options.softMax,
            softMin = options.softMin,
            linkedParent = Axis_isNumber(linkedTo) && ((_a = chart[axis.coll]) === null || _a === void 0 ? void 0 : _a[linkedTo]),
            tickPixelIntervalOption = options.tickPixelInterval;
        var maxPadding = options.maxPadding,
            minPadding = options.minPadding,
            range = 0,
            linkedParentExtremes, 
            // Only non-negative tickInterval is valid, #12961
            tickIntervalOption = Axis_isNumber(options.tickInterval) && options.tickInterval >= 0 ?
                options.tickInterval : void 0,
            thresholdMin,
            thresholdMax,
            hardMin,
            hardMax;
        if (!dateTime && !categories && !linkedParent) {
            this.getTickAmount();
        }
        // Min or max set either by zooming/setExtremes or initial options
        hardMin = Axis_pick(axis.userMin, time.parse(options.min));
        hardMax = Axis_pick(axis.userMax, time.parse(options.max));
        // Linked axis gets the extremes from the parent axis
        if (linkedParent) {
            axis.linkedParent = linkedParent;
            linkedParentExtremes = linkedParent.getExtremes();
            axis.min = Axis_pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);
            axis.max = Axis_pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);
            if (this.type !== linkedParent.type) {
                // Can't link axes of different type
                Axis_error(11, true, chart);
            }
            // Initial min and max from the extreme data values
        }
        else {
            // Adjust to hard threshold
            if (softThreshold &&
                Axis_defined(threshold) &&
                Axis_isNumber(dataMax) &&
                Axis_isNumber(dataMin)) {
                if (dataMin >= threshold) {
                    thresholdMin = threshold;
                    minPadding = 0;
                }
                else if (dataMax <= threshold) {
                    thresholdMax = threshold;
                    maxPadding = 0;
                }
            }
            axis.min = Axis_pick(hardMin, thresholdMin, dataMin);
            axis.max = Axis_pick(hardMax, thresholdMax, dataMax);
        }
        if (Axis_isNumber(axis.max) && Axis_isNumber(axis.min)) {
            if (logarithmic) {
                if (axis.positiveValuesOnly &&
                    !secondPass &&
                    Math.min(axis.min, Axis_pick(dataMin, axis.min)) <= 0) { // #978
                    // Can't plot negative values on log axis
                    Axis_error(10, true, chart);
                }
                // The correctFloat cures #934, float errors on full tens. But
                // it was too aggressive for #4360 because of conversion back to
                // lin, therefore use precision 15.
                axis.min = Axis_correctFloat(logarithmic.log2lin(axis.min), 16);
                axis.max = Axis_correctFloat(logarithmic.log2lin(axis.max), 16);
            }
            // Handle zoomed range
            if (axis.range && Axis_isNumber(dataMin)) {
                // #618, #6773:
                axis.userMin = axis.min = hardMin = Math.max(dataMin, axis.minFromRange() || 0);
                axis.userMax = hardMax = axis.max;
                axis.range = void 0; // Don't use it when running setExtremes
            }
        }
        // Hook for Highcharts Stock Scroller and bubble axis padding
        Axis_fireEvent(axis, 'foundExtremes');
        // Adjust min and max for the minimum range
        axis.adjustForMinRange();
        if (Axis_isNumber(axis.min) && Axis_isNumber(axis.max)) {
            // Handle options for floor, ceiling, softMin and softMax (#6359)
            if (!Axis_isNumber(axis.userMin) &&
                Axis_isNumber(softMin) &&
                softMin < axis.min) {
                axis.min = hardMin = softMin; // #6894
            }
            if (!Axis_isNumber(axis.userMax) &&
                Axis_isNumber(softMax) &&
                softMax > axis.max) {
                axis.max = hardMax = softMax; // #6894
            }
            // Pad the values to get clear of the chart's edges. To avoid
            // tickInterval taking the padding into account, we do this after
            // computing tick interval (#1337).
            if (!categories &&
                !axis.axisPointRange &&
                !((_b = axis.stacking) === null || _b === void 0 ? void 0 : _b.usePercentage) &&
                !linkedParent) {
                range = axis.max - axis.min;
                if (range) {
                    if (!Axis_defined(hardMin) && minPadding) {
                        axis.min -= range * minPadding;
                    }
                    if (!Axis_defined(hardMax) && maxPadding) {
                        axis.max += range * maxPadding;
                    }
                }
            }
            if (!Axis_isNumber(axis.userMin) && Axis_isNumber(floor)) {
                axis.min = Math.max(axis.min, floor);
            }
            if (!Axis_isNumber(axis.userMax) && Axis_isNumber(ceiling)) {
                axis.max = Math.min(axis.max, ceiling);
            }
            // When the threshold is soft, adjust the extreme value only if the
            // data extreme and the padded extreme land on either side of the
            // threshold. For example, a series of [0, 1, 2, 3] would make the
            // yAxis add a tick for -1 because of the default `minPadding` and
            // `startOnTick` options. This is prevented by the `softThreshold`
            // option.
            if (softThreshold &&
                Axis_isNumber(dataMin) &&
                Axis_isNumber(dataMax)) {
                var numThreshold = threshold || 0;
                if (!Axis_defined(hardMin) &&
                    axis.min < numThreshold &&
                    dataMin >= numThreshold) {
                    axis.min = options.minRange ?
                        Math.min(numThreshold, axis.max - minRange) :
                        numThreshold;
                }
                else if (!Axis_defined(hardMax) &&
                    axis.max > numThreshold &&
                    dataMax <= numThreshold) {
                    axis.max = options.minRange ?
                        Math.max(numThreshold, axis.min + minRange) :
                        numThreshold;
                }
            }
            // If min is bigger than highest, or if max less than lowest value,
            // the chart should not render points. (#14417)
            if (!chart.polar && axis.min > axis.max) {
                if (Axis_defined(options.min)) {
                    axis.max = axis.min;
                }
                else if (Axis_defined(options.max)) {
                    axis.min = axis.max;
                }
            }
            range = axis.max - axis.min;
        }
        // Get tickInterval
        if (axis.min === axis.max ||
            !Axis_isNumber(axis.min) ||
            !Axis_isNumber(axis.max)) {
            axis.tickInterval = 1;
        }
        else if (linkedParent &&
            !tickIntervalOption &&
            tickPixelIntervalOption === linkedParent.options.tickPixelInterval) {
            axis.tickInterval = tickIntervalOption = linkedParent.tickInterval;
        }
        else {
            axis.tickInterval = Axis_pick(tickIntervalOption, this.tickAmount ?
                range / Math.max(this.tickAmount - 1, 1) :
                void 0, 
            // For categorized axis, 1 is default, for linear axis use
            // tickPix
            categories ?
                1 :
                // Don't let it be more than the data range
                range * tickPixelIntervalOption /
                    Math.max(axis.len, tickPixelIntervalOption));
        }
        // Now we're finished detecting min and max, crop and group series data.
        // This is in turn needed in order to find tick positions in ordinal
        // axes.
        if (isXAxis && !secondPass) {
            var hasExtremesChanged_1 = axis.min !== ((_c = axis.old) === null || _c === void 0 ? void 0 : _c.min) ||
                    axis.max !== ((_d = axis.old) === null || _d === void 0 ? void 0 : _d.max);
            // First process all series assigned to that axis.
            axis.series.forEach(function (series) {
                var _a;
                // Allows filtering out points outside the plot area.
                series.forceCrop = (_a = series.forceCropping) === null || _a === void 0 ? void 0 : _a.call(series);
                series.processData(hasExtremesChanged_1);
            });
            // Then apply grouping if needed. The hasExtremesChanged helps to
            // decide if the data grouping should be skipped in the further
            // calculations #16319.
            Axis_fireEvent(this, 'postProcessData', { hasExtremesChanged: hasExtremesChanged_1 });
        }
        // Set the translation factor used in translate function
        axis.setAxisTranslation();
        // Hook for ordinal axes and radial axes
        Axis_fireEvent(this, 'initialAxisTranslation');
        // In column-like charts, don't cramp in more ticks than there are
        // points (#1943, #4184)
        if (axis.pointRange && !tickIntervalOption) {
            axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval);
        }
        // Before normalizing the tick interval, handle minimum tick interval.
        // This applies only if tickInterval is not defined.
        var minTickInterval = Axis_pick(options.minTickInterval, 
            // In datetime axes, don't go below the data interval, except when
            // there are scatter-like series involved (#13369).
            dateTime &&
                !axis.series.some(function (s) { return !s.sorted; }) ?
                axis.closestPointRange : 0);
        if (!tickIntervalOption && axis.tickInterval < minTickInterval) {
            axis.tickInterval = minTickInterval;
        }
        // For linear axes, normalize the interval
        if (!dateTime && !logarithmic && !tickIntervalOption) {
            axis.tickInterval = getNormalizedTickInterval(axis, axis.tickInterval);
        }
        // Prevent ticks from getting so close that we can't draw the labels
        if (!this.tickAmount) {
            axis.tickInterval = axis.unsquish();
        }
        this.setTickPositions();
    };
    /**
     * Now we have computed the normalized tickInterval, get the tick positions.
     *
     * @private
     * @function Highcharts.Axis#setTickPositions
     *
     * @emits Highcharts.Axis#event:afterSetTickPositions
     */
    Axis.prototype.setTickPositions = function () {
        var _a,
            _b;
        var axis = this,
            options = this.options,
            tickPositionsOption = options.tickPositions,
            tickPositioner = options.tickPositioner,
            minorTickIntervalOption = this.getMinorTickInterval(),
            allowEndOnTick = !this.isPanning,
            startOnTick = allowEndOnTick && options.startOnTick,
            endOnTick = allowEndOnTick && options.endOnTick;
        var tickPositions = [],
            tickPositionerResult;
        // Set the tickmarkOffset
        this.tickmarkOffset = (this.categories &&
            options.tickmarkPlacement === 'between' &&
            this.tickInterval === 1) ? 0.5 : 0; // #3202
        // When there is only one point, or all points have the same value on
        // this axis, then min and max are equal and tickPositions.length is 0
        // or 1. In this case, add some padding in order to center the point,
        // but leave it with one tick. #1337.
        this.single =
            this.min === this.max &&
                Axis_defined(this.min) &&
                !this.tickAmount &&
                (
                // Data is on integer (#6563)
                this.min % 1 === 0 ||
                    // Between integers and decimals are not allowed (#6274)
                    options.allowDecimals !== false);
        /**
         * Contains the current positions that are laid out on the axis. The
         * positions are numbers in terms of axis values. In a category axis
         * they are integers, in a datetime axis they are also integers, but
         * designating milliseconds.
         *
         * This property is read only - for modifying the tick positions, use
         * the `tickPositioner` callback or [axis.tickPositions(
         * https://api.highcharts.com/highcharts/xAxis.tickPositions) option
         * instead.
         *
         * @name Highcharts.Axis#tickPositions
         * @type {Highcharts.AxisTickPositionsArray|undefined}
         */
        if (tickPositionsOption) {
            // Find the tick positions. Work on a copy (#1565)
            tickPositions = tickPositionsOption.slice();
        }
        else if (Axis_isNumber(this.min) && Axis_isNumber(this.max)) {
            // Too many ticks (#6405). Create a friendly warning and provide two
            // ticks so at least we can show the data series.
            if (!((_a = axis.ordinal) === null || _a === void 0 ? void 0 : _a.positions) &&
                ((this.max - this.min) /
                    this.tickInterval >
                    Math.max(2 * this.len, 200))) {
                tickPositions = [this.min, this.max];
                Axis_error(19, false, this.chart);
            }
            else if (axis.dateTime) {
                tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, (_b = axis.ordinal) === null || _b === void 0 ? void 0 : _b.positions, this.closestPointRange, true);
            }
            else if (axis.logarithmic) {
                tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max);
            }
            else {
                var startingTickInterval = this.tickInterval;
                var adjustedTickInterval = startingTickInterval;
                while (adjustedTickInterval <= startingTickInterval * 2) {
                    tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max);
                    // If there are more tick positions than the set tickAmount,
                    // increase the tickInterval and continue until it fits.
                    // (#17100)
                    if (this.tickAmount &&
                        tickPositions.length > this.tickAmount) {
                        this.tickInterval = getNormalizedTickInterval(this, adjustedTickInterval *= 1.1);
                    }
                    else {
                        break;
                    }
                }
            }
            // Too dense ticks, keep only the first and last (#4477)
            if (tickPositions.length > this.len) {
                tickPositions = [
                    tickPositions[0],
                    tickPositions[tickPositions.length - 1]
                ];
                // Reduce doubled value (#7339)
                if (tickPositions[0] === tickPositions[1]) {
                    tickPositions.length = 1;
                }
            }
            // Run the tick positioner callback, that allows modifying auto tick
            // positions.
            if (tickPositioner) {
                // Make it available to the positioner
                this.tickPositions = tickPositions;
                tickPositionerResult = tickPositioner.apply(axis, [this.min, this.max]);
                if (tickPositionerResult) {
                    tickPositions = tickPositionerResult;
                }
            }
        }
        this.tickPositions = tickPositions;
        // Get minorTickInterval
        this.minorTickInterval =
            minorTickIntervalOption === 'auto' && this.tickInterval ?
                this.tickInterval / options.minorTicksPerMajor :
                minorTickIntervalOption;
        // Reset min/max or remove extremes based on start/end on tick
        this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor
        this.trimTicks(tickPositions, startOnTick, endOnTick);
        if (!this.isLinked && Axis_isNumber(this.min) && Axis_isNumber(this.max)) {
            // Substract half a unit (#2619, #2846, #2515, #3390), but not in
            // case of multiple ticks (#6897)
            if (this.single &&
                tickPositions.length < 2 &&
                !this.categories &&
                !this.series.some(function (s) {
                    return (s.is('heatmap') && s.options.pointPlacement === 'between');
                })) {
                this.min -= 0.5;
                this.max += 0.5;
            }
            if (!tickPositionsOption && !tickPositionerResult) {
                this.adjustTickAmount();
            }
        }
        Axis_fireEvent(this, 'afterSetTickPositions');
    };
    /**
     * Handle startOnTick and endOnTick by either adapting to padding min/max or
     * rounded min/max. Also handle single data points.
     *
     * @private
     * @function Highcharts.Axis#trimTicks
     *
     * @param {Array<number>} tickPositions
     * TO-DO: parameter description
     *
     * @param {boolean} [startOnTick]
     * TO-DO: parameter description
     *
     * @param {boolean} [endOnTick]
     * TO-DO: parameter description
     */
    Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) {
        var roundedMin = tickPositions[0],
            roundedMax = tickPositions[tickPositions.length - 1],
            minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716)
            Axis_fireEvent(this, 'trimTicks');
        if (!this.isLinked) {
            if (startOnTick && roundedMin !== -Infinity) { // #6502
                this.min = roundedMin;
            }
            else {
                while (this.min - minPointOffset > tickPositions[0]) {
                    tickPositions.shift();
                }
            }
            if (endOnTick) {
                this.max = roundedMax;
            }
            else {
                while (this.max + minPointOffset <
                    tickPositions[tickPositions.length - 1]) {
                    tickPositions.pop();
                }
            }
            // If no tick are left, set one tick in the middle (#3195)
            if (tickPositions.length === 0 &&
                Axis_defined(roundedMin) &&
                !this.options.tickPositions) {
                tickPositions.push((roundedMax + roundedMin) / 2);
            }
        }
    };
    /**
     * Check if there are multiple axes in the same pane.
     *
     * @private
     * @function Highcharts.Axis#alignToOthers
     *
     * @return {boolean|undefined}
     * True if there are other axes.
     */
    Axis.prototype.alignToOthers = function () {
        var axis = this,
            chart = axis.chart,
            alignedAxes = [this],
            options = axis.options,
            chartOptions = chart.options.chart,
            alignThresholds = (this.coll === 'yAxis' &&
                chartOptions.alignThresholds),
            thresholdAlignments = [];
        var hasOther;
        axis.thresholdAlignment = void 0;
        if ((
        // Only if alignTicks or alignThresholds is true
        (chartOptions.alignTicks !== false && options.alignTicks) ||
            alignThresholds) &&
            // Disabled when startOnTick or endOnTick are false (#7604)
            options.startOnTick !== false &&
            options.endOnTick !== false &&
            // Don't try to align ticks on a log axis, they are not evenly
            // spaced (#6021)
            !axis.logarithmic) {
            // Get a key identifying which pane the axis belongs to
            var getKey_1 = function (axis) {
                    var horiz = axis.horiz,
                options = axis.options;
                return [
                    horiz ? options.left : options.top,
                    options.width,
                    options.height,
                    options.pane
                ].join(',');
            };
            var thisKey_1 = getKey_1(this);
            chart[this.coll].forEach(function (otherAxis) {
                var series = otherAxis.series;
                if (
                // #4442
                series.length &&
                    series.some(function (s) { return s.visible; }) &&
                    otherAxis !== axis &&
                    getKey_1(otherAxis) === thisKey_1) {
                    hasOther = true; // #4201
                    alignedAxes.push(otherAxis);
                }
            });
        }
        if (hasOther && alignThresholds) {
            // Handle alignThresholds. The `thresholdAlignments` array keeps
            // records of where each axis in the group wants its threshold, from
            // 0 which is on `axis.min`, to 1 which is on `axis.max`.
            alignedAxes.forEach(function (otherAxis) {
                var threshAlign = otherAxis.getThresholdAlignment(axis);
                if (Axis_isNumber(threshAlign)) {
                    thresholdAlignments.push(threshAlign);
                }
            });
            // For each of the axes in the group, record the average
            // `thresholdAlignment`.
            var thresholdAlignment_1 = thresholdAlignments.length > 1 ?
                    thresholdAlignments.reduce(function (sum,
                n) { return (sum += n); }, 0) / thresholdAlignments.length :
                    void 0;
            alignedAxes.forEach(function (axis) {
                axis.thresholdAlignment = thresholdAlignment_1;
            });
        }
        return hasOther;
    };
    /**
     * Where the axis wants its threshold, from 0 which is on `axis.min`, to 1 which
     * is on `axis.max`.
     *
     * @private
     * @function Highcharts.Axis#getThresholdAlignment
     */
    Axis.prototype.getThresholdAlignment = function (callerAxis) {
        if (!Axis_isNumber(this.dataMin) ||
            (this !== callerAxis &&
                this.series.some(function (s) { return (s.isDirty || s.isDirtyData); }))) {
            this.getSeriesExtremes();
        }
        if (Axis_isNumber(this.threshold)) {
            var thresholdAlignment = Axis_clamp(((this.threshold - (this.dataMin || 0)) /
                    ((this.dataMax || 0) - (this.dataMin || 0))), 0, 1);
            if (this.options.reversed) {
                thresholdAlignment = 1 - thresholdAlignment;
            }
            return thresholdAlignment;
        }
    };
    /**
     * Find the max ticks of either the x and y axis collection, and record it
     * in `this.tickAmount`.
     *
     * @private
     * @function Highcharts.Axis#getTickAmount
     */
    Axis.prototype.getTickAmount = function () {
        var axis = this,
            options = this.options,
            tickPixelInterval = options.tickPixelInterval;
        var tickAmount = options.tickAmount;
        if (!Axis_defined(options.tickInterval) &&
            !tickAmount &&
            this.len < tickPixelInterval &&
            !this.isRadial &&
            !axis.logarithmic &&
            options.startOnTick &&
            options.endOnTick) {
            tickAmount = 2;
        }
        if (!tickAmount && this.alignToOthers()) {
            // Add 1 because 4 tick intervals require 5 ticks (including first
            // and last)
            tickAmount = Math.ceil(this.len / tickPixelInterval) + 1;
        }
        // For tick amounts of 2 and 3, compute five ticks and remove the
        // intermediate ones. This prevents the axis from adding ticks that are
        // too far away from the data extremes.
        if (tickAmount < 4) {
            this.finalTickAmt = tickAmount;
            tickAmount = 5;
        }
        this.tickAmount = tickAmount;
    };
    /**
     * When using multiple axes, adjust the number of ticks to match the highest
     * number of ticks in that group.
     *
     * @private
     * @function Highcharts.Axis#adjustTickAmount
     */
    Axis.prototype.adjustTickAmount = function () {
        var axis = this,
            finalTickAmt = axis.finalTickAmt,
            max = axis.max,
            min = axis.min,
            options = axis.options,
            tickPositions = axis.tickPositions,
            tickAmount = axis.tickAmount,
            thresholdAlignment = axis.thresholdAlignment,
            currentTickAmount = tickPositions === null || tickPositions === void 0 ? void 0 : tickPositions.length,
            threshold = Axis_pick(axis.threshold,
            axis.softThreshold ? 0 : null);
        var len,
            i,
            tickInterval = axis.tickInterval,
            thresholdTickIndex;
        var 
            // Extend the tickPositions by appending a position
            append = function () { return tickPositions.push(Axis_correctFloat(tickPositions[tickPositions.length - 1] +
                tickInterval)); }, 
            // Extend the tickPositions by prepending a position
            prepend = function () { return tickPositions.unshift(Axis_correctFloat(tickPositions[0] - tickInterval)); };
        // If `thresholdAlignment` is a number, it means the `alignThresholds`
        // option is true. The `thresholdAlignment` is a scalar value between 0
        // and 1 for where the threshold should be relative to `axis.min` and
        // `axis.max`. Now that we know the tick amount, convert this to the
        // tick index. Unless `thresholdAlignment` is exactly 0 or 1, avoid the
        // first or last tick because that would lead to series being clipped.
        if (Axis_isNumber(thresholdAlignment)) {
            thresholdTickIndex = thresholdAlignment < 0.5 ?
                Math.ceil(thresholdAlignment * (tickAmount - 1)) :
                Math.floor(thresholdAlignment * (tickAmount - 1));
            if (options.reversed) {
                thresholdTickIndex = tickAmount - 1 - thresholdTickIndex;
            }
        }
        if (axis.hasData() && Axis_isNumber(min) && Axis_isNumber(max)) { // #14769
            // Adjust extremes and translation to the modified tick positions
            var adjustExtremes = function () {
                    axis.transA *= (currentTickAmount - 1) / (tickAmount - 1);
                // Do not crop when ticks are not extremes (#9841)
                axis.min = options.startOnTick ?
                    tickPositions[0] :
                    Math.min(min, tickPositions[0]);
                axis.max = options.endOnTick ?
                    tickPositions[tickPositions.length - 1] :
                    Math.max(max, tickPositions[tickPositions.length - 1]);
            };
            // When the axis is subject to the alignThresholds option. Use
            // axis.threshold because the local threshold includes the
            // `softThreshold`.
            if (Axis_isNumber(thresholdTickIndex) && Axis_isNumber(axis.threshold)) {
                // Throw away the previously computed tickPositions and start
                // from scratch with only the threshold itself, then add ticks
                // below the threshold first, then fill up above the threshold.
                // If we are not able to fill up to axis.max, double the
                // tickInterval and run again.
                while (tickPositions[thresholdTickIndex] !== threshold ||
                    tickPositions.length !== tickAmount ||
                    tickPositions[0] > min ||
                    tickPositions[tickPositions.length - 1] < max) {
                    tickPositions.length = 0;
                    tickPositions.push(axis.threshold);
                    while (tickPositions.length < tickAmount) {
                        if (
                        // Start by prepending positions until the threshold
                        // is at the required index...
                        tickPositions[thresholdTickIndex] === void 0 ||
                            tickPositions[thresholdTickIndex] > axis.threshold) {
                            prepend();
                        }
                        else {
                            // ... then append positions until we have the
                            // required length
                            append();
                        }
                    }
                    // Safety vent
                    if (tickInterval > axis.tickInterval * 8) {
                        break;
                    }
                    tickInterval *= 2;
                }
                adjustExtremes();
            }
            else if (currentTickAmount < tickAmount) {
                while (tickPositions.length < tickAmount) {
                    // Extend evenly for both sides unless we're on the
                    // threshold (#3965)
                    if (tickPositions.length % 2 || min === threshold) {
                        append();
                    }
                    else {
                        prepend();
                    }
                }
                adjustExtremes();
            }
            // The finalTickAmt property is set in getTickAmount
            if (Axis_defined(finalTickAmt)) {
                i = len = tickPositions.length;
                while (i--) {
                    if (
                    // Remove every other tick
                    (finalTickAmt === 3 && i % 2 === 1) ||
                        // Remove all but first and last
                        (finalTickAmt <= 2 && i > 0 && i < len - 1)) {
                        tickPositions.splice(i, 1);
                    }
                }
                axis.finalTickAmt = void 0;
            }
        }
    };
    /**
     * Set the scale based on data min and max, user set min and max or options.
     *
     * @private
     * @function Highcharts.Axis#setScale
     *
     * @emits Highcharts.Axis#event:afterSetScale
     */
    Axis.prototype.setScale = function () {
        var _a,
            _b;
        var axis = this,
            coll = axis.coll,
            stacking = axis.stacking;
        var isDirtyData = false,
            isXAxisDirty = false;
        axis.series.forEach(function (series) {
            isDirtyData = isDirtyData || series.isDirtyData || series.isDirty;
            // When x axis is dirty, we need new data extremes for y as
            // well:
            isXAxisDirty = (isXAxisDirty ||
                (series.xAxis && series.xAxis.isDirty) ||
                false);
        });
        // Set the new axisLength
        axis.setAxisSize();
        var isDirtyAxisLength = axis.len !== (axis.old && axis.old.len);
        // Do we really need to go through all this?
        if (isDirtyAxisLength ||
            isDirtyData ||
            isXAxisDirty ||
            axis.isLinked ||
            axis.forceRedraw ||
            axis.userMin !== (axis.old && axis.old.userMin) ||
            axis.userMax !== (axis.old && axis.old.userMax) ||
            axis.alignToOthers()) {
            if (stacking && coll === 'yAxis') {
                stacking.buildStacks();
            }
            axis.forceRedraw = false;
            // #18066 delete minRange property to ensure that it will be
            // calculated again after dirty data in series
            if (!axis.userMinRange) {
                axis.minRange = void 0;
            }
            // Get data extremes if needed
            axis.getSeriesExtremes();
            // Get fixed positions based on tickInterval
            axis.setTickInterval();
            if (stacking && coll === 'xAxis') {
                stacking.buildStacks();
            }
            // Mark as dirty if it is not already set to dirty and extremes have
            // changed. #595.
            if (!axis.isDirty) {
                axis.isDirty =
                    isDirtyAxisLength ||
                        axis.min !== ((_a = axis.old) === null || _a === void 0 ? void 0 : _a.min) ||
                        axis.max !== ((_b = axis.old) === null || _b === void 0 ? void 0 : _b.max);
            }
        }
        else if (stacking) {
            stacking.cleanStacks();
        }
        // Recalculate all extremes object when the data has changed. It is
        // required when vertical panning is enabled.
        if (isDirtyData) {
            delete axis.allExtremes;
        }
        Axis_fireEvent(this, 'afterSetScale');
    };
    /**
     * Set the minimum and maximum of the axes after render time. If the
     * `startOnTick` and `endOnTick` options are true, the minimum and maximum
     * values are rounded off to the nearest tick. To prevent this, these
     * options can be set to false before calling setExtremes. Also, setExtremes
     * will not allow a range lower than the `minRange` option, which by default
     * is the range of five points.
     *
     * @sample highcharts/members/axis-setextremes/
     *         Set extremes from a button
     * @sample highcharts/members/axis-setextremes-datetime/
     *         Set extremes on a datetime axis
     * @sample highcharts/members/axis-setextremes-off-ticks/
     *         Set extremes off ticks
     * @sample stock/members/axis-setextremes/
     *         Set extremes in Highcharts Stock
     *
     * @function Highcharts.Axis#setExtremes
     *
     * @param {number|string} [newMin]
     * The new minimum value. For datetime axes, date strings are accepted.
     *
     * @param {number|string} [newMax]
     * The new maximum value. For datetime axes, date strings are accepted.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart or wait for an explicit call to
     * {@link Highcharts.Chart#redraw}
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
     * Enable or modify animations.
     *
     * @param {*} [eventArguments]
     * Arguments to be accessed in event handler.
     *
     * @emits Highcharts.Axis#event:setExtremes
     */
    Axis.prototype.setExtremes = function (min, max, redraw, animation, eventArguments) {
        var _this = this;
        if (redraw === void 0) { redraw = true; }
        var chart = this.chart;
        this.series.forEach(function (serie) {
            delete serie.kdTree;
        });
        min = chart.time.parse(min);
        max = chart.time.parse(max);
        // Extend the arguments with min and max
        eventArguments = Axis_extend(eventArguments, { min: min, max: max });
        // Fire the event
        Axis_fireEvent(this, 'setExtremes', eventArguments, function (e) {
            _this.userMin = e.min;
            _this.userMax = e.max;
            _this.eventArgs = e;
            if (redraw) {
                chart.redraw(animation);
            }
        });
    };
    /**
     * Update the axis metrics.
     *
     * @private
     * @function Highcharts.Axis#setAxisSize
     */
    Axis.prototype.setAxisSize = function () {
        var chart = this.chart,
            options = this.options, 
            // [top, right, bottom, left]
            offsets = options.offsets || [0, 0, 0, 0],
            horiz = this.horiz, 
            // Check for percentage based input values. Rounding fixes problems
            // with column overflow and plot line filtering (#4898, #4899)
            width = this.width = Math.round(Axis_relativeLength(Axis_pick(options.width,
            chart.plotWidth - offsets[3] + offsets[1]),
            chart.plotWidth)),
            height = this.height = Math.round(Axis_relativeLength(Axis_pick(options.height,
            chart.plotHeight - offsets[0] + offsets[2]),
            chart.plotHeight)),
            top = this.top = Math.round(Axis_relativeLength(Axis_pick(options.top,
            chart.plotTop + offsets[0]),
            chart.plotHeight,
            chart.plotTop)),
            left = this.left = Math.round(Axis_relativeLength(Axis_pick(options.left,
            chart.plotLeft + offsets[3]),
            chart.plotWidth,
            chart.plotLeft));
        // Expose basic values to use in Series object and navigator
        this.bottom = chart.chartHeight - height - top;
        this.right = chart.chartWidth - width - left;
        // Direction agnostic properties
        this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905
        /**
         * The position of the axis in terms of pixels, compared to the chart
         * edge. In a horizontal axis it is the same as `chart.plotLeft` unless
         * the axis is explicitly positioned, and in a default vertical axis it
         * is the same as `chart.plotTop`.
         *
         * @name Highcharts.Axis#pos
         * @type {number}
         */
        this.pos = horiz ? left : top; // Distance from SVG origin
    };
    /**
     * Get the current extremes for the axis.
     *
     * @sample highcharts/members/axis-getextremes/
     *         Report extremes by click on a button
     *
     * @function Highcharts.Axis#getExtremes
     *
     * @return {Highcharts.ExtremesObject}
     * An object containing extremes information.
     */
    Axis.prototype.getExtremes = function () {
        var axis = this,
            log = axis.logarithmic;
        return {
            min: log ?
                Axis_correctFloat(log.lin2log(axis.min)) :
                axis.min,
            max: log ?
                Axis_correctFloat(log.lin2log(axis.max)) :
                axis.max,
            dataMin: axis.dataMin,
            dataMax: axis.dataMax,
            userMin: axis.userMin,
            userMax: axis.userMax
        };
    };
    /**
     * Get the zero plane either based on zero or on the min or max value.
     * Used in bar and area plots.
     *
     * @function Highcharts.Axis#getThreshold
     *
     * @param {number} threshold
     * The threshold in axis values.
     *
     * @return {number}
     * The translated threshold position in terms of pixels, and corrected to
     * stay within the axis bounds.
     */
    Axis.prototype.getThreshold = function (threshold) {
        var axis = this,
            log = axis.logarithmic,
            realMin = log ? log.lin2log(axis.min) : axis.min,
            realMax = log ? log.lin2log(axis.max) : axis.max;
        if (threshold === null || threshold === -Infinity) {
            threshold = realMin;
        }
        else if (threshold === Infinity) {
            threshold = realMax;
        }
        else if (realMin > threshold) {
            threshold = realMin;
        }
        else if (realMax < threshold) {
            threshold = realMax;
        }
        return axis.translate(threshold, 0, 1, 0, 1);
    };
    /**
     * Compute auto alignment for the axis label based on which side the axis is
     * on and the given rotation for the label.
     *
     * @private
     * @function Highcharts.Axis#autoLabelAlign
     *
     * @param {number} rotation
     * The rotation in degrees as set by either the `rotation` or `autoRotation`
     * options.
     *
     * @return {Highcharts.AlignValue}
     * Can be `"center"`, `"left"` or `"right"`.
     */
    Axis.prototype.autoLabelAlign = function (rotation) {
        var angle = (Axis_pick(rotation, 0) - (this.side * 90) + 720) % 360,
            evt = { align: 'center' };
        Axis_fireEvent(this, 'autoLabelAlign', evt, function (e) {
            if (angle > 15 && angle < 165) {
                e.align = 'right';
            }
            else if (angle > 195 && angle < 345) {
                e.align = 'left';
            }
        });
        return evt.align;
    };
    /**
     * Get the tick length and width for the axis based on axis options.
     *
     * @private
     * @function Highcharts.Axis#tickSize
     *
     * @param {string} [prefix]
     * 'tick' or 'minorTick'
     *
     * @return {Array<number,number>|undefined}
     * An array of tickLength and tickWidth
     */
    Axis.prototype.tickSize = function (prefix) {
        var options = this.options,
            tickWidth = Axis_pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], 
            // Default to 1 on linear and datetime X axes
            prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0);
        var tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'],
            tickSize;
        if (tickWidth && tickLength) {
            // Negate the length
            if (options[prefix + 'Position'] === 'inside') {
                tickLength = -tickLength;
            }
            tickSize = [tickLength, tickWidth];
        }
        var e = { tickSize: tickSize };
        Axis_fireEvent(this, 'afterTickSize', e);
        return e.tickSize;
    };
    /**
     * Return the size of the labels.
     *
     * @private
     * @function Highcharts.Axis#labelMetrics
     */
    Axis.prototype.labelMetrics = function () {
        var renderer = this.chart.renderer,
            ticks = this.ticks,
            tick = ticks[Object.keys(ticks)[0]] || {};
        return this.chart.renderer.fontMetrics(tick.label ||
            tick.movedLabel ||
            renderer.box);
    };
    /**
     * Prevent the ticks from getting so close we can't draw the labels. On a
     * horizontal axis, this is handled by rotating the labels, removing ticks
     * and adding ellipsis. On a vertical axis remove ticks and add ellipsis.
     *
     * @private
     * @function Highcharts.Axis#unsquish
     */
    Axis.prototype.unsquish = function () {
        var labelOptions = this.options.labels,
            padding = labelOptions.padding || 0,
            horiz = this.horiz,
            tickInterval = this.tickInterval,
            slotSize = this.len / (((this.categories ? 1 : 0) +
                this.max -
                this.min) /
                tickInterval),
            rotationOption = labelOptions.rotation, 
            // We don't know the actual rendered line height at this point, but
            // it defaults to 0.8em
            lineHeight = Axis_correctFloat(this.labelMetrics().h * 0.8),
            range = Math.max(this.max - this.min, 0), 
            // Return the multiple of tickInterval that is needed to avoid
            // collision
            getStep = function (spaceNeeded) {
                var step = (spaceNeeded + 2 * padding) / (slotSize || 1);
            step = step > 1 ? Math.ceil(step) : 1;
            // Guard for very small or negative angles (#9835)
            if (step * tickInterval > range &&
                spaceNeeded !== Infinity &&
                slotSize !== Infinity &&
                range) {
                step = Math.ceil(range / tickInterval);
            }
            return Axis_correctFloat(step * tickInterval);
        };
        var newTickInterval = tickInterval,
            rotation,
            bestScore = Number.MAX_VALUE,
            autoRotation;
        if (horiz) {
            if (!labelOptions.staggerLines) {
                if (Axis_isNumber(rotationOption)) {
                    autoRotation = [rotationOption];
                }
                else if (slotSize < labelOptions.autoRotationLimit) {
                    autoRotation = labelOptions.autoRotation;
                }
            }
            if (autoRotation) {
                var step = void 0,
                    score = void 0;
                // Loop over the given autoRotation options, and determine which
                // gives the best score. The best score is that with the lowest
                // number of steps and a rotation closest to horizontal.
                for (var _i = 0, autoRotation_1 = autoRotation; _i < autoRotation_1.length; _i++) {
                    var rot = autoRotation_1[_i];
                    if (rot === rotationOption ||
                        (rot && rot >= -90 && rot <= 90)) { // #3891
                        step = getStep(Math.abs(lineHeight / Math.sin(Axis_deg2rad * rot)));
                        score = step + Math.abs(rot / 360);
                        if (score < bestScore) {
                            bestScore = score;
                            rotation = rot;
                            newTickInterval = step;
                        }
                    }
                }
            }
        }
        else { // #4411
            newTickInterval = getStep(lineHeight * 0.75);
        }
        this.autoRotation = autoRotation;
        this.labelRotation = Axis_pick(rotation, Axis_isNumber(rotationOption) ? rotationOption : 0);
        return labelOptions.step ? tickInterval : newTickInterval;
    };
    /**
     * Get the general slot width for labels/categories on this axis. This may
     * change between the pre-render (from Axis.getOffset) and the final tick
     * rendering and placement.
     *
     * @private
     * @function Highcharts.Axis#getSlotWidth
     *
     * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width
     * basing on tick label. It is used in highcharts-3d module, where the slots
     * has different widths depending on perspective angles.
     *
     * @return {number}
     * The pixel width allocated to each axis label.
     */
    Axis.prototype.getSlotWidth = function (tick) {
        // #5086, #1580, #1931
        var chart = this.chart,
            horiz = this.horiz,
            labelOptions = this.options.labels,
            slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1),
            marginLeft = chart.margin[3];
        // Used by grid axis
        if (tick && Axis_isNumber(tick.slotWidth)) { // #13221, can be 0
            return tick.slotWidth;
        }
        if (horiz && labelOptions.step < 2 && !this.isRadial) {
            if (labelOptions.rotation) { // #4415
                return 0;
            }
            return ((this.staggerLines || 1) * this.len) / slotCount;
        }
        if (!horiz) {
            // #7028
            var cssWidth = labelOptions.style.width;
            if (cssWidth !== void 0) {
                return parseInt(String(cssWidth), 10);
            }
            if (marginLeft) {
                return marginLeft - chart.spacing[3];
            }
        }
        // Last resort, a fraction of the available size
        return chart.chartWidth * 0.33;
    };
    /**
     * Render the axis labels and determine whether ellipsis or rotation need to
     * be applied.
     *
     * @private
     * @function Highcharts.Axis#renderUnsquish
     */
    Axis.prototype.renderUnsquish = function () {
        var chart = this.chart,
            renderer = chart.renderer,
            tickPositions = this.tickPositions,
            ticks = this.ticks,
            labelOptions = this.options.labels,
            labelStyleOptions = labelOptions.style,
            horiz = this.horiz,
            slotWidth = this.getSlotWidth(),
            innerWidth = Math.max(1,
            Math.round(slotWidth - (horiz ?
                2 * (labelOptions.padding || 0) :
                labelOptions.distance || 0 // #21172
            ))),
            attr = {},
            labelMetrics = this.labelMetrics(),
            lineClampOption = labelStyleOptions.lineClamp;
        var commonWidth,
            lineClamp = lineClampOption !== null && lineClampOption !== void 0 ? lineClampOption : (Math.floor(this.len / (tickPositions.length * labelMetrics.h)) || 1),
            maxLabelLength = 0;
        // Set rotation option unless it is "auto", like in gauges
        if (!Axis_isString(labelOptions.rotation)) {
            // #4443
            attr.rotation = labelOptions.rotation || 0;
        }
        // Get the longest label length
        tickPositions.forEach(function (tickPosition) {
            var _a;
            var tick = ticks[tickPosition];
            // Replace label - sorting animation
            if (tick.movedLabel) {
                tick.replaceMovedLabel();
            }
            var textPxLength = ((_a = tick.label) === null || _a === void 0 ? void 0 : _a.textPxLength) || 0;
            if (textPxLength > maxLabelLength) {
                maxLabelLength = textPxLength;
            }
        });
        this.maxLabelLength = maxLabelLength;
        // Handle auto rotation on horizontal axis
        if (this.autoRotation) {
            // Apply rotation only if the label is too wide for the slot, and
            // the label is wider than its height.
            if (maxLabelLength > innerWidth &&
                maxLabelLength > labelMetrics.h) {
                attr.rotation = this.labelRotation;
            }
            else {
                this.labelRotation = 0;
            }
            // Handle word-wrap or ellipsis on vertical axis
        }
        else if (slotWidth) {
            // For word-wrap or ellipsis
            commonWidth = innerWidth;
        }
        // Add ellipsis if the label length is significantly longer than ideal
        if (attr.rotation) {
            commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ?
                chart.chartHeight * 0.33 :
                maxLabelLength);
            if (!lineClampOption) {
                lineClamp = 1;
            }
        }
        // Set the explicit or automatic label alignment
        this.labelAlign = labelOptions.align ||
            this.autoLabelAlign(this.labelRotation);
        if (this.labelAlign) {
            attr.align = this.labelAlign;
        }
        // Apply general and specific CSS
        tickPositions.forEach(function (pos) {
            var tick = ticks[pos],
                label = tick && tick.label,
                widthOption = labelStyleOptions.width,
                css = {};
            if (label) {
                // This needs to go before the CSS in old IE (#4502)
                label.attr(attr);
                if (tick.shortenLabel) {
                    tick.shortenLabel();
                }
                else if (commonWidth &&
                    !widthOption &&
                    // Setting width in this case messes with the bounding box
                    // (#7975)
                    labelStyleOptions.whiteSpace !== 'nowrap' &&
                    (
                    // Speed optimizing, #7656
                    commonWidth < (label.textPxLength || 0) ||
                        // Resetting CSS, #4928
                        label.element.tagName === 'SPAN')) {
                    label.css(Axis_extend(css, {
                        width: "" + commonWidth + "px",
                        lineClamp: lineClamp
                    }));
                    // Reset previously shortened label (#8210)
                }
                else if (label.styles.width && !css.width && !widthOption) {
                    label.css({ width: 'auto' });
                }
                tick.rotation = attr.rotation;
            }
        }, this);
        // Note: Why is this not part of getLabelPosition?
        this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0);
    };
    /**
     * Return true if the axis has associated data.
     *
     * @function Highcharts.Axis#hasData
     *
     * @return {boolean}
     * True if the axis has associated visible series and those series have
     * either valid data points or explicit `min` and `max` settings.
     */
    Axis.prototype.hasData = function () {
        return this.series.some(function (s) {
            return s.hasData();
        }) ||
            (this.options.showEmpty &&
                Axis_defined(this.min) &&
                Axis_defined(this.max));
    };
    /**
     * Adds the title defined in axis.options.title.
     *
     * @function Highcharts.Axis#addTitle
     *
     * @param {boolean} [display]
     * Whether or not to display the title.
     */
    Axis.prototype.addTitle = function (display) {
        var axis = this,
            renderer = axis.chart.renderer,
            horiz = axis.horiz,
            opposite = axis.opposite,
            options = axis.options,
            axisTitleOptions = options.title,
            styledMode = axis.chart.styledMode;
        var textAlign;
        if (!axis.axisTitle) {
            textAlign = axisTitleOptions.textAlign;
            if (!textAlign) {
                textAlign = (horiz ? {
                    low: 'left',
                    middle: 'center',
                    high: 'right'
                } : {
                    low: opposite ? 'right' : 'left',
                    middle: 'center',
                    high: opposite ? 'left' : 'right'
                })[axisTitleOptions.align];
            }
            axis.axisTitle = renderer
                .text(axisTitleOptions.text || '', 0, 0, axisTitleOptions.useHTML)
                .attr({
                zIndex: 7,
                rotation: axisTitleOptions.rotation || 0,
                align: textAlign
            })
                .addClass('highcharts-axis-title');
            // #7814, don't mutate style option
            if (!styledMode) {
                axis.axisTitle.css(Axis_merge(axisTitleOptions.style));
            }
            axis.axisTitle.add(axis.axisGroup);
            axis.axisTitle.isNew = true;
        }
        // Max width defaults to the length of the axis
        if (!styledMode &&
            !axisTitleOptions.style.width &&
            !axis.isRadial) {
            axis.axisTitle.css({
                width: axis.len + 'px'
            });
        }
        // Hide or show the title depending on whether showEmpty is set
        axis.axisTitle[display ? 'show' : 'hide'](display);
    };
    /**
     * Generates a tick for initial positioning.
     *
     * @private
     * @function Highcharts.Axis#generateTick
     *
     * @param {number} pos
     * The tick position in axis values.
     *
     * @param {number} [i]
     * The index of the tick in {@link Axis.tickPositions}.
     */
    Axis.prototype.generateTick = function (pos) {
        var axis = this,
            ticks = axis.ticks;
        if (!ticks[pos]) {
            ticks[pos] = new Axis_Tick(axis, pos);
        }
        else {
            ticks[pos].addLabel(); // Update labels depending on tick interval
        }
    };
    /**
     * Create the axisGroup and gridGroup elements on first iteration.
     *
     * @private
     * @function Highcharts.Axis#getOffset
     *
     * @emits Highcharts.Axis#event:afterGetOffset
     */
    Axis.prototype.createGroups = function () {
        var _this = this;
        var _a = this,
            axisParent = _a.axisParent, // Used in color axis
            chart = _a.chart,
            coll = _a.coll,
            options = _a.options,
            renderer = chart.renderer;
        var createGroup = function (name, suffix, zIndex) { return renderer.g(name)
                .attr({ zIndex: zIndex })
                .addClass("highcharts-".concat(coll.toLowerCase()).concat(suffix, " ") +
                (_this.isRadial ? "highcharts-radial-axis".concat(suffix, " ") : '') +
                (options.className || ''))
                .add(axisParent); };
        if (!this.axisGroup) {
            this.gridGroup = createGroup('grid', '-grid', options.gridZIndex);
            this.axisGroup = createGroup('axis', '', options.zIndex);
            this.labelGroup = createGroup('axis-labels', '-labels', options.labels.zIndex);
        }
    };
    /**
     * Render the tick labels to a preliminary position to get their sizes
     *
     * @private
     * @function Highcharts.Axis#getOffset
     *
     * @emits Highcharts.Axis#event:afterGetOffset
     */
    Axis.prototype.getOffset = function () {
        var axis = this,
            chart = axis.chart,
            horiz = axis.horiz,
            options = axis.options,
            side = axis.side,
            ticks = axis.ticks,
            tickPositions = axis.tickPositions,
            coll = axis.coll,
            invertedSide = (chart.inverted && !axis.isZAxis ?
                [1, 0, 3, 2][side] :
                side),
            hasData = axis.hasData(),
            axisTitleOptions = options.title,
            labelOptions = options.labels,
            hasCrossing = Axis_isNumber(options.crossing),
            axisOffset = chart.axisOffset,
            clipOffset = chart.clipOffset,
            directionFactor = [-1, 1, 1, -1][side];
        var showAxis,
            titleOffset = 0,
            titleOffsetOption,
            titleMargin = 0,
            labelOffset = 0, // Reset
            labelOffsetPadded,
            lineHeightCorrection;
        // For reuse in Axis.render
        axis.showAxis = showAxis = hasData || options.showEmpty;
        // Set/reset staggerLines
        axis.staggerLines = (axis.horiz && labelOptions.staggerLines) || void 0;
        axis.createGroups();
        if (hasData || axis.isLinked) {
            // Generate ticks
            tickPositions.forEach(function (pos) {
                axis.generateTick(pos);
            });
            axis.renderUnsquish();
            // Left side must be align: right and right side must
            // have align: left for labels
            axis.reserveSpaceDefault = (side === 0 ||
                side === 2 ||
                { 1: 'left', 3: 'right' }[side] === axis.labelAlign);
            if (Axis_pick(labelOptions.reserveSpace, hasCrossing ? false : null, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) {
                tickPositions.forEach(function (pos) {
                    // Get the highest offset
                    labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset);
                });
            }
            if (axis.staggerLines) {
                labelOffset *= axis.staggerLines;
            }
            axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1);
        }
        else { // Doesn't have data
            Axis_objectEach(ticks, function (tick, n) {
                tick.destroy();
                delete ticks[n];
            });
        }
        if ((axisTitleOptions === null || axisTitleOptions === void 0 ? void 0 : axisTitleOptions.text) &&
            axisTitleOptions.enabled !== false) {
            axis.addTitle(showAxis);
            if (showAxis &&
                !hasCrossing &&
                axisTitleOptions.reserveSpace !== false) {
                axis.titleOffset = titleOffset =
                    axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];
                titleOffsetOption = axisTitleOptions.offset;
                titleMargin = Axis_defined(titleOffsetOption) ?
                    0 :
                    Axis_pick(axisTitleOptions.margin, horiz ? 5 : 10);
            }
        }
        // Render the axis line
        axis.renderLine();
        // Handle automatic or user set offset
        axis.offset = directionFactor * Axis_pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0);
        axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // Polar
        if (side === 0) {
            lineHeightCorrection = -axis.labelMetrics().h;
        }
        else if (side === 2) {
            lineHeightCorrection = axis.tickRotCorr.y;
        }
        else {
            lineHeightCorrection = 0;
        }
        // Find the padded label offset
        labelOffsetPadded = Math.abs(labelOffset) + titleMargin;
        if (labelOffset) {
            labelOffsetPadded -= lineHeightCorrection;
            labelOffsetPadded += directionFactor * (horiz ?
                Axis_pick(labelOptions.y, axis.tickRotCorr.y +
                    directionFactor * labelOptions.distance) :
                Axis_pick(labelOptions.x, directionFactor * labelOptions.distance));
        }
        axis.axisTitleMargin = Axis_pick(titleOffsetOption, labelOffsetPadded);
        if (axis.getMaxLabelDimensions) {
            axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions);
        }
        // Due to GridAxis.tickSize, tickSize should be calculated after ticks
        // has rendered.
        if (coll !== 'colorAxis' && clipOffset) {
            var tickSize = this.tickSize('tick');
            axisOffset[side] = Math.max(axisOffset[side], (axis.axisTitleMargin || 0) + titleOffset +
                directionFactor * axis.offset, labelOffsetPadded, // #3027
            tickPositions && tickPositions.length && tickSize ?
                tickSize[0] + directionFactor * axis.offset :
                0 // #4866
            );
            // Decide the clipping needed to keep the graph inside
            // the plot area and axis lines
            var clip = !axis.axisLine || options.offset ?
                    0 :
                    // #4308, #4371
                    axis.axisLine.strokeWidth() / 2;
            clipOffset[invertedSide] = Math.max(clipOffset[invertedSide], clip);
        }
        Axis_fireEvent(this, 'afterGetOffset');
    };
    /**
     * Internal function to get the path for the axis line. Extended for polar
     * charts.
     *
     * @function Highcharts.Axis#getLinePath
     *
     * @param {number} lineWidth
     * The line width in pixels.
     *
     * @return {Highcharts.SVGPathArray}
     * The SVG path definition in array form.
     */
    Axis.prototype.getLinePath = function (lineWidth) {
        var chart = this.chart,
            opposite = this.opposite,
            offset = this.offset,
            horiz = this.horiz,
            lineLeft = this.left + (opposite ? this.width : 0) + offset,
            lineTop = chart.chartHeight - this.bottom -
                (opposite ? this.height : 0) + offset;
        if (opposite) {
            lineWidth *= -1; // Crispify the other way - #1480, #1687
        }
        return chart.renderer
            .crispLine([
            [
                'M',
                horiz ?
                    this.left :
                    lineLeft,
                horiz ?
                    lineTop :
                    this.top
            ],
            [
                'L',
                horiz ?
                    chart.chartWidth - this.right :
                    lineLeft,
                horiz ?
                    lineTop :
                    chart.chartHeight - this.bottom
            ]
        ], lineWidth);
    };
    /**
     * Render the axis line. Called internally when rendering and redrawing the
     * axis.
     *
     * @function Highcharts.Axis#renderLine
     */
    Axis.prototype.renderLine = function () {
        if (!this.axisLine) {
            this.axisLine = this.chart.renderer.path()
                .addClass('highcharts-axis-line')
                .add(this.axisGroup);
            if (!this.chart.styledMode) {
                this.axisLine.attr({
                    stroke: this.options.lineColor,
                    'stroke-width': this.options.lineWidth,
                    zIndex: 7
                });
            }
        }
    };
    /**
     * Position the axis title.
     *
     * @private
     * @function Highcharts.Axis#getTitlePosition
     *
     * @return {Highcharts.PositionObject}
     * X and Y positions for the title.
     */
    Axis.prototype.getTitlePosition = function (axisTitle) {
        // Compute anchor points for each of the title align options
        var horiz = this.horiz,
            axisLeft = this.left,
            axisTop = this.top,
            axisLength = this.len,
            axisTitleOptions = this.options.title,
            margin = horiz ? axisLeft : axisTop,
            opposite = this.opposite,
            offset = this.offset,
            xOption = axisTitleOptions.x,
            yOption = axisTitleOptions.y,
            fontMetrics = this.chart.renderer.fontMetrics(axisTitle), 
            // The part of a multiline text that is below the baseline of the
            // first line. Subtract 1 to preserve pixel-perfectness from the
            // old behaviour (v5.0.12), where only one line was allowed.
            textHeightOvershoot = axisTitle ? Math.max(axisTitle.getBBox(false, 0).height - fontMetrics.h - 1, 0) : 0, 
            // The position in the length direction of the axis
            alongAxis = ({
                low: margin + (horiz ? 0 : axisLength),
                middle: margin + axisLength / 2,
                high: margin + (horiz ? axisLength : 0)
            })[axisTitleOptions.align], 
            // The position in the perpendicular direction of the axis
            offAxis = (horiz ? axisTop + this.height : axisLeft) +
                (horiz ? 1 : -1) * // Horizontal axis reverses the margin
                    (opposite ? -1 : 1) * // So does opposite axes
                    (this.axisTitleMargin || 0) +
                [
                    -textHeightOvershoot, // Top
                    textHeightOvershoot, // Right
                    fontMetrics.f, // Bottom
                    -textHeightOvershoot // Left
                ][this.side],
            titlePosition = {
                x: horiz ?
                    alongAxis + xOption :
                    offAxis + (opposite ? this.width : 0) + offset + xOption,
                y: horiz ?
                    offAxis + yOption - (opposite ? this.height : 0) + offset :
                    alongAxis + yOption
            };
        Axis_fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition });
        return titlePosition;
    };
    /**
     * Render a minor tick into the given position. If a minor tick already
     * exists in this position, move it.
     *
     * @function Highcharts.Axis#renderMinorTick
     *
     * @param {number} pos
     * The position in axis values.
     *
     * @param {boolean} slideIn
     * Whether the tick should animate in from last computed position
     */
    Axis.prototype.renderMinorTick = function (pos, slideIn) {
        var axis = this;
        var minorTicks = axis.minorTicks;
        if (!minorTicks[pos]) {
            minorTicks[pos] = new Axis_Tick(axis, pos, 'minor');
        }
        // Render new ticks in old position
        if (slideIn && minorTicks[pos].isNew) {
            minorTicks[pos].render(null, true);
        }
        minorTicks[pos].render(null, false, 1);
    };
    /**
     * Render a major tick into the given position. If a tick already exists
     * in this position, move it.
     *
     * @function Highcharts.Axis#renderTick
     *
     * @param {number} pos
     * The position in axis values.
     *
     * @param {number} i
     * The tick index.
     *
     * @param {boolean} slideIn
     * Whether the tick should animate in from last computed position
     */
    Axis.prototype.renderTick = function (pos, i, slideIn) {
        var axis = this,
            isLinked = axis.isLinked,
            ticks = axis.ticks;
        // Linked axes need an extra check to find out if
        if (!isLinked ||
            (pos >= axis.min && pos <= axis.max) ||
            (axis.grid && axis.grid.isColumn)) {
            if (!ticks[pos]) {
                ticks[pos] = new Axis_Tick(axis, pos);
            }
            // NOTE this seems like overkill. Could be handled in tick.render by
            // setting old position in attr, then set new position in animate.
            // render new ticks in old position
            if (slideIn && ticks[pos].isNew) {
                // Start with negative opacity so that it is visible from
                // halfway into the animation
                ticks[pos].render(i, true, -1);
            }
            ticks[pos].render(i);
        }
    };
    /**
     * Render the axis.
     *
     * @private
     * @function Highcharts.Axis#render
     *
     * @emits Highcharts.Axis#event:afterRender
     */
    Axis.prototype.render = function () {
        var axis = this,
            chart = axis.chart,
            log = axis.logarithmic,
            renderer = chart.renderer,
            options = axis.options,
            isLinked = axis.isLinked,
            tickPositions = axis.tickPositions,
            axisTitle = axis.axisTitle,
            ticks = axis.ticks,
            minorTicks = axis.minorTicks,
            alternateBands = axis.alternateBands,
            stackLabelOptions = options.stackLabels,
            alternateGridColor = options.alternateGridColor,
            crossing = options.crossing,
            tickmarkOffset = axis.tickmarkOffset,
            axisLine = axis.axisLine,
            showAxis = axis.showAxis,
            animation = Axis_animObject(renderer.globalAnimation);
        var from,
            to;
        // Reset
        axis.labelEdge.length = 0;
        axis.overlap = false;
        // Mark all elements inActive before we go over and mark the active ones
        [ticks, minorTicks, alternateBands].forEach(function (coll) {
            Axis_objectEach(coll, function (tick) {
                tick.isActive = false;
            });
        });
        // Crossing
        if (Axis_isNumber(crossing)) {
            var otherAxis = this.isXAxis ? chart.yAxis[0] : chart.xAxis[0],
                directionFactor = [1, -1, -1, 1][this.side];
            if (otherAxis) {
                var px = otherAxis.toPixels(crossing,
                    true);
                if (axis.horiz) {
                    px = otherAxis.len - px;
                }
                axis.offset = directionFactor * px;
            }
        }
        // If the series has data draw the ticks. Else only the line and title
        if (axis.hasData() || isLinked) {
            var slideInTicks_1 = axis.chart.hasRendered &&
                    axis.old && Axis_isNumber(axis.old.min);
            // Minor ticks
            if (axis.minorTickInterval && !axis.categories) {
                axis.getMinorTickPositions().forEach(function (pos) {
                    axis.renderMinorTick(pos, slideInTicks_1);
                });
            }
            // Major ticks. Pull out the first item and render it last so that
            // we can get the position of the neighbour label. #808.
            if (tickPositions.length) { // #1300
                tickPositions.forEach(function (pos, i) {
                    axis.renderTick(pos, i, slideInTicks_1);
                });
                // In a categorized axis, the tick marks are displayed
                // between labels. So we need to add a tick mark and
                // grid line at the left edge of the X axis.
                if (tickmarkOffset && (axis.min === 0 || axis.single)) {
                    if (!ticks[-1]) {
                        ticks[-1] = new Axis_Tick(axis, -1, null, true);
                    }
                    ticks[-1].render(-1);
                }
            }
            // Alternate grid color
            if (alternateGridColor) {
                tickPositions.forEach(function (pos, i) {
                    to = typeof tickPositions[i + 1] !== 'undefined' ?
                        tickPositions[i + 1] + tickmarkOffset :
                        axis.max - tickmarkOffset;
                    if (i % 2 === 0 &&
                        pos < axis.max &&
                        to <= axis.max + (chart.polar ?
                            -tickmarkOffset :
                            tickmarkOffset)) { // #2248, #4660
                        if (!alternateBands[pos]) {
                            // Should be imported from PlotLineOrBand.js, but
                            // the dependency cycle with axis is a problem
                            alternateBands[pos] = new Core_Globals.PlotLineOrBand(axis, {});
                        }
                        from = pos + tickmarkOffset; // #949
                        alternateBands[pos].options = {
                            from: log ? log.lin2log(from) : from,
                            to: log ? log.lin2log(to) : to,
                            color: alternateGridColor,
                            className: 'highcharts-alternate-grid'
                        };
                        alternateBands[pos].render();
                        alternateBands[pos].isActive = true;
                    }
                });
            }
            // Custom plot lines and bands
            if (!axis._addedPlotLB) { // Only first time
                axis._addedPlotLB = true;
                (options.plotLines || [])
                    .concat(options.plotBands || [])
                    .forEach(function (plotLineOptions) {
                    axis
                        .addPlotBandOrLine(plotLineOptions);
                });
            }
        } // End if hasData
        // Remove inactive ticks
        [ticks, minorTicks, alternateBands].forEach(function (coll) {
            var forDestruction = [],
                delay = animation.duration,
                destroyInactiveItems = function () {
                    var i = forDestruction.length;
                while (i--) {
                    // When resizing rapidly, the same items
                    // may be destroyed in different timeouts,
                    // or the may be reactivated
                    if (coll[forDestruction[i]] &&
                        !coll[forDestruction[i]].isActive) {
                        coll[forDestruction[i]].destroy();
                        delete coll[forDestruction[i]];
                    }
                }
            };
            Axis_objectEach(coll, function (tick, pos) {
                if (!tick.isActive) {
                    // Render to zero opacity
                    tick.render(pos, false, 0);
                    tick.isActive = false;
                    forDestruction.push(pos);
                }
            });
            // When the objects are finished fading out, destroy them
            Axis_syncTimeout(destroyInactiveItems, coll === alternateBands ||
                !chart.hasRendered ||
                !delay ?
                0 :
                delay);
        });
        // Set the axis line path
        if (axisLine) {
            axisLine[axisLine.isPlaced ? 'animate' : 'attr']({
                d: this.getLinePath(axisLine.strokeWidth())
            });
            axisLine.isPlaced = true;
            // Show or hide the line depending on options.showEmpty
            axisLine[showAxis ? 'show' : 'hide'](showAxis);
        }
        if (axisTitle && showAxis) {
            axisTitle[axisTitle.isNew ? 'attr' : 'animate'](axis.getTitlePosition(axisTitle));
            axisTitle.isNew = false;
        }
        // Stacked totals:
        if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) {
            axis.stacking.renderStackTotals();
        }
        // End stacked totals
        // Record old scaling for updating/animation. Pinch base must be
        // preserved until the pinch ends.
        axis.old = {
            len: axis.len,
            max: axis.max,
            min: axis.min,
            transA: axis.transA,
            userMax: axis.userMax,
            userMin: axis.userMin
        };
        axis.isDirty = false;
        Axis_fireEvent(this, 'afterRender');
    };
    /**
     * Redraw the axis to reflect changes in the data or axis extremes. Called
     * internally from Highcharts.Chart#redraw.
     *
     * @private
     * @function Highcharts.Axis#redraw
     */
    Axis.prototype.redraw = function () {
        if (this.visible) {
            // Render the axis
            this.render();
            // Move plot lines and bands
            this.plotLinesAndBands.forEach(function (plotLine) {
                plotLine.render();
            });
        }
        // Mark associated series as dirty and ready for redraw
        this.series.forEach(function (series) {
            series.isDirty = true;
        });
    };
    /**
     * Returns an array of axis properties, that should be untouched during
     * reinitialization.
     *
     * @private
     * @function Highcharts.Axis#getKeepProps
     */
    Axis.prototype.getKeepProps = function () {
        return (this.keepProps || Axis.keepProps);
    };
    /**
     * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint
     * to fully remove the axis.
     *
     * @private
     * @function Highcharts.Axis#destroy
     *
     * @param {boolean} [keepEvents]
     * Whether to preserve events, used internally in Axis.update.
     */
    Axis.prototype.destroy = function (keepEvents) {
        var axis = this,
            plotLinesAndBands = axis.plotLinesAndBands,
            eventOptions = this.eventOptions;
        Axis_fireEvent(this, 'destroy', { keepEvents: keepEvents });
        // Remove the events
        if (!keepEvents) {
            Axis_removeEvent(axis);
        }
        // Destroy collections
        [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) {
            Axis_destroyObjectProperties(coll);
        });
        if (plotLinesAndBands) {
            var i = plotLinesAndBands.length;
            while (i--) { // #1975
                plotLinesAndBands[i].destroy();
            }
        }
        // Destroy elements
        [
            'axisLine', 'axisTitle', 'axisGroup',
            'gridGroup', 'labelGroup', 'cross', 'scrollbar'
        ].forEach(function (prop) {
            if (axis[prop]) {
                axis[prop] = axis[prop].destroy();
            }
        });
        // Destroy each generated group for plotlines and plotbands
        for (var plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in
            axis.plotLinesAndBandsGroups[plotGroup] =
                axis.plotLinesAndBandsGroups[plotGroup].destroy();
        }
        // Delete all properties and fall back to the prototype.
        Axis_objectEach(axis, function (val, key) {
            if (axis.getKeepProps().indexOf(key) === -1) {
                delete axis[key];
            }
        });
        this.eventOptions = eventOptions;
    };
    /**
     * Internal function to draw a crosshair.
     *
     * @function Highcharts.Axis#drawCrosshair
     *
     * @param {Highcharts.PointerEventObject} [e]
     * The event arguments from the modified pointer event, extended with
     * `chartX` and `chartY`
     *
     * @param {Highcharts.Point} [point]
     * The Point object if the crosshair snaps to points.
     *
     * @emits Highcharts.Axis#event:afterDrawCrosshair
     * @emits Highcharts.Axis#event:drawCrosshair
     */
    Axis.prototype.drawCrosshair = function (e, point) {
        var options = this.crosshair,
            snap = Axis_pick(options && options.snap,
            true),
            chart = this.chart;
        var path,
            pos,
            categorized,
            graphic = this.cross,
            crossOptions;
        Axis_fireEvent(this, 'drawCrosshair', { e: e, point: point });
        // Use last available event when updating non-snapped crosshairs without
        // mouse interaction (#5287)
        if (!e) {
            e = this.cross && this.cross.e;
        }
        if (
        // Disabled in options
        !options ||
            // Snap
            ((Axis_defined(point) || !snap) === false)) {
            this.hideCrosshair();
        }
        else {
            // Get the path
            if (!snap) {
                pos = e &&
                    (this.horiz ?
                        e.chartX - this.pos :
                        this.len - e.chartY + this.pos);
            }
            else if (Axis_defined(point)) {
                // #3834
                pos = Axis_pick(this.coll !== 'colorAxis' ?
                    point.crosshairPos : // 3D axis extension
                    null, this.isXAxis ?
                    point.plotX :
                    this.len - point.plotY);
            }
            if (Axis_defined(pos)) {
                crossOptions = {
                    // Value, only used on radial
                    value: point && (this.isXAxis ?
                        point.x :
                        Axis_pick(point.stackY, point.y)),
                    translatedValue: pos
                };
                if (chart.polar) {
                    // Additional information required for crosshairs in
                    // polar chart
                    Axis_extend(crossOptions, {
                        isCrosshair: true,
                        chartX: e && e.chartX,
                        chartY: e && e.chartY,
                        point: point
                    });
                }
                path = this.getPlotLinePath(crossOptions) ||
                    null; // #3189
            }
            if (!Axis_defined(path)) {
                this.hideCrosshair();
                return;
            }
            categorized = this.categories && !this.isRadial;
            // Draw the cross
            if (!graphic) {
                this.cross = graphic = chart.renderer
                    .path()
                    .addClass('highcharts-crosshair highcharts-crosshair-' +
                    (categorized ? 'category ' : 'thin ') +
                    (options.className || ''))
                    .attr({
                    zIndex: Axis_pick(options.zIndex, 2)
                })
                    .add();
                // Presentational attributes
                if (!chart.styledMode) {
                    graphic.attr({
                        stroke: options.color ||
                            (categorized ?
                                Color_Color
                                    .parse("#ccd3ff" /* Palette.highlightColor20 */)
                                    .setOpacity(0.25)
                                    .get() :
                                "#cccccc" /* Palette.neutralColor20 */),
                        'stroke-width': Axis_pick(options.width, 1)
                    }).css({
                        'pointer-events': 'none'
                    });
                    if (options.dashStyle) {
                        graphic.attr({
                            dashstyle: options.dashStyle
                        });
                    }
                }
            }
            graphic.show().attr({
                d: path
            });
            if (categorized && !options.width) {
                graphic.attr({
                    'stroke-width': this.transA
                });
            }
            this.cross.e = e;
        }
        Axis_fireEvent(this, 'afterDrawCrosshair', { e: e, point: point });
    };
    /**
     * Hide the crosshair if visible.
     *
     * @function Highcharts.Axis#hideCrosshair
     */
    Axis.prototype.hideCrosshair = function () {
        if (this.cross) {
            this.cross.hide();
        }
        Axis_fireEvent(this, 'afterHideCrosshair');
    };
    /**
     * Update an axis object with a new set of options. The options are merged
     * with the existing options, so only new or altered options need to be
     * specified.
     *
     * @sample highcharts/members/axis-update/
     *         Axis update demo
     *
     * @function Highcharts.Axis#update
     *
     * @param {Highcharts.AxisOptions} options
     * The new options that will be merged in with existing options on the axis.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart after the axis is altered. If doing more
     * operations on the chart, it is a good idea to set redraw to false and
     * call {@link Chart#redraw} after.
     */
    Axis.prototype.update = function (options, redraw) {
        var chart = this.chart;
        options = Axis_merge(this.userOptions, options);
        this.destroy(true);
        this.init(chart, options);
        chart.isDirtyBox = true;
        if (Axis_pick(redraw, true)) {
            chart.redraw();
        }
    };
    /**
     * Remove the axis from the chart.
     *
     * @sample highcharts/members/chart-addaxis/
     *         Add and remove axes
     *
     * @function Highcharts.Axis#remove
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart following the remove.
     */
    Axis.prototype.remove = function (redraw) {
        var chart = this.chart,
            coll = this.coll,
            axisSeries = this.series;
        var i = axisSeries.length;
        // Remove associated series (#2687)
        while (i--) {
            if (axisSeries[i]) {
                axisSeries[i].remove(false);
            }
        }
        // Remove the axis
        Axis_erase(chart.axes, this);
        Axis_erase(chart[coll] || [], this);
        chart.orderItems(coll);
        this.destroy();
        chart.isDirtyBox = true;
        if (Axis_pick(redraw, true)) {
            chart.redraw();
        }
    };
    /**
     * Update the axis title by options after render time.
     *
     * @sample highcharts/members/axis-settitle/
     *         Set a new Y axis title
     *
     * @function Highcharts.Axis#setTitle
     *
     * @param {Highcharts.AxisTitleOptions} titleOptions
     * The additional title options.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart after setting the title.
     */
    Axis.prototype.setTitle = function (titleOptions, redraw) {
        this.update({ title: titleOptions }, redraw);
    };
    /**
     * Set new axis categories and optionally redraw.
     *
     * @sample highcharts/members/axis-setcategories/
     *         Set categories by click on a button
     *
     * @function Highcharts.Axis#setCategories
     *
     * @param {Array<string>} categories
     * The new categories.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart.
     */
    Axis.prototype.setCategories = function (categories, redraw) {
        this.update({ categories: categories }, redraw);
    };
    /* *
     *
     *  Static Properties
     *
     * */
    // Properties to survive after destroy, needed for Axis.update (#4317,
    // #5773, #5881).
    Axis.keepProps = [
        'coll',
        'extKey',
        'hcEvents',
        'len',
        'names',
        'series',
        'userMax',
        'userMin'
    ];
    return Axis;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_Axis = (Axis);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Options for the path on the Axis to be calculated.
 * @interface Highcharts.AxisPlotLinePathOptionsObject
 */ /**
* Axis value.
* @name Highcharts.AxisPlotLinePathOptionsObject#value
* @type {number|undefined}
*/ /**
* Line width used for calculation crisp line coordinates. Defaults to 1.
* @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth
* @type {number|undefined}
*/ /**
* If `false`, the function will return null when it falls outside the axis
* bounds. If `true`, the function will return a path aligned to the plot area
* sides if it falls outside. If `pass`, it will return a path outside.
* @name Highcharts.AxisPlotLinePathOptionsObject#force
* @type {string|boolean|undefined}
*/ /**
* Used in Highcharts Stock. When `true`, plot paths
* (crosshair, plotLines, gridLines)
* will be rendered on all axes when defined on the first axis.
* @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes
* @type {boolean|undefined}
*/ /**
* Use old coordinates (for resizing and rescaling).
* If not set, defaults to `false`.
* @name Highcharts.AxisPlotLinePathOptionsObject#old
* @type {boolean|undefined}
*/ /**
* If given, return the plot line path of a pixel position on the axis.
* @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue
* @type {number|undefined}
*/ /**
* Used in Polar axes. Reverse the positions for concatenation of polygonal
* plot bands
* @name Highcharts.AxisPlotLinePathOptionsObject#reverse
* @type {boolean|undefined}
*/
/**
 * Options for crosshairs on axes.
 *
 * @product highstock
 *
 * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions
 */
/**
 * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue
 */
/**
 * @callback Highcharts.AxisEventCallbackFunction
 *
 * @param {Highcharts.Axis} this
 */
/**
 * @callback Highcharts.AxisLabelsFormatterCallbackFunction
 *
 * @param {Highcharts.AxisLabelsFormatterContextObject} this
 *
 * @param {Highcharts.AxisLabelsFormatterContextObject} ctx
 *
 * @return {string}
 */
/**
 * @interface Highcharts.AxisLabelsFormatterContextObject
 */ /**
* The axis item of the label
* @name Highcharts.AxisLabelsFormatterContextObject#axis
* @type {Highcharts.Axis}
*/ /**
* The chart instance.
* @name Highcharts.AxisLabelsFormatterContextObject#chart
* @type {Highcharts.Chart}
*/ /**
* Default formatting of date/time labels.
* @name Highcharts.AxisLabelsFormatterContextObject#dateTimeLabelFormat
* @type {string|undefined}
*/ /**
* Whether the label belongs to the first tick on the axis.
* @name Highcharts.AxisLabelsFormatterContextObject#isFirst
* @type {boolean}
*/ /**
* Whether the label belongs to the last tick on the axis.
* @name Highcharts.AxisLabelsFormatterContextObject#isLast
* @type {boolean}
*/ /**
* The position on the axis in terms of axis values. For category axes, a
* zero-based index. For datetime axes, the JavaScript time in milliseconds
* since 1970.
* @name Highcharts.AxisLabelsFormatterContextObject#pos
* @type {number}
*/ /**
* The preformatted text as the result of the default formatting. For example
* dates will be formatted as strings, and numbers with language-specific comma
* separators, thousands separators and numeric symbols like `k` or `M`.
* @name Highcharts.AxisLabelsFormatterContextObject#text
* @type {string|undefined}
*/ /**
* The Tick instance.
* @name Highcharts.AxisLabelsFormatterContextObject#tick
* @type {Highcharts.Tick}
*/ /**
* This can be either a numeric value or a category string.
* @name Highcharts.AxisLabelsFormatterContextObject#value
* @type {number|string}
*/
/**
 * Options for axes.
 *
 * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions
 */
/**
 * @callback Highcharts.AxisPointBreakEventCallbackFunction
 *
 * @param {Highcharts.Axis} this
 *
 * @param {Highcharts.AxisPointBreakEventObject} evt
 */
/**
 * @interface Highcharts.AxisPointBreakEventObject
 */ /**
* @name Highcharts.AxisPointBreakEventObject#brk
* @type {Highcharts.Dictionary<number>}
*/ /**
* @name Highcharts.AxisPointBreakEventObject#point
* @type {Highcharts.Point}
*/ /**
* @name Highcharts.AxisPointBreakEventObject#preventDefault
* @type {Function}
*/ /**
* @name Highcharts.AxisPointBreakEventObject#target
* @type {Highcharts.SVGElement}
*/ /**
* @name Highcharts.AxisPointBreakEventObject#type
* @type {"pointBreak"|"pointInBreak"}
*/
/**
 * @callback Highcharts.AxisSetExtremesEventCallbackFunction
 *
 * @param {Highcharts.Axis} this
 *
 * @param {Highcharts.AxisSetExtremesEventObject} evt
 */
/**
 * @interface Highcharts.AxisSetExtremesEventObject
 * @extends Highcharts.ExtremesObject
 */ /**
* @name Highcharts.AxisSetExtremesEventObject#preventDefault
* @type {Function}
*/ /**
* @name Highcharts.AxisSetExtremesEventObject#target
* @type {Highcharts.SVGElement}
*/ /**
* @name Highcharts.AxisSetExtremesEventObject#trigger
* @type {Highcharts.AxisExtremesTriggerValue|string}
*/ /**
* @name Highcharts.AxisSetExtremesEventObject#type
* @type {"setExtremes"}
*/
/**
 * @callback Highcharts.AxisTickPositionerCallbackFunction
 *
 * @param {Highcharts.Axis} this
 *
 * @return {Highcharts.AxisTickPositionsArray}
 */
/**
 * @interface Highcharts.AxisTickPositionsArray
 * @augments Array<number>
 */
/**
 * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue
 */
/**
 * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions
 */
/**
 * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue
 */
/**
 * The returned object literal from the {@link Highcharts.Axis#getExtremes}
 * function.
 *
 * @interface Highcharts.ExtremesObject
 */ /**
* The maximum value of the axis' associated series.
* @name Highcharts.ExtremesObject#dataMax
* @type {number}
*/ /**
* The minimum value of the axis' associated series.
* @name Highcharts.ExtremesObject#dataMin
* @type {number}
*/ /**
* The maximum axis value, either automatic or set manually. If the `max` option
* is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be
* the same as `dataMax`.
* @name Highcharts.ExtremesObject#max
* @type {number}
*/ /**
* The minimum axis value, either automatic or set manually. If the `min` option
* is not set, `minPadding` is 0 and `startOnTick` is false, this value will be
* the same as `dataMin`.
* @name Highcharts.ExtremesObject#min
* @type {number}
*/ /**
* The user defined maximum, either from the `max` option or from a zoom or
* `setExtremes` action.
* @name Highcharts.ExtremesObject#userMax
* @type {number|undefined}
*/ /**
* The user defined minimum, either from the `min` option or from a zoom or
* `setExtremes` action.
* @name Highcharts.ExtremesObject#userMin
* @type {number|undefined}
*/
/**
 * Formatter function for the text of a crosshair label.
 *
 * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction
 *
 * @param {Highcharts.Axis} this
 * Axis context
 *
 * @param {number} value
 * Y value of the data point
 *
 * @return {string}
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Axis/DateTimeAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var DateTimeAxis_addEvent = Core_Utilities.addEvent, DateTimeAxis_getMagnitude = Core_Utilities.getMagnitude, DateTimeAxis_normalizeTickInterval = Core_Utilities.normalizeTickInterval, DateTimeAxis_timeUnits = Core_Utilities.timeUnits;
/* *
 *
 *  Composition
 *
 * */
/* eslint-disable valid-jsdoc */
var DateTimeAxis;
(function (DateTimeAxis) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Extends axis class with date and time support.
     * @private
     */
    function compose(AxisClass) {
        if (!AxisClass.keepProps.includes('dateTime')) {
            AxisClass.keepProps.push('dateTime');
            var axisProto = AxisClass.prototype;
            axisProto.getTimeTicks = getTimeTicks;
            DateTimeAxis_addEvent(AxisClass, 'afterSetType', onAfterSetType);
        }
        return AxisClass;
    }
    DateTimeAxis.compose = compose;
    /**
     * Set the tick positions to a time unit that makes sense, for example
     * on the first of each month or on every Monday. Return an array with
     * the time positions. Used in datetime axes as well as for grouping
     * data on a datetime axis.
     *
     * @private
     * @function Highcharts.Axis#getTimeTicks
     * @param {Highcharts.TimeNormalizeObject} normalizedInterval
     * The interval in axis values (ms) and the count.
     * @param {number} min
     * The minimum in axis values.
     * @param {number} max
     * The maximum in axis values.
     */
    function getTimeTicks() {
        return this.chart.time.getTimeTicks.apply(this.chart.time, arguments);
    }
    /**
     * @private
     */
    function onAfterSetType() {
        if (this.type !== 'datetime') {
            this.dateTime = void 0;
            return;
        }
        if (!this.dateTime) {
            this.dateTime = new Additions(this);
        }
    }
    /* *
     *
     *  Classes
     *
     * */
    var Additions = /** @class */ (function () {
            /* *
             *
             *  Constructors
             *
             * */
            function Additions(axis) {
                this.axis = axis;
        }
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Get a normalized tick interval for dates. Returns a configuration
         * object with unit range (interval), count and name. Used to prepare
         * data for `getTimeTicks`. Previously this logic was part of
         * getTimeTicks, but as `getTimeTicks` now runs of segments in stock
         * charts, the normalizing logic was extracted in order to prevent it
         * for running over again for each segment having the same interval.
         * #662, #697.
         * @private
         */
        Additions.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) {
            var units = (unitsOption || [[
                        // Unit name
                        'millisecond',
                        // Allowed multiples
                        [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]
                    ],
                [
                        'second',
                        [1, 2, 5, 10, 15, 30]
                    ],
                [
                        'minute',
                        [1, 2, 5, 10, 15, 30]
                    ],
                [
                        'hour',
                        [1, 2, 3, 4, 6, 8, 12]
                    ],
                [
                        'day',
                        [1, 2]
                    ],
                [
                        'week',
                        [1, 2]
                    ],
                [
                        'month',
                        [1, 2, 3, 4, 6]
                    ],
                [
                        'year',
                        null
                    ]]);
            var unit = units[units.length - 1], // Default unit is years
                interval = DateTimeAxis_timeUnits[unit[0]],
                multiples = unit[1],
                i;
            // Loop through the units to find the one that best fits the
            // tickInterval
            for (i = 0; i < units.length; i++) {
                unit = units[i];
                interval = DateTimeAxis_timeUnits[unit[0]];
                multiples = unit[1];
                if (units[i + 1]) {
                    // `lessThan` is in the middle between the highest multiple
                    // and the next unit.
                    var lessThan = (interval *
                            multiples[multiples.length - 1] +
                            DateTimeAxis_timeUnits[units[i + 1][0]]) / 2;
                    // Break and keep the current unit
                    if (tickInterval <= lessThan) {
                        break;
                    }
                }
            }
            // Prevent 2.5 years intervals, though 25, 250 etc. are allowed
            if (interval === DateTimeAxis_timeUnits.year && tickInterval < 5 * interval) {
                multiples = [1, 2, 5];
            }
            // Get the count
            var count = DateTimeAxis_normalizeTickInterval(tickInterval / interval, multiples, unit[0] === 'year' ? // #1913, #2360
                    Math.max(DateTimeAxis_getMagnitude(tickInterval / interval), 1) :
                    1);
            return {
                unitRange: interval,
                count: count,
                unitName: unit[0]
            };
        };
        /**
         * Get the best date format for a specific X value based on the closest
         * point range on the axis.
         *
         * @private
         */
        Additions.prototype.getXDateFormat = function (x, dateTimeLabelFormats) {
            var axis = this.axis,
                time = axis.chart.time;
            return axis.closestPointRange ?
                time.getDateFormat(axis.closestPointRange, x, axis.options.startOfWeek, dateTimeLabelFormats) ||
                    // #2546, 2581
                    time.resolveDTLFormat(dateTimeLabelFormats.year).main :
                time.resolveDTLFormat(dateTimeLabelFormats.day).main;
        };
        return Additions;
    }());
    DateTimeAxis.Additions = Additions;
})(DateTimeAxis || (DateTimeAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_DateTimeAxis = (DateTimeAxis);

;// ./code/es5/es-modules/Core/Axis/LogarithmicAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var LogarithmicAxis_addEvent = Core_Utilities.addEvent, LogarithmicAxis_normalizeTickInterval = Core_Utilities.normalizeTickInterval, LogarithmicAxis_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * @private
 */
var LogarithmicAxis;
(function (LogarithmicAxis) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Provides logarithmic support for axes.
     * @private
     */
    function compose(AxisClass) {
        if (!AxisClass.keepProps.includes('logarithmic')) {
            AxisClass.keepProps.push('logarithmic');
            LogarithmicAxis_addEvent(AxisClass, 'afterSetType', onAfterSetType);
            LogarithmicAxis_addEvent(AxisClass, 'afterInit', onAfterInit);
        }
        return AxisClass;
    }
    LogarithmicAxis.compose = compose;
    /**
     * @private
     */
    function onAfterSetType() {
        var _a;
        if (this.type !== 'logarithmic') {
            this.logarithmic = void 0;
        }
        else {
            (_a = this.logarithmic) !== null && _a !== void 0 ? _a : (this.logarithmic = new Additions(this));
        }
    }
    /**
     * @private
     */
    function onAfterInit() {
        var axis = this;
        var log = axis.logarithmic;
        // Extend logarithmic axis
        if (log) {
            axis.lin2val = function (num) {
                return log.lin2log(num);
            };
            axis.val2lin = function (num) {
                return log.log2lin(num);
            };
        }
    }
    /* *
     *
     *  Class
     *
     * */
    /**
     * Provides logarithmic support for axes.
     * @private
     * @class
     */
    var Additions = /** @class */ (function () {
            /* *
            *
            *  Constructors
            *
            * */
            function Additions(axis) {
                this.axis = axis;
        }
        /* *
        *
        *  Functions
        *
        * */
        /**
         * Set the tick positions of a logarithmic axis.
         */
        Additions.prototype.getLogTickPositions = function (interval, min, max, minor) {
            var log = this;
            var axis = log.axis;
            var axisLength = axis.len;
            var options = axis.options;
            // Since we use this method for both major and minor ticks,
            // use a local variable and return the result
            var positions = [];
            // Reset
            if (!minor) {
                log.minorAutoInterval = void 0;
            }
            // First case: All ticks fall on whole logarithms: 1, 10, 100 etc.
            if (interval >= 0.5) {
                interval = Math.round(interval);
                positions = axis.getLinearTickPositions(interval, min, max);
                // Second case: We need intermediary ticks. For example
                // 1, 2, 4, 6, 8, 10, 20, 40 etc.
            }
            else if (interval >= 0.08) {
                var roundedMin = Math.floor(min);
                var intermediate = void 0,
                    i = void 0,
                    j = void 0,
                    len = void 0,
                    pos = void 0,
                    lastPos = void 0,
                    break2 = void 0;
                if (interval > 0.3) {
                    intermediate = [1, 2, 4];
                    // 0.2 equals five minor ticks per 1, 10, 100 etc
                }
                else if (interval > 0.15) {
                    intermediate = [1, 2, 4, 6, 8];
                }
                else { // 0.1 equals ten minor ticks per 1, 10, 100 etc
                    intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                }
                for (i = roundedMin; i < max + 1 && !break2; i++) {
                    len = intermediate.length;
                    for (j = 0; j < len && !break2; j++) {
                        pos = log.log2lin(log.lin2log(i) * intermediate[j]);
                        // #1670, lastPos is #3113
                        if (pos > min &&
                            (!minor || lastPos <= max) &&
                            typeof lastPos !== 'undefined') {
                            positions.push(lastPos);
                        }
                        if (lastPos > max) {
                            break2 = true;
                        }
                        lastPos = pos;
                    }
                }
                // Third case: We are so deep in between whole logarithmic values,
                // that we might as well handle the tick positions like a linear
                // axis. For example 1.01, 1.02, 1.03, 1.04.
            }
            else {
                var realMin = log.lin2log(min),
                    realMax = log.lin2log(max),
                    tickIntervalOption = minor ?
                        axis.getMinorTickInterval() :
                        options.tickInterval,
                    filteredTickIntervalOption = tickIntervalOption === 'auto' ?
                        null :
                        tickIntervalOption,
                    tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1),
                    totalPixelLength = minor ?
                        axisLength / axis.tickPositions.length :
                        axisLength;
                interval = LogarithmicAxis_pick(filteredTickIntervalOption, log.minorAutoInterval, (realMax - realMin) *
                    tickPixelIntervalOption / (totalPixelLength || 1));
                interval = LogarithmicAxis_normalizeTickInterval(interval);
                positions = axis.getLinearTickPositions(interval, realMin, realMax).map(log.log2lin);
                if (!minor) {
                    log.minorAutoInterval = interval / 5;
                }
            }
            // Set the axis-level tickInterval variable
            if (!minor) {
                axis.tickInterval = interval;
            }
            return positions;
        };
        Additions.prototype.lin2log = function (num) {
            return Math.pow(10, num);
        };
        Additions.prototype.log2lin = function (num) {
            return Math.log(num) / Math.LN10;
        };
        return Additions;
    }());
    LogarithmicAxis.Additions = Additions;
})(LogarithmicAxis || (LogarithmicAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_LogarithmicAxis = (LogarithmicAxis);

;// ./code/es5/es-modules/Core/Axis/PlotLineOrBand/PlotLineOrBandAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var PlotLineOrBandAxis_erase = Core_Utilities.erase, PlotLineOrBandAxis_extend = Core_Utilities.extend, PlotLineOrBandAxis_isNumber = Core_Utilities.isNumber;
/* *
 *
 *  Composition
 *
 * */
var PlotLineOrBandAxis;
(function (PlotLineOrBandAxis) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Variables
     *
     * */
    var PlotLineOrBandClass;
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Add a plot band after render time.
     *
     * @sample highcharts/members/axis-addplotband/
     *         Toggle the plot band from a button
     *
     * @function Highcharts.Axis#addPlotBand
     *
     * @param {Highcharts.AxisPlotBandsOptions} options
     * A configuration object for the plot band, as defined in
     * [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands).
     *
     * @return {Highcharts.PlotLineOrBand|undefined}
     * The added plot band, or `undefined` if the options are not valid.
     */
    function addPlotBand(options) {
        return this.addPlotBandOrLine(options, 'plotBands');
    }
    /**
     * Add a plot band or plot line after render time. Called from
     * addPlotBand and addPlotLine internally.
     *
     * @private
     * @function Highcharts.Axis#addPlotBandOrLine
     * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
     * The plotBand or plotLine configuration object.
     */
    function addPlotBandOrLine(options, coll) {
        var _this = this;
        var userOptions = this.userOptions;
        var obj = new PlotLineOrBandClass(this,
            options);
        if (this.visible) {
            obj = obj.render();
        }
        if (obj) { // #2189
            if (!this._addedPlotLB) {
                this._addedPlotLB = true;
                (userOptions.plotLines || [])
                    .concat(userOptions.plotBands || [])
                    .forEach(function (plotLineOptions) {
                    _this.addPlotBandOrLine(plotLineOptions);
                });
            }
            // Add it to the user options for exporting and Axis.update
            if (coll) {
                // Workaround Microsoft/TypeScript issue #32693
                var updatedOptions = (userOptions[coll] || []);
                updatedOptions.push(options);
                userOptions[coll] = updatedOptions;
            }
            this.plotLinesAndBands.push(obj);
        }
        return obj;
    }
    /**
     * Add a plot line after render time.
     *
     * @sample highcharts/members/axis-addplotline/
     *         Toggle the plot line from a button
     *
     * @function Highcharts.Axis#addPlotLine
     *
     * @param {Highcharts.AxisPlotLinesOptions} options
     * A configuration object for the plot line, as defined in
     * [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines).
     *
     * @return {Highcharts.PlotLineOrBand|undefined}
     * The added plot line, or `undefined` if the options are not valid.
     */
    function addPlotLine(options) {
        return this.addPlotBandOrLine(options, 'plotLines');
    }
    /**
     * @private
     */
    function compose(PlotLineOrBandType, AxisClass) {
        var axisProto = AxisClass.prototype;
        if (!axisProto.addPlotBand) {
            PlotLineOrBandClass = PlotLineOrBandType;
            PlotLineOrBandAxis_extend(axisProto, {
                addPlotBand: addPlotBand,
                addPlotLine: addPlotLine,
                addPlotBandOrLine: addPlotBandOrLine,
                getPlotBandPath: getPlotBandPath,
                removePlotBand: removePlotBand,
                removePlotLine: removePlotLine,
                removePlotBandOrLine: removePlotBandOrLine
            });
        }
        return AxisClass;
    }
    PlotLineOrBandAxis.compose = compose;
    /**
     * Internal function to create the SVG path definition for a plot band.
     *
     * @function Highcharts.Axis#getPlotBandPath
     *
     * @param {number} from
     * The axis value to start from.
     *
     * @param {number} to
     * The axis value to end on.
     *
     * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
     * The plotBand or plotLine configuration object.
     *
     * @return {Highcharts.SVGPathArray}
     * The SVG path definition in array form.
     */
    function getPlotBandPath(from, to, options) {
        options = options || this.options;
        var toPath = this.getPlotLinePath({
                value: to,
                force: true,
                acrossPanes: options.acrossPanes
            }),
            result = [],
            horiz = this.horiz,
            outside = !PlotLineOrBandAxis_isNumber(this.min) ||
                !PlotLineOrBandAxis_isNumber(this.max) ||
                (from < this.min && to < this.min) ||
                (from > this.max && to > this.max),
            path = this.getPlotLinePath({
                value: from,
                force: true,
                acrossPanes: options.acrossPanes
            });
        var i, 
            // #4964 check if chart is inverted or plotband is on yAxis
            plus = 1,
            isFlat;
        if (path && toPath) {
            // Flat paths don't need labels (#3836)
            if (outside) {
                isFlat = path.toString() === toPath.toString();
                plus = 0;
            }
            // Go over each subpath - for panes in Highcharts Stock
            for (i = 0; i < path.length; i += 2) {
                var pathStart = path[i],
                    pathEnd = path[i + 1],
                    toPathStart = toPath[i],
                    toPathEnd = toPath[i + 1];
                // Type checking all affected path segments. Consider
                // something smarter.
                if ((pathStart[0] === 'M' || pathStart[0] === 'L') &&
                    (pathEnd[0] === 'M' || pathEnd[0] === 'L') &&
                    (toPathStart[0] === 'M' || toPathStart[0] === 'L') &&
                    (toPathEnd[0] === 'M' || toPathEnd[0] === 'L')) {
                    // Add 1 pixel when coordinates are the same
                    if (horiz && toPathStart[1] === pathStart[1]) {
                        toPathStart[1] += plus;
                        toPathEnd[1] += plus;
                    }
                    else if (!horiz && toPathStart[2] === pathStart[2]) {
                        toPathStart[2] += plus;
                        toPathEnd[2] += plus;
                    }
                    result.push(['M', pathStart[1], pathStart[2]], ['L', pathEnd[1], pathEnd[2]], ['L', toPathEnd[1], toPathEnd[2]], ['L', toPathStart[1], toPathStart[2]], ['Z']);
                }
                result.isFlat = isFlat;
            }
        }
        return result;
    }
    /**
     * Remove a plot band by its id.
     *
     * @sample highcharts/members/axis-removeplotband/
     *         Remove plot band by id
     * @sample highcharts/members/axis-addplotband/
     *         Toggle the plot band from a button
     *
     * @function Highcharts.Axis#removePlotBand
     *
     * @param {string} id
     *        The plot band's `id` as given in the original configuration
     *        object or in the `addPlotBand` option.
     */
    function removePlotBand(id) {
        this.removePlotBandOrLine(id);
    }
    /**
     * Remove a plot band or plot line from the chart by id. Called
     * internally from `removePlotBand` and `removePlotLine`.
     * @private
     * @function Highcharts.Axis#removePlotBandOrLine
     */
    function removePlotBandOrLine(id) {
        var plotLinesAndBands = this.plotLinesAndBands,
            options = this.options,
            userOptions = this.userOptions;
        if (plotLinesAndBands) { // #15639
            var i_1 = plotLinesAndBands.length;
            while (i_1--) {
                if (plotLinesAndBands[i_1].id === id) {
                    plotLinesAndBands[i_1].destroy();
                }
            }
            ([
                options.plotLines || [],
                userOptions.plotLines || [],
                options.plotBands || [],
                userOptions.plotBands || []
            ]).forEach(function (arr) {
                i_1 = arr.length;
                while (i_1--) {
                    if ((arr[i_1] || {}).id === id) {
                        PlotLineOrBandAxis_erase(arr, arr[i_1]);
                    }
                }
            });
        }
    }
    /**
     * Remove a plot line by its id.
     *
     * @sample highcharts/xaxis/plotlines-id/
     *         Remove plot line by id
     * @sample highcharts/members/axis-addplotline/
     *         Toggle the plot line from a button
     *
     * @function Highcharts.Axis#removePlotLine
     *
     * @param {string} id
     *        The plot line's `id` as given in the original configuration
     *        object or in the `addPlotLine` option.
     */
    function removePlotLine(id) {
        this.removePlotBandOrLine(id);
    }
})(PlotLineOrBandAxis || (PlotLineOrBandAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var PlotLineOrBand_PlotLineOrBandAxis = (PlotLineOrBandAxis);

;// ./code/es5/es-modules/Core/Axis/PlotLineOrBand/PlotLineOrBand.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var PlotLineOrBand_assign = (undefined && undefined.__assign) || function () {
    PlotLineOrBand_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 PlotLineOrBand_assign.apply(this, arguments);
};


var PlotLineOrBand_addEvent = Core_Utilities.addEvent, PlotLineOrBand_arrayMax = Core_Utilities.arrayMax, PlotLineOrBand_arrayMin = Core_Utilities.arrayMin, PlotLineOrBand_defined = Core_Utilities.defined, PlotLineOrBand_destroyObjectProperties = Core_Utilities.destroyObjectProperties, PlotLineOrBand_erase = Core_Utilities.erase, PlotLineOrBand_fireEvent = Core_Utilities.fireEvent, PlotLineOrBand_merge = Core_Utilities.merge, PlotLineOrBand_objectEach = Core_Utilities.objectEach, PlotLineOrBand_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * The object wrapper for plot lines and plot bands
 *
 * @class
 * @name Highcharts.PlotLineOrBand
 *
 * @param {Highcharts.Axis} axis
 * Related axis.
 *
 * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options]
 * Options to use.
 */
var PlotLineOrBand = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function PlotLineOrBand(axis, options) {
        /**
         * Related axis.
         *
         * @name Highcharts.PlotLineOrBand#axis
         * @type {Highcharts.Axis}
         */
        this.axis = axis;
        /**
         * Options of the plot line or band.
         *
         * @name Highcharts.PlotLineOrBand#options
         * @type {AxisPlotBandsOptions|AxisPlotLinesOptions}
         */
        this.options = options;
        this.id = options.id;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    PlotLineOrBand.compose = function (ChartClass, AxisClass) {
        PlotLineOrBand_addEvent(ChartClass, 'afterInit', function () {
            var _this = this;
            this.labelCollectors.push(function () {
                var _a;
                var labels = [];
                for (var _i = 0, _b = _this.axes; _i < _b.length; _i++) {
                    var axis = _b[_i];
                    for (var _c = 0, _d = axis.plotLinesAndBands; _c < _d.length; _c++) {
                        var _e = _d[_c],
                            label = _e.label,
                            options = _e.options;
                        if (label && !((_a = options === null || options === void 0 ? void 0 : options.label) === null || _a === void 0 ? void 0 : _a.allowOverlap)) {
                            labels.push(label);
                        }
                    }
                }
                return labels;
            });
        });
        return PlotLineOrBand_PlotLineOrBandAxis.compose(PlotLineOrBand, AxisClass);
    };
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable no-invalid-this, valid-jsdoc */
    /**
     * Render the plot line or plot band. If it is already existing,
     * move it.
     * @private
     * @function Highcharts.PlotLineOrBand#render
     */
    PlotLineOrBand.prototype.render = function () {
        var _this = this;
        var _a,
            _b,
            _c;
        PlotLineOrBand_fireEvent(this, 'render');
        var _d = this,
            axis = _d.axis,
            options = _d.options,
            horiz = axis.horiz,
            logarithmic = axis.logarithmic,
            color = options.color,
            events = options.events,
            _e = options.zIndex,
            zIndex = _e === void 0 ? 0 : _e,
            _f = axis.chart,
            renderer = _f.renderer,
            time = _f.time,
            groupAttribs = {}, 
            // These properties only exist on either band or line
            to = time.parse(options.to),
            from = time.parse(options.from),
            value = time.parse(options.value),
            borderWidth = options.borderWidth;
        var optionsLabel = options.label,
            _g = this,
            label = _g.label,
            svgElem = _g.svgElem,
            path = [],
            group;
        var isBand = PlotLineOrBand_defined(from) && PlotLineOrBand_defined(to),
            isLine = PlotLineOrBand_defined(value),
            isNew = !svgElem,
            attribs = {
                'class': 'highcharts-plot-' + (isBand ? 'band ' : 'line ') +
                    (options.className || '')
            };
        var groupName = isBand ? 'bands' : 'lines';
        // Set the presentational attributes
        if (!axis.chart.styledMode) {
            if (isLine) {
                attribs.stroke = color || "#999999" /* Palette.neutralColor40 */;
                attribs['stroke-width'] = PlotLineOrBand_pick(options.width, 1);
                if (options.dashStyle) {
                    attribs.dashstyle = options.dashStyle;
                }
            }
            else if (isBand) { // Plot band
                attribs.fill = color || "#e6e9ff" /* Palette.highlightColor10 */;
                if (borderWidth) {
                    attribs.stroke = options.borderColor;
                    attribs['stroke-width'] = borderWidth;
                }
            }
        }
        // Grouping and zIndex
        groupAttribs.zIndex = zIndex;
        groupName += '-' + zIndex;
        group = axis.plotLinesAndBandsGroups[groupName];
        if (!group) {
            axis.plotLinesAndBandsGroups[groupName] = group =
                renderer.g('plot-' + groupName)
                    .attr(groupAttribs).add();
        }
        // Create the path
        if (!svgElem) {
            /**
             * SVG element of the plot line or band.
             *
             * @name Highcharts.PlotLineOrBand#svgElem
             * @type {Highcharts.SVGElement}
             */
            this.svgElem = svgElem = renderer
                .path()
                .attr(attribs)
                .add(group);
        }
        // Set the path or return
        if (PlotLineOrBand_defined(value)) { // Plot line
            path = axis.getPlotLinePath({
                value: (_a = logarithmic === null || logarithmic === void 0 ? void 0 : logarithmic.log2lin(value)) !== null && _a !== void 0 ? _a : value,
                lineWidth: svgElem.strokeWidth(),
                acrossPanes: options.acrossPanes
            });
        }
        else if (PlotLineOrBand_defined(from) && PlotLineOrBand_defined(to)) { // Plot band
            path = axis.getPlotBandPath((_b = logarithmic === null || logarithmic === void 0 ? void 0 : logarithmic.log2lin(from)) !== null && _b !== void 0 ? _b : from, (_c = logarithmic === null || logarithmic === void 0 ? void 0 : logarithmic.log2lin(to)) !== null && _c !== void 0 ? _c : to, options);
        }
        else {
            return;
        }
        // Common for lines and bands. Add events only if they were not added
        // before.
        if (!this.eventsAdded && events) {
            PlotLineOrBand_objectEach(events, function (event, eventType) {
                svgElem === null || svgElem === void 0 ? void 0 : svgElem.on(eventType, function (e) {
                    events[eventType].apply(_this, [e]);
                });
            });
            this.eventsAdded = true;
        }
        if ((isNew || !svgElem.d) && (path === null || path === void 0 ? void 0 : path.length)) {
            svgElem.attr({ d: path });
        }
        else if (svgElem) {
            if (path) {
                svgElem.show();
                svgElem.animate({ d: path });
            }
            else if (svgElem.d) {
                svgElem.hide();
                if (label) {
                    this.label = label = label.destroy();
                }
            }
        }
        // The plot band/line label
        if (optionsLabel &&
            (PlotLineOrBand_defined(optionsLabel.text) || PlotLineOrBand_defined(optionsLabel.formatter)) &&
            (path === null || path === void 0 ? void 0 : path.length) &&
            axis.width > 0 &&
            axis.height > 0 &&
            !path.isFlat) {
            // Apply defaults
            optionsLabel = PlotLineOrBand_merge(PlotLineOrBand_assign({ align: horiz && isBand ? 'center' : void 0, x: horiz ? !isBand && 4 : 10, verticalAlign: !horiz && isBand ? 'middle' : void 0, y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, rotation: horiz && !isBand ? 90 : 0 }, (isBand ? { inside: true } : {})), optionsLabel);
            this.renderLabel(optionsLabel, path, isBand, zIndex);
            // Move out of sight
        }
        else if (label) {
            label.hide();
        }
        // Chainable
        return this;
    };
    /**
     * Render and align label for plot line or band.
     * @private
     * @function Highcharts.PlotLineOrBand#renderLabel
     */
    PlotLineOrBand.prototype.renderLabel = function (optionsLabel, path, isBand, zIndex) {
        var _a;
        var plotLine = this,
            axis = plotLine.axis,
            renderer = axis.chart.renderer,
            inside = optionsLabel.inside;
        var label = plotLine.label;
        // Add the SVG element
        if (!label) {
            /**
             * SVG element of the label.
             *
             * @name Highcharts.PlotLineOrBand#label
             * @type {Highcharts.SVGElement}
             */
            plotLine.label = label = renderer
                .text(this.getLabelText(optionsLabel), 0, 0, optionsLabel.useHTML)
                .attr({
                align: optionsLabel.textAlign || optionsLabel.align,
                rotation: optionsLabel.rotation,
                'class': 'highcharts-plot-' + (isBand ? 'band' : 'line') +
                    '-label ' + (optionsLabel.className || ''),
                zIndex: zIndex
            });
            if (!axis.chart.styledMode) {
                label.css(PlotLineOrBand_merge({
                    fontSize: '0.8em',
                    textOverflow: (isBand && !inside) ? '' : 'ellipsis'
                }, optionsLabel.style));
            }
            label.add();
        }
        // Get the bounding box and align the label
        // #3000 changed to better handle choice between plotband or plotline
        var xBounds = path.xBounds ||
                [path[0][1],
            path[1][1], (isBand ? path[2][1] : path[0][1])],
            yBounds = path.yBounds ||
                [path[0][2],
            path[1][2], (isBand ? path[2][2] : path[0][2])],
            x = PlotLineOrBand_arrayMin(xBounds),
            y = PlotLineOrBand_arrayMin(yBounds),
            bBoxWidth = PlotLineOrBand_arrayMax(xBounds) - x;
        label.align(optionsLabel, false, {
            x: x,
            y: y,
            width: bBoxWidth,
            height: PlotLineOrBand_arrayMax(yBounds) - y
        });
        if (!label.alignValue ||
            label.alignValue === 'left' ||
            PlotLineOrBand_defined(inside)) {
            label.css({
                width: (((_a = optionsLabel.style) === null || _a === void 0 ? void 0 : _a.width) || ((!isBand ||
                    !inside) ? (label.rotation === 90 ?
                    axis.height - (label.alignAttr.y -
                        axis.top) : (optionsLabel.clip ?
                    axis.width :
                    axis.chart.chartWidth) - (label.alignAttr.x - axis.left)) :
                    bBoxWidth)) + 'px'
            });
        }
        label.show(true);
    };
    /**
     * Get label's text content.
     * @private
     * @function Highcharts.PlotLineOrBand#getLabelText
     */
    PlotLineOrBand.prototype.getLabelText = function (optionsLabel) {
        return PlotLineOrBand_defined(optionsLabel.formatter) ?
            optionsLabel.formatter
                .call(this) :
            optionsLabel.text;
    };
    /**
     * Remove the plot line or band.
     *
     * @function Highcharts.PlotLineOrBand#destroy
     */
    PlotLineOrBand.prototype.destroy = function () {
        // Remove it from the lookup
        PlotLineOrBand_erase(this.axis.plotLinesAndBands, this);
        delete this.axis;
        PlotLineOrBand_destroyObjectProperties(this);
    };
    return PlotLineOrBand;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var PlotLineOrBand_PlotLineOrBand = (PlotLineOrBand);
/* *
 *
 *  API Options
 *
 * */
/**
 * Options for plot bands on axes.
 *
 * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions
 */
/**
 * Options for plot band labels on axes.
 *
 * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions
 */
/**
 * Options for plot lines on axes.
 *
 * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions
 */
/**
 * Options for plot line labels on axes.
 *
 * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions
 */
('');
/* *
 *
 *  API Options
 *
 * */
/**
 * An array of colored bands stretching across the plot area marking an
 * interval on the axis.
 *
 * In styled mode, the plot bands are styled by the `.highcharts-plot-band`
 * class in addition to the `className` option.
 *
 * @productdesc {highcharts}
 * In a gauge, a plot band on the Y axis (value axis) will stretch along the
 * perimeter of the gauge.
 *
 * @type      {Array<*>}
 * @product   highcharts highstock gantt
 * @apioption xAxis.plotBands
 */
/**
 * Flag to decide if plotBand should be rendered across all panes.
 *
 * @since     7.1.2
 * @product   highstock
 * @type      {boolean}
 * @default   true
 * @apioption xAxis.plotBands.acrossPanes
 */
/**
 * Border color for the plot band. Also requires `borderWidth` to be set.
 *
 * @type      {Highcharts.ColorString}
 * @apioption xAxis.plotBands.borderColor
 */
/**
 * Border radius for the plot band. Applies only to gauges. Can be a pixel
 * value or a percentage, for example `50%`.
 *
 * @type      {number|string}
 * @since 11.4.2
 * @sample    {highcharts} highcharts/xaxis/plotbands-gauge-borderradius
 *            Angular gauge with rounded plot bands
 * @apioption xAxis.plotBands.borderRadius
 */
/**
 * Border width for the plot band. Also requires `borderColor` to be set.
 *
 * @type      {number}
 * @default   0
 * @apioption xAxis.plotBands.borderWidth
 */
/**
 * A custom class name, in addition to the default `highcharts-plot-band`,
 * to apply to each individual band.
 *
 * @type      {string}
 * @since     5.0.0
 * @apioption xAxis.plotBands.className
 */
/**
 * The color of the plot band.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-color/
 *         Color band
 * @sample {highstock} stock/xaxis/plotbands/
 *         Plot band on Y axis
 *
 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
 * @default   ${palette.highlightColor10}
 * @apioption xAxis.plotBands.color
 */
/**
 * An object defining mouse events for the plot band. Supported properties
 * are `click`, `mouseover`, `mouseout`, `mousemove`.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-events/
 *         Mouse events demonstrated
 *
 * @since     1.2
 * @apioption xAxis.plotBands.events
 */
/**
 * Click event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotBands.events.click
 */
/**
 * Mouse move event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotBands.events.mousemove
 */
/**
 * Mouse out event on the corner of a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotBands.events.mouseout
 */
/**
 * Mouse over event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotBands.events.mouseover
 */
/**
 * The start position of the plot band in axis units.
 *
 * On datetime axes, the value can be given as a timestamp or a date string.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-color/
 *         Datetime axis
 * @sample {highcharts} highcharts/xaxis/plotbands-from/
 *         Categorized axis
 * @sample {highstock} stock/xaxis/plotbands/
 *         Plot band on Y axis
 *
 * @type      {number|string}
 * @apioption xAxis.plotBands.from
 */
/**
 * An id used for identifying the plot band in Axis.removePlotBand.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-id/
 *         Remove plot band by id
 * @sample {highstock} highcharts/xaxis/plotbands-id/
 *         Remove plot band by id
 *
 * @type      {string}
 * @apioption xAxis.plotBands.id
 */
/**
 * The end position of the plot band in axis units.
 *
 * On datetime axes, the value can be given as a timestamp or a date string.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-color/
 *         Datetime axis
 * @sample {highcharts} highcharts/xaxis/plotbands-from/
 *         Categorized axis
 * @sample {highstock} stock/xaxis/plotbands/
 *         Plot band on Y axis
 *
 * @type      {number|string}
 * @apioption xAxis.plotBands.to
 */
/**
 * The z index of the plot band within the chart, relative to other
 * elements. Using the same z index as another element may give
 * unpredictable results, as the last rendered element will be on top.
 * Values from 0 to 20 make sense.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-color/
 *         Behind plot lines by default
 * @sample {highcharts} highcharts/xaxis/plotbands-zindex/
 *         Above plot lines
 * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/
 *         Above plot lines and series
 *
 * @type      {number}
 * @since     1.2
 * @apioption xAxis.plotBands.zIndex
 */
/**
 * Text labels for the plot bands
 *
 * @product   highcharts highstock gantt
 * @apioption xAxis.plotBands.label
 */
/**
 * Horizontal alignment of the label. Can be one of "left", "center" or
 * "right".
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
 *         Aligned to the right
 * @sample {highstock} stock/xaxis/plotbands-label/
 *         Plot band with labels
 *
 * @type      {Highcharts.AlignValue}
 * @default   center
 * @since     2.1
 * @apioption xAxis.plotBands.label.align
 */
/**
 * Whether or not the label can be hidden if it overlaps with another label.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-allowoverlap/
 *         A Plotband label overlapping another
 *
 * @type      {boolean}
 * @default   undefined
 * @since     11.4.8
 * @apioption xAxis.plotBands.label.allowOverlap
 */
/**
 * Wether or not the text of the label can exceed the width of the label.
 *
 * @type      {boolean}
 * @product   highcharts highstock gantt
 * @sample {highcharts} highcharts/xaxis/plotbands-label-textwidth/
 *         Displaying text with text-wrapping/ellipsis, or the full text.
 *
 * @default   true
 * @since     11.4.6
 * @apioption xAxis.plotBands.label.inside
 */
/**
 * Rotation of the text label in degrees .
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
 *         Vertical text
 *
 * @type      {number}
 * @default   0
 * @since     2.1
 * @apioption xAxis.plotBands.label.rotation
 */
/**
 * CSS styles for the text label.
 *
 * In styled mode, the labels are styled by the
 * `.highcharts-plot-band-label` class.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-style/
 *         Blue and bold label
 *
 * @type      {Highcharts.CSSObject}
 * @since     2.1
 * @apioption xAxis.plotBands.label.style
 */
/**
 * The string text itself. A subset of HTML is supported.
 *
 * @type      {string}
 * @since     2.1
 * @apioption xAxis.plotBands.label.text
 */
/**
 * The text alignment for the label. While `align` determines where the
 * texts anchor point is placed within the plot band, `textAlign` determines
 * how the text is aligned against its anchor point. Possible values are
 * "left", "center" and "right". Defaults to the same as the `align` option.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
 *         Vertical text in center position but text-aligned left
 *
 * @type       {Highcharts.AlignValue}
 * @since      2.1
 * @apioption  xAxis.plotBands.label.textAlign
 */
/**
 * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
 * to render the labels.
 *
 * @type      {boolean}
 * @default   false
 * @since     3.0.3
 * @apioption xAxis.plotBands.label.useHTML
 */
/**
 * Vertical alignment of the label relative to the plot band. Can be one of
 * "top", "middle" or "bottom".
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/
 *         Vertically centered label
 * @sample {highstock} stock/xaxis/plotbands-label/
 *         Plot band with labels
 *
 * @type       {Highcharts.VerticalAlignValue}
 * @default    top
 * @since      2.1
 * @apioption  xAxis.plotBands.label.verticalAlign
 */
/**
 * Horizontal position relative the alignment. Default varies by
 * orientation.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
 *         Aligned 10px from the right edge
 * @sample {highstock} stock/xaxis/plotbands-label/
 *         Plot band with labels
 *
 * @type      {number}
 * @since     2.1
 * @apioption xAxis.plotBands.label.x
 */
/**
 * Vertical position of the text baseline relative to the alignment. Default
 * varies by orientation.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-label-y/
 *         Label on x axis
 * @sample {highstock} stock/xaxis/plotbands-label/
 *         Plot band with labels
 *
 * @type      {number}
 * @since     2.1
 * @apioption xAxis.plotBands.label.y
 */
/**
 * An array of lines stretching across the plot area, marking a specific
 * value on one of the axes.
 *
 * In styled mode, the plot lines are styled by the
 * `.highcharts-plot-line` class in addition to the `className` option.
 *
 * @type      {Array<*>}
 * @product   highcharts highstock gantt
 * @sample {highcharts} highcharts/xaxis/plotlines-color/
 *         Basic plot line
 * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
 *         Solid gauge plot line
 * @apioption xAxis.plotLines
 */
/**
 * Flag to decide if plotLine should be rendered across all panes.
 *
 * @sample {highstock} stock/xaxis/plotlines-acrosspanes/
 *         Plot lines on different panes
 *
 * @since     7.1.2
 * @product   highstock
 * @type      {boolean}
 * @default   true
 * @apioption xAxis.plotLines.acrossPanes
 */
/**
 * A custom class name, in addition to the default `highcharts-plot-line`,
 * to apply to each individual line.
 *
 * @type      {string}
 * @since     5.0.0
 * @apioption xAxis.plotLines.className
 */
/**
 * The color of the line.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-color/
 *         A red line from X axis
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {Highcharts.ColorString}
 * @default   ${palette.neutralColor40}
 * @apioption xAxis.plotLines.color
 */
/**
 * The dashing or dot style for the plot line. For possible values see
 * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/
 *         Dash and dot pattern
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {Highcharts.DashStyleValue}
 * @default   Solid
 * @since     1.2
 * @apioption xAxis.plotLines.dashStyle
 */
/**
 * An object defining mouse events for the plot line. Supported
 * properties are `click`, `mouseover`, `mouseout`, `mousemove`.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-events/
 *         Mouse events demonstrated
 *
 * @since     1.2
 * @apioption xAxis.plotLines.events
 */
/**
 * Click event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotLines.events.click
 */
/**
 * Mouse move event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotLines.events.mousemove
 */
/**
 * Mouse out event on the corner of a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotLines.events.mouseout
 */
/**
 * Mouse over event on a plot band.
 *
 * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotLines.events.mouseover
 */
/**
 * An id used for identifying the plot line in Axis.removePlotLine.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-id/
 *         Remove plot line by id
 *
 * @type      {string}
 * @apioption xAxis.plotLines.id
 */
/**
 * The position of the line in axis units.
 *
 * On datetime axes, the value can be given as a timestamp or a date string.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-color/
 *         Between two categories on X axis
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {number|string}
 * @apioption xAxis.plotLines.value
 */
/**
 * The width or thickness of the plot line.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-color/
 *         2px wide line from X axis
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {number}
 * @default   2
 * @apioption xAxis.plotLines.width
 */
/**
 * The z index of the plot line within the chart.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/
 *         Behind plot lines by default
 * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/
 *         Above plot lines
 * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/
 *         Above plot lines and series
 *
 * @type      {number}
 * @since     1.2
 * @apioption xAxis.plotLines.zIndex
 */
/**
 * Text labels for the plot bands
 *
 * @apioption xAxis.plotLines.label
 */
/**
 * Horizontal alignment of the label. Can be one of "left", "center" or
 * "right".
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
 *         Aligned to the right
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type       {Highcharts.AlignValue}
 * @default    left
 * @since      2.1
 * @apioption  xAxis.plotLines.label.align
 */
/**
 * Whether to hide labels that are outside the plot area.
 *
 * @type      {boolean}
 * @default   false
 * @since 10.3.3
 * @apioption xAxis.plotLines.labels.clip
 */
/**
 * Callback JavaScript function to format the label. Useful properties like
 * the value of plot line or the range of plot band (`from` & `to`
 * properties) can be found in `this.options` object.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter
 *         Label formatters for plot line and plot band.
 * @type      {Highcharts.FormatterCallbackFunction<Highcharts.PlotLineOrBand>}
 * @apioption xAxis.plotLines.label.formatter
 */
/**
 * Rotation of the text label in degrees. Defaults to 0 for horizontal plot
 * lines and 90 for vertical lines.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
 *         Slanted text
 *
 * @type      {number}
 * @since     2.1
 * @apioption xAxis.plotLines.label.rotation
 */
/**
 * CSS styles for the text label.
 *
 * In styled mode, the labels are styled by the
 * `.highcharts-plot-line-label` class.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-style/
 *         Blue and bold label
 *
 * @type      {Highcharts.CSSObject}
 * @since     2.1
 * @apioption xAxis.plotLines.label.style
 */
/**
 * The text itself. A subset of HTML is supported.
 *
 * @type      {string}
 * @since     2.1
 * @apioption xAxis.plotLines.label.text
 */
/**
 * The text alignment for the label. While `align` determines where the
 * texts anchor point is placed within the plot band, `textAlign` determines
 * how the text is aligned against its anchor point. Possible values are
 * "left", "center" and "right". Defaults to the same as the `align` option.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/
 *         Text label in bottom position
 *
 * @type      {Highcharts.AlignValue}
 * @since     2.1
 * @apioption xAxis.plotLines.label.textAlign
 */
/**
 * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
 * to render the labels.
 *
 * @type      {boolean}
 * @default   false
 * @since     3.0.3
 * @apioption xAxis.plotLines.label.useHTML
 */
/**
 * Vertical alignment of the label relative to the plot line. Can be
 * one of "top", "middle" or "bottom".
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
 *         Vertically centered label
 *
 * @type       {Highcharts.VerticalAlignValue}
 * @default    {highcharts} top
 * @default    {highstock} top
 * @since      2.1
 * @apioption  xAxis.plotLines.label.verticalAlign
 */
/**
 * Horizontal position relative the alignment. Default varies by
 * orientation.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
 *         Aligned 10px from the right edge
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {number}
 * @since     2.1
 * @apioption xAxis.plotLines.label.x
 */
/**
 * Vertical position of the text baseline relative to the alignment. Default
 * varies by orientation.
 *
 * @sample {highcharts} highcharts/xaxis/plotlines-label-y/
 *         Label below the plot line
 * @sample {highstock} stock/xaxis/plotlines/
 *         Plot line on Y axis
 *
 * @type      {number}
 * @since     2.1
 * @apioption xAxis.plotLines.label.y
 */
/**
 * @type      {Array<*>}
 * @extends   xAxis.plotBands
 * @apioption yAxis.plotBands
 */
/**
 * In a gauge chart, this option determines the inner radius of the
 * plot band that stretches along the perimeter. It can be given as
 * a percentage string, like `"100%"`, or as a pixel number, like `100`.
 * By default, the inner radius is controlled by the [thickness](
 * #yAxis.plotBands.thickness) option.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-gauge
 *         Gauge plot band
 *
 * @type      {number|string}
 * @since     2.3
 * @product   highcharts
 * @apioption yAxis.plotBands.innerRadius
 */
/**
 * In a gauge chart, this option determines the outer radius of the
 * plot band that stretches along the perimeter. It can be given as
 * a percentage string, like `"100%"`, or as a pixel number, like `100`.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-gauge
 *         Gauge plot band
 *
 * @type      {number|string}
 * @default   100%
 * @since     2.3
 * @product   highcharts
 * @apioption yAxis.plotBands.outerRadius
 */
/**
 * In a gauge chart, this option sets the width of the plot band
 * stretching along the perimeter. It can be given as a percentage
 * string, like `"10%"`, or as a pixel number, like `10`. The default
 * value 10 is the same as the default [tickLength](#yAxis.tickLength),
 * thus making the plot band act as a background for the tick markers.
 *
 * @sample {highcharts} highcharts/xaxis/plotbands-gauge
 *         Gauge plot band
 *
 * @type      {number|string}
 * @default   10
 * @since     2.3
 * @product   highcharts
 * @apioption yAxis.plotBands.thickness
 */
/**
 * @type      {Array<*>}
 * @extends   xAxis.plotLines
 * @apioption yAxis.plotLines
 */
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Tooltip.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Tooltip_animObject = AnimationUtilities.animObject;

var Tooltip_format = Core_Templating.format;

var Tooltip_composed = Core_Globals.composed, dateFormats = Core_Globals.dateFormats, Tooltip_doc = Core_Globals.doc, isSafari = Core_Globals.isSafari;

var distribute = Renderer_RendererUtilities.distribute;


var Tooltip_addEvent = Core_Utilities.addEvent, Tooltip_clamp = Core_Utilities.clamp, Tooltip_css = Core_Utilities.css, Tooltip_discardElement = Core_Utilities.discardElement, Tooltip_extend = Core_Utilities.extend, Tooltip_fireEvent = Core_Utilities.fireEvent, Tooltip_isArray = Core_Utilities.isArray, Tooltip_isNumber = Core_Utilities.isNumber, Tooltip_isObject = Core_Utilities.isObject, Tooltip_isString = Core_Utilities.isString, Tooltip_merge = Core_Utilities.merge, Tooltip_pick = Core_Utilities.pick, Tooltip_pushUnique = Core_Utilities.pushUnique, Tooltip_splat = Core_Utilities.splat, Tooltip_syncTimeout = Core_Utilities.syncTimeout;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * Tooltip of a chart.
 *
 * @class
 * @name Highcharts.Tooltip
 *
 * @param {Highcharts.Chart} chart
 * The chart instance.
 *
 * @param {Highcharts.TooltipOptions} options
 * Tooltip options.
 *
 * @param {Highcharts.Pointer} pointer
 * The pointer instance.
 */
var Tooltip = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Tooltip(chart, options, pointer) {
        /* *
         *
         *  Properties
         *
         * */
        this.allowShared = true;
        this.crosshairs = [];
        this.distance = 0;
        this.isHidden = true;
        this.isSticky = false;
        this.options = {};
        this.outside = false;
        this.chart = chart;
        this.init(chart, options);
        this.pointer = pointer;
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Build the body (lines) of the tooltip by iterating over the items and
     * returning one entry for each item, abstracting this functionality allows
     * to easily overwrite and extend it.
     *
     * @private
     * @function Highcharts.Tooltip#bodyFormatter
     */
    Tooltip.prototype.bodyFormatter = function (points) {
        return points.map(function (point) {
            var tooltipOptions = point.series.tooltipOptions,
                formatPrefix = point.formatPrefix || 'point';
            return (tooltipOptions[formatPrefix + 'Formatter'] ||
                point.tooltipFormatter).call(point, tooltipOptions[formatPrefix + 'Format'] || '');
        });
    };
    /**
     * Destroy the single tooltips in a split tooltip.
     * If the tooltip is active then it is not destroyed, unless forced to.
     *
     * @private
     * @function Highcharts.Tooltip#cleanSplit
     *
     * @param {boolean} [force]
     * Force destroy all tooltips.
     */
    Tooltip.prototype.cleanSplit = function (force) {
        this.chart.series.forEach(function (series) {
            var tt = series && series.tt;
            if (tt) {
                if (!tt.isActive || force) {
                    series.tt = tt.destroy();
                }
                else {
                    tt.isActive = false;
                }
            }
        });
    };
    /**
     * In case no user defined formatter is given, this will be used. Note that
     * the context here is an object holding point, series, x, y etc.
     *
     * @function Highcharts.Tooltip#defaultFormatter
     *
     * @param {Highcharts.Tooltip} tooltip
     *
     * @return {string|Array<string>}
     * Returns a string (single tooltip and shared)
     * or an array of strings (split tooltip)
     */
    Tooltip.prototype.defaultFormatter = function (tooltip) {
        var hoverPoints = this.points || Tooltip_splat(this);
        var s;
        // Build the header
        s = [tooltip.headerFooterFormatter(hoverPoints[0])];
        // Build the values
        s = s.concat(tooltip.bodyFormatter(hoverPoints));
        // Footer
        s.push(tooltip.headerFooterFormatter(hoverPoints[0], true));
        return s;
    };
    /**
     * Removes and destroys the tooltip and its elements.
     *
     * @function Highcharts.Tooltip#destroy
     */
    Tooltip.prototype.destroy = function () {
        // Destroy and clear local variables
        if (this.label) {
            this.label = this.label.destroy();
        }
        if (this.split) {
            this.cleanSplit(true);
            if (this.tt) {
                this.tt = this.tt.destroy();
            }
        }
        if (this.renderer) {
            this.renderer = this.renderer.destroy();
            Tooltip_discardElement(this.container);
        }
        Core_Utilities.clearTimeout(this.hideTimer);
    };
    /**
     * Extendable method to get the anchor position of the tooltip
     * from a point or set of points
     *
     * @private
     * @function Highcharts.Tooltip#getAnchor
     */
    Tooltip.prototype.getAnchor = function (points, mouseEvent) {
        var _a = this,
            chart = _a.chart,
            pointer = _a.pointer,
            inverted = chart.inverted,
            plotTop = chart.plotTop,
            plotLeft = chart.plotLeft;
        var ret;
        points = Tooltip_splat(points);
        // If reversedStacks are false the tooltip position should be taken from
        // the last point (#17948)
        if (points[0].series &&
            points[0].series.yAxis &&
            !points[0].series.yAxis.options.reversedStacks) {
            points = points.slice().reverse();
        }
        // When tooltip follows mouse, relate the position to the mouse
        if (this.followPointer && mouseEvent) {
            if (typeof mouseEvent.chartX === 'undefined') {
                mouseEvent = pointer.normalize(mouseEvent);
            }
            ret = [
                mouseEvent.chartX - plotLeft,
                mouseEvent.chartY - plotTop
            ];
            // Some series types use a specificly calculated tooltip position for
            // each point
        }
        else if (points[0].tooltipPos) {
            ret = points[0].tooltipPos;
            // Calculate the average position and adjust for axis positions
        }
        else {
            var chartX_1 = 0,
                chartY_1 = 0;
            points.forEach(function (point) {
                var pos = point.pos(true);
                if (pos) {
                    chartX_1 += pos[0];
                    chartY_1 += pos[1];
                }
            });
            chartX_1 /= points.length;
            chartY_1 /= points.length;
            // When shared, place the tooltip next to the mouse (#424)
            if (this.shared && points.length > 1 && mouseEvent) {
                if (inverted) {
                    chartX_1 = mouseEvent.chartX;
                }
                else {
                    chartY_1 = mouseEvent.chartY;
                }
            }
            // Use the average position for multiple points
            ret = [chartX_1 - plotLeft, chartY_1 - plotTop];
        }
        return ret.map(Math.round);
    };
    /**
     * Get the CSS class names for the tooltip's label. Styles the label
     * by `colorIndex` or user-defined CSS.
     *
     * @function Highcharts.Tooltip#getClassName
     *
     * @return {string}
     *         The class names.
     */
    Tooltip.prototype.getClassName = function (point, isSplit, isHeader) {
        var options = this.options,
            series = point.series,
            seriesOptions = series.options;
        return [
            options.className,
            'highcharts-label',
            isHeader && 'highcharts-tooltip-header',
            isSplit ? 'highcharts-tooltip-box' : 'highcharts-tooltip',
            !isHeader && 'highcharts-color-' + Tooltip_pick(point.colorIndex, series.colorIndex),
            (seriesOptions && seriesOptions.className)
        ].filter(Tooltip_isString).join(' ');
    };
    /**
     * Creates the Tooltip label element if it does not exist, then returns it.
     *
     * @function Highcharts.Tooltip#getLabel
     *
     * @return {Highcharts.SVGElement}
     * Tooltip label
     */
    Tooltip.prototype.getLabel = function (_a) {
        var _b = _a === void 0 ? { anchorX: 0,
            anchorY: 0 } : _a,
            anchorX = _b.anchorX,
            anchorY = _b.anchorY;
        var tooltip = this,
            styledMode = this.chart.styledMode,
            options = this.options,
            doSplit = this.split && this.allowShared;
        var container = this.container,
            renderer = this.chart.renderer;
        // If changing from a split tooltip to a non-split tooltip, we must
        // destroy it in order to get the SVG right. #13868.
        if (this.label) {
            var wasSplit = !this.label.hasClass('highcharts-label');
            if ((!doSplit && wasSplit) || (doSplit && !wasSplit)) {
                this.destroy();
            }
        }
        if (!this.label) {
            if (this.outside) {
                var chart = this.chart,
                    chartStyle = chart.options.chart.style,
                    Renderer = Renderer_RendererRegistry.getRendererType();
                /**
                 * Reference to the tooltip's container, when
                 * [Highcharts.Tooltip#outside] is set to true, otherwise
                 * it's undefined.
                 *
                 * @name Highcharts.Tooltip#container
                 * @type {Highcharts.HTMLDOMElement|undefined}
                 */
                this.container = container = Core_Globals.doc.createElement('div');
                container.className = ('highcharts-tooltip-container ' +
                    (chart.renderTo.className.match(/(highcharts[a-zA-Z0-9-]+)\s?/gm) || [].join(' ')));
                // We need to set pointerEvents = 'none' as otherwise it makes
                // the area under the tooltip non-hoverable even after the
                // tooltip disappears, #19035.
                Tooltip_css(container, {
                    position: 'absolute',
                    top: '1px',
                    pointerEvents: 'none',
                    zIndex: Math.max(this.options.style.zIndex || 0, (chartStyle && chartStyle.zIndex || 0) + 3)
                });
                /**
                 * Reference to the tooltip's renderer, when
                 * [Highcharts.Tooltip#outside] is set to true, otherwise
                 * it's undefined.
                 *
                 * @name Highcharts.Tooltip#renderer
                 * @type {Highcharts.SVGRenderer|undefined}
                 */
                this.renderer = renderer = new Renderer(container, 0, 0, chartStyle, void 0, void 0, renderer.styledMode);
            }
            // Create the label
            if (doSplit) {
                this.label = renderer.g('tooltip');
            }
            else {
                this.label = renderer
                    .label('', anchorX, anchorY, options.shape, void 0, void 0, options.useHTML, void 0, 'tooltip')
                    .attr({
                    padding: options.padding,
                    r: options.borderRadius
                });
                if (!styledMode) {
                    this.label
                        .attr({
                        fill: options.backgroundColor,
                        'stroke-width': options.borderWidth || 0
                    })
                        // #2301, #2657
                        .css(options.style)
                        .css({
                        pointerEvents: (options.style.pointerEvents ||
                            (this.shouldStickOnContact() ? 'auto' : 'none'))
                    });
                }
            }
            // Split tooltip use updateTooltipContainer to position the tooltip
            // container.
            if (tooltip.outside) {
                var label_1 = this.label;
                [label_1.xSetter, label_1.ySetter].forEach(function (setter, i) {
                    label_1[i ? 'ySetter' : 'xSetter'] = function (value) {
                        setter.call(label_1, tooltip.distance);
                        label_1[i ? 'y' : 'x'] = value;
                        if (container) {
                            container.style[i ? 'top' : 'left'] = "" + value + "px";
                        }
                    };
                });
            }
            this.label
                .attr({ zIndex: 8 })
                .shadow(options.shadow)
                .add();
        }
        if (container && !container.parentElement) {
            Core_Globals.doc.body.appendChild(container);
        }
        return this.label;
    };
    /**
     * Get the total area available area to place the tooltip
     *
     * @private
     */
    Tooltip.prototype.getPlayingField = function () {
        var body = Tooltip_doc.body,
            documentElement = Tooltip_doc.documentElement,
            _a = this,
            chart = _a.chart,
            distance = _a.distance,
            outside = _a.outside;
        return {
            width: outside ?
                // Subtract distance to prevent scrollbars
                Math.max(body.scrollWidth, documentElement.scrollWidth, body.offsetWidth, documentElement.offsetWidth, documentElement.clientWidth) - (2 * distance) - 2 :
                chart.chartWidth,
            height: outside ?
                Math.max(body.scrollHeight, documentElement.scrollHeight, body.offsetHeight, documentElement.offsetHeight, documentElement.clientHeight) :
                chart.chartHeight
        };
    };
    /**
     * Place the tooltip in a chart without spilling over and not covering the
     * point itself.
     *
     * @function Highcharts.Tooltip#getPosition
     *
     * @param {number} boxWidth
     *        Width of the tooltip box.
     *
     * @param {number} boxHeight
     *        Height of the tooltip box.
     *
     * @param {Highcharts.Point} point
     *        Tooltip related point.
     *
     * @return {Highcharts.PositionObject}
     *         Recommended position of the tooltip.
     */
    Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) {
        var _a,
            _b;
        var _c = this, distance = _c.distance, chart = _c.chart, outside = _c.outside, pointer = _c.pointer, inverted = chart.inverted, plotLeft = chart.plotLeft, plotTop = chart.plotTop, polar = chart.polar, _d = point.plotX, plotX = _d === void 0 ? 0 : _d, _e = point.plotY, plotY = _e === void 0 ? 0 : _e, ret = {}, 
            // Don't use h if chart isn't inverted (#7242) ???
            h = (inverted && point.h) || 0, // #4117 ???
            _f = this.getPlayingField(), outerHeight = _f.height, outerWidth = _f.width, chartPosition = pointer.getChartPosition(), scaleX = function (val) { return (val * chartPosition.scaleX); }, scaleY = function (val) { return (val * chartPosition.scaleY); }, 
            // Build parameter arrays for firstDimension()/secondDimension()
            buildDimensionArray = function (dim) {
                var isX = dim === 'x';
            return [
                dim, // Dimension - x or y
                isX ? outerWidth : outerHeight,
                isX ? boxWidth : boxHeight
            ].concat(outside ? [
                // If we are using tooltip.outside, we need to scale the
                // position to match scaling of the container in case there
                // is a transform/zoom on the container. #11329
                isX ? scaleX(boxWidth) : scaleY(boxHeight),
                isX ? chartPosition.left - distance +
                    scaleX(plotX + plotLeft) :
                    chartPosition.top - distance +
                        scaleY(plotY + plotTop),
                0,
                isX ? outerWidth : outerHeight
            ] : [
                // Not outside, no scaling is needed
                isX ? boxWidth : boxHeight,
                isX ? plotX + plotLeft : plotY + plotTop,
                isX ? plotLeft : plotTop,
                isX ? plotLeft + chart.plotWidth :
                    plotTop + chart.plotHeight
            ]);
        };
        var first = buildDimensionArray('y'), second = buildDimensionArray('x'), swapped;
        // Handle negative points or reversed axis (#13780)
        var flipped = !!point.negative;
        if (!polar &&
            ((_b = (_a = chart.hoverSeries) === null || _a === void 0 ? void 0 : _a.yAxis) === null || _b === void 0 ? void 0 : _b.reversed)) {
            flipped = !flipped;
        }
        // The far side is right or bottom
        var preferFarSide = !this.followPointer &&
                Tooltip_pick(point.ttBelow,
            polar ? false : !inverted === flipped), // #4984
            /*
             * Handle the preferred dimension. When the preferred dimension is
             * tooltip on top or bottom of the point,
            it will look for space
             * there.
             *
             * @private
             */
            firstDimension = function (dim,
            outerSize,
            innerSize,
            scaledInnerSize, // #11329
            point,
            min,
            max) {
                var scaledDist = outside ?
                    (dim === 'y' ? scaleY(distance) : scaleX(distance)) :
                    distance,
            scaleDiff = (innerSize - scaledInnerSize) / 2,
            roomLeft = scaledInnerSize < point - distance,
            roomRight = point + distance + scaledInnerSize < outerSize,
            alignedLeft = point - scaledDist - innerSize + scaleDiff,
            alignedRight = point + scaledDist - scaleDiff;
            if (preferFarSide && roomRight) {
                ret[dim] = alignedRight;
            }
            else if (!preferFarSide && roomLeft) {
                ret[dim] = alignedLeft;
            }
            else if (roomLeft) {
                ret[dim] = Math.min(max - scaledInnerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h);
            }
            else if (roomRight) {
                ret[dim] = Math.max(min, alignedRight + h + innerSize > outerSize ?
                    alignedRight :
                    alignedRight + h);
            }
            else {
                return false;
            }
        }, 
        /*
         * Handle the secondary dimension. If the preferred dimension is
         * tooltip on top or bottom of the point, the second dimension is to
         * align the tooltip above the point, trying to align center but
         * allowing left or right align within the chart box.
         *
         * @private
         */
        secondDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329
        point) {
            // Too close to the edge, return false and swap dimensions
            if (point < distance || point > outerSize - distance) {
                return false;
            }
            // Align left/top
            if (point < innerSize / 2) {
                ret[dim] = 1;
                // Align right/bottom
            }
            else if (point > outerSize - scaledInnerSize / 2) {
                ret[dim] = outerSize - scaledInnerSize - 2;
                // Align center
            }
            else {
                ret[dim] = point - innerSize / 2;
            }
        }, 
        /*
         * Swap the dimensions
         */
        swap = function (count) {
            var _a;
            _a = [second, first], first = _a[0], second = _a[1];
            swapped = count;
        }, run = function () {
            if (firstDimension.apply(0, first) !== false) {
                if (secondDimension.apply(0, second) === false &&
                    !swapped) {
                    swap(true);
                    run();
                }
            }
            else if (!swapped) {
                swap(true);
                run();
            }
            else {
                ret.x = ret.y = 0;
            }
        };
        // Under these conditions, prefer the tooltip on the side of the point
        if ((inverted && !polar) || this.len > 1) {
            swap();
        }
        run();
        return ret;
    };
    /**
     * Hides the tooltip with a fade out animation.
     *
     * @function Highcharts.Tooltip#hide
     *
     * @param {number} [delay]
     *        The fade out in milliseconds. If no value is provided the value
     *        of the tooltip.hideDelay option is used. A value of 0 disables
     *        the fade out animation.
     */
    Tooltip.prototype.hide = function (delay) {
        var tooltip = this;
        // Disallow duplicate timers (#1728, #1766)
        Core_Utilities.clearTimeout(this.hideTimer);
        delay = Tooltip_pick(delay, this.options.hideDelay);
        if (!this.isHidden) {
            this.hideTimer = Tooltip_syncTimeout(function () {
                var label = tooltip.getLabel();
                // If there is a delay, fade out with the default duration. If
                // the hideDelay is 0, we assume no animation is wanted, so we
                // pass 0 duration. #12994.
                tooltip.getLabel().animate({
                    opacity: 0
                }, {
                    duration: delay ? 150 : delay,
                    complete: function () {
                        // #3088, assuming we're only using this for tooltips
                        label.hide();
                        // Clear the container for outside tooltip (#18490)
                        if (tooltip.container) {
                            tooltip.container.remove();
                        }
                    }
                });
                tooltip.isHidden = true;
            }, delay);
        }
    };
    /**
     * Initialize tooltip.
     *
     * @private
     * @function Highcharts.Tooltip#init
     *
     * @param {Highcharts.Chart} chart
     *        The chart instance.
     *
     * @param {Highcharts.TooltipOptions} options
     *        Tooltip options.
     */
    Tooltip.prototype.init = function (chart, options) {
        /**
         * Chart of the tooltip.
         *
         * @readonly
         * @name Highcharts.Tooltip#chart
         * @type {Highcharts.Chart}
         */
        this.chart = chart;
        /**
         * Used tooltip options.
         *
         * @readonly
         * @name Highcharts.Tooltip#options
         * @type {Highcharts.TooltipOptions}
         */
        this.options = options;
        /**
         * List of crosshairs.
         *
         * @private
         * @readonly
         * @name Highcharts.Tooltip#crosshairs
         * @type {Array<null>}
         */
        this.crosshairs = [];
        /**
         * Tooltips are initially hidden.
         *
         * @private
         * @readonly
         * @name Highcharts.Tooltip#isHidden
         * @type {boolean}
         */
        this.isHidden = true;
        /**
         * True, if the tooltip is split into one label per series, with the
         * header close to the axis.
         *
         * @readonly
         * @name Highcharts.Tooltip#split
         * @type {boolean|undefined}
         */
        this.split = options.split && !chart.inverted && !chart.polar;
        /**
         * When the tooltip is shared, the entire plot area will capture mouse
         * movement or touch events.
         *
         * @readonly
         * @name Highcharts.Tooltip#shared
         * @type {boolean|undefined}
         */
        this.shared = options.shared || this.split;
        /**
         * Whether to allow the tooltip to render outside the chart's SVG
         * element box. By default (false), the tooltip is rendered within the
         * chart's SVG element, which results in the tooltip being aligned
         * inside the chart area.
         *
         * @readonly
         * @name Highcharts.Tooltip#outside
         * @type {boolean}
         *
         * @todo
         * Split tooltip does not support outside in the first iteration. Should
         * not be too complicated to implement.
         */
        this.outside = Tooltip_pick(options.outside, Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY));
    };
    Tooltip.prototype.shouldStickOnContact = function (pointerEvent) {
        return !!(!this.followPointer &&
            this.options.stickOnContact &&
            (!pointerEvent || this.pointer.inClass(pointerEvent.target, 'highcharts-tooltip')));
    };
    /**
     * Moves the tooltip with a soft animation to a new position.
     *
     * @private
     * @function Highcharts.Tooltip#move
     *
     * @param {number} x
     *
     * @param {number} y
     *
     * @param {number} anchorX
     *
     * @param {number} anchorY
     */
    Tooltip.prototype.move = function (x, y, anchorX, anchorY) {
        var tooltip = this,
            animation = Tooltip_animObject(!tooltip.isHidden && tooltip.options.animation),
            skipAnchor = tooltip.followPointer || (tooltip.len || 0) > 1,
            attr = { x: x,
            y: y };
        if (!skipAnchor) {
            attr.anchorX = anchorX;
            attr.anchorY = anchorY;
        }
        animation.step = function () { return tooltip.drawTracker(); };
        tooltip.getLabel().animate(attr, animation);
    };
    /**
     * Refresh the tooltip's text and position.
     *
     * @function Highcharts.Tooltip#refresh
     *
     * @param {Highcharts.Point|Array<Highcharts.Point>} pointOrPoints
     *        Either a point or an array of points.
     *
     * @param {Highcharts.PointerEventObject} [mouseEvent]
     *        Mouse event, that is responsible for the refresh and should be
     *        used for the tooltip update.
     */
    Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) {
        var tooltip = this,
            _a = this,
            chart = _a.chart,
            options = _a.options,
            pointer = _a.pointer,
            shared = _a.shared,
            points = Tooltip_splat(pointOrPoints),
            point = points[0],
            formatString = options.format,
            formatter = options.formatter || tooltip.defaultFormatter,
            styledMode = chart.styledMode;
        var wasShared = tooltip.allowShared;
        if (!options.enabled || !point.series) { // #16820
            return;
        }
        Core_Utilities.clearTimeout(this.hideTimer);
        // A switch saying if this specific tooltip configuration allows shared
        // or split modes
        tooltip.allowShared = !(!Tooltip_isArray(pointOrPoints) &&
            pointOrPoints.series &&
            pointOrPoints.series.noSharedTooltip);
        wasShared = wasShared && !tooltip.allowShared;
        // Get the reference point coordinates (pie charts use tooltipPos)
        tooltip.followPointer = (!tooltip.split && point.series.tooltipOptions.followPointer);
        var anchor = tooltip.getAnchor(pointOrPoints,
            mouseEvent),
            x = anchor[0],
            y = anchor[1];
        // Shared tooltip, array is sent over
        if (shared && tooltip.allowShared) {
            pointer.applyInactiveState(points);
            // Now set hover state for the chosen ones:
            points.forEach(function (item) { return item.setState('hover'); });
            point.points = points;
        }
        this.len = points.length; // #6128
        var text = Tooltip_isString(formatString) ?
                Tooltip_format(formatString,
            point,
            chart) :
                formatter.call(point,
            tooltip);
        // Reset the preliminary circular references
        point.points = void 0;
        // Register the current series
        var currentSeries = point.series;
        this.distance = Tooltip_pick(currentSeries.tooltipOptions.distance, 16);
        // Update the inner HTML
        if (text === false) {
            this.hide();
        }
        else {
            // Update text
            if (tooltip.split && tooltip.allowShared) { // #13868
                this.renderSplit(text, points);
            }
            else {
                var checkX_1 = x;
                var checkY_1 = y;
                if (mouseEvent && pointer.isDirectTouch) {
                    checkX_1 = mouseEvent.chartX - chart.plotLeft;
                    checkY_1 = mouseEvent.chartY - chart.plotTop;
                }
                // #11493, #13095
                if (chart.polar ||
                    currentSeries.options.clip === false ||
                    points.some(function (p) {
                        return pointer.isDirectTouch || // ##17929
                            p.series.shouldShowTooltip(checkX_1, checkY_1);
                    })) {
                    var label = tooltip.getLabel(wasShared && tooltip.tt || {});
                    // Prevent the tooltip from flowing over the chart box
                    // (#6659)
                    if (!options.style.width || styledMode) {
                        label.css({
                            width: (this.outside ?
                                this.getPlayingField() :
                                chart.spacingBox).width + 'px'
                        });
                    }
                    label.attr({
                        // Add class before the label BBox calculation (#21035)
                        'class': tooltip.getClassName(point),
                        text: text && text.join ?
                            text.join('') :
                            text
                    });
                    // When the length of the label has increased, immediately
                    // update the x position to prevent tooltip from flowing
                    // outside the viewport during animation (#21371)
                    if (this.outside) {
                        label.attr({
                            x: Tooltip_clamp(label.x || 0, 0, this.getPlayingField().width -
                                (label.width || 0) -
                                1)
                        });
                    }
                    if (!styledMode) {
                        label.attr({
                            stroke: (options.borderColor ||
                                point.color ||
                                currentSeries.color ||
                                "#666666" /* Palette.neutralColor60 */)
                        });
                    }
                    tooltip.updatePosition({
                        plotX: x,
                        plotY: y,
                        negative: point.negative,
                        ttBelow: point.ttBelow,
                        h: anchor[2] || 0
                    });
                }
                else {
                    tooltip.hide();
                    return;
                }
            }
            // Show it
            if (tooltip.isHidden && tooltip.label) {
                tooltip.label.attr({
                    opacity: 1
                }).show();
            }
            tooltip.isHidden = false;
        }
        Tooltip_fireEvent(this, 'refresh');
    };
    /**
     * Render the split tooltip. Loops over each point's text and adds
     * a label next to the point, then uses the distribute function to
     * find best non-overlapping positions.
     *
     * @private
     * @function Highcharts.Tooltip#renderSplit
     *
     * @param {string|Array<(boolean|string)>} labels
     *
     * @param {Array<Highcharts.Point>} points
     */
    Tooltip.prototype.renderSplit = function (labels, points) {
        var _a;
        var tooltip = this;
        var chart = tooltip.chart,
            _b = tooltip.chart,
            chartWidth = _b.chartWidth,
            chartHeight = _b.chartHeight,
            plotHeight = _b.plotHeight,
            plotLeft = _b.plotLeft,
            plotTop = _b.plotTop,
            _c = _b.scrollablePixelsY,
            scrollablePixelsY = _c === void 0 ? 0 : _c,
            scrollablePixelsX = _b.scrollablePixelsX,
            styledMode = _b.styledMode,
            distance = tooltip.distance,
            options = tooltip.options,
            positioner = tooltip.options.positioner,
            pointer = tooltip.pointer;
        var _d = ((_a = chart.scrollablePlotArea) === null || _a === void 0 ? void 0 : _a.scrollingContainer) || {},
            _e = _d.scrollLeft,
            scrollLeft = _e === void 0 ? 0 : _e,
            _f = _d.scrollTop,
            scrollTop = _f === void 0 ? 0 : _f;
        // The area which the tooltip should be limited to. Limit to scrollable
        // plot area if enabled, otherwise limit to the chart container. If
        // outside is true it should be the whole viewport
        var bounds = (tooltip.outside &&
                typeof scrollablePixelsX !== 'number') ?
                Tooltip_doc.documentElement.getBoundingClientRect() : {
                left: scrollLeft,
                right: scrollLeft + chartWidth,
                top: scrollTop,
                bottom: scrollTop + chartHeight
            };
        var tooltipLabel = tooltip.getLabel();
        var ren = this.renderer || chart.renderer;
        var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite);
        var _g = pointer.getChartPosition(),
            chartLeft = _g.left,
            chartTop = _g.top;
        var distributionBoxTop = plotTop + scrollTop;
        var headerHeight = 0;
        var adjustedPlotHeight = plotHeight - scrollablePixelsY;
        /**
         * Calculates the anchor position for the partial tooltip
         *
         * @private
         * @param {Highcharts.Point} point The point related to the tooltip
         * @return {Object} Returns an object with anchorX and anchorY
         */
        function getAnchor(point) {
            var isHeader = point.isHeader,
                _a = point.plotX,
                plotX = _a === void 0 ? 0 : _a,
                _b = point.plotY,
                plotY = _b === void 0 ? 0 : _b,
                series = point.series;
            var anchorX;
            var anchorY;
            if (isHeader) {
                // Set anchorX to plotX
                anchorX = Math.max(plotLeft + plotX, plotLeft);
                // Set anchorY to center of visible plot area.
                anchorY = plotTop + plotHeight / 2;
            }
            else {
                var xAxis = series.xAxis,
                    yAxis = series.yAxis;
                // Set anchorX to plotX. Limit to within xAxis.
                anchorX = xAxis.pos + Tooltip_clamp(plotX, -distance, xAxis.len + distance);
                // Set anchorY, limit to the scrollable plot area
                if (series.shouldShowTooltip(0, yAxis.pos - plotTop + plotY, {
                    ignoreX: true
                })) {
                    anchorY = yAxis.pos + plotY;
                }
            }
            // Limit values to plot area
            anchorX = Tooltip_clamp(anchorX, bounds.left - distance, bounds.right + distance);
            return { anchorX: anchorX, anchorY: anchorY };
        }
        /**
         * Calculates the position of the partial tooltip
         *
         * @private
         * @param {number} anchorX
         * The partial tooltip anchor x position
         *
         * @param {number} anchorY
         * The partial tooltip anchor y position
         *
         * @param {boolean|undefined} isHeader
         * Whether the partial tooltip is a header
         *
         * @param {number} boxWidth
         * Width of the partial tooltip
         *
         * @return {Highcharts.PositionObject}
         * Returns the partial tooltip x and y position
         */
        function defaultPositioner(anchorX, anchorY, isHeader, boxWidth, alignedLeft) {
            if (alignedLeft === void 0) { alignedLeft = true; }
            var y;
            var x;
            if (isHeader) {
                y = headerTop ? 0 : adjustedPlotHeight;
                x = Tooltip_clamp(anchorX - (boxWidth / 2), bounds.left, bounds.right - boxWidth - (tooltip.outside ? chartLeft : 0));
            }
            else {
                y = anchorY - distributionBoxTop;
                x = alignedLeft ?
                    anchorX - boxWidth - distance :
                    anchorX + distance;
                x = Tooltip_clamp(x, alignedLeft ? x : bounds.left, bounds.right);
            }
            // NOTE: y is relative to distributionBoxTop
            return { x: x, y: y };
        }
        /**
         * Updates the attributes and styling of the partial tooltip. Creates a
         * new partial tooltip if it does not exists.
         *
         * @private
         * @param {Highcharts.SVGElement|undefined} partialTooltip
         *  The partial tooltip to update
         * @param {Highcharts.Point} point
         *  The point related to the partial tooltip
         * @param {boolean|string} str The text for the partial tooltip
         * @return {Highcharts.SVGElement} Returns the updated partial tooltip
         */
        function updatePartialTooltip(partialTooltip, point, str) {
            var _a;
            var tt = partialTooltip;
            var isHeader = point.isHeader,
                series = point.series;
            if (!tt) {
                var attribs = {
                        padding: options.padding,
                        r: options.borderRadius
                    };
                if (!styledMode) {
                    attribs.fill = options.backgroundColor;
                    attribs['stroke-width'] = (_a = options.borderWidth) !== null && _a !== void 0 ? _a : 1;
                }
                tt = ren
                    .label('', 0, 0, (options[isHeader ? 'headerShape' : 'shape']), void 0, void 0, options.useHTML)
                    .addClass(tooltip.getClassName(point, true, isHeader))
                    .attr(attribs)
                    .add(tooltipLabel);
            }
            tt.isActive = true;
            tt.attr({
                text: str
            });
            if (!styledMode) {
                tt.css(options.style)
                    .attr({
                    stroke: (options.borderColor ||
                        point.color ||
                        series.color ||
                        "#333333" /* Palette.neutralColor80 */)
                });
            }
            return tt;
        }
        // Graceful degradation for legacy formatters
        if (Tooltip_isString(labels)) {
            labels = [false, labels];
        }
        // Create the individual labels for header and points, ignore footer
        var boxes = labels.slice(0,
            points.length + 1).reduce(function (boxes,
            str,
            i) {
                if (str !== false && str !== '') {
                    var point = (points[i - 1] ||
                        {
                            // Item 0 is the header. Instead of this, we could also
                            // use the crosshair label
                            isHeader: true,
                            plotX: points[0].plotX,
                            plotY: plotHeight,
                            series: {}
                        });
                var isHeader = point.isHeader;
                // Store the tooltip label reference on the series
                var owner = isHeader ? tooltip : point.series;
                var tt = owner.tt = updatePartialTooltip(owner.tt,
                    point,
                    str.toString());
                // Get X position now, so we can move all to the other side in
                // case of overflow
                var bBox = tt.getBBox();
                var boxWidth = bBox.width + tt.strokeWidth();
                if (isHeader) {
                    headerHeight = bBox.height;
                    adjustedPlotHeight += headerHeight;
                    if (headerTop) {
                        distributionBoxTop -= headerHeight;
                    }
                }
                var _a = getAnchor(point),
                    anchorX = _a.anchorX,
                    anchorY = _a.anchorY;
                if (typeof anchorY === 'number') {
                    var size = bBox.height + 1;
                    var boxPosition = (positioner ?
                            positioner.call(tooltip,
                        boxWidth,
                        size,
                        point) :
                            defaultPositioner(anchorX,
                        anchorY,
                        isHeader,
                        boxWidth));
                    boxes.push({
                        // 0-align to the top, 1-align to the bottom
                        align: positioner ? 0 : void 0,
                        anchorX: anchorX,
                        anchorY: anchorY,
                        boxWidth: boxWidth,
                        point: point,
                        rank: Tooltip_pick(boxPosition.rank, isHeader ? 1 : 0),
                        size: size,
                        target: boxPosition.y,
                        tt: tt,
                        x: boxPosition.x
                    });
                }
                else {
                    // Hide tooltips which anchorY is outside the visible plot
                    // area
                    tt.isActive = false;
                }
            }
            return boxes;
        }, []);
        // Realign the tooltips towards the right if there is not enough space
        // to the left and there is space to the right
        if (!positioner && boxes.some(function (box) {
            // Always realign if the beginning of a label is outside bounds
            var outside = tooltip.outside;
            var boxStart = (outside ? chartLeft : 0) + box.anchorX;
            if (boxStart < bounds.left &&
                boxStart + box.boxWidth < bounds.right) {
                return true;
            }
            // Otherwise, check if there is more space available to the right
            return boxStart < (chartLeft - bounds.left) + box.boxWidth &&
                bounds.right - boxStart > boxStart;
        })) {
            boxes = boxes.map(function (box) {
                var _a = defaultPositioner(box.anchorX,
                    box.anchorY,
                    box.point.isHeader,
                    box.boxWidth,
                    false),
                    x = _a.x,
                    y = _a.y;
                return Tooltip_extend(box, {
                    target: y,
                    x: x
                });
            });
        }
        // Clean previous run (for missing points)
        tooltip.cleanSplit();
        // Distribute and put in place
        distribute(boxes, adjustedPlotHeight);
        var boxExtremes = {
                left: chartLeft,
                right: chartLeft
            };
        // Get the extremes from series tooltips
        boxes.forEach(function (box) {
            var x = box.x,
                boxWidth = box.boxWidth,
                isHeader = box.isHeader;
            if (!isHeader) {
                if (tooltip.outside && chartLeft + x < boxExtremes.left) {
                    boxExtremes.left = chartLeft + x;
                }
                if (!isHeader &&
                    tooltip.outside &&
                    boxExtremes.left + boxWidth > boxExtremes.right) {
                    boxExtremes.right = chartLeft + x;
                }
            }
        });
        boxes.forEach(function (box) {
            var x = box.x,
                anchorX = box.anchorX,
                anchorY = box.anchorY,
                pos = box.pos,
                isHeader = box.point.isHeader;
            var attributes = {
                    visibility: typeof pos === 'undefined' ? 'hidden' : 'inherit',
                    x: x,
                    /* NOTE: y should equal pos to be consistent with !split
                     * tooltip,
                but is currently relative to plotTop. Is left as is
                     * to avoid breaking change. Remove distributionBoxTop to make
                     * it consistent.
                     */
                    y: (pos || 0) + distributionBoxTop,
                    anchorX: anchorX,
                    anchorY: anchorY
                };
            // Handle left-aligned tooltips overflowing the chart area
            if (tooltip.outside && x < anchorX) {
                var offset = chartLeft - boxExtremes.left;
                // Skip this if there is no overflow
                if (offset > 0) {
                    if (!isHeader) {
                        attributes.x = x + offset;
                        attributes.anchorX = anchorX + offset;
                    }
                    if (isHeader) {
                        attributes.x = (boxExtremes.right - boxExtremes.left) / 2;
                        attributes.anchorX = anchorX + offset;
                    }
                }
            }
            // Put the label in place
            box.tt.attr(attributes);
        });
        /* If we have a separate tooltip container, then update the necessary
         * container properties.
         * Test that tooltip has its own container and renderer before executing
         * the operation.
         */
        var container = tooltip.container,
            outside = tooltip.outside,
            renderer = tooltip.renderer;
        if (outside && container && renderer) {
            // Set container size to fit the bounds
            var _h = tooltipLabel.getBBox(),
                width = _h.width,
                height = _h.height,
                x = _h.x,
                y = _h.y;
            renderer.setSize(width + x, height + y, false);
            // Position the tooltip container to the chart container
            container.style.left = boxExtremes.left + 'px';
            container.style.top = chartTop + 'px';
        }
        // Workaround for #18927, artefacts left by the shadows of split
        // tooltips in Safari v16 (2023). Check again with later versions if we
        // can remove this.
        if (isSafari) {
            tooltipLabel.attr({
                // Force a redraw of the whole group by chaining the opacity
                // slightly
                opacity: tooltipLabel.opacity === 1 ? 0.999 : 1
            });
        }
    };
    /**
     * If the `stickOnContact` option is active, this will add a tracker shape.
     *
     * @private
     * @function Highcharts.Tooltip#drawTracker
     */
    Tooltip.prototype.drawTracker = function () {
        var tooltip = this;
        if (!this.shouldStickOnContact()) {
            if (tooltip.tracker) {
                tooltip.tracker = tooltip.tracker.destroy();
            }
            return;
        }
        var chart = tooltip.chart;
        var label = tooltip.label;
        var points = tooltip.shared ? chart.hoverPoints : chart.hoverPoint;
        if (!label || !points) {
            return;
        }
        var box = {
                x: 0,
                y: 0,
                width: 0,
                height: 0
            };
        // Combine anchor and tooltip
        var anchorPos = this.getAnchor(points);
        var labelBBox = label.getBBox();
        anchorPos[0] += chart.plotLeft - (label.translateX || 0);
        anchorPos[1] += chart.plotTop - (label.translateY || 0);
        // When the mouse pointer is between the anchor point and the label,
        // the label should stick.
        box.x = Math.min(0, anchorPos[0]);
        box.y = Math.min(0, anchorPos[1]);
        box.width = (anchorPos[0] < 0 ?
            Math.max(Math.abs(anchorPos[0]), labelBBox.width - anchorPos[0]) :
            Math.max(Math.abs(anchorPos[0]), labelBBox.width));
        box.height = (anchorPos[1] < 0 ?
            Math.max(Math.abs(anchorPos[1]), labelBBox.height - Math.abs(anchorPos[1])) :
            Math.max(Math.abs(anchorPos[1]), labelBBox.height));
        if (tooltip.tracker) {
            tooltip.tracker.attr(box);
        }
        else {
            tooltip.tracker = label.renderer
                .rect(box)
                .addClass('highcharts-tracker')
                .add(label);
            if (!chart.styledMode) {
                tooltip.tracker.attr({
                    fill: 'rgba(0,0,0,0)'
                });
            }
        }
    };
    /**
     * @private
     */
    Tooltip.prototype.styledModeFormat = function (formatString) {
        return formatString
            .replace('style="font-size: 0.8em"', 'class="highcharts-header"')
            .replace(/style="color:{(point|series)\.color}"/g, 'class="highcharts-color-{$1.colorIndex} ' +
            '{series.options.className} ' +
            '{point.options.className}"');
    };
    /**
     * Format the footer/header of the tooltip
     * #3397: abstraction to enable formatting of footer and header
     *
     * @private
     * @function Highcharts.Tooltip#headerFooterFormatter
     */
    Tooltip.prototype.headerFooterFormatter = function (point, isFooter) {
        var series = point.series,
            tooltipOptions = series.tooltipOptions,
            xAxis = series.xAxis,
            dateTime = xAxis && xAxis.dateTime,
            e = {
                isFooter: isFooter,
                point: point
            };
        var xDateFormat = tooltipOptions.xDateFormat || '', formatString = tooltipOptions[isFooter ? 'footerFormat' : 'headerFormat'];
        Tooltip_fireEvent(this, 'headerFormatter', e, function (e) {
            // Guess the best date format based on the closest point distance
            // (#568, #3418)
            if (dateTime && !xDateFormat && Tooltip_isNumber(point.key)) {
                xDateFormat = dateTime.getXDateFormat(point.key, tooltipOptions.dateTimeLabelFormats);
            }
            // Insert the footer date format if any
            if (dateTime && xDateFormat) {
                if (Tooltip_isObject(xDateFormat)) {
                    var format_1 = xDateFormat;
                    dateFormats[0] = function (timestamp) {
                        return series.chart.time.dateFormat(format_1, timestamp);
                    };
                    xDateFormat = '%0';
                }
                (point.tooltipDateKeys || ['key']).forEach(function (key) {
                    formatString = formatString.replace(new RegExp('point\\.' + key + '([ \\)}])', ''), "(point.".concat(key, ":").concat(xDateFormat, ")$1"));
                });
            }
            // Replace default header style with class name
            if (series.chart.styledMode) {
                formatString = this.styledModeFormat(formatString);
            }
            e.text = Tooltip_format(formatString, point, this.chart);
        });
        return e.text || '';
    };
    /**
     * Updates the tooltip with the provided tooltip options.
     *
     * @function Highcharts.Tooltip#update
     *
     * @param {Highcharts.TooltipOptions} options
     *        The tooltip options to update.
     */
    Tooltip.prototype.update = function (options) {
        this.destroy();
        this.init(this.chart, Tooltip_merge(true, this.options, options));
    };
    /**
     * Find the new position and perform the move
     *
     * @private
     * @function Highcharts.Tooltip#updatePosition
     *
     * @param {Highcharts.Point} point
     */
    Tooltip.prototype.updatePosition = function (point) {
        var _a = this,
            chart = _a.chart,
            container = _a.container,
            distance = _a.distance,
            options = _a.options,
            pointer = _a.pointer,
            renderer = _a.renderer,
            _b = this.getLabel(),
            _c = _b.height,
            height = _c === void 0 ? 0 : _c,
            _d = _b.width,
            width = _d === void 0 ? 0 : _d, 
            // Needed for outside: true (#11688)
            _e = pointer.getChartPosition(),
            left = _e.left,
            top = _e.top,
            scaleX = _e.scaleX,
            scaleY = _e.scaleY,
            pos = (options.positioner || this.getPosition).call(this,
            width,
            height,
            point),
            doc = Core_Globals.doc;
        var anchorX = (point.plotX || 0) + chart.plotLeft,
            anchorY = (point.plotY || 0) + chart.plotTop,
            pad;
        // Set the renderer size dynamically to prevent document size to change.
        // Renderer only exists when tooltip is outside.
        if (renderer && container) {
            // Corrects positions, occurs with tooltip positioner (#16944)
            if (options.positioner) {
                pos.x += left - distance;
                pos.y += top - distance;
            }
            // Pad it by the border width and distance. Add 2 to make room for
            // the default shadow (#19314).
            pad = (options.borderWidth || 0) + 2 * distance + 2;
            renderer.setSize(
            // Clamp width to keep tooltip in viewport (#21698)
            // and subtract one since tooltip container has 'left: 1px;'
            Tooltip_clamp(width + pad, 0, doc.documentElement.clientWidth) - 1, height + pad, false);
            // Anchor and tooltip container need scaling if chart container has
            // scale transform/css zoom. #11329.
            if (scaleX !== 1 || scaleY !== 1) {
                Tooltip_css(container, {
                    transform: "scale(".concat(scaleX, ", ").concat(scaleY, ")")
                });
                anchorX *= scaleX;
                anchorY *= scaleY;
            }
            anchorX += left - pos.x;
            anchorY += top - pos.y;
        }
        // Do the move
        this.move(Math.round(pos.x), Math.round(pos.y || 0), // Can be undefined (#3977)
        anchorX, anchorY);
    };
    return Tooltip;
}());
/* *
 *
 *  Class namespace
 *
 * */
(function (Tooltip) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    function compose(PointerClass) {
        if (Tooltip_pushUnique(Tooltip_composed, 'Core.Tooltip')) {
            Tooltip_addEvent(PointerClass, 'afterInit', function () {
                var chart = this.chart;
                if (chart.options.tooltip) {
                    /**
                     * Tooltip object for points of series.
                     *
                     * @name Highcharts.Chart#tooltip
                     * @type {Highcharts.Tooltip}
                     */
                    chart.tooltip = new Tooltip(chart, chart.options.tooltip, this);
                }
            });
        }
    }
    Tooltip.compose = compose;
})(Tooltip || (Tooltip = {}));
/* *
 *
 *  Default export
 *
 * */
/* harmony default export */ var Core_Tooltip = (Tooltip);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Callback function to format the text of the tooltip from scratch.
 *
 * In case of single or shared tooltips, a string should be returned. In case
 * of split tooltips, it should return an array where the first item is the
 * header, and subsequent items are mapped to the points. Return `false` to
 * disable tooltip for a specific point on series.
 *
 * @callback Highcharts.TooltipFormatterCallbackFunction
 *
 * @param {Highcharts.Point} this
 * The formatter's context is the hovered `Point` instance. In case of shared or
 * split tooltips, all points are available in `this.points`.
 *
 * @param {Highcharts.Tooltip} tooltip
 * The tooltip instance
 *
 * @return {false|string|Array<(string|null|undefined)>|null|undefined}
 * Formatted text or false
 */
/**
 * A callback function to place the tooltip in a specific position.
 *
 * @callback Highcharts.TooltipPositionerCallbackFunction
 *
 * @param {Highcharts.Tooltip} this
 * Tooltip context of the callback.
 *
 * @param {number} labelWidth
 * Width of the tooltip.
 *
 * @param {number} labelHeight
 * Height of the tooltip.
 *
 * @param {Highcharts.TooltipPositionerPointObject} point
 * Point information for positioning a tooltip.
 *
 * @return {Highcharts.PositionObject}
 * New position for the tooltip.
 */
/**
 * Point information for positioning a tooltip.
 *
 * @interface Highcharts.TooltipPositionerPointObject
 * @extends Highcharts.Point
 */ /**
* If `tooltip.split` option is enabled and positioner is called for each of the
* boxes separately, this property indicates the call on the xAxis header, which
* is not a point itself.
* @name Highcharts.TooltipPositionerPointObject#isHeader
* @type {boolean}
*/ /**
* The reference point relative to the plot area. Add chart.plotLeft to get the
* full coordinates.
* @name Highcharts.TooltipPositionerPointObject#plotX
* @type {number}
*/ /**
* The reference point relative to the plot area. Add chart.plotTop to get the
* full coordinates.
* @name Highcharts.TooltipPositionerPointObject#plotY
* @type {number}
*/
/**
 * @typedef {"callout"|"circle"|"rect"} Highcharts.TooltipShapeValue
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Series/Point.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var Point_animObject = AnimationUtilities.animObject;

var Point_defaultOptions = Defaults.defaultOptions;

var Point_format = Core_Templating.format;

var Point_addEvent = Core_Utilities.addEvent, Point_crisp = Core_Utilities.crisp, Point_erase = Core_Utilities.erase, Point_extend = Core_Utilities.extend, Point_fireEvent = Core_Utilities.fireEvent, Point_getNestedProperty = Core_Utilities.getNestedProperty, Point_isArray = Core_Utilities.isArray, Point_isFunction = Core_Utilities.isFunction, Point_isNumber = Core_Utilities.isNumber, Point_isObject = Core_Utilities.isObject, Point_merge = Core_Utilities.merge, Point_pick = Core_Utilities.pick, Point_syncTimeout = Core_Utilities.syncTimeout, Point_removeEvent = Core_Utilities.removeEvent, Point_uniqueKey = Core_Utilities.uniqueKey;
/* eslint-disable no-invalid-this, valid-jsdoc */
/* *
 *
 *  Class
 *
 * */
/**
 * The Point object. The point objects are generated from the `series.data`
 * configuration objects or raw numbers. They can be accessed from the
 * `Series.points` array. Other ways to instantiate points are through {@link
 * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
 *
 * @class
 * @name Highcharts.Point
 */
var Point = /** @class */ (function () {
    /**
     * Initialize the point. Called internally based on the `series.data`
     * option.
     *
     * @function Highcharts.Point#init
     *
     * @param {Highcharts.Series} series
     *        The series object containing this point.
     *
     * @param {Highcharts.PointOptionsType} options
     *        The data in either number, array or object format.
     *
     * @param {number} [x]
     *        Optionally, the X value of the point.
     *
     * @return {Highcharts.Point}
     *         The Point instance.
     *
     * @emits Highcharts.Point#event:afterInit
     */
    function Point(series, options, x) {
        var _a;
        this.formatPrefix = 'point';
        this.visible = true;
        // For tooltip and data label formatting
        this.point = this;
        this.series = series;
        this.applyOptions(options, x);
        // Add a unique ID to the point if none is assigned
        (_a = this.id) !== null && _a !== void 0 ? _a : (this.id = Point_uniqueKey());
        this.resolveColor();
        series.chart.pointCount++;
        Point_fireEvent(this, 'afterInit');
    }
    /**
     * For categorized axes this property holds the category name for the
     * point. For other axes it holds the X value.
     *
     * @name Highcharts.Point#category
     * @type {number|string}
     */
    /**
     * The name of the point. The name can be given as the first position of the
     * point configuration array, or as a `name` property in the configuration:
     *
     * @example
     * // Array config
     * data: [
     *     ['John', 1],
     *     ['Jane', 2]
     * ]
     *
     * // Object config
     * data: [{
     *        name: 'John',
     *        y: 1
     * }, {
     *     name: 'Jane',
     *     y: 2
     * }]
     *
     * @name Highcharts.Point#name
     * @type {string}
     */
    /**
     * The point's name if it is defined, or its category in case of a category,
     * otherwise the x value. Convenient for tooltip and data label formatting.
     *
     * @name Highcharts.Point#key
     * @type {number|string}
     */
    /**
     * The point's options as applied in the initial configuration, or
     * extended through `Point.update`.
     *
     * In TypeScript you have to extend `PointOptionsObject` via an
     * additional interface to allow custom data options:
     *
     * ```
     * declare interface PointOptionsObject {
     *     customProperty: string;
     * }
     * ```
     *
     * @name Highcharts.Point#options
     * @type {Highcharts.PointOptionsObject}
     */
    /**
     * The percentage for points in a stacked series, pies or gauges.
     *
     * @name Highcharts.Point#percentage
     * @type {number|undefined}
     */
    /**
     * The series object associated with the point.
     *
     * @name Highcharts.Point#series
     * @type {Highcharts.Series}
     */
    /**
     * The attributes of the rendered SVG shape like in `column` or `pie`
     * series.
     *
     * @readonly
     * @name Highcharts.Point#shapeArgs
     * @type {Readonly<Highcharts.SVGAttributes>|undefined}
     */
    /**
     * The total of values in either a stack for stacked series, or a pie in a
     * pie series.
     *
     * @name Highcharts.Point#total
     * @type {number|undefined}
     */
    /**
     * For certain series types, like pie charts, where individual points can
     * be shown or hidden.
     *
     * @name Highcharts.Point#visible
     * @type {boolean}
     * @default true
     */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Animate SVG elements associated with the point.
     *
     * @private
     * @function Highcharts.Point#animateBeforeDestroy
     */
    Point.prototype.animateBeforeDestroy = function () {
        var point = this,
            animateParams = { x: point.startXPos,
            opacity: 0 },
            graphicalProps = point.getGraphicalProps();
        graphicalProps.singular.forEach(function (prop) {
            var isDataLabel = prop === 'dataLabel';
            point[prop] = point[prop].animate(isDataLabel ? {
                x: point[prop].startXPos,
                y: point[prop].startYPos,
                opacity: 0
            } : animateParams);
        });
        graphicalProps.plural.forEach(function (plural) {
            point[plural].forEach(function (item) {
                if (item.element) {
                    item.animate(Point_extend({ x: point.startXPos }, (item.startYPos ? {
                        x: item.startXPos,
                        y: item.startYPos
                    } : {})));
                }
            });
        });
    };
    /**
     * Apply the options containing the x and y data and possible some extra
     * properties. Called on point init or from point.update.
     *
     * @private
     * @function Highcharts.Point#applyOptions
     *
     * @param {Highcharts.PointOptionsType} options
     *        The point options as defined in series.data.
     *
     * @param {number} [x]
     *        Optionally, the x value.
     *
     * @return {Highcharts.Point}
     *         The Point instance.
     */
    Point.prototype.applyOptions = function (options, x) {
        var point = this,
            series = point.series,
            pointValKey = series.options.pointValKey || series.pointValKey;
        options = Point.prototype.optionsToObject.call(this, options);
        // Copy options directly to point
        Point_extend(point, options);
        point.options = point.options ?
            Point_extend(point.options, options) :
            options;
        // Since options are copied into the Point instance, some accidental
        // options must be shielded (#5681)
        if (options.group) {
            delete point.group;
        }
        if (options.dataLabels) {
            delete point.dataLabels;
        }
        /**
         * The y value of the point.
         * @name Highcharts.Point#y
         * @type {number|undefined}
         */
        // For higher dimension series types. For instance, for ranges, point.y
        // is mapped to point.low.
        if (pointValKey) {
            point.y = Point.prototype.getNestedProperty.call(point, pointValKey);
        }
        // The point is initially selected by options (#5777)
        if (point.selected) {
            point.state = 'select';
        }
        /**
         * The x value of the point.
         * @name Highcharts.Point#x
         * @type {number}
         */
        // If no x is set by now, get auto incremented value. All points must
        // have an x value, however the y value can be null to create a gap in
        // the series
        if ('name' in point &&
            typeof x === 'undefined' &&
            series.xAxis &&
            series.xAxis.hasNames) {
            point.x = series.xAxis.nameToX(point);
        }
        if (typeof point.x === 'undefined' && series) {
            point.x = x !== null && x !== void 0 ? x : series.autoIncrement();
        }
        else if (Point_isNumber(options.x) && series.options.relativeXValue) {
            point.x = series.autoIncrement(options.x);
            // If x is a string, try to parse it to a datetime
        }
        else if (typeof point.x === 'string') {
            x !== null && x !== void 0 ? x : (x = series.chart.time.parse(point.x));
            if (Point_isNumber(x)) {
                point.x = x;
            }
        }
        point.isNull = this.isValid && !this.isValid();
        point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874
        return point;
    };
    /**
     * Destroy a point to clear memory. Its reference still stays in
     * `series.data`.
     *
     * @private
     * @function Highcharts.Point#destroy
     */
    Point.prototype.destroy = function () {
        if (!this.destroyed) {
            var point_1 = this,
                series = point_1.series,
                chart = series.chart,
                dataSorting = series.options.dataSorting,
                hoverPoints = chart.hoverPoints,
                globalAnimation = point_1.series.chart.renderer.globalAnimation,
                animation = Point_animObject(globalAnimation);
            /**
             * Allow to call after animation.
             * @private
             */
            var destroyPoint = function () {
                    // Remove all events and elements
                    if (point_1.graphic ||
                        point_1.graphics ||
                        point_1.dataLabel ||
                        point_1.dataLabels) {
                        Point_removeEvent(point_1);
                    point_1.destroyElements();
                }
                for (var prop in point_1) { // eslint-disable-line guard-for-in
                    delete point_1[prop];
                }
            };
            if (point_1.legendItem) {
                // Pies have legend items
                chart.legend.destroyItem(point_1);
            }
            if (hoverPoints) {
                point_1.setState();
                Point_erase(hoverPoints, point_1);
                if (!hoverPoints.length) {
                    chart.hoverPoints = null;
                }
            }
            if (point_1 === chart.hoverPoint) {
                point_1.onMouseOut();
            }
            // Remove properties after animation
            if (!dataSorting || !dataSorting.enabled) {
                destroyPoint();
            }
            else {
                this.animateBeforeDestroy();
                Point_syncTimeout(destroyPoint, animation.duration);
            }
            chart.pointCount--;
        }
        this.destroyed = true;
    };
    /**
     * Destroy SVG elements associated with the point.
     *
     * @private
     * @function Highcharts.Point#destroyElements
     * @param {Highcharts.Dictionary<number>} [kinds]
     */
    Point.prototype.destroyElements = function (kinds) {
        var point = this,
            props = point.getGraphicalProps(kinds);
        props.singular.forEach(function (prop) {
            point[prop] = point[prop].destroy();
        });
        props.plural.forEach(function (plural) {
            point[plural].forEach(function (item) {
                if (item && item.element) {
                    item.destroy();
                }
            });
            delete point[plural];
        });
    };
    /**
     * Fire an event on the Point object.
     *
     * @private
     * @function Highcharts.Point#firePointEvent
     *
     * @param {string} eventType
     *        Type of the event.
     *
     * @param {Highcharts.Dictionary<any>|Event} [eventArgs]
     *        Additional event arguments.
     *
     * @param {Highcharts.EventCallbackFunction<Highcharts.Point>|Function} [defaultFunction]
     *        Default event handler.
     *
     * @emits Highcharts.Point#event:*
     */
    Point.prototype.firePointEvent = function (eventType, eventArgs, defaultFunction) {
        var point = this,
            series = this.series,
            seriesOptions = series.options;
        // Load event handlers on demand to save time on mouseover/out
        point.manageEvent(eventType);
        // Add default handler if in selection mode
        if (eventType === 'click' && seriesOptions.allowPointSelect) {
            defaultFunction = function (event) {
                // Control key is for Windows, meta (= Cmd key) for Mac, Shift
                // for Opera.
                if (!point.destroyed && point.select) { // #2911, #19075
                    point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
                }
            };
        }
        Point_fireEvent(point, eventType, eventArgs, defaultFunction);
    };
    /**
     * Get the CSS class names for individual points. Used internally where the
     * returned value is set on every point.
     *
     * @function Highcharts.Point#getClassName
     *
     * @return {string}
     *         The class names.
     */
    Point.prototype.getClassName = function () {
        var point = this;
        return 'highcharts-point' +
            (point.selected ? ' highcharts-point-select' : '') +
            (point.negative ? ' highcharts-negative' : '') +
            (point.isNull ? ' highcharts-null-point' : '') +
            (typeof point.colorIndex !== 'undefined' ?
                ' highcharts-color-' + point.colorIndex : '') +
            (point.options.className ? ' ' + point.options.className : '') +
            (point.zone && point.zone.className ? ' ' +
                point.zone.className.replace('highcharts-negative', '') : '');
    };
    /**
     * Get props of all existing graphical point elements.
     *
     * @private
     * @function Highcharts.Point#getGraphicalProps
     */
    Point.prototype.getGraphicalProps = function (kinds) {
        var point = this,
            props = [],
            graphicalProps = { singular: [],
            plural: [] };
        var prop,
            i;
        kinds = kinds || { graphic: 1, dataLabel: 1 };
        if (kinds.graphic) {
            props.push('graphic', 'connector' // Used by dumbbell
            );
        }
        if (kinds.dataLabel) {
            props.push('dataLabel', 'dataLabelPath', 'dataLabelUpper');
        }
        i = props.length;
        while (i--) {
            prop = props[i];
            if (point[prop]) {
                graphicalProps.singular.push(prop);
            }
        }
        [
            'graphic',
            'dataLabel'
        ].forEach(function (prop) {
            var plural = prop + 's';
            if (kinds[prop] && point[plural]) {
                graphicalProps.plural.push(plural);
            }
        });
        return graphicalProps;
    };
    /**
     * Returns the value of the point property for a given value.
     * @private
     */
    Point.prototype.getNestedProperty = function (key) {
        if (!key) {
            return;
        }
        if (key.indexOf('custom.') === 0) {
            return Point_getNestedProperty(key, this.options);
        }
        return this[key];
    };
    /**
     * In a series with `zones`, return the zone that the point belongs to.
     *
     * @function Highcharts.Point#getZone
     *
     * @return {Highcharts.SeriesZonesOptionsObject}
     *         The zone item.
     */
    Point.prototype.getZone = function () {
        var series = this.series,
            zones = series.zones,
            zoneAxis = series.zoneAxis || 'y';
        var zone,
            i = 0;
        zone = zones[i];
        while (this[zoneAxis] >= zone.value) {
            zone = zones[++i];
        }
        // For resetting or reusing the point (#8100)
        if (!this.nonZonedColor) {
            this.nonZonedColor = this.color;
        }
        if (zone && zone.color && !this.options.color) {
            this.color = zone.color;
        }
        else {
            this.color = this.nonZonedColor;
        }
        return zone;
    };
    /**
     * Utility to check if point has new shape type. Used in column series and
     * all others that are based on column series.
     * @private
     */
    Point.prototype.hasNewShapeType = function () {
        var point = this;
        var oldShapeType = point.graphic &&
                (point.graphic.symbolName || point.graphic.element.nodeName);
        return oldShapeType !== this.shapeType;
    };
    /**
     * Determine if point is valid.
     * @private
     * @function Highcharts.Point#isValid
     */
    Point.prototype.isValid = function () {
        return ((Point_isNumber(this.x) ||
            this.x instanceof Date) &&
            Point_isNumber(this.y));
    };
    /**
     * Transform number or array configs into objects. Also called for object
     * configs. Used internally to unify the different configuration formats for
     * points. For example, a simple number `10` in a line series will be
     * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a
     * scatter series will be transformed to `{ x: 1, y: 10 }`.
     *
     * @function Highcharts.Point#optionsToObject
     *
     * @param {Highcharts.PointOptionsType} options
     * Series data options.
     *
     * @return {Highcharts.Dictionary<*>}
     * Transformed point options.
     */
    Point.prototype.optionsToObject = function (options) {
        var _a;
        var series = this.series,
            keys = series.options.keys,
            pointArrayMap = keys || series.pointArrayMap || ['y'],
            valueCount = pointArrayMap.length;
        var ret = {},
            firstItemType,
            i = 0,
            j = 0;
        if (Point_isNumber(options) || options === null) {
            ret[pointArrayMap[0]] = options;
        }
        else if (Point_isArray(options)) {
            // With leading x value
            if (!keys && options.length > valueCount) {
                firstItemType = typeof options[0];
                if (firstItemType === 'string') {
                    if ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.dateTime) {
                        ret.x = series.chart.time.parse(options[0]);
                    }
                    else {
                        ret.name = options[0];
                    }
                }
                else if (firstItemType === 'number') {
                    ret.x = options[0];
                }
                i++;
            }
            while (j < valueCount) {
                // Skip undefined positions for keys
                if (!keys || typeof options[i] !== 'undefined') {
                    if (pointArrayMap[j].indexOf('.') > 0) {
                        // Handle nested keys, e.g. ['color.pattern.image']
                        // Avoid function call unless necessary.
                        Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]);
                    }
                    else {
                        ret[pointArrayMap[j]] = options[i];
                    }
                }
                i++;
                j++;
            }
        }
        else if (typeof options === 'object') {
            ret = options;
            // This is the fastest way to detect if there are individual point
            // dataLabels that need to be considered in drawDataLabels. These
            // can only occur in object configs.
            if (options.dataLabels) {
                // Override the prototype function to always return true,
                // regardless of whether data labels are enabled series-wide
                series.hasDataLabels = function () { return true; };
            }
            // Same approach as above for markers
            if (options.marker) {
                series._hasPointMarkers = true;
            }
        }
        return ret;
    };
    /**
     * Get the pixel position of the point relative to the plot area.
     * @function Highcharts.Point#pos
     *
     * @sample highcharts/point/position
     *         Get point's position in pixels.
     *
     * @param {boolean} chartCoordinates
     * If true, the returned position is relative to the full chart area.
     * If false, it is relative to the plot area determined by the axes.
     *
     * @param {number|undefined} plotY
     * A custom plot y position to be computed. Used internally for some
     * series types that have multiple `y` positions, like area range (low
     * and high values).
     *
     * @return {Array<number>|undefined}
     * Coordinates of the point if the point exists.
     */
    Point.prototype.pos = function (chartCoordinates, plotY) {
        if (plotY === void 0) { plotY = this.plotY; }
        if (!this.destroyed) {
            var _a = this,
                plotX = _a.plotX,
                series = _a.series,
                chart = series.chart,
                xAxis = series.xAxis,
                yAxis = series.yAxis;
            var posX = 0,
                posY = 0;
            if (Point_isNumber(plotX) && Point_isNumber(plotY)) {
                if (chartCoordinates) {
                    posX = xAxis ? xAxis.pos : chart.plotLeft;
                    posY = yAxis ? yAxis.pos : chart.plotTop;
                }
                return chart.inverted && xAxis && yAxis ?
                    [yAxis.len - plotY + posY, xAxis.len - plotX + posX] :
                    [plotX + posX, plotY + posY];
            }
        }
    };
    /**
     * @private
     * @function Highcharts.Point#resolveColor
     */
    Point.prototype.resolveColor = function () {
        var series = this.series,
            optionsChart = series.chart.options.chart,
            styledMode = series.chart.styledMode;
        var color,
            colors,
            colorCount = optionsChart.colorCount,
            colorIndex;
        // Remove points nonZonedColor for later recalculation
        delete this.nonZonedColor;
        if (series.options.colorByPoint) {
            if (!styledMode) {
                colors = series.options.colors || series.chart.options.colors;
                color = colors[series.colorCounter];
                colorCount = colors.length;
            }
            colorIndex = series.colorCounter;
            series.colorCounter++;
            // Loop back to zero
            if (series.colorCounter === colorCount) {
                series.colorCounter = 0;
            }
        }
        else {
            if (!styledMode) {
                color = series.color;
            }
            colorIndex = series.colorIndex;
        }
        /**
         * The point's current color index, used in styled mode instead of
         * `color`. The color index is inserted in class names used for styling.
         *
         * @name Highcharts.Point#colorIndex
         * @type {number|undefined}
         */
        this.colorIndex = Point_pick(this.options.colorIndex, colorIndex);
        /**
         * The point's current color.
         *
         * @name Highcharts.Point#color
         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
         */
        this.color = Point_pick(this.options.color, color);
    };
    /**
     * Set a value in an object, on the property defined by key. The key
     * supports nested properties using dot notation. The function modifies the
     * input object and does not make a copy.
     *
     * @function Highcharts.Point#setNestedProperty<T>
     *
     * @param {T} object
     *        The object to set the value on.
     *
     * @param {*} value
     *        The value to set.
     *
     * @param {string} key
     *        Key to the property to set.
     *
     * @return {T}
     *         The modified object.
     */
    Point.prototype.setNestedProperty = function (object, value, key) {
        var nestedKeys = key.split('.');
        nestedKeys.reduce(function (result, key, i, arr) {
            var isLastKey = arr.length - 1 === i;
            result[key] = (isLastKey ?
                value :
                Point_isObject(result[key], true) ?
                    result[key] :
                    {});
            return result[key];
        }, object);
        return object;
    };
    Point.prototype.shouldDraw = function () {
        return !this.isNull;
    };
    /**
     * Extendable method for formatting each point's tooltip line.
     *
     * @function Highcharts.Point#tooltipFormatter
     *
     * @param {string} pointFormat
     *        The point format.
     *
     * @return {string}
     *         A string to be concatenated in to the common tooltip text.
     */
    Point.prototype.tooltipFormatter = function (pointFormat) {
        var _a;
        // Insert options for valueDecimals, valuePrefix, and valueSuffix
        var _b = this.series, chart = _b.chart, _c = _b.pointArrayMap, pointArrayMap = _c === void 0 ? ['y'] : _c, tooltipOptions = _b.tooltipOptions, _d = tooltipOptions.valueDecimals, valueDecimals = _d === void 0 ? '' : _d, _e = tooltipOptions.valuePrefix, valuePrefix = _e === void 0 ? '' : _e, _f = tooltipOptions.valueSuffix, valueSuffix = _f === void 0 ? '' : _f;
        // Replace default point style with class name
        if (chart.styledMode) {
            pointFormat = ((_a = chart.tooltip) === null || _a === void 0 ? void 0 : _a.styledModeFormat(pointFormat)) ||
                pointFormat;
        }
        // Loop over the point array map and replace unformatted values with
        // sprintf formatting markup
        pointArrayMap.forEach(function (key) {
            key = '{point.' + key; // Without the closing bracket
            if (valuePrefix || valueSuffix) {
                pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix);
            }
            pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}');
        });
        return Point_format(pointFormat, this, chart);
    };
    /**
     * Update point with new options (typically x/y data) and optionally redraw
     * the series.
     *
     * @sample highcharts/members/point-update-column/
     *         Update column value
     * @sample highcharts/members/point-update-pie/
     *         Update pie slice
     * @sample maps/members/point-update/
     *         Update map area value in Highmaps
     *
     * @function Highcharts.Point#update
     *
     * @param {Highcharts.PointOptionsType} options
     *        The point options. Point options are handled as described under
     *        the `series.type.data` item for each series type. For example
     *        for a line series, if options is a single number, the point will
     *        be given that number as the marin y value. If it is an array, it
     *        will be interpreted as x and y values respectively. If it is an
     *        object, advanced options are applied.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after the point is updated. If doing
     *        more operations on the chart, it is best practice to set
     *        `redraw` to false and call `chart.redraw()` after.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
     *        Whether to apply animation, and optionally animation
     *        configuration.
     *
     * @emits Highcharts.Point#event:update
     */
    Point.prototype.update = function (options, redraw, animation, runEvent) {
        var point = this,
            series = point.series,
            graphic = point.graphic,
            chart = series.chart,
            seriesOptions = series.options;
        var i;
        redraw = Point_pick(redraw, true);
        /**
         * @private
         */
        function update() {
            point.applyOptions(options);
            // Update visuals, #4146
            // Handle mock graphic elements for a11y, #12718
            var hasMockGraphic = graphic && point.hasMockGraphic;
            var shouldDestroyGraphic = point.y === null ?
                    !hasMockGraphic :
                    hasMockGraphic;
            if (graphic && shouldDestroyGraphic) {
                point.graphic = graphic.destroy();
                delete point.hasMockGraphic;
            }
            if (Point_isObject(options, true)) {
                // Destroy so we can get new elements
                if (graphic && graphic.element) {
                    // "null" is also a valid symbol
                    if (options &&
                        options.marker &&
                        typeof options.marker.symbol !== 'undefined') {
                        point.graphic = graphic.destroy();
                    }
                }
                if ((options === null || options === void 0 ? void 0 : options.dataLabels) && point.dataLabel) {
                    point.dataLabel = point.dataLabel.destroy(); // #2468
                }
            }
            // Record changes in the data table
            i = point.index;
            var row = {};
            for (var _i = 0, _a = series.dataColumnKeys(); _i < _a.length; _i++) {
                var key = _a[_i];
                row[key] = point[key];
            }
            series.dataTable.setRow(row, i);
            // Record the options to options.data. If the old or the new config
            // is an object, use point options, otherwise use raw options
            // (#4701, #4916).
            seriesOptions.data[i] = (Point_isObject(seriesOptions.data[i], true) ||
                Point_isObject(options, true)) ?
                point.options :
                Point_pick(options, seriesOptions.data[i]);
            // Redraw
            series.isDirty = series.isDirtyData = true;
            if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320
                chart.isDirtyBox = true;
            }
            if (seriesOptions.legendType === 'point') { // #1831, #1885
                chart.isDirtyLegend = true;
            }
            if (redraw) {
                chart.redraw(animation);
            }
        }
        // Fire the event with a default handler of doing the update
        if (runEvent === false) { // When called from setData
            update();
        }
        else {
            point.firePointEvent('update', { options: options }, update);
        }
    };
    /**
     * Remove a point and optionally redraw the series and if necessary the axes
     *
     * @sample highcharts/plotoptions/series-point-events-remove/
     *         Remove point and confirm
     * @sample highcharts/members/point-remove/
     *         Remove pie slice
     * @sample maps/members/point-remove/
     *         Remove selected points in Highmaps
     *
     * @function Highcharts.Point#remove
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart or wait for an explicit call. When
     *        doing more operations on the chart, for example running
     *        `point.remove()` in a loop, it is best practice to set `redraw`
     *        to false and call `chart.redraw()` after.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
     *        Whether to apply animation, and optionally animation
     *        configuration.
     */
    Point.prototype.remove = function (redraw, animation) {
        this.series.removePoint(this.series.data.indexOf(this), redraw, animation);
    };
    /**
     * Toggle the selection status of a point.
     *
     * @see Highcharts.Chart#getSelectedPoints
     *
     * @sample highcharts/members/point-select/
     *         Select a point from a button
     * @sample highcharts/members/point-select-lasso/
     *         Lasso selection
     * @sample highcharts/chart/events-selection-points/
     *         Rectangle selection
     * @sample maps/series/data-id/
     *         Select a point in Highmaps
     *
     * @function Highcharts.Point#select
     *
     * @param {boolean} [selected]
     * When `true`, the point is selected. When `false`, the point is
     * unselected. When `null` or `undefined`, the selection state is toggled.
     *
     * @param {boolean} [accumulate=false]
     * When `true`, the selection is added to other selected points.
     * When `false`, other selected points are deselected. Internally in
     * Highcharts, when
     * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect)
     * is `true`, selected points are accumulated on Control, Shift or Cmd
     * clicking the point.
     *
     * @emits Highcharts.Point#event:select
     * @emits Highcharts.Point#event:unselect
     */
    Point.prototype.select = function (selected, accumulate) {
        var point = this,
            series = point.series,
            chart = series.chart;
        selected = Point_pick(selected, !point.selected);
        this.selectedStaging = selected;
        // Fire the event with the default handler
        point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () {
            /**
             * Whether the point is selected or not.
             *
             * @see Point#select
             * @see Chart#getSelectedPoints
             *
             * @name Highcharts.Point#selected
             * @type {boolean}
             */
            point.selected = point.options.selected = selected;
            series.options.data[series.data.indexOf(point)] =
                point.options;
            point.setState(selected && 'select');
            // Unselect all other points unless Ctrl or Cmd + click
            if (!accumulate) {
                chart.getSelectedPoints().forEach(function (loopPoint) {
                    var loopSeries = loopPoint.series;
                    if (loopPoint.selected && loopPoint !== point) {
                        loopPoint.selected = loopPoint.options.selected =
                            false;
                        loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options;
                        // Programmatically selecting a point should restore
                        // normal state, but when click happened on other
                        // point, set inactive state to match other points
                        loopPoint.setState(chart.hoverPoints &&
                            loopSeries.options.inactiveOtherPoints ?
                            'inactive' : '');
                        loopPoint.firePointEvent('unselect');
                    }
                });
            }
        });
        delete this.selectedStaging;
    };
    /**
     * Runs on mouse over the point. Called internally from mouse and touch
     * events.
     *
     * @function Highcharts.Point#onMouseOver
     *
     * @param {Highcharts.PointerEventObject} [e]
     *        The event arguments.
     */
    Point.prototype.onMouseOver = function (e) {
        var point = this,
            series = point.series,
            _a = series.chart,
            inverted = _a.inverted,
            pointer = _a.pointer;
        if (pointer) {
            e = e ?
                pointer.normalize(e) :
                // In cases where onMouseOver is called directly without an
                // event
                pointer.getChartCoordinatesFromPoint(point, inverted);
            pointer.runPointActions(e, point);
        }
    };
    /**
     * Runs on mouse out from the point. Called internally from mouse and touch
     * events.
     *
     * @function Highcharts.Point#onMouseOut
     * @emits Highcharts.Point#event:mouseOut
     */
    Point.prototype.onMouseOut = function () {
        var point = this,
            chart = point.series.chart;
        point.firePointEvent('mouseOut');
        if (!point.series.options.inactiveOtherPoints) {
            (chart.hoverPoints || []).forEach(function (p) {
                p.setState();
            });
        }
        chart.hoverPoints = chart.hoverPoint = null;
    };
    /**
     * Manage specific event from the series' and point's options. Only do it on
     * demand, to save processing time on hovering.
     *
     * @private
     * @function Highcharts.Point#importEvents
     */
    Point.prototype.manageEvent = function (eventType) {
        var _a,
            _b,
            _c,
            _d,
            _e,
            _f,
            _g;
        var point = this,
            options = Point_merge(point.series.options.point,
            point.options),
            userEvent = (_a = options.events) === null || _a === void 0 ? void 0 : _a[eventType];
        if (Point_isFunction(userEvent) &&
            (!((_b = point.hcEvents) === null || _b === void 0 ? void 0 : _b[eventType]) ||
                // Some HC modules, like marker-clusters, draggable-poins etc.
                // use events in their logic, so we need to be sure, that
                // callback function is different
                ((_d = (_c = point.hcEvents) === null || _c === void 0 ? void 0 : _c[eventType]) === null || _d === void 0 ? void 0 : _d.map(function (el) { return el.fn; }).indexOf(userEvent)) === -1)) {
            // While updating the existing callback event the old one should be
            // removed
            (_e = point.importedUserEvent) === null || _e === void 0 ? void 0 : _e.call(point);
            point.importedUserEvent = Point_addEvent(point, eventType, userEvent);
            if (point.hcEvents) {
                point.hcEvents[eventType].userEvent = true;
            }
        }
        else if (point.importedUserEvent &&
            !userEvent &&
            ((_f = point.hcEvents) === null || _f === void 0 ? void 0 : _f[eventType]) &&
            ((_g = point.hcEvents) === null || _g === void 0 ? void 0 : _g[eventType].userEvent)) {
            Point_removeEvent(point, eventType);
            delete point.hcEvents[eventType];
            if (!Object.keys(point.hcEvents)) {
                delete point.importedUserEvent;
            }
        }
    };
    /**
     * Set the point's state.
     *
     * @function Highcharts.Point#setState
     *
     * @param {Highcharts.PointStateValue|""} [state]
     *        The new state, can be one of `'hover'`, `'select'`, `'inactive'`,
     *        or `''` (an empty string), `'normal'` or `undefined` to set to
     *        normal state.
     * @param {boolean} [move]
     *        State for animation.
     *
     * @emits Highcharts.Point#event:afterSetState
     */
    Point.prototype.setState = function (state, move) {
        var _a;
        var point = this,
            series = point.series,
            previousState = point.state,
            stateOptions = (series.options.states[state || 'normal'] ||
                {}),
            markerOptions = (Point_defaultOptions.plotOptions[series.type].marker &&
                series.options.marker),
            normalDisabled = (markerOptions && markerOptions.enabled === false),
            markerStateOptions = ((markerOptions &&
                markerOptions.states &&
                markerOptions.states[state || 'normal']) || {}),
            stateDisabled = markerStateOptions.enabled === false,
            pointMarker = point.marker || {},
            chart = series.chart,
            hasMarkers = (markerOptions && series.markerAttribs);
        var halo = series.halo,
            markerAttribs,
            pointAttribs,
            pointAttribsAnimation,
            stateMarkerGraphic = series.stateMarkerGraphic,
            newSymbol;
        state = state || ''; // Empty string
        if (
        // Already has this state
        (state === point.state && !move) ||
            // Selected points don't respond to hover
            (point.selected && state !== 'select') ||
            // Series' state options is disabled
            (stateOptions.enabled === false) ||
            // General point marker's state options is disabled
            (state && (stateDisabled ||
                (normalDisabled &&
                    markerStateOptions.enabled === false))) ||
            // Individual point marker's state options is disabled
            (state &&
                pointMarker.states &&
                pointMarker.states[state] &&
                pointMarker.states[state].enabled === false) // #1610
        ) {
            return;
        }
        point.state = state;
        if (hasMarkers) {
            markerAttribs = series.markerAttribs(point, state);
        }
        // Apply hover styles to the existing point
        // Prevent from mocked null points (#14966)
        if (point.graphic && !point.hasMockGraphic) {
            if (previousState) {
                point.graphic.removeClass('highcharts-point-' + previousState);
            }
            if (state) {
                point.graphic.addClass('highcharts-point-' + state);
            }
            if (!chart.styledMode) {
                pointAttribs = series.pointAttribs(point, state);
                pointAttribsAnimation = Point_pick(chart.options.chart.animation, stateOptions.animation);
                var opacity_1 = pointAttribs.opacity;
                // Some inactive points (e.g. slices in pie) should apply
                // opacity also for their labels
                if (series.options.inactiveOtherPoints && Point_isNumber(opacity_1)) {
                    (point.dataLabels || []).forEach(function (label) {
                        if (label &&
                            !label.hasClass('highcharts-data-label-hidden')) {
                            label.animate({ opacity: opacity_1 }, pointAttribsAnimation);
                            if (label.connector) {
                                label.connector.animate({ opacity: opacity_1 }, pointAttribsAnimation);
                            }
                        }
                    });
                }
                point.graphic.animate(pointAttribs, pointAttribsAnimation);
            }
            if (markerAttribs) {
                point.graphic.animate(markerAttribs, Point_pick(
                // Turn off globally:
                chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation));
            }
            // Zooming in from a range with no markers to a range with markers
            if (stateMarkerGraphic) {
                stateMarkerGraphic.hide();
            }
        }
        else {
            // If a graphic is not applied to each point in the normal state,
            // create a shared graphic for the hover state
            if (state && markerStateOptions) {
                newSymbol = pointMarker.symbol || series.symbol;
                // If the point has another symbol than the previous one, throw
                // away the state marker graphic and force a new one (#1459)
                if (stateMarkerGraphic &&
                    stateMarkerGraphic.currentSymbol !== newSymbol) {
                    stateMarkerGraphic = stateMarkerGraphic.destroy();
                }
                // Add a new state marker graphic
                if (markerAttribs) {
                    if (!stateMarkerGraphic) {
                        if (newSymbol) {
                            series.stateMarkerGraphic = stateMarkerGraphic =
                                chart.renderer
                                    .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, Point_merge(markerOptions, markerStateOptions))
                                    .add(series.markerGroup);
                            stateMarkerGraphic.currentSymbol = newSymbol;
                        }
                        // Move the existing graphic
                    }
                    else {
                        stateMarkerGraphic[move ? 'animate' : 'attr']({
                            x: markerAttribs.x,
                            y: markerAttribs.y
                        });
                    }
                }
                if (!chart.styledMode && stateMarkerGraphic &&
                    point.state !== 'inactive') {
                    stateMarkerGraphic.attr(series.pointAttribs(point, state));
                }
            }
            if (stateMarkerGraphic) {
                stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450
                stateMarkerGraphic.element.point = point; // #4310
                stateMarkerGraphic.addClass(point.getClassName(), true);
            }
        }
        // Show me your halo
        var haloOptions = stateOptions.halo;
        var markerGraphic = (point.graphic || stateMarkerGraphic);
        var markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit');
        if (haloOptions &&
            haloOptions.size &&
            markerGraphic &&
            markerVisibility !== 'hidden' &&
            !point.isCluster) {
            if (!halo) {
                series.halo = halo = chart.renderer.path()
                    // #5818, #5903, #6705
                    .add(markerGraphic.parentGroup);
            }
            halo.show()[move ? 'animate' : 'attr']({
                d: point.haloPath(haloOptions.size)
            });
            halo.attr({
                'class': 'highcharts-halo highcharts-color-' +
                    Point_pick(point.colorIndex, series.colorIndex) +
                    (point.className ? ' ' + point.className : ''),
                'visibility': markerVisibility,
                'zIndex': -1 // #4929, #8276
            });
            halo.point = point; // #6055
            if (!chart.styledMode) {
                halo.attr(Point_extend({
                    'fill': point.color || series.color,
                    'fill-opacity': haloOptions.opacity
                }, HTML_AST.filterUserAttributes(haloOptions.attributes || {})));
            }
        }
        else if (((_a = halo === null || halo === void 0 ? void 0 : halo.point) === null || _a === void 0 ? void 0 : _a.haloPath) &&
            !halo.point.destroyed) {
            // Animate back to 0 on the current halo point (#6055)
            halo.animate({ d: halo.point.haloPath(0) }, null, 
            // Hide after unhovering. The `complete` callback runs in the
            // halo's context (#7681).
            halo.hide);
        }
        Point_fireEvent(point, 'afterSetState', { state: state });
    };
    /**
     * Get the path definition for the halo, which is usually a shadow-like
     * circle around the currently hovered point.
     *
     * @function Highcharts.Point#haloPath
     *
     * @param {number} size
     *        The radius of the circular halo.
     *
     * @return {Highcharts.SVGPathArray}
     *         The path definition.
     */
    Point.prototype.haloPath = function (size) {
        var pos = this.pos();
        return pos ? this.series.chart.renderer.symbols.circle(Point_crisp(pos[0], 1) - size, pos[1] - size, size * 2, size * 2) : [];
    };
    return Point;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Series_Point = (Point);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Function callback when a series point is clicked. Return false to cancel the
 * action.
 *
 * @callback Highcharts.PointClickCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        The point where the event occurred.
 *
 * @param {Highcharts.PointClickEventObject} event
 *        Event arguments.
 */
/**
 * Common information for a click event on a series point.
 *
 * @interface Highcharts.PointClickEventObject
 * @extends Highcharts.PointerEventObject
 */ /**
* Clicked point.
* @name Highcharts.PointClickEventObject#point
* @type {Highcharts.Point}
*/
/**
 * Gets fired when the mouse leaves the area close to the point.
 *
 * @callback Highcharts.PointMouseOutCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {global.PointerEvent} event
 *        Event that occurred.
 */
/**
 * Gets fired when the mouse enters the area close to the point.
 *
 * @callback Highcharts.PointMouseOverCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {global.Event} event
 *        Event that occurred.
 */
/**
 * The generic point options for all series.
 *
 * In TypeScript you have to extend `PointOptionsObject` with an additional
 * declaration to allow custom data options:
 *
 * ```
 * declare interface PointOptionsObject {
 *     customProperty: string;
 * }
 * ```
 *
 * @interface Highcharts.PointOptionsObject
 */
/**
 * Possible option types for a data point. Use `null` to indicate a gap.
 *
 * @typedef {number|string|Highcharts.PointOptionsObject|Array<(number|string|null)>|null} Highcharts.PointOptionsType
 */
/**
 * Gets fired when the point is removed using the `.remove()` method.
 *
 * @callback Highcharts.PointRemoveCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {global.Event} event
 *        Event that occurred.
 */
/**
 * Possible key values for the point state options.
 *
 * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue
 */
/**
 * Gets fired when the point is updated programmatically through the `.update()`
 * method.
 *
 * @callback Highcharts.PointUpdateCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {Highcharts.PointUpdateEventObject} event
 *        Event that occurred.
 */
/**
 * Information about the update event.
 *
 * @interface Highcharts.PointUpdateEventObject
 * @extends global.Event
 */ /**
* Options data of the update event.
* @name Highcharts.PointUpdateEventObject#options
* @type {Highcharts.PointOptionsType}
*/
/**
 * @interface Highcharts.PointEventsOptionsObject
 */ /**
* Fires when the point is selected either programmatically or following a click
* on the point. One parameter, `event`, is passed to the function. Returning
* `false` cancels the operation.
* @name Highcharts.PointEventsOptionsObject#select
* @type {Highcharts.PointSelectCallbackFunction|undefined}
*/ /**
* Fires when the point is unselected either programmatically or following a
* click on the point. One parameter, `event`, is passed to the function.
* Returning `false` cancels the operation.
* @name Highcharts.PointEventsOptionsObject#unselect
* @type {Highcharts.PointUnselectCallbackFunction|undefined}
*/
/**
 * Information about the select/unselect event.
 *
 * @interface Highcharts.PointInteractionEventObject
 * @extends global.Event
 */ /**
* @name Highcharts.PointInteractionEventObject#accumulate
* @type {boolean}
*/
/**
 * Gets fired when the point is selected either programmatically or following a
 * click on the point.
 *
 * @callback Highcharts.PointSelectCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {Highcharts.PointInteractionEventObject} event
 *        Event that occurred.
 */
/**
 * Fires when the point is unselected either programmatically or following a
 * click on the point.
 *
 * @callback Highcharts.PointUnselectCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        Point where the event occurred.
 *
 * @param {Highcharts.PointInteractionEventObject} event
 *        Event that occurred.
 */
''; // Keeps doclets above in JS file.

;// ./code/es5/es-modules/Core/Pointer.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var Pointer_assign = (undefined && undefined.__assign) || function () {
    Pointer_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 Pointer_assign.apply(this, arguments);
};

var Pointer_color = Color_Color.parse;

var Pointer_charts = Core_Globals.charts, Pointer_composed = Core_Globals.composed, Pointer_isTouchDevice = Core_Globals.isTouchDevice;

var Pointer_addEvent = Core_Utilities.addEvent, Pointer_attr = Core_Utilities.attr, Pointer_css = Core_Utilities.css, Pointer_extend = Core_Utilities.extend, Pointer_find = Core_Utilities.find, Pointer_fireEvent = Core_Utilities.fireEvent, Pointer_isNumber = Core_Utilities.isNumber, Pointer_isObject = Core_Utilities.isObject, Pointer_objectEach = Core_Utilities.objectEach, Pointer_offset = Core_Utilities.offset, Pointer_pick = Core_Utilities.pick, Pointer_pushUnique = Core_Utilities.pushUnique, Pointer_splat = Core_Utilities.splat;
/* *
 *
 *  Class
 *
 * */
/**
 * The mouse and touch tracker object. Each {@link Chart} item has one
 * associated Pointer item that can be accessed from the  {@link Chart.pointer}
 * property.
 *
 * @class
 * @name Highcharts.Pointer
 *
 * @param {Highcharts.Chart} chart
 * The chart instance.
 *
 * @param {Highcharts.Options} options
 * The root options object. The pointer uses options from the chart and tooltip
 * structures.
 */
var Pointer = /** @class */ (function () {
    /**
     * Initialize the Pointer.
     *
     * @private
     * @function Highcharts.Pointer#init
     *
     * @param {Highcharts.Chart} chart
     * The Chart instance.
     *
     * @param {Highcharts.Options} options
     * The root options object. The pointer uses options from the chart and
     * tooltip structures.
     */
    function Pointer(chart, options) {
        var _a;
        this.hasDragged = 0;
        this.pointerCaptureEventsToUnbind = [];
        this.eventsToUnbind = [];
        // Store references
        this.options = options;
        this.chart = chart;
        // Do we need to handle click on a touch device?
        this.runChartClick = Boolean((_a = options.chart.events) === null || _a === void 0 ? void 0 : _a.click);
        this.pinchDown = [];
        this.setDOMEvents();
        Pointer_fireEvent(this, 'afterInit');
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Set inactive state to all series that are not currently hovered,
     * or, if `inactiveOtherPoints` is set to true, set inactive state to
     * all points within that series.
     *
     * @private
     * @function Highcharts.Pointer#applyInactiveState
     *
     * @param {Array<Highcharts.Point>} points
     * Currently hovered points
     */
    Pointer.prototype.applyInactiveState = function (points) {
        var activeSeries = [],
            series;
        // Get all active series from the hovered points
        (points || []).forEach(function (item) {
            series = item.series;
            // Include itself
            activeSeries.push(series);
            // Include parent series
            if (series.linkedParent) {
                activeSeries.push(series.linkedParent);
            }
            // Include all child series
            if (series.linkedSeries) {
                activeSeries = activeSeries.concat(series.linkedSeries);
            }
            // Include navigator series
            if (series.navigatorSeries) {
                activeSeries.push(series.navigatorSeries);
            }
        });
        // Now loop over all series, filtering out active series
        this.chart.series.forEach(function (inactiveSeries) {
            if (activeSeries.indexOf(inactiveSeries) === -1) {
                // Inactive series
                inactiveSeries.setState('inactive', true);
            }
            else if (inactiveSeries.options.inactiveOtherPoints) {
                // Active series, but other points should be inactivated
                inactiveSeries.setAllPointsToState('inactive');
            }
        });
    };
    /**
     * Destroys the Pointer object and disconnects DOM events.
     *
     * @function Highcharts.Pointer#destroy
     */
    Pointer.prototype.destroy = function () {
        var pointer = this;
        this.eventsToUnbind.forEach(function (unbind) { return unbind(); });
        this.eventsToUnbind = [];
        if (!Core_Globals.chartCount) {
            Pointer.unbindDocumentMouseUp.forEach(function (el) { return el.unbind(); });
            Pointer.unbindDocumentMouseUp.length = 0;
            if (Pointer.unbindDocumentTouchEnd) {
                Pointer.unbindDocumentTouchEnd = (Pointer.unbindDocumentTouchEnd());
            }
        }
        // Memory and CPU leak
        clearInterval(pointer.tooltipTimeout);
        Pointer_objectEach(pointer, function (_val, prop) {
            pointer[prop] = void 0;
        });
    };
    /**
     * Calculate attrs for selection marker.
     * @private
     * @function Highcharts.Pointer#getSelectionMarkerAttrs
     * @emits getSelectionMarkerAttrs
     */
    Pointer.prototype.getSelectionMarkerAttrs = function (chartX, chartY) {
        var _this = this;
        var e = {
                args: { chartX: chartX,
            chartY: chartY },
                attrs: {},
                shapeType: 'rect'
            };
        Pointer_fireEvent(this, 'getSelectionMarkerAttrs', e, function (e) {
            var _a = _this,
                chart = _a.chart,
                zoomHor = _a.zoomHor,
                zoomVert = _a.zoomVert,
                _b = chart.mouseDownX,
                mouseDownX = _b === void 0 ? 0 : _b,
                _c = chart.mouseDownY,
                mouseDownY = _c === void 0 ? 0 : _c,
                attrs = e.attrs;
            var size;
            attrs.x = chart.plotLeft;
            attrs.y = chart.plotTop;
            attrs.width = zoomHor ? 1 : chart.plotWidth;
            attrs.height = zoomVert ? 1 : chart.plotHeight;
            // Adjust the width of the selection marker. Firefox needs at
            // least one pixel width or height in order to return a bounding
            // box.
            if (zoomHor) {
                size = chartX - mouseDownX;
                attrs.width = Math.max(1, Math.abs(size));
                attrs.x = (size > 0 ? 0 : size) + mouseDownX;
            }
            // Adjust the height of the selection marker
            if (zoomVert) {
                size = chartY - mouseDownY;
                attrs.height = Math.max(1, Math.abs(size));
                attrs.y = (size > 0 ? 0 : size) + mouseDownY;
            }
        });
        return e;
    };
    /**
     * Perform a drag operation in response to a mousemove event while the mouse
     * is down.
     * @private
     * @function Highcharts.Pointer#drag
     */
    Pointer.prototype.drag = function (e) {
        var chart = this.chart,
            _a = chart.mouseDownX,
            mouseDownX = _a === void 0 ? 0 : _a,
            _b = chart.mouseDownY,
            mouseDownY = _b === void 0 ? 0 : _b,
            _c = chart.options.chart,
            panning = _c.panning,
            panKey = _c.panKey,
            selectionMarkerFill = _c.selectionMarkerFill,
            plotLeft = chart.plotLeft,
            plotTop = chart.plotTop,
            plotWidth = chart.plotWidth,
            plotHeight = chart.plotHeight,
            panningEnabled = Pointer_isObject(panning) ?
                panning.enabled :
                panning,
            panKeyPressed = panKey && e["" + panKey + "Key"];
        var chartX = e.chartX,
            chartY = e.chartY,
            clickedInside,
            selectionMarker = this.selectionMarker;
        // If the device supports both touch and mouse (like IE11), and we are
        // touch-dragging inside the plot area, don't handle the mouse event.
        // #4339.
        if (selectionMarker && selectionMarker.touch) {
            return;
        }
        // If the mouse is outside the plot area, adjust to coordinates
        // inside to prevent the selection marker from going outside
        if (chartX < plotLeft) {
            chartX = plotLeft;
        }
        else if (chartX > plotLeft + plotWidth) {
            chartX = plotLeft + plotWidth;
        }
        if (chartY < plotTop) {
            chartY = plotTop;
        }
        else if (chartY > plotTop + plotHeight) {
            chartY = plotTop + plotHeight;
        }
        // Determine if the mouse has moved more than 10px
        this.hasDragged = Math.sqrt(Math.pow(mouseDownX - chartX, 2) +
            Math.pow(mouseDownY - chartY, 2));
        if (this.hasDragged > 10) {
            clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop, {
                visiblePlotOnly: true
            });
            var _d = this.getSelectionMarkerAttrs(chartX,
                chartY),
                shapeType = _d.shapeType,
                attrs = _d.attrs;
            // Make a selection
            if ((chart.hasCartesianSeries || chart.mapView) &&
                this.hasZoom &&
                clickedInside &&
                !panKeyPressed) {
                if (!selectionMarker) {
                    this.selectionMarker = selectionMarker =
                        chart.renderer[shapeType]();
                    selectionMarker
                        .attr({
                        'class': 'highcharts-selection-marker',
                        zIndex: 7
                    })
                        .add();
                    if (!chart.styledMode) {
                        selectionMarker.attr({
                            fill: selectionMarkerFill ||
                                Pointer_color("#334eff" /* Palette.highlightColor80 */)
                                    .setOpacity(0.25).get()
                        });
                    }
                }
            }
            if (selectionMarker) {
                selectionMarker.attr(attrs);
            }
            // Panning
            if (clickedInside && !selectionMarker && panningEnabled) {
                chart.pan(e, panning);
            }
        }
    };
    /**
     * Start a drag operation.
     * @private
     * @function Highcharts.Pointer#dragStart
     */
    Pointer.prototype.dragStart = function (e) {
        var chart = this.chart;
        // Record the start position
        chart.mouseIsDown = e.type;
        chart.cancelClick = false;
        chart.mouseDownX = e.chartX;
        chart.mouseDownY = e.chartY;
    };
    /**
     * Get selection box to calculate extremes
     * @private
     * @function Highcharts.Pointer#getSelectionBox
     * @emits getSelectionBox
     */
    Pointer.prototype.getSelectionBox = function (marker) {
        var e = {
                args: { marker: marker },
                result: marker.getBBox()
            };
        Pointer_fireEvent(this, 'getSelectionBox', e);
        return e.result;
    };
    /**
     * On mouse up or touch end across the entire document, drop the selection.
     * @private
     * @function Highcharts.Pointer#drop
     */
    Pointer.prototype.drop = function (e) {
        var _this = this;
        var _a = this,
            chart = _a.chart,
            selectionMarker = _a.selectionMarker;
        // During a mouse, touch or mousewheel pan, the `startOnTick` and
        // `endOnTick` options are ignored. Otherwise the zooming or panning
        // would be jumpy, or even not performed because the end ticks would
        // block it. After the touch has ended, we undo this and render again.
        var redraw;
        for (var _i = 0, _b = chart.axes; _i < _b.length; _i++) {
            var axis = _b[_i];
            if (axis.isPanning) {
                axis.isPanning = false;
                if (axis.options.startOnTick ||
                    axis.options.endOnTick ||
                    axis.series.some(function (s) { return s.boosted; })) {
                    axis.forceRedraw = true;
                    axis.setExtremes(axis.userMin, axis.userMax, false);
                    redraw = true;
                }
            }
        }
        if (redraw) {
            chart.redraw();
        }
        if (selectionMarker && e) {
            // A selection has been made
            if (this.hasDragged) {
                var from = this.getSelectionBox(selectionMarker);
                chart.transform({
                    axes: chart.axes.filter(function (a) {
                        return a.zoomEnabled &&
                            ((a.coll === 'xAxis' && _this.zoomX) ||
                                (a.coll === 'yAxis' && _this.zoomY));
                    }),
                    selection: Pointer_assign({ originalEvent: e, xAxis: [], yAxis: [] }, from),
                    from: from
                });
            }
            if (Pointer_isNumber(chart.index)) {
                this.selectionMarker = selectionMarker.destroy();
            }
        }
        // Reset all. Check isNumber because it may be destroyed on mouse up
        // (#877)
        if (chart && Pointer_isNumber(chart.index)) {
            Pointer_css(chart.container, { cursor: chart._cursor });
            chart.cancelClick = this.hasDragged > 10; // #370
            chart.mouseIsDown = false;
            this.hasDragged = 0;
            this.pinchDown = [];
        }
    };
    /**
     * Finds the closest point to a set of coordinates, using the k-d-tree
     * algorithm.
     *
     * @function Highcharts.Pointer#findNearestKDPoint
     *
     * @param {Array<Highcharts.Series>} series
     * All the series to search in.
     *
     * @param {boolean|undefined} shared
     * Whether it is a shared tooltip or not.
     *
     * @param {Highcharts.PointerEventObject} e
     * The pointer event object, containing chart coordinates of the pointer.
     *
     * @return {Highcharts.Point|undefined}
     * The point closest to given coordinates.
     */
    Pointer.prototype.findNearestKDPoint = function (series, shared, e) {
        var closest;
        /** @private */
        function sort(p1, p2) {
            var _a,
                _b;
            var isCloserX = p1.distX - p2.distX,
                isCloser = p1.dist - p2.dist,
                isAbove = (((_a = p2.series.group) === null || _a === void 0 ? void 0 : _a.zIndex) -
                    ((_b = p1.series.group) === null || _b === void 0 ? void 0 : _b.zIndex));
            var result;
            // We have two points which are not in the same place on xAxis
            // and shared tooltip:
            if (isCloserX !== 0 && shared) { // #5721
                result = isCloserX;
                // Points are not exactly in the same place on x/yAxis:
            }
            else if (isCloser !== 0) {
                result = isCloser;
                // The same xAxis and yAxis position, sort by z-index:
            }
            else if (isAbove !== 0) {
                result = isAbove;
                // The same zIndex, sort by array index:
            }
            else {
                result =
                    p1.series.index > p2.series.index ?
                        -1 :
                        1;
            }
            return result;
        }
        series.forEach(function (s) {
            var noSharedTooltip = s.noSharedTooltip && shared,
                compareX = (!noSharedTooltip &&
                    s.options.findNearestPointBy.indexOf('y') < 0),
                point = s.searchPoint(e,
                compareX);
            if ( // Check that we actually found a point on the series.
            Pointer_isObject(point, true) && point.series &&
                // Use the new point if it is closer.
                (!Pointer_isObject(closest, true) ||
                    (sort(closest, point) > 0))) {
                closest = point;
            }
        });
        return closest;
    };
    /**
     * @private
     * @function Highcharts.Pointer#getChartCoordinatesFromPoint
     */
    Pointer.prototype.getChartCoordinatesFromPoint = function (point, inverted) {
        var _a,
            _b;
        var _c = point.series,
            xAxis = _c.xAxis,
            yAxis = _c.yAxis,
            shapeArgs = point.shapeArgs;
        if (xAxis && yAxis) {
            var x = (_b = (_a = point.clientX) !== null && _a !== void 0 ? _a : point.plotX) !== null && _b !== void 0 ? _b : 0,
                y = point.plotY || 0;
            if (point.isNode &&
                shapeArgs &&
                Pointer_isNumber(shapeArgs.x) &&
                Pointer_isNumber(shapeArgs.y)) {
                x = shapeArgs.x;
                y = shapeArgs.y;
            }
            return inverted ? {
                chartX: yAxis.len + yAxis.pos - y,
                chartY: xAxis.len + xAxis.pos - x
            } : {
                chartX: x + xAxis.pos,
                chartY: y + yAxis.pos
            };
        }
        if (shapeArgs && shapeArgs.x && shapeArgs.y) {
            // E.g. pies do not have axes
            return {
                chartX: shapeArgs.x,
                chartY: shapeArgs.y
            };
        }
    };
    /**
     * Return the cached chartPosition if it is available on the Pointer,
     * otherwise find it. Running offset is quite expensive, so it should be
     * avoided when we know the chart hasn't moved.
     *
     * @function Highcharts.Pointer#getChartPosition
     *
     * @return {Highcharts.ChartPositionObject}
     * The offset of the chart container within the page
     */
    Pointer.prototype.getChartPosition = function () {
        if (this.chartPosition) {
            return this.chartPosition;
        }
        var container = this.chart.container;
        var pos = Pointer_offset(container);
        this.chartPosition = {
            left: pos.left,
            top: pos.top,
            scaleX: 1,
            scaleY: 1
        };
        var offsetHeight = container.offsetHeight,
            offsetWidth = container.offsetWidth;
        // #13342 - tooltip was not visible in Chrome, when chart
        // updates height.
        if (offsetWidth > 2 && // #13342
            offsetHeight > 2 // #13342
        ) {
            this.chartPosition.scaleX = pos.width / offsetWidth;
            this.chartPosition.scaleY = pos.height / offsetHeight;
        }
        return this.chartPosition;
    };
    /**
     * Get the click position in terms of axis values.
     *
     * @function Highcharts.Pointer#getCoordinates
     *
     * @param {Highcharts.PointerEventObject} e
     * Pointer event, extended with `chartX` and `chartY` properties.
     *
     * @return {Highcharts.PointerAxisCoordinatesObject}
     * Axis coordinates.
     */
    Pointer.prototype.getCoordinates = function (e) {
        var coordinates = {
                xAxis: [],
                yAxis: []
            };
        for (var _i = 0, _a = this.chart.axes; _i < _a.length; _i++) {
            var axis = _a[_i];
            coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({
                axis: axis,
                value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY'])
            });
        }
        return coordinates;
    };
    /**
     * Calculates what is the current hovered point/points and series.
     *
     * @private
     * @function Highcharts.Pointer#getHoverData
     *
     * @param {Highcharts.Point|undefined} existingHoverPoint
     * The point currently being hovered.
     *
     * @param {Highcharts.Series|undefined} existingHoverSeries
     * The series currently being hovered.
     *
     * @param {Array<Highcharts.Series>} series
     * All the series in the chart.
     *
     * @param {boolean} isDirectTouch
     * Is the pointer directly hovering the point.
     *
     * @param {boolean|undefined} shared
     * Whether it is a shared tooltip or not.
     *
     * @param {Highcharts.PointerEventObject} [e]
     * The triggering event, containing chart coordinates of the pointer.
     *
     * @return {Object}
     * Object containing resulting hover data: hoverPoint, hoverSeries, and
     * hoverPoints.
     */
    Pointer.prototype.getHoverData = function (existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) {
        var hoverPoints = [],
            useExisting = !!(isDirectTouch && existingHoverPoint),
            filter = function (s) {
                return (s.visible &&
                    !(!shared && s.directTouch) && // #3821
                    Pointer_pick(s.options.enableMouseTracking,
            true));
        };
        var hoverSeries = existingHoverSeries, 
            // Which series to look in for the hover point
            searchSeries, 
            // Parameters needed for beforeGetHoverData event.
            eventArgs = {
                chartX: e ? e.chartX : void 0,
                chartY: e ? e.chartY : void 0,
                shared: shared
            };
        // Find chart.hoverPane and update filter method in polar.
        Pointer_fireEvent(this, 'beforeGetHoverData', eventArgs);
        var notSticky = hoverSeries && !hoverSeries.stickyTracking;
        searchSeries = notSticky ?
            // Only search on hovered series if it has stickyTracking false
            [hoverSeries] :
            // Filter what series to look in.
            series.filter(function (s) { return s.stickyTracking &&
                (eventArgs.filter || filter)(s); });
        // Use existing hovered point or find the one closest to coordinates.
        var hoverPoint = useExisting || !e ?
                existingHoverPoint :
                this.findNearestKDPoint(searchSeries,
            shared,
            e);
        // Assign hover series
        hoverSeries = hoverPoint && hoverPoint.series;
        // If we have a hoverPoint, assign hoverPoints.
        if (hoverPoint) {
            // When tooltip is shared, it displays more than one point
            if (shared && !hoverSeries.noSharedTooltip) {
                searchSeries = series.filter(function (s) {
                    return eventArgs.filter ?
                        eventArgs.filter(s) : filter(s) && !s.noSharedTooltip;
                });
                // Get all points with the same x value as the hoverPoint
                searchSeries.forEach(function (s) {
                    var point = Pointer_find(s.points,
                        function (p) {
                            return p.x === hoverPoint.x && !p.isNull;
                    });
                    if (Pointer_isObject(point)) {
                        /*
                        * Boost returns a minimal point. Convert it to a usable
                        * point for tooltip and states.
                        */
                        if (s.boosted && s.boost) {
                            point = s.boost.getPoint(point);
                        }
                        hoverPoints.push(point);
                    }
                });
            }
            else {
                hoverPoints.push(hoverPoint);
            }
        }
        // Check whether the hoverPoint is inside pane we are hovering over.
        eventArgs = { hoverPoint: hoverPoint };
        Pointer_fireEvent(this, 'afterGetHoverData', eventArgs);
        return {
            hoverPoint: eventArgs.hoverPoint,
            hoverSeries: hoverSeries,
            hoverPoints: hoverPoints
        };
    };
    /**
     * @private
     * @function Highcharts.Pointer#getPointFromEvent
     */
    Pointer.prototype.getPointFromEvent = function (e) {
        var target = e.target,
            point;
        while (target && !point) {
            point = target.point;
            target = target.parentNode;
        }
        return point;
    };
    /**
     * @private
     * @function Highcharts.Pointer#onTrackerMouseOut
     */
    Pointer.prototype.onTrackerMouseOut = function (e) {
        var chart = this.chart;
        var relatedTarget = e.relatedTarget;
        var series = chart.hoverSeries;
        this.isDirectTouch = false;
        if (series &&
            relatedTarget &&
            !series.stickyTracking &&
            !this.inClass(relatedTarget, 'highcharts-tooltip') &&
            (!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465, #5553
                !this.inClass(relatedTarget, 'highcharts-tracker'))) {
            series.onMouseOut();
        }
    };
    /**
     * Utility to detect whether an element has, or has a parent with, a
     * specific class name. Used on detection of tracker objects and on deciding
     * whether hovering the tooltip should cause the active series to mouse out.
     *
     * @function Highcharts.Pointer#inClass
     *
     * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
     * The element to investigate.
     *
     * @param {string} className
     * The class name to look for.
     *
     * @return {boolean|undefined}
     * True if either the element or one of its parents has the given class
     * name.
     */
    Pointer.prototype.inClass = function (element, className) {
        var elem = element,
            elemClassName;
        while (elem) {
            elemClassName = Pointer_attr(elem, 'class');
            if (elemClassName) {
                if (elemClassName.indexOf(className) !== -1) {
                    return true;
                }
                if (elemClassName.indexOf('highcharts-container') !== -1) {
                    return false;
                }
            }
            elem = elem.parentElement;
        }
    };
    /**
     * Takes a browser event object and extends it with custom Highcharts
     * properties `chartX` and `chartY` in order to work on the internal
     * coordinate system.
     *
     * On map charts, the properties `lon` and `lat` are added to the event
     * object given that the chart has projection information.
     *
     * @function Highcharts.Pointer#normalize
     *
     * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e
     * Event object in standard browsers.
     *
     * @param {Highcharts.OffsetObject} [chartPosition]
     * Additional chart offset.
     *
     * @return {Highcharts.PointerEventObject}
     * A browser event with extended properties `chartX` and `chartY`.
     */
    Pointer.prototype.normalize = function (e, chartPosition) {
        var touches = e.touches;
        // Position for iOS (#2757)
        var ePos = (touches ?
                touches.length ?
                    touches.item(0) :
                    (Pointer_pick(// #13534
                    touches.changedTouches,
            e.changedTouches))[0] :
                e);
        // Get mouse position
        if (!chartPosition) {
            chartPosition = this.getChartPosition();
        }
        var chartX = ePos.pageX - chartPosition.left,
            chartY = ePos.pageY - chartPosition.top;
        // #11329 - when there is scaling on a parent element, we need to take
        // this into account
        chartX /= chartPosition.scaleX;
        chartY /= chartPosition.scaleY;
        return Pointer_extend(e, {
            chartX: Math.round(chartX),
            chartY: Math.round(chartY)
        });
    };
    /**
     * @private
     * @function Highcharts.Pointer#onContainerClick
     */
    Pointer.prototype.onContainerClick = function (e) {
        var chart = this.chart;
        var hoverPoint = chart.hoverPoint;
        var pEvt = this.normalize(e);
        var plotLeft = chart.plotLeft;
        var plotTop = chart.plotTop;
        if (!chart.cancelClick) {
            // On tracker click, fire the series and point events. #783, #1583
            if (hoverPoint &&
                this.inClass(pEvt.target, 'highcharts-tracker')) {
                // The series click event
                Pointer_fireEvent(hoverPoint.series, 'click', Pointer_extend(pEvt, {
                    point: hoverPoint
                }));
                // The point click event
                if (chart.hoverPoint) { // It may be destroyed (#1844)
                    hoverPoint.firePointEvent('click', pEvt);
                }
                // When clicking outside a tracker, fire a chart event
            }
            else {
                Pointer_extend(pEvt, this.getCoordinates(pEvt));
                // Fire a click event in the chart
                if (chart.isInsidePlot(pEvt.chartX - plotLeft, pEvt.chartY - plotTop, {
                    visiblePlotOnly: true
                })) {
                    Pointer_fireEvent(chart, 'click', pEvt);
                }
            }
        }
    };
    /**
     * @private
     * @function Highcharts.Pointer#onContainerMouseDown
     */
    Pointer.prototype.onContainerMouseDown = function (e) {
        var _a;
        var isPrimaryButton = ((e.buttons || e.button) & 1) === 1;
        e = this.normalize(e);
        // #11635, Firefox does not reliably fire move event after click scroll
        if (Core_Globals.isFirefox &&
            e.button !== 0) {
            this.onContainerMouseMove(e);
        }
        // #11635, limiting to primary button
        if (typeof e.button === 'undefined' ||
            isPrimaryButton) {
            this.zoomOption(e);
            // #295, #13737 solve conflict between container drag and chart zoom
            if (isPrimaryButton) {
                (_a = e.preventDefault) === null || _a === void 0 ? void 0 : _a.call(e);
            }
            this.dragStart(e);
        }
    };
    /**
     * When mouse leaves the container, hide the tooltip.
     * @private
     * @function Highcharts.Pointer#onContainerMouseLeave
     */
    Pointer.prototype.onContainerMouseLeave = function (e) {
        var pointer = (Pointer_charts[Pointer_pick(Pointer.hoverChartIndex, -1)] || {}).pointer;
        e = this.normalize(e);
        this.onContainerMouseMove(e);
        // #4886, MS Touch end fires mouseleave but with no related target
        if (pointer &&
            !this.inClass(e.relatedTarget, 'highcharts-tooltip')) {
            pointer.reset();
            // Also reset the chart position, used in #149 fix
            pointer.chartPosition = void 0;
        }
    };
    /**
     * When mouse enters the container, delete pointer's chartPosition.
     * @private
     * @function Highcharts.Pointer#onContainerMouseEnter
     */
    Pointer.prototype.onContainerMouseEnter = function () {
        delete this.chartPosition;
    };
    /**
     * The mousemove, touchmove and touchstart event handler
     * @private
     * @function Highcharts.Pointer#onContainerMouseMove
     */
    Pointer.prototype.onContainerMouseMove = function (e) {
        var chart = this.chart,
            tooltip = chart.tooltip,
            pEvt = this.normalize(e);
        this.setHoverChartIndex(e);
        if (chart.mouseIsDown === 'mousedown' || this.touchSelect(pEvt)) {
            this.drag(pEvt);
        }
        // Show the tooltip and run mouse over events (#977)
        if (!chart.openMenu &&
            (this.inClass(pEvt.target, 'highcharts-tracker') ||
                chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop, {
                    visiblePlotOnly: true
                })) &&
            // If the tooltip has stickOnContact enabled, do nothing. This
            // applies regardless of any combinations of the `split` and
            // `useHTML` options.
            !(tooltip &&
                tooltip.shouldStickOnContact(pEvt))) {
            if (this.inClass(pEvt.target, 'highcharts-no-tooltip')) {
                this.reset(false, 0);
            }
            else {
                this.runPointActions(pEvt);
            }
        }
    };
    /**
     * @private
     * @function Highcharts.Pointer#onDocumentTouchEnd
     */
    Pointer.prototype.onDocumentTouchEnd = function (e) {
        this.onDocumentMouseUp(e);
    };
    /**
     * @private
     * @function Highcharts.Pointer#onContainerTouchMove
     */
    Pointer.prototype.onContainerTouchMove = function (e) {
        if (this.touchSelect(e)) {
            this.onContainerMouseMove(e);
        }
        else {
            this.touch(e);
        }
    };
    /**
     * @private
     * @function Highcharts.Pointer#onContainerTouchStart
     */
    Pointer.prototype.onContainerTouchStart = function (e) {
        if (this.touchSelect(e)) {
            this.onContainerMouseDown(e);
        }
        else {
            this.zoomOption(e);
            this.touch(e, true);
        }
    };
    /**
     * Special handler for mouse move that will hide the tooltip when the mouse
     * leaves the plotarea. Issue #149 workaround. The mouseleave event does not
     * always fire.
     * @private
     * @function Highcharts.Pointer#onDocumentMouseMove
     */
    Pointer.prototype.onDocumentMouseMove = function (e) {
        var chart = this.chart;
        var tooltip = chart.tooltip;
        var chartPosition = this.chartPosition;
        var pEvt = this.normalize(e,
            chartPosition);
        // If we're outside, hide the tooltip
        if (chartPosition &&
            !chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop, {
                visiblePlotOnly: true
            }) &&
            !(tooltip &&
                tooltip.shouldStickOnContact(pEvt)) && (pEvt.target === chart.container.ownerDocument ||
            !this.inClass(pEvt.target, 'highcharts-tracker'))) {
            this.reset();
        }
    };
    /**
     * @private
     * @function Highcharts.Pointer#onDocumentMouseUp
     */
    Pointer.prototype.onDocumentMouseUp = function (e) {
        var _a,
            _b;
        (_b = (_a = Pointer_charts[Pointer_pick(Pointer.hoverChartIndex, -1)]) === null || _a === void 0 ? void 0 : _a.pointer) === null || _b === void 0 ? void 0 : _b.drop(e);
    };
    /**
     * Handle touch events with two touches
     * @private
     * @function Highcharts.Pointer#pinch
     */
    Pointer.prototype.pinch = function (e) {
        var _this = this;
        var pointer = this,
            chart = pointer.chart,
            hasZoom = pointer.hasZoom,
            lastTouches = pointer.lastTouches,
            touches = [].map.call(e.touches || [], 
            // Normalize each touch
            function (touch) { return pointer.normalize(touch); }),
            touchesLength = touches.length,
            fireClickEvent = touchesLength === 1 && ((pointer.inClass(e.target, 'highcharts-tracker') &&
                chart.runTrackerClick) ||
                pointer.runChartClick),
            tooltip = chart.tooltip,
            followTouchMove = touchesLength === 1 &&
                Pointer_pick(tooltip === null || tooltip === void 0 ? void 0 : tooltip.options.followTouchMove,
            true);
        // Don't initiate panning until the user has pinched. This prevents us
        // from blocking page scrolling as users scroll down a long page
        // (#4210).
        if (touchesLength > 1) {
            pointer.initiated = true;
        }
        else if (followTouchMove) {
            // #16119: Prevent blocking scroll when single-finger panning is
            // not enabled
            pointer.initiated = false;
        }
        // On touch devices, only proceed to trigger click if a handler is
        // defined
        if (hasZoom &&
            pointer.initiated &&
            !fireClickEvent &&
            e.cancelable !== false) {
            e.preventDefault();
        }
        // Register the touch start position
        if (e.type === 'touchstart') {
            pointer.pinchDown = touches;
            pointer.res = true; // Reset on next move
            chart.mouseDownX = e.chartX;
            // Optionally move the tooltip on touchmove
        }
        else if (followTouchMove) {
            this.runPointActions(pointer.normalize(e));
            // Event type is touchmove, handle panning and pinching. The length can
            // be 0 when releasing, if touchend fires first
        }
        else if (lastTouches) {
            Pointer_fireEvent(chart, 'touchpan', {
                originalEvent: e,
                touches: touches
            }, function () {
                var boxFromTouches = function (touches) {
                        var finger0 = touches[0],
                    finger1 = touches[1] || finger0;
                    return {
                        x: finger0.chartX,
                        y: finger0.chartY,
                        width: finger1.chartX - finger0.chartX,
                        height: finger1.chartY - finger0.chartY
                    };
                };
                chart.transform({
                    axes: chart.axes
                        .filter(function (axis) {
                        return axis.zoomEnabled &&
                            ((_this.zoomHor && axis.horiz) ||
                                (_this.zoomVert && !axis.horiz));
                    }),
                    to: boxFromTouches(touches),
                    from: boxFromTouches(lastTouches),
                    trigger: e.type
                });
            });
            if (pointer.res) {
                pointer.res = false;
                this.reset(false, 0);
            }
        }
        pointer.lastTouches = touches;
    };
    /**
     * Run translation operations
     * @private
     * @function Highcharts.Pointer#pinchTranslate
     * /
    public pinchTranslate(
        pinchDown: Array<any>,
        touches: Array<PointerEvent>,
        transform: any,
        selectionMarker: any,
        clip: any,
        lastValidTouch: any
    ): void {
        if (this.zoomHor) {
            this.pinchTranslateDirection(
                true,
                pinchDown,
                touches,
                transform,
                selectionMarker,
                clip,
                lastValidTouch
            );
        }
        if (this.zoomVert) {
            this.pinchTranslateDirection(
                false,
                pinchDown,
                touches,
                transform,
                selectionMarker,
                clip,
                lastValidTouch
            );
        }
    }
    */
    /**
     * Run translation operations for each direction (horizontal and vertical)
     * independently.
     * @private
     * @function Highcharts.Pointer#pinchTranslateDirection
     * /
    public pinchTranslateDirection(
        horiz: boolean,
        pinchDown: Array<any>,
        touches: Array<PointerEvent>,
        transform: any,
        selectionMarker: any,
        clip: any,
        lastValidTouch: any,
        forcedScale?: number
    ): void {
        const chart = this.chart,
            xy: ('x'|'y') = horiz ? 'x' : 'y',
            XY: ('X'|'Y') = horiz ? 'X' : 'Y',
            sChartXY: ('chartX'|'chartY') = ('chart' + XY) as any,
            wh = horiz ? 'width' : 'height',
            plotLeftTop = (chart as any)['plot' + (horiz ? 'Left' : 'Top')],
            inverted = chart.inverted,
            bounds = chart.bounds[horiz ? 'h' : 'v'],
            singleTouch = pinchDown.length === 1,
            touch0Start = pinchDown[0][sChartXY],
            touch1Start = !singleTouch && pinchDown[1][sChartXY],
            setScale = function (): void {
                // Don't zoom if fingers are too close on this axis
                if (
                    typeof touch1Now === 'number' &&
                    Math.abs(touch0Start - touch1Start) > 20
                ) {
                    scale = forcedScale ||
                        Math.abs(touch0Now - touch1Now) /
                        Math.abs(touch0Start - touch1Start);
                }

                clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start;
                selectionWH = (chart as any)[
                    'plot' + (horiz ? 'Width' : 'Height')
                ] / scale;
            };

        let selectionWH: any,
            selectionXY,
            clipXY: any,
            scale = forcedScale || 1,
            touch0Now = touches[0][sChartXY],
            touch1Now = !singleTouch && touches[1][sChartXY],
            outOfBounds;

        // Set the scale, first pass
        setScale();

        // The clip position (x or y) is altered if out of bounds, the selection
        // position is not
        selectionXY = clipXY;

        // Out of bounds
        if (selectionXY < bounds.min) {
            selectionXY = bounds.min;
            outOfBounds = true;
        } else if (selectionXY + selectionWH > bounds.max) {
            selectionXY = bounds.max - selectionWH;
            outOfBounds = true;
        }

        // Is the chart dragged off its bounds, determined by dataMin and
        // dataMax?
        if (outOfBounds) {

            // Modify the touchNow position in order to create an elastic drag
            // movement. This indicates to the user that the chart is responsive
            // but can't be dragged further.
            touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]);
            if (typeof touch1Now === 'number') {
                touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]);
            }

            // Set the scale, second pass to adapt to the modified touchNow
            // positions
            setScale();

        } else {
            lastValidTouch[xy] = [touch0Now, touch1Now];
        }

        // Set geometry for clipping, selection and transformation
        if (!inverted) {
            clip[xy] = clipXY - plotLeftTop;
            clip[wh] = selectionWH;
        }
        const scaleKey = inverted ?
            (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY;
        const transformScale = inverted ? 1 / scale : scale;

        selectionMarker[wh] = selectionWH;
        selectionMarker[xy] = selectionXY;
        // Invert scale if needed (#19217)
        transform[scaleKey] = scale * (inverted && !horiz ? -1 : 1);
        transform['translate' + XY] = (transformScale * plotLeftTop) +
            (touch0Now - (transformScale * touch0Start));
    }
    */
    /**
     * Reset the tracking by hiding the tooltip, the hover series state and the
     * hover point
     *
     * @function Highcharts.Pointer#reset
     *
     * @param {boolean} [allowMove]
     * Instead of destroying the tooltip altogether, allow moving it if
     * possible.
     *
     * @param {number} [delay]
     */
    Pointer.prototype.reset = function (allowMove, delay) {
        var pointer = this,
            chart = pointer.chart,
            hoverSeries = chart.hoverSeries,
            hoverPoint = chart.hoverPoint,
            hoverPoints = chart.hoverPoints,
            tooltip = chart.tooltip,
            tooltipPoints = tooltip && tooltip.shared ?
                hoverPoints :
                hoverPoint;
        // Check if the points have moved outside the plot area (#1003, #4736,
        // #5101)
        if (allowMove && tooltipPoints) {
            Pointer_splat(tooltipPoints).forEach(function (point) {
                if (point.series.isCartesian &&
                    typeof point.plotX === 'undefined') {
                    allowMove = false;
                }
            });
        }
        // Just move the tooltip, #349
        if (allowMove) {
            if (tooltip && tooltipPoints && Pointer_splat(tooltipPoints).length) {
                tooltip.refresh(tooltipPoints);
                if (tooltip.shared && hoverPoints) { // #8284
                    hoverPoints.forEach(function (point) {
                        point.setState(point.state, true);
                        if (point.series.isCartesian) {
                            if (point.series.xAxis.crosshair) {
                                point.series.xAxis
                                    .drawCrosshair(null, point);
                            }
                            if (point.series.yAxis.crosshair) {
                                point.series.yAxis
                                    .drawCrosshair(null, point);
                            }
                        }
                    });
                }
                else if (hoverPoint) { // #2500
                    hoverPoint.setState(hoverPoint.state, true);
                    chart.axes.forEach(function (axis) {
                        if (axis.crosshair &&
                            hoverPoint.series[axis.coll] === axis) {
                            axis.drawCrosshair(null, hoverPoint);
                        }
                    });
                }
            }
            // Full reset
        }
        else {
            if (hoverPoint) {
                hoverPoint.onMouseOut();
            }
            if (hoverPoints) {
                hoverPoints.forEach(function (point) {
                    point.setState();
                });
            }
            if (hoverSeries) {
                hoverSeries.onMouseOut();
            }
            if (tooltip) {
                tooltip.hide(delay);
            }
            if (pointer.unDocMouseMove) {
                pointer.unDocMouseMove = pointer.unDocMouseMove();
            }
            // Remove crosshairs
            chart.axes.forEach(function (axis) {
                axis.hideCrosshair();
            });
            chart.hoverPoints = chart.hoverPoint = void 0;
        }
    };
    /**
     * With line type charts with a single tracker, get the point closest to the
     * mouse. Run Point.onMouseOver and display tooltip for the point or points.
     *
     * @private
     * @function Highcharts.Pointer#runPointActions
     *
     * @emits Highcharts.Point#event:mouseOut
     * @emits Highcharts.Point#event:mouseOver
     */
    Pointer.prototype.runPointActions = function (e, p, force) {
        var pointer = this,
            chart = pointer.chart,
            series = chart.series,
            tooltip = (chart.tooltip && chart.tooltip.options.enabled ?
                chart.tooltip :
                void 0),
            shared = (tooltip ?
                tooltip.shared :
                false);
        var hoverPoint = p || chart.hoverPoint,
            hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries;
        var // `onMouseOver` or already hovering a series with directTouch
            isDirectTouch = (!e || e.type !== 'touchmove') && (!!p || ((hoverSeries && hoverSeries.directTouch) &&
                pointer.isDirectTouch)),
            hoverData = this.getHoverData(hoverPoint,
            hoverSeries,
            series,
            isDirectTouch,
            shared,
            e);
        // Update variables from hoverData.
        hoverPoint = hoverData.hoverPoint;
        hoverSeries = hoverData.hoverSeries;
        var points = hoverData.hoverPoints,
            followPointer = hoverSeries &&
                hoverSeries.tooltipOptions.followPointer &&
                !hoverSeries.tooltipOptions.split,
            useSharedTooltip = (shared &&
                hoverSeries &&
                !hoverSeries.noSharedTooltip);
        // Refresh tooltip for kdpoint if new hover point or tooltip was hidden
        // #3926, #4200
        if (hoverPoint &&
            (force ||
                hoverPoint !== chart.hoverPoint ||
                (tooltip && tooltip.isHidden))) {
            (chart.hoverPoints || []).forEach(function (p) {
                if (points.indexOf(p) === -1) {
                    p.setState();
                }
            });
            // Set normal state to previous series
            if (chart.hoverSeries !== hoverSeries) {
                hoverSeries.onMouseOver();
            }
            pointer.applyInactiveState(points);
            // Do mouseover on all points (#3919, #3985, #4410, #5622)
            (points || []).forEach(function (p) {
                p.setState('hover');
            });
            // If tracking is on series in stead of on each point,
            // fire mouseOver on hover point. // #4448
            if (chart.hoverPoint) {
                chart.hoverPoint.firePointEvent('mouseOut');
            }
            // Hover point may have been destroyed in the event handlers (#7127)
            if (!hoverPoint.series) {
                return;
            }
            /**
             * Contains all hovered points.
             *
             * @name Highcharts.Chart#hoverPoints
             * @type {Array<Highcharts.Point>|null}
             */
            chart.hoverPoints = points;
            /**
             * Contains the original hovered point.
             *
             * @name Highcharts.Chart#hoverPoint
             * @type {Highcharts.Point|null}
             */
            chart.hoverPoint = hoverPoint;
            /**
             * Hover state should not be lost when axis is updated (#12569)
             * Axis.update runs pointer.reset which uses chart.hoverPoint.state
             * to apply state which does not exist in hoverPoint yet.
             * The mouseOver event should be triggered when hoverPoint
             * is correct.
             */
            hoverPoint.firePointEvent('mouseOver', void 0, function () {
                // Draw tooltip if necessary
                if (tooltip && hoverPoint) {
                    tooltip.refresh(useSharedTooltip ? points : hoverPoint, e);
                }
            });
            // Update positions (regardless of kdpoint or hoverPoint)
        }
        else if (followPointer && tooltip && !tooltip.isHidden) {
            var anchor = tooltip.getAnchor([{}],
                e);
            if (chart.isInsidePlot(anchor[0], anchor[1], {
                visiblePlotOnly: true
            })) {
                tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] });
            }
        }
        // Start the event listener to pick up the tooltip and crosshairs
        if (!pointer.unDocMouseMove) {
            pointer.unDocMouseMove = Pointer_addEvent(chart.container.ownerDocument, 'mousemove', function (e) {
                var _a,
                    _b,
                    _c;
                return (_c = (_b = Pointer_charts[(_a = Pointer.hoverChartIndex) !== null && _a !== void 0 ? _a : -1]) === null || _b === void 0 ? void 0 : _b.pointer) === null || _c === void 0 ? void 0 : _c.onDocumentMouseMove(e);
            });
            pointer.eventsToUnbind.push(pointer.unDocMouseMove);
        }
        // Issues related to crosshair #4927, #5269 #5066, #5658
        chart.axes.forEach(function drawAxisCrosshair(axis) {
            var snap = Pointer_pick((axis.crosshair || {}).snap,
                true);
            var point;
            if (snap) {
                point = chart.hoverPoint; // #13002
                if (!point || point.series[axis.coll] !== axis) {
                    point = Pointer_find(points, function (p) {
                        return p.series && p.series[axis.coll] === axis;
                    });
                }
            }
            // Axis has snapping crosshairs, and one of the hover points belongs
            // to axis. Always call drawCrosshair when it is not snap.
            if (point || !snap) {
                axis.drawCrosshair(e, point);
                // Axis has snapping crosshairs, but no hover point belongs to axis
            }
            else {
                axis.hideCrosshair();
            }
        });
    };
    /**
     * Set the JS DOM events on the container and document. This method should
     * contain a one-to-one assignment between methods and their handlers. Any
     * advanced logic should be moved to the handler reflecting the event's
     * name.
     * @private
     * @function Highcharts.Pointer#setDOMEvents
     */
    Pointer.prototype.setDOMEvents = function () {
        var _this = this;
        var container = this.chart.container,
            ownerDoc = container.ownerDocument;
        container.onmousedown = this.onContainerMouseDown.bind(this);
        container.onmousemove = this.onContainerMouseMove.bind(this);
        container.onclick = this.onContainerClick.bind(this);
        this.eventsToUnbind.push(Pointer_addEvent(container, 'mouseenter', this.onContainerMouseEnter.bind(this)), Pointer_addEvent(container, 'mouseleave', this.onContainerMouseLeave.bind(this)));
        if (!Pointer.unbindDocumentMouseUp.some(function (el) { return el.doc === ownerDoc; })) {
            Pointer.unbindDocumentMouseUp.push({
                doc: ownerDoc,
                unbind: Pointer_addEvent(ownerDoc, 'mouseup', this.onDocumentMouseUp.bind(this))
            });
        }
        // In case we are dealing with overflow, reset the chart position when
        // scrolling parent elements
        var parent = this.chart.renderTo.parentElement;
        while (parent && parent.tagName !== 'BODY') {
            this.eventsToUnbind.push(Pointer_addEvent(parent, 'scroll', function () {
                delete _this.chartPosition;
            }));
            parent = parent.parentElement;
        }
        this.eventsToUnbind.push(Pointer_addEvent(container, 'touchstart', this.onContainerTouchStart.bind(this), { passive: false }), Pointer_addEvent(container, 'touchmove', this.onContainerTouchMove.bind(this), { passive: false }));
        if (!Pointer.unbindDocumentTouchEnd) {
            Pointer.unbindDocumentTouchEnd = Pointer_addEvent(ownerDoc, 'touchend', this.onDocumentTouchEnd.bind(this), { passive: false });
        }
        this.setPointerCapture();
        Pointer_addEvent(this.chart, 'redraw', this.setPointerCapture.bind(this));
    };
    /**
     * Sets, or removes on update, pointer events using pointer capture for
     * tooltip.followTouchMove if any series has findNearestPointBy that
     * includes the y dimension.
     * @private
     * @function Highcharts.Pointer#setPointerCapture
    */
    Pointer.prototype.setPointerCapture = function () {
        var _a,
            _b;
        // Only for touch
        if (!Pointer_isTouchDevice) {
            return;
        }
        var pointer = this,
            events = pointer.pointerCaptureEventsToUnbind,
            chart = pointer.chart,
            container = chart.container,
            followTouchMove = Pointer_pick((_a = chart.options.tooltip) === null || _a === void 0 ? void 0 : _a.followTouchMove,
            true),
            shouldHave = followTouchMove && chart.series.some(function (series) { return series.options.findNearestPointBy
                .indexOf('y') > -1; });
        if (!pointer.hasPointerCapture && shouldHave) {
            // Add
            // Bind
            events.push(Pointer_addEvent(container, 'pointerdown', function (e) {
                var _a,
                    _b;
                if ((_a = e.target) === null || _a === void 0 ? void 0 : _a.hasPointerCapture(e.pointerId)) {
                    (_b = e.target) === null || _b === void 0 ? void 0 : _b.releasePointerCapture(e.pointerId);
                }
            }), Pointer_addEvent(container, 'pointermove', function (e) {
                var _a,
                    _b;
                (_b = (_a = chart.pointer) === null || _a === void 0 ? void 0 : _a.getPointFromEvent(e)) === null || _b === void 0 ? void 0 : _b.onMouseOver(e);
            }));
            if (!chart.styledMode) {
                Pointer_css(container, { 'touch-action': 'none' });
            }
            // Mostly for styled mode
            container.className += ' highcharts-no-touch-action';
            pointer.hasPointerCapture = true;
        }
        else if (pointer.hasPointerCapture && !shouldHave) {
            // Remove
            // Unbind
            events.forEach(function (e) { return e(); });
            events.length = 0;
            if (!chart.styledMode) {
                Pointer_css(container, {
                    'touch-action': Pointer_pick((_b = chart.options.chart.style) === null || _b === void 0 ? void 0 : _b['touch-action'], 'manipulation')
                });
            }
            // Mostly for styled mode
            container.className = container.className.replace(' highcharts-no-touch-action', '');
            pointer.hasPointerCapture = false;
        }
    };
    /**
     * Sets the index of the hovered chart and leaves the previous hovered
     * chart, to reset states like tooltip.
     * @private
     * @function Highcharts.Pointer#setHoverChartIndex
     */
    Pointer.prototype.setHoverChartIndex = function (e) {
        var _a;
        var chart = this.chart;
        var hoverChart = Core_Globals.charts[Pointer_pick(Pointer.hoverChartIndex, -1)];
        if (hoverChart &&
            hoverChart !== chart) {
            var relatedTargetObj = { relatedTarget: chart.container };
            if (e && !(e === null || e === void 0 ? void 0 : e.relatedTarget)) {
                // #17192, Non-enumerable properties of "e" are dropped with
                // spreading (...e). Using Object.assign ensures integrity.
                Object.assign({}, e, relatedTargetObj);
            }
            (_a = hoverChart.pointer) === null || _a === void 0 ? void 0 : _a.onContainerMouseLeave(e || relatedTargetObj);
        }
        if (!hoverChart ||
            !hoverChart.mouseIsDown) {
            Pointer.hoverChartIndex = chart.index;
        }
    };
    /**
     * General touch handler shared by touchstart and touchmove.
     * @private
     * @function Highcharts.Pointer#touch
     */
    Pointer.prototype.touch = function (e, start) {
        var _a = this,
            chart = _a.chart,
            _b = _a.pinchDown,
            pinchDown = _b === void 0 ? [] : _b;
        var hasMoved,
            isInside;
        this.setHoverChartIndex();
        e = this.normalize(e);
        if (e.touches.length === 1) {
            isInside = chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop, {
                visiblePlotOnly: true
            });
            if (isInside && !chart.openMenu) {
                // Run mouse events and display tooltip etc
                if (start) {
                    this.runPointActions(e);
                }
                // Android fires touchmove events after the touchstart even if
                // the finger hasn't moved, or moved only a pixel or two. In iOS
                // however, the touchmove doesn't fire unless the finger moves
                // more than ~4px. So we emulate this behaviour in Android by
                // checking how much it moved, and cancelling on small
                // distances. #3450. Tested and still relevant as of 2024.
                if (e.type === 'touchmove') {
                    hasMoved = pinchDown[0] ? // #5266
                        (Math.pow(pinchDown[0].chartX - e.chartX, 2) +
                            Math.pow(pinchDown[0].chartY - e.chartY, 2)) >= 16 :
                        false;
                }
                if (Pointer_pick(hasMoved, true)) {
                    this.pinch(e);
                }
            }
            else if (start) {
                // Hide the tooltip on touching outside the plot area (#1203)
                this.reset();
            }
        }
        else if (e.touches.length === 2) {
            this.pinch(e);
        }
    };
    /**
     * Returns true if the chart is set up for zooming by single touch and the
     * event is capable
     * @private
     * @function Highcharts.Pointer#touchSelect
     */
    Pointer.prototype.touchSelect = function (e) {
        return Boolean(this.chart.zooming.singleTouch &&
            e.touches &&
            e.touches.length === 1);
    };
    /**
     * Resolve the zoomType option, this is reset on all touch start and mouse
     * down events.
     * @private
     * @function Highcharts.Pointer#zoomOption
     */
    Pointer.prototype.zoomOption = function (e) {
        var chart = this.chart,
            inverted = chart.inverted;
        var zoomType = chart.zooming.type || '',
            zoomX,
            zoomY;
        // Look for the pinchType option
        if (/touch/.test(e.type)) {
            zoomType = Pointer_pick(chart.zooming.pinchType, zoomType);
        }
        this.zoomX = zoomX = /x/.test(zoomType);
        this.zoomY = zoomY = /y/.test(zoomType);
        this.zoomHor = (zoomX && !inverted) || (zoomY && inverted);
        this.zoomVert = (zoomY && !inverted) || (zoomX && inverted);
        this.hasZoom = zoomX || zoomY;
    };
    Pointer.unbindDocumentMouseUp = [];
    return Pointer;
}());
/* *
 *
 *  Class Namespace
 *
 * */
(function (Pointer) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    function compose(ChartClass) {
        if (Pointer_pushUnique(Pointer_composed, 'Core.Pointer')) {
            Pointer_addEvent(ChartClass, 'beforeRender', function () {
                /**
                 * The Pointer that keeps track of mouse and touch
                 * interaction.
                 *
                 * @memberof Highcharts.Chart
                 * @name pointer
                 * @type {Highcharts.Pointer}
                 * @instance
                 */
                this.pointer = new Pointer(this, this.options);
            });
        }
    }
    Pointer.compose = compose;
})(Pointer || (Pointer = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Core_Pointer = (Pointer);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Chart position and scale.
 *
 * @interface Highcharts.ChartPositionObject
 */ /**
* @name Highcharts.ChartPositionObject#left
* @type {number}
*/ /**
* @name Highcharts.ChartPositionObject#scaleX
* @type {number}
*/ /**
* @name Highcharts.ChartPositionObject#scaleY
* @type {number}
*/ /**
* @name Highcharts.ChartPositionObject#top
* @type {number}
*/
/**
 * One position in relation to an axis.
 *
 * @interface Highcharts.PointerAxisCoordinateObject
 */ /**
* Related axis.
*
* @name Highcharts.PointerAxisCoordinateObject#axis
* @type {Highcharts.Axis}
*/ /**
* Axis value.
*
* @name Highcharts.PointerAxisCoordinateObject#value
* @type {number}
*/
/**
 * Positions in terms of axis values.
 *
 * @interface Highcharts.PointerAxisCoordinatesObject
 */ /**
* Positions on the x-axis.
* @name Highcharts.PointerAxisCoordinatesObject#xAxis
* @type {Array<Highcharts.PointerAxisCoordinateObject>}
*/ /**
* Positions on the y-axis.
* @name Highcharts.PointerAxisCoordinatesObject#yAxis
* @type {Array<Highcharts.PointerAxisCoordinateObject>}
*/
/**
 * Pointer coordinates.
 *
 * @interface Highcharts.PointerCoordinatesObject
 */ /**
* @name Highcharts.PointerCoordinatesObject#chartX
* @type {number}
*/ /**
* @name Highcharts.PointerCoordinatesObject#chartY
* @type {number}
*/
/**
 * A native browser mouse or touch event, extended with position information
 * relative to the {@link Chart.container}.
 *
 * @interface Highcharts.PointerEventObject
 * @extends global.PointerEvent
 */ /**
* The X coordinate of the pointer interaction relative to the chart.
*
* @name Highcharts.PointerEventObject#chartX
* @type {number}
*/ /**
* The Y coordinate of the pointer interaction relative to the chart.
*
* @name Highcharts.PointerEventObject#chartY
* @type {number}
*/
/**
 * Axis-specific data of a selection.
 *
 * @interface Highcharts.SelectDataObject
 */ /**
* The selected Axis.
* @name Highcharts.SelectDataObject#axis
* @type {Highcharts.Axis}
*/ /**
* The maximum axis value, either automatic or set manually.
* @name Highcharts.SelectDataObject#max
* @type {number}
*/ /**
* The minimum axis value, either automatic or set manually.
* @name Highcharts.SelectDataObject#min
* @type {number}
*/
/**
 * Object for select events.
 * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a
 * datetime axis is milliseconds since 1970-01-01 00:00:00.
 *
 * @interface Highcharts.SelectEventObject
 */ /**
* The related browser event.
* @name Highcharts.SelectEventObject#originalEvent
* @type {global.Event}
*/ /**
* Prevents the default action for the event, if called.
* @name Highcharts.SelectEventObject#preventDefault
* @type {Function}
*/ /**
* Indicates a reset event to restore default state.
* @name Highcharts.SelectEventObject#resetSelection
* @type {boolean|undefined}
*/ /**
* Arrays containing the axes of each dimension and each axis' min and max
* values.
* @name Highcharts.SelectEventObject#xAxis
* @type {Array<Highcharts.SelectDataObject>}
*/ /**
* Arrays containing the axes of each dimension and each axis' min and max
* values.
* @name Highcharts.SelectEventObject#yAxis
* @type {Array<Highcharts.SelectDataObject>}
*/
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Data/DataTableCore.js
/* *
 *
 *  (c) 2009-2024 Highsoft AS
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 *  Authors:
 *  - Sophie Bremer
 *  - Gøran Slettemark
 *  - Torstein Hønsi
 *
 * */


var DataTableCore_fireEvent = Core_Utilities.fireEvent, DataTableCore_isArray = Core_Utilities.isArray, DataTableCore_objectEach = Core_Utilities.objectEach, DataTableCore_uniqueKey = Core_Utilities.uniqueKey;
/* *
 *
 *  Class
 *
 * */
/**
 * Class to manage columns and rows in a table structure. It provides methods
 * to add, remove, and manipulate columns and rows, as well as to retrieve data
 * from specific cells.
 *
 * @class
 * @name Highcharts.DataTable
 *
 * @param {Highcharts.DataTableOptions} [options]
 * Options to initialize the new DataTable instance.
 */
var DataTableCore = /** @class */ (function () {
    /**
     * Constructs an instance of the DataTable class.
     *
     * @example
     * const dataTable = new Highcharts.DataTableCore({
     *   columns: {
     *     year: [2020, 2021, 2022, 2023],
     *     cost: [11, 13, 12, 14],
     *     revenue: [12, 15, 14, 18]
     *   }
     * });

     *
     * @param {Highcharts.DataTableOptions} [options]
     * Options to initialize the new DataTable instance.
     */
    function DataTableCore(options) {
        if (options === void 0) { options = {}; }
        var _this = this;
        /**
         * Whether the ID was automatic generated or given in the constructor.
         *
         * @name Highcharts.DataTable#autoId
         * @type {boolean}
         */
        this.autoId = !options.id;
        this.columns = {};
        /**
         * ID of the table for indentification purposes.
         *
         * @name Highcharts.DataTable#id
         * @type {string}
         */
        this.id = (options.id || DataTableCore_uniqueKey());
        this.modified = this;
        this.rowCount = 0;
        this.versionTag = DataTableCore_uniqueKey();
        var rowCount = 0;
        DataTableCore_objectEach(options.columns || {}, function (column, columnName) {
            _this.columns[columnName] = column.slice();
            rowCount = Math.max(rowCount, column.length);
        });
        this.applyRowCount(rowCount);
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Applies a row count to the table by setting the `rowCount` property and
     * adjusting the length of all columns.
     *
     * @private
     * @param {number} rowCount The new row count.
     */
    DataTableCore.prototype.applyRowCount = function (rowCount) {
        this.rowCount = rowCount;
        DataTableCore_objectEach(this.columns, function (column) {
            if (DataTableCore_isArray(column)) { // Not on typed array
                column.length = rowCount;
            }
        });
    };
    /**
     * Fetches the given column by the canonical column name. Simplified version
     * of the full `DataTable.getRow` method, always returning by reference.
     *
     * @param {string} columnName
     * Name of the column to get.
     *
     * @return {Highcharts.DataTableColumn|undefined}
     * A copy of the column, or `undefined` if not found.
     */
    DataTableCore.prototype.getColumn = function (columnName, 
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    asReference) {
        return this.columns[columnName];
    };
    /**
     * Retrieves all or the given columns. Simplified version of the full
     * `DataTable.getColumns` method, always returning by reference.
     *
     * @param {Array<string>} [columnNames]
     * Column names to retrieve.
     *
     * @return {Highcharts.DataTableColumnCollection}
     * Collection of columns. If a requested column was not found, it is
     * `undefined`.
     */
    DataTableCore.prototype.getColumns = function (columnNames, 
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    asReference) {
        var _this = this;
        return (columnNames || Object.keys(this.columns)).reduce(function (columns, columnName) {
            columns[columnName] = _this.columns[columnName];
            return columns;
        }, {});
    };
    /**
     * Retrieves the row at a given index.
     *
     * @param {number} rowIndex
     * Row index to retrieve. First row has index 0.
     *
     * @param {Array<string>} [columnNames]
     * Column names to retrieve.
     *
     * @return {Record<string, number|string|undefined>|undefined}
     * Returns the row values, or `undefined` if not found.
     */
    DataTableCore.prototype.getRow = function (rowIndex, columnNames) {
        var _this = this;
        return (columnNames || Object.keys(this.columns)).map(function (key) { var _a; return (_a = _this.columns[key]) === null || _a === void 0 ? void 0 : _a[rowIndex]; });
    };
    /**
     * Sets cell values for a column. Will insert a new column, if not found.
     *
     * @param {string} columnName
     * Column name to set.
     *
     * @param {Highcharts.DataTableColumn} [column]
     * Values to set in the column.
     *
     * @param {number} [rowIndex=0]
     * Index of the first row to change. (Default: 0)
     *
     * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail]
     * Custom information for pending events.
     *
     * @emits #setColumns
     * @emits #afterSetColumns
     */
    DataTableCore.prototype.setColumn = function (columnName, column, rowIndex, eventDetail) {
        var _a;
        if (column === void 0) { column = []; }
        if (rowIndex === void 0) { rowIndex = 0; }
        this.setColumns((_a = {}, _a[columnName] = column, _a), rowIndex, eventDetail);
    };
    /**
     * * Sets cell values for multiple columns. Will insert new columns, if not
     * found. Simplified version of the full `DataTable.setColumns`, limited to
     * full replacement of the columns (undefined `rowIndex`).
     *
     * @param {Highcharts.DataTableColumnCollection} columns
     * Columns as a collection, where the keys are the column names.
     *
     * @param {number} [rowIndex]
     * Index of the first row to change. Keep undefined to reset.
     *
     * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail]
     * Custom information for pending events.
     *
     * @emits #setColumns
     * @emits #afterSetColumns
     */
    DataTableCore.prototype.setColumns = function (columns, rowIndex, eventDetail) {
        var _this = this;
        var rowCount = this.rowCount;
        DataTableCore_objectEach(columns, function (column, columnName) {
            _this.columns[columnName] = column.slice();
            rowCount = column.length;
        });
        this.applyRowCount(rowCount);
        if (!(eventDetail === null || eventDetail === void 0 ? void 0 : eventDetail.silent)) {
            DataTableCore_fireEvent(this, 'afterSetColumns');
            this.versionTag = DataTableCore_uniqueKey();
        }
    };
    /**
     * Sets cell values of a row. Will insert a new row if no index was
     * provided, or if the index is higher than the total number of table rows.
     * A simplified version of the full `DateTable.setRow`, limited to objects.
     *
     * @param {Record<string, number|string|undefined>} row
     * Cell values to set.
     *
     * @param {number} [rowIndex]
     * Index of the row to set. Leave `undefind` to add as a new row.
     *
     * @param {boolean} [insert]
     * Whether to insert the row at the given index, or to overwrite the row.
     *
     * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail]
     * Custom information for pending events.
     *
     * @emits #afterSetRows
     */
    DataTableCore.prototype.setRow = function (row, rowIndex, insert, eventDetail) {
        if (rowIndex === void 0) { rowIndex = this.rowCount; }
        var columns = this.columns,
            indexRowCount = insert ? this.rowCount + 1 : rowIndex + 1;
        DataTableCore_objectEach(row, function (cellValue, columnName) {
            var column = columns[columnName] ||
                    (eventDetail === null || eventDetail === void 0 ? void 0 : eventDetail.addColumns) !== false && new Array(indexRowCount);
            if (column) {
                if (insert) {
                    column.splice(rowIndex, 0, cellValue);
                }
                else {
                    column[rowIndex] = cellValue;
                }
                columns[columnName] = column;
            }
        });
        if (indexRowCount > this.rowCount) {
            this.applyRowCount(indexRowCount);
        }
        if (!(eventDetail === null || eventDetail === void 0 ? void 0 : eventDetail.silent)) {
            DataTableCore_fireEvent(this, 'afterSetRows');
            this.versionTag = DataTableCore_uniqueKey();
        }
    };
    return DataTableCore;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Data_DataTableCore = (DataTableCore);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * A column of values in a data table.
 * @typedef {Array<boolean|null|number|string|undefined>} Highcharts.DataTableColumn
 */ /**
* A collection of data table columns defined by a object where the key is the
* column name and the value is an array of the column values.
* @typedef {Record<string, Highcharts.DataTableColumn>} Highcharts.DataTableColumnCollection
*/
/**
 * Options for the `DataTable` or `DataTableCore` classes.
 * @interface Highcharts.DataTableOptions
 */ /**
* The column options for the data table. The columns are defined by an object
* where the key is the column ID and the value is an array of the column
* values.
*
* @name Highcharts.DataTableOptions.columns
* @type {Highcharts.DataTableColumnCollection|undefined}
*/ /**
* Custom ID to identify the new DataTable instance.
*
* @name Highcharts.DataTableOptions.id
* @type {string|undefined}
*/
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Legend/LegendSymbol.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var LegendSymbol_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};

var LegendSymbol_extend = Core_Utilities.extend, LegendSymbol_merge = Core_Utilities.merge, LegendSymbol_pick = Core_Utilities.pick;
/* *
 *
 *  Namespace
 *
 * */
var LegendSymbol;
(function (LegendSymbol) {
    /* *
    *
    *  Functions
    *
    * */
    /**
     * Draw a line, a point marker and an area in the legend.
     *
     * @private
     * @function Highcharts.LegendSymbolMixin.areaMarker
     *
     * @param {Highcharts.Legend} legend
     * The legend object.
     */
    function areaMarker(legend, item) {
        lineMarker.call(this, legend, item, true);
    }
    LegendSymbol.areaMarker = areaMarker;
    /**
     * Draw a line and a point marker in the legend.
     *
     * @private
     * @function Highcharts.LegendSymbolMixin.lineMarker
     *
     * @param {Highcharts.Legend} legend
     * The legend object.
     */
    function lineMarker(legend, item, hasArea) {
        var _a,
            _b;
        var legendItem = this.legendItem = this.legendItem || {},
            _c = this,
            chart = _c.chart,
            options = _c.options,
            _d = legend.baseline,
            baseline = _d === void 0 ? 0 : _d,
            symbolWidth = legend.symbolWidth,
            symbolHeight = legend.symbolHeight,
            symbol = this.symbol || 'circle',
            generalRadius = symbolHeight / 2,
            renderer = chart.renderer,
            legendItemGroup = legendItem.group,
            verticalCenter = baseline - Math.round((((_a = legend.fontMetrics) === null || _a === void 0 ? void 0 : _a.b) || symbolHeight) *
                // Render line and marker slightly higher to make room for the
                // area
                (hasArea ? 0.4 : 0.3)),
            attr = {};
        var legendSymbol,
            markerOptions = options.marker,
            lineSizer = 0;
        // Draw the line
        if (!chart.styledMode) {
            attr['stroke-width'] = Math.min(options.lineWidth || 0, 24);
            if (options.dashStyle) {
                attr.dashstyle = options.dashStyle;
            }
            else if (options.linecap !== 'square') {
                attr['stroke-linecap'] = 'round';
            }
        }
        legendItem.line = renderer
            .path()
            .addClass('highcharts-graph')
            .attr(attr)
            .add(legendItemGroup);
        if (hasArea) {
            legendItem.area = renderer
                .path()
                .addClass('highcharts-area')
                .add(legendItemGroup);
        }
        if (attr['stroke-linecap']) {
            lineSizer = Math.min(legendItem.line.strokeWidth(), symbolWidth) / 2;
        }
        if (symbolWidth) {
            var d = [
                    ['M',
                lineSizer,
                verticalCenter],
                    ['L',
                symbolWidth - lineSizer,
                verticalCenter]
                ];
            legendItem.line.attr({ d: d });
            (_b = legendItem.area) === null || _b === void 0 ? void 0 : _b.attr({
                d: LegendSymbol_spreadArray(LegendSymbol_spreadArray([], d, true), [
                    ['L', symbolWidth - lineSizer, baseline],
                    ['L', lineSizer, baseline]
                ], false)
            });
        }
        // Draw the marker
        if (markerOptions && markerOptions.enabled !== false && symbolWidth) {
            // Do not allow the marker to be larger than the symbolHeight
            var radius = Math.min(LegendSymbol_pick(markerOptions.radius,
                generalRadius),
                generalRadius);
            // Restrict symbol markers size
            if (symbol.indexOf('url') === 0) {
                markerOptions = LegendSymbol_merge(markerOptions, {
                    width: symbolHeight,
                    height: symbolHeight
                });
                radius = 0;
            }
            legendItem.symbol = legendSymbol = renderer
                .symbol(symbol, (symbolWidth / 2) - radius, verticalCenter - radius, 2 * radius, 2 * radius, LegendSymbol_extend({ context: 'legend' }, markerOptions))
                .addClass('highcharts-point')
                .add(legendItemGroup);
            legendSymbol.isMarker = true;
        }
    }
    LegendSymbol.lineMarker = lineMarker;
    /**
     * Get the series' symbol in the legend.
     *
     * This method should be overridable to create custom symbols through
     * Highcharts.seriesTypes[type].prototype.drawLegendSymbol.
     *
     * @private
     * @function Highcharts.LegendSymbolMixin.rectangle
     *
     * @param {Highcharts.Legend} legend
     * The legend object
     *
     * @param {Highcharts.Point|Highcharts.Series} item
     * The series (this) or point
     */
    function rectangle(legend, item) {
        var legendItem = item.legendItem || {},
            options = legend.options,
            symbolHeight = legend.symbolHeight,
            square = options.squareSymbol,
            symbolWidth = square ? symbolHeight : legend.symbolWidth;
        legendItem.symbol = this.chart.renderer
            .rect(square ? (legend.symbolWidth - symbolHeight) / 2 : 0, legend.baseline - symbolHeight + 1, // #3988
        symbolWidth, symbolHeight, LegendSymbol_pick(legend.options.symbolRadius, symbolHeight / 2))
            .addClass('highcharts-point')
            .attr({
            zIndex: 3
        })
            .add(legendItem.group);
    }
    LegendSymbol.rectangle = rectangle;
})(LegendSymbol || (LegendSymbol = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Legend_LegendSymbol = (LegendSymbol);

;// ./code/es5/es-modules/Core/Series/SeriesDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * General options for all series types.
 *
 * @optionparent plotOptions.series
 */
var seriesDefaults = {
    // Base series options
    /**
     * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
     * of a line graph. Round means that lines are rounded in the ends and
     * bends.
     *
     * @type       {Highcharts.SeriesLinecapValue}
     * @default    round
     * @since      3.0.7
     * @apioption  plotOptions.line.linecap
     */
    /**
     * Pixel width of the graph line.
     *
     * @see In styled mode, the line stroke-width can be set with the
     *      `.highcharts-graph` class name.
     *
     * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/
     *         On all series
     * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/
     *         On one single series
     *
     * @product highcharts highstock
     */
    lineWidth: 2,
    /**
     * For some series, there is a limit that shuts down animation
     * by default when the total number of points in the chart is too high.
     * For example, for a column chart and its derivatives, animation does
     * not run if there is more than 250 points totally. To disable this
     * cap, set `animationLimit` to `Infinity`. This option works if animation
     * is fired on individual points, not on a group of points like e.g. during
     * the initial animation.
     *
     * @sample {highcharts} highcharts/plotoptions/series-animationlimit/
     *         Animation limit on updating individual points
     *
     * @type      {number}
     * @apioption plotOptions.series.animationLimit
     */
    /**
     * Allow this series' points to be selected by clicking on the graphic
     * (columns, point markers, pie slices, map areas etc).
     *
     * The selected points can be handled by point select and unselect
     * events, or collectively by the [getSelectedPoints
     * ](/class-reference/Highcharts.Chart#getSelectedPoints) function.
     *
     * And alternative way of selecting points is through dragging.
     *
     * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/
     *         Line
     * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/
     *         Column
     * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/
     *         Pie
     * @sample {highcharts} highcharts/chart/events-selection-points/
     *         Select a range of points through a drag selection
     * @sample {highmaps} maps/plotoptions/series-allowpointselect/
     *         Map area
     * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
     *         Map bubble
     *
     * @since 1.2.0
     *
     * @private
     */
    allowPointSelect: false,
    /**
     * When true, each point or column edge is rounded to its nearest pixel
     * in order to render sharp on screen. In some cases, when there are a
     * lot of densely packed columns, this leads to visible difference
     * in column widths or distance between columns. In these cases,
     * setting `crisp` to `false` may look better, even though each column
     * is rendered blurry.
     *
     * @sample {highcharts} highcharts/plotoptions/column-crisp-false/
     *         Crisp is false
     *
     * @since   5.0.10
     * @product highcharts highstock gantt
     *
     * @private
     */
    crisp: true,
    /**
     * If true, a checkbox is displayed next to the legend item to allow
     * selecting the series. The state of the checkbox is determined by
     * the `selected` option.
     *
     * @productdesc {highmaps}
     * Note that if a `colorAxis` is defined, the color axis is represented
     * in the legend, not the series.
     *
     * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/
     *         Show select box
     *
     * @since 1.2.0
     *
     * @private
     */
    showCheckbox: false,
    /**
     * Enable or disable the initial animation when a series is displayed.
     * The animation can also be set as a configuration object. Please
     * note that this option only applies to the initial animation of the
     * series itself. For other animations, see [chart.animation](
     * #chart.animation) and the animation parameter under the API methods.
     * The following properties are supported:
     *
     * - `defer`: The animation delay time in milliseconds.
     *
     * - `duration`: The duration of the animation in milliseconds. (Defaults to
     *   `1000`)
     *
     * - `easing`: Can be a string reference to an easing function set on
     *   the `Math` object or a function. See the _Custom easing function_
     *   demo below. (Defaults to `easeInOutSine`)
     *
     * Due to poor performance, animation is disabled in old IE browsers
     * for several chart types.
     *
     * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/
     *         Animation disabled
     * @sample {highcharts} highcharts/plotoptions/series-animation-slower/
     *         Slower animation
     * @sample {highcharts} highcharts/plotoptions/series-animation-easing/
     *         Custom easing function
     * @sample {highstock} stock/plotoptions/animation-slower/
     *         Slower animation
     * @sample {highstock} stock/plotoptions/animation-easing/
     *         Custom easing function
     * @sample {highmaps} maps/plotoptions/series-animation-true/
     *         Animation enabled on map series
     * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/
     *         Disabled on mapbubble series
     *
     * @type    {boolean|Highcharts.AnimationOptionsObject}
     * @default {highcharts} true
     * @default {highstock} true
     * @default {highmaps} false
     *
     * @private
     */
    animation: {
        /** @ignore-option */
        duration: 1000
    },
    /**
     * An additional class name to apply to the series' graphical elements.
     * This option does not replace default class names of the graphical
     * element. Changes to the series' color will also be reflected in a
     * chart's legend and tooltip.
     *
     * @sample {highcharts} highcharts/css/point-series-classname
     *         Series and point class name
     *
     * @type      {string}
     * @since     5.0.0
     * @apioption plotOptions.series.className
     */
    /**
     * Disable this option to allow series rendering in the whole plotting
     * area.
     *
     * **Note:** Clipping should be always enabled when
     * [chart.zoomType](#chart.zoomType) is set
     *
     * @sample {highcharts} highcharts/plotoptions/series-clip/
     *         Disabled clipping
     *
     * @default   true
     * @type      {boolean}
     * @since     3.0.0
     * @apioption plotOptions.series.clip
     */
    /**
     * The main color of the series. In line type series it applies to the
     * line and the point markers unless otherwise specified. In bar type
     * series it applies to the bars unless a color is specified per point.
     * The default value is pulled from the `options.colors` array.
     *
     * In styled mode, the color can be defined by the
     * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
     * color can be set with the `.highcharts-series`,
     * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
     * `.highcharts-series-{n}` class, or individual classes given by the
     * `className` option.
     *
     * @productdesc {highmaps}
     * In maps, the series color is rarely used, as most choropleth maps use
     * the color to denote the value of each point. The series color can
     * however be used in a map with multiple series holding categorized
     * data.
     *
     * @sample {highcharts} highcharts/plotoptions/series-color-general/
     *         General plot option
     * @sample {highcharts} highcharts/plotoptions/series-color-specific/
     *         One specific series
     * @sample {highcharts} highcharts/plotoptions/series-color-area/
     *         Area color
     * @sample {highcharts} highcharts/series/infographic/
     *         Pattern fill
     * @sample {highmaps} maps/demo/category-map/
     *         Category map by multiple series
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @apioption plotOptions.series.color
     */
    /**
     * Styled mode only. A specific color index to use for the series, so its
     * graphic representations are given the class name `highcharts-color-{n}`.
     *
     * Since v11, CSS variables on the form `--highcharts-color-{n}` make
     * changing the color scheme very convenient.
     *
     * @sample    {highcharts} highcharts/css/colorindex/ Series and point color
     *            index
     *
     * @type      {number}
     * @since     5.0.0
     * @apioption plotOptions.series.colorIndex
     */
    /**
     * Whether to connect a graph line across null points, or render a gap
     * between the two points on either side of the null.
     *
     * In stacked area chart, if `connectNulls` is set to true,
     * null points are interpreted as 0.
     *
     * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/
     *         False by default
     * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/
     *         True
     *
     * @type      {boolean}
     * @default   false
     * @product   highcharts highstock
     * @apioption plotOptions.series.connectNulls
     */
    /**
     * You can set the cursor to "pointer" if you have click events attached
     * to the series, to signal to the user that the points and lines can
     * be clicked.
     *
     * In styled mode, the series cursor can be set with the same classes
     * as listed under [series.color](#plotOptions.series.color).
     *
     * @sample {highcharts} highcharts/plotoptions/series-cursor-line/
     *         On line graph
     * @sample {highcharts} highcharts/plotoptions/series-cursor-column/
     *         On columns
     * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/
     *         On scatter markers
     * @sample {highstock} stock/plotoptions/cursor/
     *         Pointer on a line graph
     * @sample {highmaps} maps/plotoptions/series-allowpointselect/
     *         Map area
     * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
     *         Map bubble
     *
     * @type      {string|Highcharts.CursorValue}
     * @apioption plotOptions.series.cursor
     */
    /**
     * A reserved subspace to store options and values for customized
     * functionality. Here you can add additional data for your own event
     * callbacks and formatter callbacks.
     *
     * @sample {highcharts} highcharts/point/custom/
     *         Point and series with custom data
     *
     * @type      {Highcharts.Dictionary<*>}
     * @apioption plotOptions.series.custom
     */
    /**
     * Name of the dash style to use for the graph, or for some series types
     * the outline of each shape.
     *
     * In styled mode, the
     * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/)
     * can be set with the same classes as listed under
     * [series.color](#plotOptions.series.color).
     *
     * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/
     *         Possible values demonstrated
     * @sample {highcharts} highcharts/plotoptions/series-dashstyle/
     *         Chart suitable for printing in black and white
     * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/
     *         Possible values demonstrated
     * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/
     *         Possible values demonstrated
     * @sample {highmaps} maps/plotoptions/series-dashstyle/
     *         Dotted borders on a map
     *
     * @type      {Highcharts.DashStyleValue}
     * @default   Solid
     * @since     2.1
     * @apioption plotOptions.series.dashStyle
     */
    /**
     * A description of the series to add to the screen reader information
     * about the series.
     *
     * @type      {string}
     * @since     5.0.0
     * @requires  modules/accessibility
     * @apioption plotOptions.series.description
     */
    /**
     * Options for the series data sorting.
     *
     * @type      {Highcharts.DataSortingOptionsObject}
     * @since     8.0.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.dataSorting
     */
    /**
     * Enable or disable data sorting for the series. Use [xAxis.reversed](
     * #xAxis.reversed) to change the sorting order.
     *
     * @sample {highcharts} highcharts/datasorting/animation/
     *         Data sorting in scatter-3d
     * @sample {highcharts} highcharts/datasorting/labels-animation/
     *         Axis labels animation
     * @sample {highcharts} highcharts/datasorting/dependent-sorting/
     *         Dependent series sorting
     * @sample {highcharts} highcharts/datasorting/independent-sorting/
     *         Independent series sorting
     *
     * @type      {boolean}
     * @since     8.0.0
     * @apioption plotOptions.series.dataSorting.enabled
     */
    /**
     * Whether to allow matching points by name in an update. If this option
     * is disabled, points will be matched by order.
     *
     * @sample {highcharts} highcharts/datasorting/match-by-name/
     *         Enabled match by name
     *
     * @type      {boolean}
     * @since     8.0.0
     * @apioption plotOptions.series.dataSorting.matchByName
     */
    /**
     * Determines what data value should be used to sort by.
     *
     * @sample {highcharts} highcharts/datasorting/sort-key/
     *         Sort key as `z` value
     *
     * @type      {string}
     * @since     8.0.0
     * @default   y
     * @apioption plotOptions.series.dataSorting.sortKey
     */
    /**
     * Enable or disable the mouse tracking for a specific series. This
     * includes point tooltips and click events on graphs and points. For
     * large datasets it improves performance.
     *
     * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/
     *         No mouse tracking
     * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/
     *         No mouse tracking
     *
     * @type      {boolean}
     * @default   true
     * @apioption plotOptions.series.enableMouseTracking
     */
    enableMouseTracking: true,
    /**
     * Whether to use the Y extremes of the total chart width or only the
     * zoomed area when zooming in on parts of the X axis. By default, the
     * Y axis adjusts to the min and max of the visible data. Cartesian
     * series only.
     *
     * @type      {boolean}
     * @default   false
     * @since     4.1.6
     * @product   highcharts highstock gantt
     * @apioption plotOptions.series.getExtremesFromAll
     */
    /**
     * Highlight only the hovered point and fade the remaining points.
     *
     * Scatter-type series require enabling the 'inactive' marker state and
     * adjusting opacity. Note that this approach could affect performance
     * with large datasets.
     *
     * @sample {highcharts} highcharts/plotoptions/series-inactiveotherpoints-enabled/
     *         Chart with inactiveOtherPoints option enabled.
     *
     * @type      {boolean}
     * @default   false
     * @apioption plotOptions.series.inactiveOtherPoints
     */
    /**
     * An array specifying which option maps to which key in the data point
     * array. This makes it convenient to work with unstructured data arrays
     * from different sources.
     *
     * @see [series.data](#series.line.data)
     *
     * @sample {highcharts|highstock} highcharts/series/data-keys/
     *         An extended data array with keys
     * @sample {highcharts|highstock} highcharts/series/data-nested-keys/
     *         Nested keys used to access object properties
     *
     * @type      {Array<string>}
     * @since     4.1.6
     * @apioption plotOptions.series.keys
     */
    /**
     * The line cap used for line ends and line joins on the graph.
     *
     * @sample highcharts/series-line/linecap/
     *         Line cap comparison
     *
     * @type       {Highcharts.SeriesLinecapValue}
     * @default    round
     * @product    highcharts highstock
     * @apioption  plotOptions.series.linecap
     */
    /**
     * The [id](#series.id) of another series to link to. Additionally,
     * the value can be ":previous" to link to the previous series. When
     * two series are linked, only the first one appears in the legend.
     * Toggling the visibility of this also toggles the linked series.
     *
     * If master series uses data sorting and linked series does not have
     * its own sorting definition, the linked series will be sorted in the
     * same order as the master one.
     *
     * @sample {highcharts|highstock} highcharts/demo/arearange-line/
     *         Linked series
     *
     * @type      {string}
     * @since     3.0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.series.linkedTo
     */
    /**
     * Options for the corresponding navigator series if `showInNavigator`
     * is `true` for this series. Available options are the same as any
     * series, documented at [plotOptions](#plotOptions.series) and
     * [series](#series).
     *
     * These options are merged with options in [navigator.series](
     * #navigator.series), and will take precedence if the same option is
     * defined both places.
     *
     * @see [navigator.series](#navigator.series)
     *
     * @type      {Highcharts.PlotSeriesOptions}
     * @since     5.0.0
     * @product   highstock
     * @apioption plotOptions.series.navigatorOptions
     */
    /**
     * The color for the parts of the graph or points that are below the
     * [threshold](#plotOptions.series.threshold). Note that `zones` takes
     * precedence over the negative color. Using `negativeColor` is
     * equivalent to applying a zone with value of 0.
     *
     * @see In styled mode, a negative color is applied by setting this option
     *      to `true` combined with the `.highcharts-negative` class name.
     *
     * @sample {highcharts} highcharts/plotoptions/series-negative-color/
     *         Spline, area and column
     * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/
     *         Arearange
     * @sample {highcharts} highcharts/css/series-negative-color/
     *         Styled mode
     * @sample {highstock} highcharts/plotoptions/series-negative-color/
     *         Spline, area and column
     * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/
     *         Arearange
     * @sample {highmaps} highcharts/plotoptions/series-negative-color/
     *         Spline, area and column
     * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/
     *         Arearange
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @since     3.0
     * @apioption plotOptions.series.negativeColor
     */
    /**
     * Same as
     * [accessibility.point.descriptionFormat](#accessibility.point.descriptionFormat),
     * but for an individual series. Overrides the chart wide configuration.
     *
     * @type      {Function}
     * @since 11.1.0
     * @apioption plotOptions.series.pointDescriptionFormat
     */
    /**
     * Same as
     * [accessibility.series.descriptionFormatter](#accessibility.series.descriptionFormatter),
     * but for an individual series. Overrides the chart wide configuration.
     *
     * @type      {Function}
     * @since     5.0.12
     * @apioption plotOptions.series.pointDescriptionFormatter
     */
    /**
     * If no x values are given for the points in a series, `pointInterval`
     * defines the interval of the x values. For example, if a series
     * contains one value every decade starting from year 0, set
     * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval`
     * is set in milliseconds.
     *
     * It can be also be combined with `pointIntervalUnit` to draw irregular
     * time intervals.
     *
     * If combined with `relativeXValue`, an x value can be set on each
     * point, and the `pointInterval` is added x times to the `pointStart`
     * setting.
     *
     * Please note that this options applies to the _series data_, not the
     * interval of the axis ticks, which is independent.
     *
     * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
     *         Datetime X axis
     * @sample {highcharts} highcharts/plotoptions/series-relativexvalue/
     *         Relative x value
     * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
     *         Using pointStart and pointInterval
     * @sample {highstock} stock/plotoptions/relativexvalue/
     *         Relative x value
     *
     * @type      {number}
     * @default   1
     * @product   highcharts highstock gantt
     * @apioption plotOptions.series.pointInterval
     */
    /**
     * On datetime series, this allows for setting the
     * [pointInterval](#plotOptions.series.pointInterval) to irregular time
     * units, `day`, `month` and `year`. A day is usually the same as 24
     * hours, but `pointIntervalUnit` also takes the DST crossover into
     * consideration when dealing with local time. Combine this option with
     * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc.
     *
     * Please note that this options applies to the _series data_, not the
     * interval of the axis ticks, which is independent.
     *
     * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/
     *         One point a month
     * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/
     *         One point a month
     *
     * @type       {string}
     * @since      4.1.0
     * @product    highcharts highstock gantt
     * @validvalue ["day", "month", "year"]
     * @apioption  plotOptions.series.pointIntervalUnit
     */
    /**
     * Possible values: `"on"`, `"between"`, `number`.
     *
     * In a column chart, when pointPlacement is `"on"`, the point will not
     * create any padding of the X axis. In a polar column chart this means
     * that the first column points directly north. If the pointPlacement is
     * `"between"`, the columns will be laid out between ticks. This is
     * useful for example for visualising an amount between two points in
     * time or in a certain sector of a polar chart.
     *
     * Since Highcharts 3.0.2, the point placement can also be numeric,
     * where 0 is on the axis value, -0.5 is between this value and the
     * previous, and 0.5 is between this value and the next. Unlike the
     * textual options, numeric point placement options won't affect axis
     * padding.
     *
     * Note that pointPlacement needs a [pointRange](
     * #plotOptions.series.pointRange) to work. For column series this is
     * computed, but for line-type series it needs to be set.
     *
     * For the `xrange` series type and gantt charts, if the Y axis is a
     * category axis, the `pointPlacement` applies to the Y axis rather than
     * the (typically datetime) X axis.
     *
     * Defaults to `undefined` in cartesian charts, `"between"` in polar
     * charts.
     *
     * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement)
     *
     * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/
     *         Between in a column chart
     * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/
     *         Numeric placement for custom layout
     * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/
     *         Placement in heatmap
     *
     * @type      {string|number}
     * @since     2.3.0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.series.pointPlacement
     */
    /**
     * If no x values are given for the points in a series, `pointStart`
     * defines on what value to start. For example, if a series contains one
     * yearly value starting from 1945, set `pointStart` to 1945.
     *
     * The `pointStart` setting can be a number, or a datetime string that is
     * parsed according to the `time.timezone` setting.
     *
     * If combined with `relativeXValue`, an x value can be set on each
     * point. The x value from the point options is multiplied by
     * `pointInterval` and added to `pointStart` to produce a modified x
     * value.
     *
     * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/
     *         Linear
     * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
     *         Datetime
     * @sample {highcharts} highcharts/plotoptions/series-relativexvalue/
     *         Relative x value
     * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
     *         Using pointStart and pointInterval
     * @sample {highstock} stock/plotoptions/relativexvalue/
     *         Relative x value
     *
     * @type      {number|string}
     * @default   0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.series.pointStart
     */
    /**
     * When true, X values in the data set are relative to the current
     * `pointStart`, `pointInterval` and `pointIntervalUnit` settings. This
     * allows compression of the data for datasets with irregular X values.
     *
     * The real X values are computed on the formula `f(x) = ax + b`, where
     * `a` is the `pointInterval` (optionally with a time unit given by
     * `pointIntervalUnit`), and `b` is the `pointStart`.
     *
     * @sample {highcharts} highcharts/plotoptions/series-relativexvalue/
     *         Relative X value
     * @sample {highstock} stock/plotoptions/relativexvalue/
     *         Relative X value
     *
     * @type      {boolean}
     * @default   false
     * @product   highcharts highstock
     * @apioption plotOptions.series.relativeXValue
     */
    /**
     * Whether to select the series initially. If `showCheckbox` is true,
     * the checkbox next to the series name in the legend will be checked
     * for a selected series.
     *
     * @sample {highcharts} highcharts/plotoptions/series-selected/
     *         One out of two series selected
     *
     * @type      {boolean}
     * @default   false
     * @since     1.2.0
     * @apioption plotOptions.series.selected
     */
    /**
     * Whether to apply a drop shadow to the graph line. Since 2.3 the
     * shadow can be an object configuration containing `color`, `offsetX`,
     * `offsetY`, `opacity` and `width`.
     *
     * Note that in some cases, like stacked columns or other dense layouts, the
     * series may cast shadows on each other. In that case, the
     * `chart.seriesGroupShadow` allows applying a common drop shadow to the
     * whole series group.
     *
     * @sample {highcharts} highcharts/plotoptions/series-shadow/
     *         Shadow enabled
     *
     * @type      {boolean|Highcharts.ShadowOptionsObject}
     * @default   false
     * @apioption plotOptions.series.shadow
     */
    /**
     * Whether to display this particular series or series type in the
     * legend. Standalone series are shown in legend by default, and linked
     * series are not. Since v7.2.0 it is possible to show series that use
     * colorAxis by setting this option to `true`.
     *
     * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
     *         One series in the legend, one hidden
     *
     * @type      {boolean}
     * @apioption plotOptions.series.showInLegend
     */
    /**
     * Whether or not to show the series in the navigator. Takes precedence
     * over [navigator.baseSeries](#navigator.baseSeries) if defined.
     *
     * @type      {boolean}
     * @since     5.0.0
     * @product   highstock
     * @apioption plotOptions.series.showInNavigator
     */
    /**
     * If set to `true`, the accessibility module will skip past the points
     * in this series for keyboard navigation.
     *
     * @type      {boolean}
     * @since     5.0.12
     * @apioption plotOptions.series.skipKeyboardNavigation
     */
    /**
     * Whether to stack the values of each series on top of each other.
     * Possible values are `undefined` to disable, `"normal"` to stack by
     * value or `"percent"`.
     *
     * When stacking is enabled, data must be sorted
     * in ascending X order.
     *
     * Some stacking options are related to specific series types. In the
     * streamgraph series type, the stacking option is set to `"stream"`.
     * The second one is `"overlap"`, which only applies to waterfall
     * series.
     *
     * @see [yAxis.reversedStacks](#yAxis.reversedStacks)
     *
     * @sample {highcharts} highcharts/plotoptions/series-stacking-line/
     *         Line
     * @sample {highcharts} highcharts/plotoptions/series-stacking-column/
     *         Column
     * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/
     *         Bar
     * @sample {highcharts} highcharts/plotoptions/series-stacking-area/
     *         Area
     * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/
     *         Line
     * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/
     *         Column
     * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/
     *         Bar
     * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/
     *         Area
     * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking
     *         Waterfall with normal stacking
     * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking
     *         Waterfall with overlap stacking
     * @sample {highstock} stock/plotoptions/stacking/
     *         Area
     *
     * @type       {string}
     * @product    highcharts highstock
     * @validvalue ["normal", "overlap", "percent", "stream"]
     * @apioption  plotOptions.series.stacking
     */
    /**
     * Whether to apply steps to the line. Possible values are `left`,
     * `center` and `right`.
     *
     * @sample {highcharts} highcharts/plotoptions/line-step/
     *         Different step line options
     * @sample {highcharts} highcharts/plotoptions/area-step/
     *         Stepped, stacked area
     * @sample {highstock} stock/plotoptions/line-step/
     *         Step line
     *
     * @type       {string}
     * @since      1.2.5
     * @product    highcharts highstock
     * @validvalue ["left", "center", "right"]
     * @apioption  plotOptions.series.step
     */
    /**
     * The threshold, also called zero level or base level. For line type
     * series this is only used in conjunction with
     * [negativeColor](#plotOptions.series.negativeColor).
     *
     * @see [softThreshold](#plotOptions.series.softThreshold).
     *
     * @type      {number|null}
     * @default   0
     * @since     3.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.threshold
     */
    /**
     * Set the initial visibility of the series.
     *
     * @sample {highcharts} highcharts/plotoptions/series-visible/
     *         Two series, one hidden and one visible
     * @sample {highstock} stock/plotoptions/series-visibility/
     *         Hidden series
     *
     * @type      {boolean}
     * @default   true
     * @apioption plotOptions.series.visible
     */
    /**
     * Defines the Axis on which the zones are applied.
     *
     * @see [zones](#plotOptions.series.zones)
     *
     * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/
     *         Zones on the X-Axis
     * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/
     *         Zones on the X-Axis
     *
     * @type      {string}
     * @default   y
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zoneAxis
     */
    /**
     * General event handlers for the series items. These event hooks can
     * also be attached to the series at run time using the
     * `Highcharts.addEvent` function.
     *
     * @declare Highcharts.SeriesEventsOptionsObject
     *
     * @private
     */
    events: {},
    /**
     * Fires after the series has finished its initial animation, or in case
     * animation is disabled, immediately as the series is displayed.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/
     *         Show label after animate
     * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/
     *         Show label after animate
     *
     * @type      {Highcharts.SeriesAfterAnimateCallbackFunction}
     * @since     4.0
     * @product   highcharts highstock gantt
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.afterAnimate
     */
    /**
     * Fires when the checkbox next to the series' name in the legend is
     * clicked. One parameter, `event`, is passed to the function. The state
     * of the checkbox is found by `event.checked`. The checked item is
     * found by `event.item`. Return `false` to prevent the default action
     * which is to toggle the select state of the series.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
     *         Alert checkbox status
     *
     * @type      {Highcharts.SeriesCheckboxClickCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.checkboxClick
     */
    /**
     * Fires when the series is clicked. One parameter, `event`, is passed
     * to the function, containing common event information. Additionally,
     * `event.point` holds a pointer to the nearest point on the graph.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-click/
     *         Alert click info
     * @sample {highstock} stock/plotoptions/series-events-click/
     *         Alert click info
     * @sample {highmaps} maps/plotoptions/series-events-click/
     *         Display click info in subtitle
     *
     * @type      {Highcharts.SeriesClickCallbackFunction}
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.click
     */
    /**
     * Fires when the series is hidden after chart generation time, either
     * by clicking the legend item or by calling `.hide()`.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-hide/
     *         Alert when the series is hidden by clicking the legend item
     *
     * @type      {Highcharts.SeriesHideCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.hide
     */
    /**
     * Fires when the legend item belonging to the series is clicked. One
     * parameter, `event`, is passed to the function. The default action
     * is to toggle the visibility of the series. This can be prevented
     * by returning `false` or calling `event.preventDefault()`.
     *
     * **Note:** This option is deprecated in favor of
     * [legend.events.itemClick](#legend.events.itemClick).
     *
     * @type       {Highcharts.SeriesLegendItemClickCallbackFunction}
     * @deprecated 11.4.4
     * @context    Highcharts.Series
     * @apioption  plotOptions.series.events.legendItemClick
     */
    /**
     * Fires when the mouse leaves the graph. One parameter, `event`, is
     * passed to the function, containing common event information. If the
     * [stickyTracking](#plotOptions.series) option is true, `mouseOut`
     * doesn't happen before the mouse enters another graph or leaves the
     * plot area.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
     *         With sticky tracking by default
     * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
     *         Without sticky tracking
     *
     * @type      {Highcharts.SeriesMouseOutCallbackFunction}
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.mouseOut
     */
    /**
     * Fires when the mouse enters the graph. One parameter, `event`, is
     * passed to the function, containing common event information.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
     *         With sticky tracking by default
     * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
     *         Without sticky tracking
     *
     * @type      {Highcharts.SeriesMouseOverCallbackFunction}
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.mouseOver
     */
    /**
     * Fires when the series is shown after chart generation time, either
     * by clicking the legend item or by calling `.show()`.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-show/
     *         Alert when the series is shown by clicking the legend item.
     *
     * @type      {Highcharts.SeriesShowCallbackFunction}
     * @since     1.2.0
     * @context   Highcharts.Series
     * @apioption plotOptions.series.events.show
     */
    /**
     * Options for the point markers of line and scatter-like series. Properties
     * like `fillColor`, `lineColor` and `lineWidth` define the visual
     * appearance of the markers. The `symbol` option defines the shape. Other
     * series types, like column series, don't have markers, but have visual
     * options on the series level instead.
     *
     * In styled mode, the markers can be styled with the `.highcharts-point`,
     * `.highcharts-point-hover` and `.highcharts-point-select` class names.
     *
     * @declare Highcharts.PointMarkerOptionsObject
     *
     * @sample {highmaps} maps/demo/mappoint-mapmarker
     *         Using the mapmarker symbol for points
     *
     * @private
     */
    marker: {
        /**
         * Enable or disable the point marker. If `undefined`, the markers
         * are hidden when the data is dense, and shown for more widespread
         * data points.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/
         *         Disabled markers
         * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/
         *         Disabled in normal state but enabled on hover
         * @sample {highstock} stock/plotoptions/series-marker/
         *         Enabled markers
         *
         * @type      {boolean}
         * @default   {highcharts} undefined
         * @default   {highstock} false
         * @apioption plotOptions.series.marker.enabled
         */
        /**
         * The threshold for how dense the point markers should be before
         * they are hidden, given that `enabled` is not defined. The number
         * indicates the horizontal distance between the two closest points
         * in the series, as multiples of the `marker.radius`. In other
         * words, the default value of 2 means points are hidden if
         * overlapping horizontally.
         *
         * @sample highcharts/plotoptions/series-marker-enabledthreshold
         *         A higher threshold
         *
         * @since 6.0.5
         */
        enabledThreshold: 2,
        /**
         * The fill color of the point marker. When `undefined`, the series'
         * or point's color is used.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
         *         White fill
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @apioption plotOptions.series.marker.fillColor
         */
        /**
         * Image markers only. Set the image width explicitly. When using
         * this option, a `width` must also be set.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
         *         Fixed width and height
         * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
         *         Fixed width and height
         *
         * @type      {number}
         * @since     4.0.4
         * @apioption plotOptions.series.marker.height
         */
        /**
         * The color of the point marker's outline. When `undefined`, the
         * series' or point's color is used.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
         *         Inherit from series color (undefined)
         *
         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         */
        lineColor: "#ffffff" /* Palette.backgroundColor */,
        /**
         * The width of the point marker's outline.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
         *         2px blue marker
         */
        lineWidth: 0,
        /**
         * The radius of the point marker.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-radius/
         *         Bigger markers
         *
         * @default {highstock} 2
         * @default {highcharts} 4
         *
         */
        radius: 4,
        /**
         * A predefined shape or symbol for the marker. When undefined, the
         * symbol is pulled from options.symbols. Other possible values are
         * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and
         * `'triangle-down'`.
         *
         * Additionally, the URL to a graphic can be given on this form:
         * `'url(graphic.png)'`. Note that for the image to be applied to
         * exported charts, its URL needs to be accessible by the export
         * server.
         *
         * Custom callbacks for symbol path generation can also be added to
         * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
         * used by its method name, as shown in the demo.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/
         *         Predefined, graphic and custom markers
         * @sample {highstock} highcharts/plotoptions/series-marker-symbol/
         *         Predefined, graphic and custom markers
         * @sample {highmaps} maps/demo/mappoint-mapmarker
         *         Using the mapmarker symbol for points
         *
         * @type      {string}
         * @apioption plotOptions.series.marker.symbol
         */
        /**
         * Image markers only. Set the image width explicitly. When using
         * this option, a `height` must also be set.
         *
         * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
         *         Fixed width and height
         * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
         *         Fixed width and height
         *
         * @type      {number}
         * @since     4.0.4
         * @apioption plotOptions.series.marker.width
         */
        /**
         * States for a single point marker.
         *
         * @declare Highcharts.PointStatesOptionsObject
         */
        states: {
            /**
             * The normal state of a single point marker. Currently only
             * used for setting animation when returning to normal state
             * from hover.
             *
             * @declare Highcharts.PointStatesNormalOptionsObject
             */
            normal: {
                /**
                 * Animation when returning to normal state after hovering.
                 *
                 * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
                 */
                animation: true
            },
            /**
             * The hover state for a single point marker.
             *
             * @declare Highcharts.PointStatesHoverOptionsObject
             */
            hover: {
                /**
                 * Animation when hovering over the marker.
                 *
                 * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
                 */
                animation: {
                    /** @internal */
                    duration: 150
                },
                /**
                 * Enable or disable the point marker.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/
                 *         Disabled hover state
                 */
                enabled: true,
                /**
                 * The fill color of the marker in hover state. When
                 * `undefined`, the series' or point's fillColor for normal
                 * state is used.
                 *
                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                 * @apioption plotOptions.series.marker.states.hover.fillColor
                 */
                /**
                 * The color of the point marker's outline. When
                 * `undefined`, the series' or point's lineColor for normal
                 * state is used.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/
                 *         White fill color, black line color
                 *
                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                 * @apioption plotOptions.series.marker.states.hover.lineColor
                 */
                /**
                 * The width of the point marker's outline. When
                 * `undefined`, the series' or point's lineWidth for normal
                 * state is used.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/
                 *         3px line width
                 *
                 * @type      {number}
                 * @apioption plotOptions.series.marker.states.hover.lineWidth
                 */
                /**
                 * The radius of the point marker. In hover state, it
                 * defaults to the normal state's radius + 2 as per the
                 * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus)
                 * option.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/
                 *         10px radius
                 *
                 * @type      {number}
                 * @apioption plotOptions.series.marker.states.hover.radius
                 */
                /**
                 * The number of pixels to increase the radius of the
                 * hovered point.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
                 *         5 pixels greater radius on hover
                 * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
                 *         5 pixels greater radius on hover
                 *
                 * @since 4.0.3
                 */
                radiusPlus: 2,
                /**
                 * The additional line width for a hovered point.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
                 *         2 pixels wider on hover
                 * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
                 *         2 pixels wider on hover
                 *
                 * @since 4.0.3
                 */
                lineWidthPlus: 1
            },
            /**
             * The appearance of the point marker when selected. In order to
             * allow a point to be selected, set the
             * `series.allowPointSelect` option to true.
             *
             * @declare Highcharts.PointStatesSelectOptionsObject
             */
            select: {
                /**
                 * Enable or disable visible feedback for selection.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/
                 *         Disabled select state
                 *
                 * @type      {boolean}
                 * @default   true
                 * @apioption plotOptions.series.marker.states.select.enabled
                 */
                /**
                 * The radius of the point marker. In hover state, it
                 * defaults to the normal state's radius + 2.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/
                 *         10px radius for selected points
                 *
                 * @type      {number}
                 * @apioption plotOptions.series.marker.states.select.radius
                 */
                /**
                 * The fill color of the point marker.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/
                 *         Solid red discs for selected points
                 *
                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                 */
                fillColor: "#cccccc" /* Palette.neutralColor20 */,
                /**
                 * The color of the point marker's outline. When
                 * `undefined`, the series' or point's color is used.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/
                 *         Red line color for selected points
                 *
                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                 */
                lineColor: "#000000" /* Palette.neutralColor100 */,
                /**
                 * The width of the point marker's outline.
                 *
                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/
                 *         3px line width for selected points
                 */
                lineWidth: 2
            }
        }
    },
    /**
     * Properties for each single point.
     *
     * @declare Highcharts.PlotSeriesPointOptions
     *
     * @private
     */
    point: {
        /**
         * Fires when a point is clicked. One parameter, `event`, is passed
         * to the function, containing common event information.
         *
         * If the `series.allowPointSelect` option is true, the default
         * action for the point's click event is to toggle the point's
         * select state. Returning `false` cancels this action.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-click/
         *         Click marker to alert values
         * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/
         *         Click column
         * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/
         *         Go to URL
         * @sample {highmaps} maps/plotoptions/series-point-events-click/
         *         Click marker to display values
         * @sample {highmaps} maps/plotoptions/series-point-events-click-url/
         *         Go to URL
         *
         * @type      {Highcharts.PointClickCallbackFunction}
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.click
         */
        /**
         * Fires when the mouse leaves the area close to the point. One
         * parameter, `event`, is passed to the function, containing common
         * event information.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
         *         Show values in the chart's corner on mouse over
         *
         * @type      {Highcharts.PointMouseOutCallbackFunction}
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.mouseOut
         */
        /**
         * Fires when the mouse enters the area close to the point. One
         * parameter, `event`, is passed to the function, containing common
         * event information.
         *
         * Returning `false` cancels the default behavior, which is to show a
         * tooltip for the point.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
         *         Show values in the chart's corner on mouse over
         *
         * @type      {Highcharts.PointMouseOverCallbackFunction}
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.mouseOver
         */
        /**
         * Fires when the point is removed using the `.remove()` method. One
         * parameter, `event`, is passed to the function. Returning `false`
         * cancels the operation.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/
         *         Remove point and confirm
         *
         * @type      {Highcharts.PointRemoveCallbackFunction}
         * @since     1.2.0
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.remove
         */
        /**
         * Fires when the point is selected either programmatically or
         * following a click on the point. One parameter, `event`, is passed
         * to the function. Returning `false` cancels the operation.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-select/
         *         Report the last selected point
         * @sample {highmaps} maps/plotoptions/series-allowpointselect/
         *         Report select and unselect
         *
         * @type      {Highcharts.PointSelectCallbackFunction}
         * @since     1.2.0
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.select
         */
        /**
         * Fires when the point is unselected either programmatically or
         * following a click on the point. One parameter, `event`, is passed
         * to the function.
         *  Returning `false` cancels the operation.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/
         *         Report the last unselected point
         * @sample {highmaps} maps/plotoptions/series-allowpointselect/
         *         Report select and unselect
         *
         * @type      {Highcharts.PointUnselectCallbackFunction}
         * @since     1.2.0
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.unselect
         */
        /**
         * Fires when the point is updated programmatically through the
         * `.update()` method. One parameter, `event`, is passed to the
         * function. The new point options can be accessed through
         * `event.options`. Returning `false` cancels the operation.
         *
         * @sample {highcharts} highcharts/plotoptions/series-point-events-update/
         *         Confirm point updating
         *
         * @type      {Highcharts.PointUpdateCallbackFunction}
         * @since     1.2.0
         * @context   Highcharts.Point
         * @apioption plotOptions.series.point.events.update
         */
        /**
         * Events for each single point.
         *
         * @declare Highcharts.PointEventsOptionsObject
         */
        events: {}
    },
    /**
     * Options for the series data labels, appearing next to each data
     * point.
     *
     * Since v6.2.0, multiple data labels can be applied to each single
     * point by defining them as an array of configs.
     *
     * In styled mode, the data labels can be styled with the
     * `.highcharts-data-label-box` and `.highcharts-data-label` class names
     * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)).
     *
     * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled
     *         Data labels enabled
     * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple
     *         Multiple data labels on a bar series
     * @sample {highcharts} highcharts/css/series-datalabels
     *         Styled mode example
     * @sample {highmaps} maps/demo/color-axis
     *         Choropleth map with data labels
     * @sample {highmaps} maps/demo/mappoint-datalabels-mapmarker
     *         Using data labels as map markers
     *
     * @type    {*|Array<*>}
     * @product highcharts highstock highmaps gantt
     *
     * @private
     */
    dataLabels: {
        /**
         * Enable or disable the initial animation when a series is displayed
         * for the `dataLabels`. The animation can also be set as a
         * configuration object. Please note that this option only applies to
         * the initial animation.
         *
         * For other animations, see [chart.animation](#chart.animation) and the
         * animation parameter under the API methods. The following properties
         * are supported:
         *
         * - `defer`: The animation delay time in milliseconds.
         *
         * @sample {highcharts} highcharts/plotoptions/animation-defer/
         *          Animation defer settings
         *
         * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
         * @since     8.2.0
         * @apioption plotOptions.series.dataLabels.animation
         */
        animation: {},
        /**
         * The animation delay time in milliseconds. Set to `0` to render the
         * data labels immediately. As `undefined` inherits defer time from the
         * [series.animation.defer](#plotOptions.series.animation.defer).
         *
         * @type      {number}
         * @since     8.2.0
         * @apioption plotOptions.series.dataLabels.animation.defer
         */
        /**
         * The alignment of the data label compared to the point. If `right`,
         * the right side of the label should be touching the point. For points
         * with an extent, like columns, the alignments also dictates how to
         * align it inside the box, as given with the
         * [inside](#plotOptions.column.dataLabels.inside) option. Can be one of
         * `left`, `center` or `right`.
         *
         * @sample {highcharts}
         *         highcharts/plotoptions/series-datalabels-align-left/ Left
         *         aligned
         * @sample {highcharts}
         *         highcharts/plotoptions/bar-datalabels-align-inside-bar/ Data
         *         labels inside the bar
         *
         * @type {Highcharts.AlignValue|null}
         */
        align: 'center',
        /**
         * Alignment method for data labels. If set to `plotEdges`, the labels
         * are aligned within the plot area in the direction of the y-axis. So
         * in a regular column chart, the labels are aligned vertically
         * according to the `verticalAlign` setting. In a bar chart, which is
         * inverted, the labels are aligned horizontally according to the
         * `align` setting. Applies to cartesian series only.
         *
         * @sample {highcharts} highcharts/series-bar/datalabels-alignto/
         *         Align to plot edges
         *
         * @type      {string}
         * @since 11.4.2
         * @apioption plotOptions.series.dataLabels.alignTo
         */
        /**
         * Whether to allow data labels to overlap. To make the labels less
         * sensitive for overlapping, the
         * [dataLabels.padding](#plotOptions.series.dataLabels.padding)
         * can be set to 0.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/
         *         Don't allow overlap
         *
         * @type      {boolean}
         * @default   false
         * @since     4.1.0
         * @apioption plotOptions.series.dataLabels.allowOverlap
         */
        /**
         * The background color or gradient for the data label. Setting it to
         * `auto` will use the point's color.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         * @sample {highmaps} maps/plotoptions/series-datalabels-box/
         *         Data labels box options
         * @sample {highmaps} maps/demo/mappoint-datalabels-mapmarker
         *         Data labels as map markers
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @since     2.2.1
         * @apioption plotOptions.series.dataLabels.backgroundColor
         */
        /**
         * The border color for the data label. Setting it to `auto` will use
         * the point's color. Defaults to `undefined`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @since     2.2.1
         * @apioption plotOptions.series.dataLabels.borderColor
         */
        /**
         * The border radius in pixels for the data label.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         * @sample {highmaps} maps/plotoptions/series-datalabels-box/
         *         Data labels box options
         *
         * @type      {number}
         * @default   0
         * @since     2.2.1
         * @apioption plotOptions.series.dataLabels.borderRadius
         */
        /**
         * The border width in pixels for the data label.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         *
         * @type      {number}
         * @default   0
         * @since     2.2.1
         * @apioption plotOptions.series.dataLabels.borderWidth
         */
        borderWidth: 0,
        /**
         * A class name for the data label. Particularly in styled mode,
         * this can be used to give each series' or point's data label
         * unique styling. In addition to this option, a default color class
         * name is added so that we can give the labels a contrast text
         * shadow.
         *
         * @sample {highcharts} highcharts/css/data-label-contrast/
         *         Contrast text shadow
         * @sample {highcharts} highcharts/css/series-datalabels/
         *         Styling by CSS
         *
         * @type      {string}
         * @since     5.0.0
         * @apioption plotOptions.series.dataLabels.className
         */
        /**
         * This options is deprecated.
         * Use [style.color](#plotOptions.series.dataLabels.style) instead.
         *
         * The text color for the data labels. Defaults to `undefined`. For
         * certain series types, like column or map, the data labels can be
         * drawn inside the points. In this case the data label will be
         * drawn with maximum contrast by default. Additionally, it will be
         * given a `text-outline` style with the opposite color, to further
         * increase the contrast. This can be overridden by setting the
         * `text-outline` style to `none` in the `dataLabels.style` option.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/
         *         Red data labels
         * @sample {highmaps} maps/demo/color-axis/
         *         White data labels
         *
         * @see [style.color](#plotOptions.series.dataLabels.style)
         *
         * @type       {Highcharts.ColorType}
         * @deprecated 10.3
         * @apioption  plotOptions.series.dataLabels.color
         */
        /**
         * Whether to hide data labels that are outside the plot area. By
         * default, the data label is moved inside the plot area according
         * to the
         * [overflow](#plotOptions.series.dataLabels.overflow)
         * option.
         *
         * @type      {boolean}
         * @default   true
         * @since     2.3.3
         * @apioption plotOptions.series.dataLabels.crop
         */
        /**
         * Whether to defer displaying the data labels until the initial
         * series animation has finished. Setting to `false` renders the
         * data label immediately. If set to `true` inherits the defer
         * time set in [plotOptions.series.animation](#plotOptions.series.animation).
         *
         * @since     4.0.0
         * @type      {boolean}
         * @product   highcharts highstock gantt
         */
        defer: true,
        /**
         * Enable or disable the data labels.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/
         *         Data labels enabled
         * @sample {highmaps} maps/demo/color-axis/
         *         Data labels enabled
         *
         * @type      {boolean}
         * @default   false
         * @apioption plotOptions.series.dataLabels.enabled
         */
        /**
         * A declarative filter to control of which data labels to display.
         * The declarative filter is designed for use when callback
         * functions are not available, like when the chart options require
         * a pure JSON structure or for use with graphical editors. For
         * programmatic control, use the `formatter` instead, and return
         * `undefined` to disable a single data label.
         *
         * @example
         * filter: {
         *     property: 'percentage',
         *     operator: '>',
         *     value: 4
         * }
         *
         * @sample {highcharts} highcharts/demo/pie-monochrome
         *         Data labels filtered by percentage
         *
         * @declare   Highcharts.DataLabelsFilterOptionsObject
         * @since     6.0.3
         * @apioption plotOptions.series.dataLabels.filter
         */
        /**
         * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`,
         * `==`, `===`, `!=` and `!==`.
         *
         * @type       {string}
         * @validvalue [">", "<", ">=", "<=", "==", "===", "!=", "!=="]
         * @apioption  plotOptions.series.dataLabels.filter.operator
         */
        /**
         * The point property to filter by. Point options are passed
         * directly to properties, additionally there are `y` value,
         * `percentage` and others listed under {@link Highcharts.Point}
         * members.
         *
         * @type      {string}
         * @apioption plotOptions.series.dataLabels.filter.property
         */
        /**
         * The value to compare against.
         *
         * @type      {number}
         * @apioption plotOptions.series.dataLabels.filter.value
         */
        /**
         * A
         * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
         * for the data label. Available variables are the same as for
         * `formatter`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
         *         Add a unit
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-format-subexpression/
         *         Complex logic in the format string
         * @sample {highmaps} maps/plotoptions/series-datalabels-format/
         *         Formatted value in the data label
         *
         * @type      {string}
         * @default   y
         * @default   point.value
         * @since     3.0
         * @apioption plotOptions.series.dataLabels.format
         */
        // eslint-disable-next-line valid-jsdoc
        /**
         * Callback JavaScript function to format the data label. Note that if a
         * `format` is defined, the format takes precedence and the formatter is
         * ignored.
         *
         * @sample {highmaps} maps/plotoptions/series-datalabels-format/
         *         Formatted value
         *
         * @type {Highcharts.DataLabelsFormatterCallbackFunction}
         */
        formatter: function () {
            var numberFormatter = this.series.chart.numberFormatter;
            return typeof this.y !== 'number' ?
                '' : numberFormatter(this.y, -1);
        },
        /**
         * For points with an extent, like columns or map areas, whether to
         * align the data label inside the box or to the actual value point.
         * Defaults to `false` in most cases, `true` in stacked columns.
         *
         * @type      {boolean}
         * @since     3.0
         * @apioption plotOptions.series.dataLabels.inside
         */
        /**
         * Format for points with the value of null. Works analogously to
         * [format](#plotOptions.series.dataLabels.format). `nullFormat` can
         * be applied only to series which support displaying null points
         * i.e `heatmap` or `tilemap`. Does not work with series that don't
         * display null points, like `line`, `column`, `bar` or `pie`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-nullformat/
         *         Format data label for null points in heat map
         *
         * @type      {boolean|string}
         * @since     7.1.0
         * @apioption plotOptions.series.dataLabels.nullFormat
         */
        /**
         * Callback JavaScript function that defines formatting for points
         * with the value of null. Works analogously to
         * [formatter](#plotOptions.series.dataLabels.formatter).
         * `nullFormatter` can be applied only to series which support
         * displaying null points i.e `heatmap` or `tilemap`. Does not work
         * with series that don't display null points, like `line`, `column`,
         * `bar` or `pie`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-nullformat/
         *         Format data label for null points in heat map
         *
         * @type      {Highcharts.DataLabelsFormatterCallbackFunction}
         * @since     7.1.0
         * @apioption plotOptions.series.dataLabels.nullFormatter
         */
        /**
         * How to handle data labels that flow outside the plot area. The
         * default is `"justify"`, which aligns them inside the plot area.
         * For columns and bars, this means it will be moved inside the bar.
         * To display data labels outside the plot area, set `crop` to
         * `false` and `overflow` to `"allow"`.
         *
         * @type       {Highcharts.DataLabelsOverflowValue}
         * @default    justify
         * @since      3.0.6
         * @apioption  plotOptions.series.dataLabels.overflow
         */
        /**
         * When either the `borderWidth` or the `backgroundColor` is set,
         * this is the padding within the box.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         * @sample {highmaps} maps/plotoptions/series-datalabels-box/
         *         Data labels box options
         *
         * @since 2.2.1
         */
        padding: 5,
        /**
         * Aligns data labels relative to points. If `center` alignment is
         * not possible, it defaults to `right`.
         *
         * @type      {Highcharts.AlignValue}
         * @default   center
         * @apioption plotOptions.series.dataLabels.position
         */
        /**
         * Text rotation in degrees. Note that due to a more complex
         * structure, backgrounds, borders and padding will be lost on a
         * rotated data label.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
         *         Vertical labels
         *
         * @type      {number}
         * @default   0
         * @apioption plotOptions.series.dataLabels.rotation
         */
        /**
         * The shadow of the box. Works best with `borderWidth` or
         * `backgroundColor`. Since 2.3 the shadow can be an object
         * configuration containing `color`, `offsetX`, `offsetY`, `opacity`
         * and `width`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
         *         Data labels box options
         *
         * @type      {boolean|Highcharts.ShadowOptionsObject}
         * @default   false
         * @since     2.2.1
         * @apioption plotOptions.series.dataLabels.shadow
         */
        /**
         * The name of a symbol to use for the border around the label.
         * Symbols are predefined functions on the Renderer object.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/
         *         A callout for annotations
         *
         * @type      {string}
         * @default   square
         * @since     4.1.2
         * @apioption plotOptions.series.dataLabels.shape
         */
        /**
         * Styles for the label. The default `color` setting is
         * `"contrast"`, which is a pseudo color that Highcharts picks up
         * and applies the maximum contrast to the underlying point item,
         * for example the bar in a bar chart.
         *
         * The `textOutline` is a pseudo property that applies an outline of
         * the given width with the given color, which by default is the
         * maximum contrast to the text. So a bright text color will result
         * in a black text outline for maximum readability on a mixed
         * background. In some cases, especially with grayscale text, the
         * text outline doesn't work well, in which cases it can be disabled
         * by setting it to `"none"`. When `useHTML` is true, the
         * `textOutline` will not be picked up. In this, case, the same
         * effect can be acheived through the `text-shadow` CSS property.
         *
         * For some series types, where each point has an extent, like for
         * example tree maps, the data label may overflow the point. There
         * are two strategies for handling overflow. By default, the text
         * will wrap to multiple lines. The other strategy is to set
         * `style.textOverflow` to `ellipsis`, which will keep the text on
         * one line plus it will break inside long words.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/
         *         Bold labels
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/
         *         Long labels truncated with an ellipsis in a pie
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/
         *         Long labels are wrapped in a pie
         * @sample {highmaps} maps/demo/color-axis/
         *         Bold labels
         *
         * @type      {Highcharts.CSSObject}
         * @since     4.1.0
         * @apioption plotOptions.series.dataLabels.style
         */
        style: {
            /** @internal */
            fontSize: '0.7em',
            /** @internal */
            fontWeight: 'bold',
            /** @internal */
            color: 'contrast',
            /** @internal */
            textOutline: '1px contrast'
        },
        /**
         * Options for a label text which should follow marker's shape.
         * Border and background are disabled for a label that follows a
         * path.
         *
         * **Note:** Only SVG-based renderer supports this option. Setting
         * `useHTML` to true will disable this option.
         *
         * @declare   Highcharts.DataLabelsTextPathOptionsObject
         * @since     7.1.0
         * @apioption plotOptions.series.dataLabels.textPath
         */
        /**
         * Presentation attributes for the text path.
         *
         * @type      {Highcharts.SVGAttributes}
         * @since     7.1.0
         * @apioption plotOptions.series.dataLabels.textPath.attributes
         */
        /**
         * Enable or disable `textPath` option for link's or marker's data
         * labels.
         *
         * @type      {boolean}
         * @since     7.1.0
         * @apioption plotOptions.series.dataLabels.textPath.enabled
         */
        /**
         * Whether to
         * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
         * to render the labels.
         *
         * @type      {boolean}
         * @default   false
         * @apioption plotOptions.series.dataLabels.useHTML
         */
        /**
         * The vertical alignment of a data label. Can be one of `top`,
         * `middle` or `bottom`. The default value depends on the data, for
         * instance in a column chart, the label is above positive values
         * and below negative values.
         *
         * @type  {Highcharts.VerticalAlignValue|null}
         * @since 2.3.3
         */
        verticalAlign: 'bottom',
        /**
         * The x position offset of the label relative to the point in
         * pixels.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
         *         Vertical and positioned
         * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/
         *         Data labels inside the bar
         */
        x: 0,
        /**
         * The z index of the data labels. Use a `zIndex` of 6 to display it above
         * the series, or use a `zIndex` of 2 to display it behind the series.
         *
         * @type      {number}
         * @default   6
         * @since     2.3.5
         * @apioption plotOptions.series.dataLabels.zIndex
         */
        /**
         * The y position offset of the label relative to the point in
         * pixels.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
         *         Vertical and positioned
         */
        y: 0
    },
    /**
     * When the series contains less points than the crop threshold, all
     * points are drawn, even if the points fall outside the visible plot
     * area at the current zoom. The advantage of drawing all points
     * (including markers and columns), is that animation is performed on
     * updates. On the other hand, when the series contains more points than
     * the crop threshold, the series data is cropped to only contain points
     * that fall within the plot area. The advantage of cropping away
     * invisible points is to increase performance on large series.
     *
     * @since   2.2
     * @product highcharts highstock
     *
     * @private
     */
    cropThreshold: 300,
    /**
     * Opacity of a series parts: line, fill (e.g. area) and dataLabels.
     *
     * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity)
     *
     * @since 7.1.0
     *
     * @private
     */
    opacity: 1,
    /**
     * The width of each point on the x axis. For example in a column chart
     * with one value each day, the pointRange would be 1 day (= 24 * 3600
     * * 1000 milliseconds). This is normally computed automatically, but
     * this option can be used to override the automatic value.
     *
     * @product highstock
     *
     * @private
     */
    pointRange: 0,
    /**
     * When this is true, the series will not cause the Y axis to cross
     * the zero plane (or [threshold](#plotOptions.series.threshold) option)
     * unless the data actually crosses the plane.
     *
     * For example, if `softThreshold` is `false`, a series of 0, 1, 2,
     * 3 will make the Y axis show negative values according to the
     * `minPadding` option. If `softThreshold` is `true`, the Y axis starts
     * at 0.
     *
     * @since   4.1.9
     * @product highcharts highstock
     *
     * @private
     */
    softThreshold: true,
    /**
     * @declare Highcharts.SeriesStatesOptionsObject
     *
     * @private
     */
    states: {
        /**
         * The normal state of a series, or for point items in column, pie
         * and similar series. Currently only used for setting animation
         * when returning to normal state from hover.
         *
         * @declare Highcharts.SeriesStatesNormalOptionsObject
         */
        normal: {
            /**
             * Animation when returning to normal state after hovering.
             *
                 * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
             */
            animation: true
        },
        /**
         * Options for the hovered series. These settings override the
         * normal state options when a series is moused over or touched.
         *
         * @declare Highcharts.SeriesStatesHoverOptionsObject
         */
        hover: {
            /**
             * Enable separate styles for the hovered series to visualize
             * that the user hovers either the series itself or the legend.
             *
             * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/
             *         Line
             * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/
             *         Column
             * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/
             *         Pie
             *
             * @type      {boolean}
             * @default   true
             * @since     1.2
             * @apioption plotOptions.series.states.hover.enabled
             */
            /**
             * Animation setting for hovering the graph in line-type series.
             *
             * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
             * @since   5.0.8
             * @product highcharts highstock
             */
            animation: {
                /**
                 * The duration of the hover animation in milliseconds. By
                 * default the hover state animates quickly in, and slowly
                 * back to normal.
                 *
                 * @internal
                 */
                duration: 150
            },
            /**
             * Pixel width of the graph line. By default this property is
             * undefined, and the `lineWidthPlus` property dictates how much
             * to increase the linewidth from normal state.
             *
             * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/
             *         5px line on hover
             *
             * @type      {number}
             * @product   highcharts highstock
             * @apioption plotOptions.series.states.hover.lineWidth
             */
            /**
             * The additional line width for the graph of a hovered series.
             *
             * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
             *         5 pixels wider
             * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
             *         5 pixels wider
             *
             * @since   4.0.3
             * @product highcharts highstock
             */
            lineWidthPlus: 1,
            /**
             * In Highcharts 1.0, the appearance of all markers belonging
             * to the hovered series. For settings on the hover state of the
             * individual point, see
             * [marker.states.hover](#plotOptions.series.marker.states.hover).
             *
             * @deprecated
             *
             * @extends   plotOptions.series.marker
             * @excluding states, symbol
             * @product   highcharts highstock
             */
            marker: {
            // `lineWidth: base + 1`,
            // `radius: base + 1`
            },
            /**
             * Options for the halo appearing around the hovered point in
             * line-type series as well as outside the hovered slice in pie
             * charts. By default the halo is filled by the current point or
             * series color with an opacity of 0.25\. The halo can be
             * disabled by setting the `halo` option to `null`.
             *
             * In styled mode, the halo is styled with the
             * `.highcharts-halo` class, with colors inherited from
             * `.highcharts-color-{n}`.
             *
             * @sample {highcharts} highcharts/plotoptions/halo/
             *         Halo options
             * @sample {highstock} highcharts/plotoptions/halo/
             *         Halo options
             *
             * @declare Highcharts.SeriesStatesHoverHaloOptionsObject
             * @type    {null|*}
             * @since   4.0
             * @product highcharts highstock
             */
            halo: {
                /**
                 * A collection of SVG attributes to override the appearance
                 * of the halo, for example `fill`, `stroke` and
                 * `stroke-width`.
                 *
                 * @type      {Highcharts.SVGAttributes}
                 * @since     4.0
                 * @product   highcharts highstock
                 * @apioption plotOptions.series.states.hover.halo.attributes
                 */
                /**
                 * The pixel size of the halo. For point markers this is the
                 * radius of the halo. For pie slices it is the width of the
                 * halo outside the slice. For bubbles it defaults to 5 and
                 * is the width of the halo outside the bubble.
                 *
                 * @since   4.0
                 * @product highcharts highstock
                 */
                size: 10,
                /**
                 * Opacity for the halo unless a specific fill is overridden
                 * using the `attributes` setting. Note that Highcharts is
                 * only able to apply opacity to colors of hex or rgb(a)
                 * formats.
                 *
                 * @since   4.0
                 * @product highcharts highstock
                 */
                opacity: 0.25
            }
        },
        /**
         * Specific options for point in selected states, after being
         * selected by
         * [allowPointSelect](#plotOptions.series.allowPointSelect)
         * or programmatically.
         *
         * @sample maps/plotoptions/series-allowpointselect/
         *         Allow point select demo
         *
         * @declare   Highcharts.SeriesStatesSelectOptionsObject
         * @extends   plotOptions.series.states.hover
         * @excluding brightness
         */
        select: {
            animation: {
                /** @internal */
                duration: 0
            }
        },
        /**
         * The opposite state of a hover for series.
         *
         * @sample highcharts/plotoptions/series-states-inactive-disabled
         *         Disabled inactive state
         *
         * @declare Highcharts.SeriesStatesInactiveOptionsObject
         */
        inactive: {
            /**
             * Enable or disable the inactive state for a series
             *
             * @sample highcharts/plotoptions/series-states-inactive-disabled
             *         Disabled inactive state
             *
             * @type {boolean}
             * @default true
             * @apioption plotOptions.series.states.inactive.enabled
             */
            /**
             * The animation for entering the inactive state.
             *
             * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
             */
            animation: {
                /** @internal */
                duration: 150
            },
            /**
             * Opacity of series elements (dataLabels, line, area).
             *
             * @type {number}
             */
            opacity: 0.2
        }
    },
    /**
     * Sticky tracking of mouse events. When true, the `mouseOut` event on a
     * series isn't triggered until the mouse moves over another series, or
     * out of the plot area. When false, the `mouseOut` event on a series is
     * triggered when the mouse leaves the area around the series' graph or
     * markers. This also implies the tooltip when not shared. When
     * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
     * will be hidden when moving the mouse between series. Defaults to true
     * for line and area type series, but to false for columns, pies etc.
     *
     * **Note:** The boost module will force this option because of
     * technical limitations.
     *
     * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/
     *         True by default
     * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/
     *         False
     *
     * @default {highcharts} true
     * @default {highstock} true
     * @default {highmaps} false
     * @since   2.0
     *
     * @private
     */
    stickyTracking: true,
    /**
     * A configuration object for the tooltip rendering of each single
     * series. Properties are inherited from [tooltip](#tooltip), but only
     * the following properties can be defined on a series level.
     *
     * @declare   Highcharts.SeriesTooltipOptionsObject
     * @since     2.3
     * @extends   tooltip
     * @excluding animation, backgroundColor, borderColor, borderRadius,
     *            borderWidth, className, crosshairs, enabled, formatter,
     *            headerShape, hideDelay, outside, padding, positioner,
     *            shadow, shape, shared, snap, split, stickOnContact,
     *            style, useHTML
     * @apioption plotOptions.series.tooltip
     */
    /**
     * When a series contains a `data` array that is longer than this, the
     * Series class looks for data configurations of plain numbers or arrays of
     * numbers. The first and last valid points are checked. If found, the rest
     * of the data is assumed to be the same. This saves expensive data checking
     * and indexing in long series, and makes data-heavy charts render faster.
     *
     * Set it to `0` disable.
     *
     * Note:
     * - In boost mode turbo threshold is forced. Only array of numbers or two
     *   dimensional arrays are allowed.
     * - In version 11.4.3 and earlier, if object configurations were passed
     *   beyond the turbo threshold, a warning was logged in the console and the
     *   data series didn't render.
     *
     * @since   2.2
     * @product highcharts highstock gantt
     *
     * @private
     */
    turboThreshold: 1000,
    /**
     * An array defining zones within a series. Zones can be applied to the
     * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis`
     * option. The zone definitions have to be in ascending order regarding
     * to the value.
     *
     * In styled mode, the color zones are styled with the
     * `.highcharts-zone-{n}` class, or custom classed from the `className`
     * option
     * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)).
     *
     * @see [zoneAxis](#plotOptions.series.zoneAxis)
     *
     * @sample {highcharts} highcharts/series/color-zones-simple/
     *         Color zones
     * @sample {highstock} highcharts/series/color-zones-simple/
     *         Color zones
     *
     * @declare   Highcharts.SeriesZonesOptionsObject
     * @type      {Array<*>}
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zones
     */
    /**
     * Styled mode only. A custom class name for the zone.
     *
     * @sample highcharts/css/color-zones/
     *         Zones styled by class name
     *
     * @type      {string}
     * @since     5.0.0
     * @apioption plotOptions.series.zones.className
     */
    /**
     * Defines the color of the series.
     *
     * @see [series color](#plotOptions.series.color)
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zones.color
     */
    /**
     * A name for the dash style to use for the graph.
     *
     * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
     *
     * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/
     *         Dashed line indicates prognosis
     *
     * @type      {Highcharts.DashStyleValue}
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zones.dashStyle
     */
    /**
     * Defines the fill color for the series (in area type series)
     *
     * @see [fillColor](#plotOptions.area.fillColor)
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zones.fillColor
     */
    /**
     * The value up to where the zone extends, if undefined the zones
     * stretches to the last value in the series.
     *
     * @type      {number}
     * @since     4.1.0
     * @product   highcharts highstock
     * @apioption plotOptions.series.zones.value
     */
    /**
     * When using dual or multiple color axes, this number defines which
     * colorAxis the particular series is connected to. It refers to
     * either the
     * {@link #colorAxis.id|axis id}
     * or the index of the axis in the colorAxis array, with 0 being the
     * first. Set this option to false to prevent a series from connecting
     * to the default color axis.
     *
     * Since v7.2.0 the option can also be an axis id or an axis index
     * instead of a boolean flag.
     *
     * @sample highcharts/coloraxis/coloraxis-with-pie/
     *         Color axis with pie series
     * @sample highcharts/coloraxis/multiple-coloraxis/
     *         Multiple color axis
     *
     * @type      {number|string|boolean}
     * @default   0
     * @product   highcharts highstock highmaps
     * @apioption plotOptions.series.colorAxis
     */
    /**
     * Determines what data value should be used to calculate point color
     * if `colorAxis` is used. Requires to set `min` and `max` if some
     * custom point property is used or if approximation for data grouping
     * is set to `'sum'`.
     *
     * @sample highcharts/coloraxis/custom-color-key/
     *         Custom color key
     * @sample highcharts/coloraxis/color-key-with-stops/
     *         Custom colorKey with color axis stops
     * @sample highcharts/coloraxis/changed-default-color-key/
     *         Changed default color key
     *
     * @type      {string}
     * @default   y
     * @since     7.2.0
     * @product   highcharts highstock highmaps
     * @apioption plotOptions.series.colorKey
     */
    /**
     * What type of legend symbol to render for this series. Can be one of
     * `areaMarker`, `lineMarker` or `rectangle`.
     *
     * @validvalue ["areaMarker", "lineMarker", "rectangle"]
     *
     * @sample {highcharts} highcharts/series/legend-symbol/
     *         Change the legend symbol
     *
     * @type      {string}
     * @default   rectangle
     * @since     11.0.1
     * @apioption plotOptions.series.legendSymbol
     */
    /**
     * Defines the color of the legend symbol for this series. Defaults to
     * undefined, in which case the series color is used. Does not work with
     * styled mode.
     *
     * @sample {highcharts|highstock} highcharts/series/legend-symbol-color/
     *         Change the legend symbol color
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default   undefined
     * @since 12.0.0
     * @product   highcharts highstock highmaps
     * @apioption plotOptions.series.legendSymbolColor
     */
    /**
     * Determines whether the series should look for the nearest point
     * in both dimensions or just the x-dimension when hovering the series.
     * Defaults to `'xy'` for scatter series and `'x'` for most other
     * series. If the data has duplicate x-values, it is recommended to
     * set this to `'xy'` to allow hovering over all points.
     *
     * Applies only to series types using nearest neighbor search (not
     * direct hover) for tooltip.
     *
     * @sample {highcharts} highcharts/series/findnearestpointby/
     *         Different hover behaviors
     * @sample {highstock} highcharts/series/findnearestpointby/
     *         Different hover behaviors
     * @sample {highmaps} highcharts/series/findnearestpointby/
     *         Different hover behaviors
     *
     * @since      5.0.10
     * @validvalue ["x", "xy"]
     *
     * @private
     */
    findNearestPointBy: 'x'
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var SeriesDefaults = (seriesDefaults);

;// ./code/es5/es-modules/Core/Series/SeriesRegistry.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var SeriesRegistry_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();


var SeriesRegistry_defaultOptions = Defaults.defaultOptions;


var SeriesRegistry_extend = Core_Utilities.extend, SeriesRegistry_extendClass = Core_Utilities.extendClass, SeriesRegistry_merge = Core_Utilities.merge;
/* *
 *
 *  Namespace
 *
 * */
var SeriesRegistry;
(function (SeriesRegistry) {
    /* *
     *
     *  Properties
     *
     * */
    /**
     * @internal
     * @todo Move `Globals.seriesTypes` code to her.
     */
    SeriesRegistry.seriesTypes = Core_Globals.seriesTypes;
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Registers class pattern of a series.
     *
     * @private
     */
    function registerSeriesType(seriesType, SeriesClass) {
        var defaultPlotOptions = SeriesRegistry_defaultOptions.plotOptions || {},
            seriesOptions = SeriesClass.defaultOptions,
            seriesProto = SeriesClass.prototype;
        seriesProto.type = seriesType;
        if (!seriesProto.pointClass) {
            seriesProto.pointClass = Series_Point;
        }
        if (SeriesRegistry.seriesTypes[seriesType]) {
            return false;
        }
        if (seriesOptions) {
            defaultPlotOptions[seriesType] = seriesOptions;
        }
        SeriesRegistry.seriesTypes[seriesType] = SeriesClass;
        return true;
    }
    SeriesRegistry.registerSeriesType = registerSeriesType;
    /**
     * Old factory to create new series prototypes.
     *
     * @deprecated
     * @function Highcharts.seriesType
     *
     * @param {string} type
     * The series type name.
     *
     * @param {string} parent
     * The parent series type name. Use `line` to inherit from the basic
     * {@link Series} object.
     *
     * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options
     * The additional default options that are merged with the parent's options.
     *
     * @param {Highcharts.Dictionary<*>} [props]
     * The properties (functions and primitives) to set on the new prototype.
     *
     * @param {Highcharts.Dictionary<*>} [pointProps]
     * Members for a series-specific extension of the {@link Point} prototype if
     * needed.
     *
     * @return {Highcharts.Series}
     * The newly created prototype as extended from {@link Series} or its
     * derivatives.
     */
    function seriesType(type, parent, options, seriesProto, pointProto) {
        var defaultPlotOptions = SeriesRegistry_defaultOptions.plotOptions || {};
        parent = parent || '';
        // Merge the options
        defaultPlotOptions[type] = SeriesRegistry_merge(defaultPlotOptions[parent], options);
        // Create the class
        delete SeriesRegistry.seriesTypes[type];
        registerSeriesType(type, SeriesRegistry_extendClass(SeriesRegistry.seriesTypes[parent] || function () { }, seriesProto));
        SeriesRegistry.seriesTypes[type].prototype.type = type;
        // Create the point class if needed
        if (pointProto) {
            var PointClass = /** @class */ (function (_super) {
                    SeriesRegistry_extends(PointClass, _super);
                function PointClass() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                return PointClass;
            }(Series_Point));
            SeriesRegistry_extend(PointClass.prototype, pointProto);
            SeriesRegistry.seriesTypes[type].prototype.pointClass = PointClass;
        }
        return SeriesRegistry.seriesTypes[type];
    }
    SeriesRegistry.seriesType = seriesType;
})(SeriesRegistry || (SeriesRegistry = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Series_SeriesRegistry = (SeriesRegistry);

;// ./code/es5/es-modules/Core/Series/Series.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var Series_assign = (undefined && undefined.__assign) || function () {
    Series_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 Series_assign.apply(this, arguments);
};
var Series_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};

var Series_animObject = AnimationUtilities.animObject, Series_setAnimation = AnimationUtilities.setAnimation;


var Series_defaultOptions = Defaults.defaultOptions;

var Series_registerEventOptions = Core_Foundation.registerEventOptions;

var Series_svg = Core_Globals.svg, Series_win = Core_Globals.win;




var seriesTypes = Series_SeriesRegistry.seriesTypes;


var Series_arrayMax = Core_Utilities.arrayMax, Series_arrayMin = Core_Utilities.arrayMin, Series_clamp = Core_Utilities.clamp, Series_correctFloat = Core_Utilities.correctFloat, Series_crisp = Core_Utilities.crisp, Series_defined = Core_Utilities.defined, Series_destroyObjectProperties = Core_Utilities.destroyObjectProperties, Series_diffObjects = Core_Utilities.diffObjects, Series_erase = Core_Utilities.erase, Series_error = Core_Utilities.error, Series_extend = Core_Utilities.extend, Series_find = Core_Utilities.find, Series_fireEvent = Core_Utilities.fireEvent, Series_getClosestDistance = Core_Utilities.getClosestDistance, Series_getNestedProperty = Core_Utilities.getNestedProperty, Series_insertItem = Core_Utilities.insertItem, Series_isArray = Core_Utilities.isArray, Series_isNumber = Core_Utilities.isNumber, Series_isString = Core_Utilities.isString, Series_merge = Core_Utilities.merge, Series_objectEach = Core_Utilities.objectEach, Series_pick = Core_Utilities.pick, Series_removeEvent = Core_Utilities.removeEvent, Series_syncTimeout = Core_Utilities.syncTimeout;
/* *
 *
 *  Class
 *
 * */
/**
 * This is the base series prototype that all other series types inherit from.
 * A new series is initialized either through the
 * [series](https://api.highcharts.com/highcharts/series)
 * option structure, or after the chart is initialized, through
 * {@link Highcharts.Chart#addSeries}.
 *
 * The object can be accessed in a number of ways. All series and point event
 * handlers give a reference to the `series` object. The chart object has a
 * {@link Highcharts.Chart#series|series} property that is a collection of all
 * the chart's series. The point objects and axis objects also have the same
 * reference.
 *
 * Another way to reference the series programmatically is by `id`. Add an id
 * in the series configuration options, and get the series object by
 * {@link Highcharts.Chart#get}.
 *
 * Configuration options for the series are given in three levels. Options for
 * all series in a chart are given in the
 * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series)
 * object. Then options for all series of a specific type
 * are given in the plotOptions of that type, for example `plotOptions.line`.
 * Next, options for one single series are given in the series array, or as
 * arguments to `chart.addSeries`.
 *
 * The data in the series is stored in various arrays.
 *
 * - First, `series.options.data` contains all the original config options for
 *   each point whether added by options or methods like `series.addPoint`.
 *
 * - The `series.dataTable` refers to an instance of [DataTableCore](https://api.highcharts.com/class-reference/Highcharts.Data)
 *   or `DataTable` that contains the data in a tabular format. Individual
 *   columns can be read from `series.getColumn()`.
 *
 * - Next, `series.data` contains those values converted to points, but in case
 *   the series data length exceeds the `cropThreshold`, or if the data is
 *   grouped, `series.data` doesn't contain all the points. It only contains the
 *   points that have been created on demand.
 *
 * - Then there's `series.points` that contains all currently visible point
 *   objects. In case of cropping, the cropped-away points are not part of this
 *   array. The `series.points` array starts at `series.cropStart` compared to
 *   `series.data` and `series.options.data`. If however the series data is
 *   grouped, these can't be correlated one to one.
 *
 * @class
 * @name Highcharts.Series
 *
 * @param {Highcharts.Chart} chart
 * The chart instance.
 *
 * @param {Highcharts.SeriesOptionsType|object} options
 * The series options.
 */
var Series = /** @class */ (function () {
    function Series() {
        /* *
         *
         *  Static Properties
         *
         * */
        this.zoneAxis = 'y';
        // eslint-enable valid-jsdoc
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    Series.prototype.init = function (chart, userOptions) {
        var _a;
        Series_fireEvent(this, 'init', { options: userOptions });
        // Create the data table
        (_a = this.dataTable) !== null && _a !== void 0 ? _a : (this.dataTable = new Data_DataTableCore());
        var series = this,
            chartSeries = chart.series;
        // The 'eventsToUnbind' property moved from prototype into the
        // Series init to avoid reference to the same array between
        // the different series and charts. #12959, #13937
        this.eventsToUnbind = [];
        /**
         * Read only. The chart that the series belongs to.
         *
         * @name Highcharts.Series#chart
         * @type {Highcharts.Chart}
         */
        series.chart = chart;
        /**
         * Read only. The series' type, like "line", "area", "column" etc.
         * The type in the series options anc can be altered using
         * {@link Series#update}.
         *
         * @name Highcharts.Series#type
         * @type {string}
         */
        /**
         * Read only. The series' current options. To update, use
         * {@link Series#update}.
         *
         * @name Highcharts.Series#options
         * @type {Highcharts.SeriesOptionsType}
         */
        series.options = series.setOptions(userOptions);
        var options = series.options,
            visible = options.visible !== false;
        /**
         * All child series that are linked to the current series through the
         * [linkedTo](https://api.highcharts.com/highcharts/series.line.linkedTo)
         * option.
         *
         * @name Highcharts.Series#linkedSeries
         * @type {Array<Highcharts.Series>}
         * @readonly
         */
        series.linkedSeries = [];
        // Bind the axes
        series.bindAxes();
        Series_extend(series, {
            /**
             * The series name as given in the options. Defaults to
             * "Series {n}".
             *
             * @name Highcharts.Series#name
             * @type {string}
             */
            name: options.name,
            state: '',
            /**
             * Read only. The series' visibility state as set by {@link
             * Series#show}, {@link Series#hide}, or in the initial
             * configuration.
             *
             * @name Highcharts.Series#visible
             * @type {boolean}
             */
            visible: visible, // True by default
            /**
             * Read only. The series' selected state as set by {@link
             * Highcharts.Series#select}.
             *
             * @name Highcharts.Series#selected
             * @type {boolean}
             */
            selected: options.selected === true // False by default
        });
        Series_registerEventOptions(this, options);
        var events = options.events;
        if ((events && events.click) ||
            (options.point &&
                options.point.events &&
                options.point.events.click) ||
            options.allowPointSelect) {
            chart.runTrackerClick = true;
        }
        series.getColor();
        series.getSymbol();
        // Mark cartesian
        if (series.isCartesian) {
            chart.hasCartesianSeries = true;
        }
        // Get the index and register the series in the chart. The index is
        // one more than the current latest series index (#5960).
        var lastSeries;
        if (chartSeries.length) {
            lastSeries = chartSeries[chartSeries.length - 1];
        }
        series._i = Series_pick(lastSeries && lastSeries._i, -1) + 1;
        series.opacity = series.options.opacity;
        // Insert the series and re-order all series above the insertion
        // point.
        chart.orderItems('series', Series_insertItem(this, chartSeries));
        // Set options for series with sorting and set data later.
        if (options.dataSorting && options.dataSorting.enabled) {
            series.setDataSortingOptions();
        }
        else if (!series.points && !series.data) {
            series.setData(options.data, false);
        }
        Series_fireEvent(this, 'afterInit');
    };
    /**
     * Check whether the series item is itself or inherits from a certain
     * series type.
     *
     * @function Highcharts.Series#is
     * @param {string} type The type of series to check for, can be either
     *        featured or custom series types. For example `column`, `pie`,
     *        `ohlc` etc.
     *
     * @return {boolean}
     *        True if this item is or inherits from the given type.
     */
    Series.prototype.is = function (type) {
        return seriesTypes[type] && this instanceof seriesTypes[type];
    };
    /**
     * Set the xAxis and yAxis properties of cartesian series, and register
     * the series in the `axis.series` array.
     *
     * @private
     * @function Highcharts.Series#bindAxes
     */
    Series.prototype.bindAxes = function () {
        var series = this,
            seriesOptions = series.options,
            chart = series.chart;
        var axisOptions;
        Series_fireEvent(this, 'bindAxes', null, function () {
            // Repeat for xAxis and yAxis
            (series.axisTypes || []).forEach(function (coll) {
                // Loop through the chart's axis objects
                (chart[coll] || []).forEach(function (axis) {
                    axisOptions = axis.options;
                    // Apply if the series xAxis or yAxis option matches
                    // the number of the axis, or if undefined, use the
                    // first axis
                    if (Series_pick(seriesOptions[coll], 0) === axis.index ||
                        (typeof seriesOptions[coll] !==
                            'undefined' &&
                            seriesOptions[coll] === axisOptions.id)) {
                        // Register this series in the axis.series lookup
                        Series_insertItem(series, axis.series);
                        // Set this series.xAxis or series.yAxis reference
                        /**
                         * Read only. The unique xAxis object associated
                         * with the series.
                         *
                         * @name Highcharts.Series#xAxis
                         * @type {Highcharts.Axis}
                         */
                        /**
                         * Read only. The unique yAxis object associated
                         * with the series.
                         *
                         * @name Highcharts.Series#yAxis
                         * @type {Highcharts.Axis}
                         */
                        series[coll] = axis;
                        // Mark dirty for redraw
                        axis.isDirty = true;
                    }
                });
                // The series needs an X and an Y axis
                if (!series[coll] &&
                    series.optionalAxis !== coll) {
                    Series_error(18, true, chart);
                }
            });
        });
        Series_fireEvent(this, 'afterBindAxes');
    };
    /**
     * Define hasData functions for series. These return true if there
     * are data points on this series within the plot area.
     *
     * @private
     * @function Highcharts.Series#hasData
     */
    Series.prototype.hasData = function () {
        return ((this.visible &&
            typeof this.dataMax !== 'undefined' &&
            typeof this.dataMin !== 'undefined') || ( // #3703
        this.visible &&
            this.dataTable.rowCount > 0 // #9758
        ));
    };
    /**
     * Determine whether the marker in a series has changed.
     *
     * @private
     * @function Highcharts.Series#hasMarkerChanged
     */
    Series.prototype.hasMarkerChanged = function (options, oldOptions) {
        var marker = options.marker,
            oldMarker = oldOptions.marker || {};
        return marker && ((oldMarker.enabled && !marker.enabled) ||
            oldMarker.symbol !== marker.symbol || // #10870, #15946
            oldMarker.height !== marker.height || // #16274
            oldMarker.width !== marker.width // #16274
        );
    };
    /**
     * Return an auto incremented x value based on the pointStart and
     * pointInterval options. This is only used if an x value is not given
     * for the point that calls autoIncrement.
     *
     * @private
     * @function Highcharts.Series#autoIncrement
     */
    Series.prototype.autoIncrement = function (x) {
        var _a,
            _b;
        var options = this.options,
            _c = this.options,
            pointIntervalUnit = _c.pointIntervalUnit,
            relativeXValue = _c.relativeXValue,
            time = this.chart.time,
            xIncrement = (_b = (_a = this.xIncrement) !== null && _a !== void 0 ? _a : time.parse(options.pointStart)) !== null && _b !== void 0 ? _b : 0;
        var pointInterval;
        this.pointInterval = pointInterval = Series_pick(this.pointInterval, options.pointInterval, 1);
        if (relativeXValue && Series_isNumber(x)) {
            pointInterval *= x;
        }
        // Added code for pointInterval strings
        if (pointIntervalUnit) {
            var d = time.toParts(xIncrement);
            if (pointIntervalUnit === 'day') {
                d[2] += pointInterval;
            }
            else if (pointIntervalUnit === 'month') {
                d[1] += pointInterval;
            }
            else if (pointIntervalUnit === 'year') {
                d[0] += pointInterval;
            }
            pointInterval = time.makeTime.apply(time, d) - xIncrement;
        }
        if (relativeXValue && Series_isNumber(x)) {
            return xIncrement + pointInterval;
        }
        this.xIncrement = xIncrement + pointInterval;
        return xIncrement;
    };
    /**
     * Internal function to set properties for series if data sorting is
     * enabled.
     *
     * @private
     * @function Highcharts.Series#setDataSortingOptions
     */
    Series.prototype.setDataSortingOptions = function () {
        var options = this.options;
        Series_extend(this, {
            requireSorting: false,
            sorted: false,
            enabledDataSorting: true,
            allowDG: false
        });
        // To allow unsorted data for column series.
        if (!Series_defined(options.pointRange)) {
            options.pointRange = 1;
        }
    };
    /**
     * Set the series options by merging from the options tree. Called
     * internally on initializing and updating series. This function will
     * not redraw the series. For API usage, use {@link Series#update}.
     * @private
     * @function Highcharts.Series#setOptions
     * @param {Highcharts.SeriesOptionsType} itemOptions
     * The series options.
     * @emits Highcharts.Series#event:afterSetOptions
     */
    Series.prototype.setOptions = function (itemOptions) {
        var _a,
            _b;
        var chart = this.chart,
            chartOptions = chart.options,
            plotOptions = chartOptions.plotOptions,
            userOptions = chart.userOptions || {},
            seriesUserOptions = Series_merge(itemOptions),
            styledMode = chart.styledMode,
            e = {
                plotOptions: plotOptions,
                userOptions: seriesUserOptions
            };
        var zone;
        Series_fireEvent(this, 'setOptions', e);
        // These may be modified by the event
        var typeOptions = e.plotOptions[this.type],
            userPlotOptions = (userOptions.plotOptions || {}),
            userPlotOptionsSeries = userPlotOptions.series || {},
            defaultPlotOptionsType = (Series_defaultOptions.plotOptions[this.type] || {}),
            userPlotOptionsType = userPlotOptions[this.type] || {};
        // Use copy to prevent undetected changes (#9762)
        /**
         * Contains series options by the user without defaults.
         * @name Highcharts.Series#userOptions
         * @type {Highcharts.SeriesOptionsType}
         */
        this.userOptions = e.userOptions;
        var options = Series_merge(typeOptions,
            plotOptions.series, 
            // #3881, chart instance plotOptions[type] should trump
            // plotOptions.series
            userPlotOptionsType,
            seriesUserOptions);
        // The tooltip options are merged between global and series specific
        // options. Importance order asscendingly:
        // globals: (1)tooltip, (2)plotOptions.series,
        // (3)plotOptions[this.type]
        // init userOptions with possible later updates: 4-6 like 1-3 and
        // (7)this series options
        this.tooltipOptions = Series_merge(Series_defaultOptions.tooltip, // 1
        (_a = Series_defaultOptions.plotOptions.series) === null || _a === void 0 ? void 0 : _a.tooltip, // 2
        defaultPlotOptionsType === null || defaultPlotOptionsType === void 0 ? void 0 : defaultPlotOptionsType.tooltip, // 3
        chart.userOptions.tooltip, // 4
        (_b = userPlotOptions.series) === null || _b === void 0 ? void 0 : _b.tooltip, // 5
        userPlotOptionsType.tooltip, // 6
        seriesUserOptions.tooltip // 7
        );
        // When shared tooltip, stickyTracking is true by default,
        // unless user says otherwise.
        this.stickyTracking = Series_pick(seriesUserOptions.stickyTracking, userPlotOptionsType.stickyTracking, userPlotOptionsSeries.stickyTracking, (this.tooltipOptions.shared && !this.noSharedTooltip ?
            true :
            options.stickyTracking));
        // Delete marker object if not allowed (#1125)
        if (typeOptions.marker === null) {
            delete options.marker;
        }
        // Handle color zones
        this.zoneAxis = options.zoneAxis || 'y';
        var zones = this.zones = // #20440, create deep copy of zones options
                (options.zones || []).map(function (z) { return (Series_assign({},
            z)); });
        if ((options.negativeColor || options.negativeFillColor) &&
            !options.zones) {
            zone = {
                value: options[this.zoneAxis + 'Threshold'] ||
                    options.threshold ||
                    0,
                className: 'highcharts-negative'
            };
            if (!styledMode) {
                zone.color = options.negativeColor;
                zone.fillColor = options.negativeFillColor;
            }
            zones.push(zone);
        }
        // Push one extra zone for the rest
        if (zones.length && Series_defined(zones[zones.length - 1].value)) {
            zones.push(styledMode ? {} : {
                color: this.color,
                fillColor: this.fillColor
            });
        }
        Series_fireEvent(this, 'afterSetOptions', { options: options });
        return options;
    };
    /**
     * Return series name in "Series {Number}" format or the one defined by
     * a user. This method can be simply overridden as series name format
     * can vary (e.g. technical indicators).
     *
     * @function Highcharts.Series#getName
     *
     * @return {string}
     * The series name.
     */
    Series.prototype.getName = function () {
        // #4119
        return Series_pick(this.options.name, 'Series ' + (this.index + 1));
    };
    /**
     * @private
     * @function Highcharts.Series#getCyclic
     */
    Series.prototype.getCyclic = function (prop, value, defaults) {
        var chart = this.chart, indexName = "" + prop + "Index", counterName = "" + prop + "Counter", len = (
            // Symbol count
            (defaults === null || defaults === void 0 ? void 0 : defaults.length) ||
                // Color count
                chart.options.chart.colorCount);
        var i,
            setting;
        if (!value) {
            // Pick up either the colorIndex option, or the series.colorIndex
            // after Series.update()
            setting = Series_pick(prop === 'color' ? this.options.colorIndex : void 0, this[indexName]);
            if (Series_defined(setting)) { // After Series.update()
                i = setting;
            }
            else {
                // #6138
                if (!chart.series.length) {
                    chart[counterName] = 0;
                }
                i = chart[counterName] % len;
                chart[counterName] += 1;
            }
            if (defaults) {
                value = defaults[i];
            }
        }
        // Set the colorIndex
        if (typeof i !== 'undefined') {
            this[indexName] = i;
        }
        this[prop] = value;
    };
    /**
     * Get the series' color based on either the options or pulled from
     * global options.
     *
     * @private
     * @function Highcharts.Series#getColor
     */
    Series.prototype.getColor = function () {
        if (this.chart.styledMode) {
            this.getCyclic('color');
        }
        else if (this.options.colorByPoint) {
            this.color = "#cccccc" /* Palette.neutralColor20 */;
        }
        else {
            this.getCyclic('color', this.options.color ||
                Series_defaultOptions.plotOptions[this.type].color, this.chart.options.colors);
        }
    };
    /**
     * Get all points' instances created for this series.
     *
     * @private
     * @function Highcharts.Series#getPointsCollection
     */
    Series.prototype.getPointsCollection = function () {
        return (this.hasGroupedData ? this.points : this.data) || [];
    };
    /**
     * Get the series' symbol based on either the options or pulled from
     * global options.
     *
     * @private
     * @function Highcharts.Series#getSymbol
     */
    Series.prototype.getSymbol = function () {
        var seriesMarkerOption = this.options.marker;
        this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols);
    };
    /**
     * Shorthand to get one of the series' data columns from `Series.dataTable`.
     *
     * @private
     * @function Highcharts.Series#getColumn
     */
    Series.prototype.getColumn = function (columnName, modified) {
        return (modified ? this.dataTable.modified : this.dataTable)
            .getColumn(columnName, true) || [];
    };
    /**
     * Finds the index of an existing point that matches the given point
     * options.
     *
     * @private
     * @function Highcharts.Series#findPointIndex
     * @param {Highcharts.PointOptionsObject} optionsObject
     * The options of the point.
     * @param {number} fromIndex
     * The index to start searching from, used for optimizing series with
     * required sorting.
     * @return {number|undefined}
     * Returns the index of a matching point, or undefined if no match is found.
     */
    Series.prototype.findPointIndex = function (optionsObject, fromIndex) {
        var id = optionsObject.id,
            x = optionsObject.x,
            oldData = this.points,
            dataSorting = this.options.dataSorting;
        var matchingPoint,
            matchedById,
            pointIndex;
        if (id) {
            var item = this.chart.get(id);
            if (item instanceof Series_Point) {
                matchingPoint = item;
            }
        }
        else if (this.linkedParent ||
            this.enabledDataSorting ||
            this.options.relativeXValue) {
            var matcher = function (oldPoint) { return !oldPoint.touched &&
                    oldPoint.index === optionsObject.index; };
            if (dataSorting && dataSorting.matchByName) {
                matcher = function (oldPoint) { return !oldPoint.touched &&
                    oldPoint.name === optionsObject.name; };
            }
            else if (this.options.relativeXValue) {
                matcher = function (oldPoint) { return !oldPoint.touched &&
                    oldPoint.options.x === optionsObject.x; };
            }
            matchingPoint = Series_find(oldData, matcher);
            // Add unmatched point as a new point
            if (!matchingPoint) {
                return void 0;
            }
        }
        if (matchingPoint) {
            pointIndex = matchingPoint && matchingPoint.index;
            if (typeof pointIndex !== 'undefined') {
                matchedById = true;
            }
        }
        // Search for the same X in the existing data set
        if (typeof pointIndex === 'undefined' && Series_isNumber(x)) {
            pointIndex = this.getColumn('x').indexOf(x, fromIndex);
        }
        // Reduce pointIndex if data is cropped
        if (pointIndex !== -1 &&
            typeof pointIndex !== 'undefined' &&
            this.cropped) {
            pointIndex = (pointIndex >= this.cropStart) ?
                pointIndex - this.cropStart : pointIndex;
        }
        if (!matchedById &&
            Series_isNumber(pointIndex) &&
            oldData[pointIndex] && oldData[pointIndex].touched) {
            pointIndex = void 0;
        }
        return pointIndex;
    };
    /**
     * Internal function called from setData. If the point count is the same
     * as it was, or if there are overlapping X values, just run
     * Point.update which is cheaper, allows animation, and keeps references
     * to points. This also allows adding or removing points if the X-es
     * don't match.
     *
     * @private
     * @function Highcharts.Series#updateData
     */
    Series.prototype.updateData = function (data, animation) {
        var options = this.options,
            dataSorting = options.dataSorting,
            oldData = this.points,
            pointsToAdd = [],
            requireSorting = this.requireSorting,
            equalLength = data.length === oldData.length;
        var hasUpdatedByKey,
            i,
            point,
            lastIndex,
            succeeded = true;
        this.xIncrement = null;
        // Iterate the new data
        data.forEach(function (pointOptions, i) {
            var optionsObject = (Series_defined(pointOptions) &&
                    this.pointClass.prototype.optionsToObject.call({ series: this },
                pointOptions)) || {};
            var pointIndex;
            // Get the x of the new data point
            var x = optionsObject.x,
                id = optionsObject.id;
            if (id || Series_isNumber(x)) {
                pointIndex = this.findPointIndex(optionsObject, lastIndex);
                // Matching X not found
                // or used already due to ununique x values (#8995),
                // add point (but later)
                if (pointIndex === -1 ||
                    typeof pointIndex === 'undefined') {
                    pointsToAdd.push(pointOptions);
                    // Matching X found, update
                }
                else if (oldData[pointIndex] &&
                    pointOptions !== options.data[pointIndex]) {
                    oldData[pointIndex].update(pointOptions, false, null, false);
                    // Mark it touched, below we will remove all points that
                    // are not touched.
                    oldData[pointIndex].touched = true;
                    // Speed optimize by only searching after last known
                    // index. Performs ~20% bettor on large data sets.
                    if (requireSorting) {
                        lastIndex = pointIndex + 1;
                    }
                    // Point exists, no changes, don't remove it
                }
                else if (oldData[pointIndex]) {
                    oldData[pointIndex].touched = true;
                }
                // If the length is equal and some of the nodes had a
                // match in the same position, we don't want to remove
                // non-matches.
                if (!equalLength ||
                    i !== pointIndex ||
                    (dataSorting && dataSorting.enabled) ||
                    this.hasDerivedData) {
                    hasUpdatedByKey = true;
                }
            }
            else {
                // Gather all points that are not matched
                pointsToAdd.push(pointOptions);
            }
        }, this);
        // Remove points that don't exist in the updated data set
        if (hasUpdatedByKey) {
            i = oldData.length;
            while (i--) {
                point = oldData[i];
                if (point && !point.touched && point.remove) {
                    point.remove(false, animation);
                }
            }
            // If we did not find keys (ids or x-values), and the length is the
            // same, update one-to-one
        }
        else if (equalLength && (!dataSorting || !dataSorting.enabled)) {
            data.forEach(function (point, i) {
                // .update doesn't exist on a linked, hidden series (#3709)
                // (#10187)
                if (point !== oldData[i].y && !oldData[i].destroyed) {
                    oldData[i].update(point, false, null, false);
                }
            });
            // Don't add new points since those configs are used above
            pointsToAdd.length = 0;
            // Did not succeed in updating data
        }
        else {
            succeeded = false;
        }
        oldData.forEach(function (point) {
            if (point) {
                point.touched = false;
            }
        });
        if (!succeeded) {
            return false;
        }
        // Add new points
        pointsToAdd.forEach(function (point) {
            this.addPoint(point, false, null, null, false);
        }, this);
        var xData = this.getColumn('x');
        if (this.xIncrement === null &&
            xData.length) {
            this.xIncrement = Series_arrayMax(xData);
            this.autoIncrement();
        }
        return true;
    };
    Series.prototype.dataColumnKeys = function () {
        return Series_spreadArray(['x'], (this.pointArrayMap || ['y']), true);
    };
    /**
     * Apply a new set of data to the series and optionally redraw it. The
     * new data array is passed by reference (except in case of
     * `updatePoints`), and may later be mutated when updating the chart
     * data.
     *
     * Note the difference in behaviour when setting the same amount of
     * points, or a different amount of points, as handled by the
     * `updatePoints` parameter.
     *
     * @sample highcharts/members/series-setdata/
     *         Set new data from a button
     * @sample highcharts/members/series-setdata-pie/
     *         Set data in a pie
     * @sample stock/members/series-setdata/
     *         Set new data in Highcharts Stock
     * @sample maps/members/series-setdata/
     *         Set new data in Highmaps
     *
     * @function Highcharts.Series#setData
     *
     * @param {Array<Highcharts.PointOptionsType>} data
     *        Takes an array of data in the same format as described under
     *        `series.{type}.data` for the given series type, for example a
     *        line series would take data in the form described under
     *        [series.line.data](https://api.highcharts.com/highcharts/series.line.data).
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after the series is altered. If
     *        doing more operations on the chart, it is a good idea to set
     *        redraw to false and call {@link Chart#redraw} after.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        When the updated data is the same length as the existing data,
     *        points will be updated by default, and animation visualizes
     *        how the points are changed. Set false to disable animation, or
     *        a configuration object to set duration or easing.
     *
     * @param {boolean} [updatePoints=true]
     *        When this is true, points will be updated instead of replaced
     *        whenever possible. This occurs a) when the updated data is the
     *        same length as the existing data, b) when points are matched
     *        by their id's, or c) when points can be matched by X values.
     *        This allows updating with animation and performs better. In
     *        this case, the original array is not passed by reference. Set
     *        `false` to prevent.
     */
    Series.prototype.setData = function (data, redraw, animation, updatePoints) {
        var _a,
            _b;
        var _c,
            _d;
        if (redraw === void 0) { redraw = true; }
        var series = this,
            oldData = series.points,
            oldDataLength = (oldData && oldData.length) || 0,
            options = series.options,
            chart = series.chart,
            dataSorting = options.dataSorting,
            xAxis = series.xAxis,
            turboThreshold = options.turboThreshold,
            table = this.dataTable,
            dataColumnKeys = this.dataColumnKeys(),
            pointValKey = series.pointValKey || 'y',
            pointArrayMap = series.pointArrayMap || [],
            valueCount = pointArrayMap.length,
            keys = options.keys;
        var i,
            updatedData,
            indexOfX = 0,
            indexOfY = 1,
            copiedData;
        if (!chart.options.chart.allowMutatingData) { // #4259
            // Remove old reference
            if (options.data) {
                delete series.options.data;
            }
            if (series.userOptions.data) {
                delete series.userOptions.data;
            }
            copiedData = Series_merge(true, data);
        }
        data = copiedData || data || [];
        var dataLength = data.length;
        if (dataSorting && dataSorting.enabled) {
            data = this.sortData(data);
        }
        // First try to run Point.update which is cheaper, allows animation, and
        // keeps references to points.
        if (chart.options.chart.allowMutatingData &&
            updatePoints !== false &&
            dataLength &&
            oldDataLength &&
            !series.cropped &&
            !series.hasGroupedData &&
            series.visible &&
            // Soft updating has no benefit in boost, and causes JS error
            // (#8355)
            !series.boosted) {
            updatedData = this.updateData(data, animation);
        }
        if (!updatedData) {
            // Reset properties
            series.xIncrement = null;
            series.colorCounter = 0; // For series with colorByPoint (#1547)
            // In turbo mode, look for one- or twodimensional arrays of numbers.
            // The first and the last valid value are tested, and we assume that
            // all the rest are defined the same way. Although the 'for' loops
            // are similar, they are repeated inside each if-else conditional
            // for max performance.
            var runTurbo = turboThreshold && dataLength > turboThreshold;
            if (runTurbo) {
                var firstPoint = series.getFirstValidPoint(data),
                    lastPoint = series.getFirstValidPoint(data,
                    dataLength - 1, -1),
                    isShortArray = function (a) { return Boolean(Series_isArray(a) && (keys || Series_isNumber(a[0]))); };
                // Assume all points are numbers
                if (Series_isNumber(firstPoint) && Series_isNumber(lastPoint)) {
                    var x = [],
                        valueData = [];
                    for (var _e = 0, data_1 = data; _e < data_1.length; _e++) {
                        var value = data_1[_e];
                        x.push(this.autoIncrement());
                        valueData.push(value);
                    }
                    table.setColumns((_a = {
                            x: x
                        },
                        _a[pointValKey] = valueData,
                        _a));
                    // Assume all points are arrays when first point is
                }
                else if (isShortArray(firstPoint) &&
                    isShortArray(lastPoint)) {
                    if (valueCount) { // [x, low, high] or [x, o, h, l, c]
                        // When autoX is 1, the x is skipped: [low, high]. When
                        // autoX is 0, the x is included: [x, low, high]
                        var autoX = firstPoint.length === valueCount ?
                                1 : 0,
                            colArray_1 = new Array(dataColumnKeys.length)
                                .fill(0).map(function () { return []; });
                        for (var _f = 0, _g = data; _f < _g.length; _f++) {
                            var pt = _g[_f];
                            if (autoX) {
                                colArray_1[0].push(this.autoIncrement());
                            }
                            for (var j = autoX; j <= valueCount; j++) {
                                (_c = colArray_1[j]) === null || _c === void 0 ? void 0 : _c.push(pt[j - autoX]);
                            }
                        }
                        table.setColumns(dataColumnKeys.reduce(function (columns, columnName, i) {
                            columns[columnName] = colArray_1[i];
                            return columns;
                        }, {}));
                    }
                    else { // [x, y]
                        if (keys) {
                            indexOfX = keys.indexOf('x');
                            indexOfY = keys.indexOf('y');
                            indexOfX = indexOfX >= 0 ? indexOfX : 0;
                            indexOfY = indexOfY >= 0 ? indexOfY : 1;
                        }
                        if (firstPoint.length === 1) {
                            indexOfY = 0;
                        }
                        var xData = [],
                            valueData = [];
                        if (indexOfX === indexOfY) {
                            for (var _h = 0, data_2 = data; _h < data_2.length; _h++) {
                                var pt = data_2[_h];
                                xData.push(this.autoIncrement());
                                valueData.push(pt[indexOfY]);
                            }
                        }
                        else {
                            for (var _j = 0, data_3 = data; _j < data_3.length; _j++) {
                                var pt = data_3[_j];
                                xData.push(pt[indexOfX]);
                                valueData.push(pt[indexOfY]);
                            }
                        }
                        table.setColumns((_b = {
                                x: xData
                            },
                            _b[pointValKey] = valueData,
                            _b));
                    }
                }
                else {
                    // Highcharts expects configs to be numbers or arrays in
                    // turbo mode
                    runTurbo = false;
                }
            }
            if (!runTurbo) {
                var columns = dataColumnKeys.reduce(function (columns,
                    columnName) {
                        columns[columnName] = [];
                    return columns;
                }, {});
                for (i = 0; i < dataLength; i++) {
                    var pt = series.pointClass.prototype.applyOptions.apply({ series: series },
                        [data[i]]);
                    for (var _k = 0, dataColumnKeys_1 = dataColumnKeys; _k < dataColumnKeys_1.length; _k++) {
                        var key = dataColumnKeys_1[_k];
                        columns[key][i] = pt[key];
                    }
                }
                table.setColumns(columns);
            }
            // Forgetting to cast strings to numbers is a common caveat when
            // handling CSV or JSON
            if (Series_isString(this.getColumn('y')[0])) {
                Series_error(14, true, chart);
            }
            series.data = [];
            series.options.data = series.userOptions.data = data;
            // Destroy old points
            i = oldDataLength;
            while (i--) {
                (_d = oldData[i]) === null || _d === void 0 ? void 0 : _d.destroy();
            }
            // Reset minRange (#878)
            if (xAxis) {
                xAxis.minRange = xAxis.userMinRange;
            }
            // Redraw
            series.isDirty = chart.isDirtyBox = true;
            series.isDirtyData = !!oldData;
            animation = false;
        }
        // Typically for pie series, points need to be processed and
        // generated prior to rendering the legend
        if (options.legendType === 'point') {
            this.processData();
            this.generatePoints();
        }
        if (redraw) {
            chart.redraw(animation);
        }
    };
    /**
     * Internal function to sort series data
     *
     * @private
     * @function Highcharts.Series#sortData
     * @param {Array<Highcharts.PointOptionsType>} data
     * Force data grouping.
     */
    Series.prototype.sortData = function (data) {
        var series = this,
            options = series.options,
            dataSorting = options.dataSorting,
            sortKey = dataSorting.sortKey || 'y',
            getPointOptionsObject = function (series,
            pointOptions) {
                return (Series_defined(pointOptions) &&
                    series.pointClass.prototype.optionsToObject.call({
                        series: series
                    },
            pointOptions)) || {};
        };
        data.forEach(function (pointOptions, i) {
            data[i] = getPointOptionsObject(series, pointOptions);
            data[i].index = i;
        }, this);
        // Sorting
        var sortedData = data.concat().sort(function (a,
            b) {
                var aValue = Series_getNestedProperty(sortKey,
            a);
            var bValue = Series_getNestedProperty(sortKey,
                b);
            return bValue < aValue ? -1 : bValue > aValue ? 1 : 0;
        });
        // Set x value depending on the position in the array
        sortedData.forEach(function (point, i) {
            point.x = i;
        }, this);
        // Set the same x for linked series points if they don't have their
        // own sorting
        if (series.linkedSeries) {
            series.linkedSeries.forEach(function (linkedSeries) {
                var options = linkedSeries.options,
                    seriesData = options.data;
                if ((!options.dataSorting ||
                    !options.dataSorting.enabled) &&
                    seriesData) {
                    seriesData.forEach(function (pointOptions, i) {
                        seriesData[i] = getPointOptionsObject(linkedSeries, pointOptions);
                        if (data[i]) {
                            seriesData[i].x = data[i].x;
                            seriesData[i].index = i;
                        }
                    });
                    linkedSeries.setData(seriesData, false);
                }
            });
        }
        return data;
    };
    /**
     * Internal function to process the data by cropping away unused data
     * points if the series is longer than the crop threshold. This saves
     * computing time for large series.
     *
     * @private
     * @function Highcharts.Series#getProcessedData
     * @param {boolean} [forceExtremesFromAll]
     * Force getting extremes of a total series data range.
     */
    Series.prototype.getProcessedData = function (forceExtremesFromAll) {
        var series = this,
            table = series.dataTable,
            isCartesian = series.isCartesian,
            options = series.options,
            xAxis = series.xAxis,
            cropThreshold = options.cropThreshold,
            getExtremesFromAll = forceExtremesFromAll ||
                // X-range series etc, #21003
                series.getExtremesFromAll,
            logarithmic = xAxis === null || xAxis === void 0 ? void 0 : xAxis.logarithmic,
            dataLength = table.rowCount;
        var croppedData,
            cropped,
            cropStart = 0,
            xExtremes,
            min,
            max,
            xData = series.getColumn('x'),
            modified = table,
            updatingNames = false;
        if (xAxis) {
            // Corrected for log axis (#3053)
            xExtremes = xAxis.getExtremes();
            min = xExtremes.min;
            max = xExtremes.max;
            updatingNames = !!(xAxis.categories && !xAxis.names.length);
            // Optionally filter out points outside the plot area
            if (isCartesian &&
                series.sorted &&
                !getExtremesFromAll &&
                (!cropThreshold ||
                    dataLength > cropThreshold ||
                    series.forceCrop)) {
                // It's outside current extremes
                if (xData[dataLength - 1] < min ||
                    xData[0] > max) {
                    modified = new Data_DataTableCore();
                    // Only crop if it's actually spilling out
                }
                else if (
                // Don't understand why this condition is needed
                series.getColumn(series.pointValKey || 'y').length && (xData[0] < min ||
                    xData[dataLength - 1] > max)) {
                    croppedData = this.cropData(table, min, max);
                    modified = croppedData.modified;
                    cropStart = croppedData.start;
                    cropped = true;
                }
            }
        }
        // Find the closest distance between processed points
        xData = modified.getColumn('x') || [];
        var closestPointRange = Series_getClosestDistance([
                logarithmic ?
                    xData.map(logarithmic.log2lin) :
                    xData
            ], 
            // Unsorted data is not supported by the line tooltip, as well as
            // data grouping and navigation in Stock charts (#725) and width
            // calculation of columns (#1900). Avoid warning during the
            // premature processing pass in updateNames (#16104).
            function () { return (series.requireSorting &&
                !updatingNames &&
                Series_error(15,
            false,
            series.chart)); });
        return {
            modified: modified,
            cropped: cropped,
            cropStart: cropStart,
            closestPointRange: closestPointRange
        };
    };
    /**
     * Internal function to apply processed data.
     * In Highcharts Stock, this function is extended to provide data grouping.
     *
     * @private
     * @function Highcharts.Series#processData
     * @param {boolean} [force]
     * Force data grouping.
     */
    Series.prototype.processData = function (force) {
        var series = this,
            xAxis = series.xAxis,
            table = series.dataTable;
        // If the series data or axes haven't changed, don't go through
        // this. Return false to pass the message on to override methods
        // like in data grouping.
        if (series.isCartesian &&
            !series.isDirty &&
            !xAxis.isDirty &&
            !series.yAxis.isDirty &&
            !force) {
            return false;
        }
        var processedData = series.getProcessedData();
        // Record the properties
        table.modified = processedData.modified;
        series.cropped = processedData.cropped; // Undefined or true
        series.cropStart = processedData.cropStart;
        series.closestPointRange = (series.basePointRange = processedData.closestPointRange);
        Series_fireEvent(series, 'afterProcessData');
    };
    /**
     * Iterate over xData and crop values between min and max. Returns
     * object containing crop start/end cropped xData with corresponding
     * part of yData, dataMin and dataMax within the cropped range.
     *
     * @private
     * @function Highcharts.Series#cropData
     */
    Series.prototype.cropData = function (table, min, max) {
        var xData = table.getColumn('x',
            true) || [],
            dataLength = xData.length,
            columns = {};
        var i,
            j,
            start = 0,
            end = dataLength;
        // Iterate up to find slice start
        for (i = 0; i < dataLength; i++) {
            if (xData[i] >= min) {
                start = Math.max(0, i - 1);
                break;
            }
        }
        // Proceed to find slice end
        for (j = i; j < dataLength; j++) {
            if (xData[j] > max) {
                end = j + 1;
                break;
            }
        }
        for (var _a = 0, _b = this.dataColumnKeys(); _a < _b.length; _a++) {
            var key = _b[_a];
            var column = table.getColumn(key,
                true);
            if (column) {
                columns[key] = column.slice(start, end);
            }
        }
        return {
            modified: new Data_DataTableCore({ columns: columns }),
            start: start,
            end: end
        };
    };
    /**
     * Generate the data point after the data has been processed by cropping
     * away unused points and optionally grouped in Highcharts Stock.
     *
     * @private
     * @function Highcharts.Series#generatePoints
     */
    Series.prototype.generatePoints = function () {
        var _a,
            _b,
            _c,
            _d;
        var series = this,
            options = series.options,
            dataOptions = series.processedData || options.data,
            table = series.dataTable.modified,
            xData = series.getColumn('x',
            true),
            PointClass = series.pointClass,
            processedDataLength = table.rowCount,
            cropStart = series.cropStart || 0,
            hasGroupedData = series.hasGroupedData,
            keys = options.keys,
            points = [],
            groupCropStartIndex = (options.dataGrouping &&
                options.dataGrouping.groupAll ?
                cropStart :
                0),
            categories = (_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.categories,
            pointArrayMap = series.pointArrayMap || ['y'], 
            // Create a configuration object out of a data row
            dataColumnKeys = this.dataColumnKeys();
        var dataLength,
            cursor,
            point,
            i,
            data = series.data,
            pOptions;
        if (!data && !hasGroupedData) {
            var arr = [];
            arr.length = (dataOptions === null || dataOptions === void 0 ? void 0 : dataOptions.length) || 0;
            data = series.data = arr;
        }
        if (keys && hasGroupedData) {
            // Grouped data has already applied keys (#6590)
            series.options.keys = false;
        }
        for (i = 0; i < processedDataLength; i++) {
            cursor = cropStart + i;
            if (!hasGroupedData) {
                point = data[cursor];
                pOptions = dataOptions ?
                    dataOptions[cursor] :
                    table.getRow(i, pointArrayMap);
                // #970:
                if (!point &&
                    pOptions !== void 0) {
                    data[cursor] = point = new PointClass(series, pOptions, xData[i]);
                }
            }
            else {
                // Splat the y data in case of ohlc data array
                point = new PointClass(series, table.getRow(i, dataColumnKeys) || []);
                point.dataGroup = series.groupMap[groupCropStartIndex + i];
                if ((_b = point.dataGroup) === null || _b === void 0 ? void 0 : _b.options) {
                    point.options = point.dataGroup.options;
                    Series_extend(point, point.dataGroup.options);
                    // Collision of props and options (#9770)
                    delete point.dataLabels;
                }
            }
            if (point) { // #6279
                /**
                 * Contains the point's index in the `Series.points` array.
                 *
                 * @name Highcharts.Point#index
                 * @type {number}
                 * @readonly
                 */
                // For faster access in Point.update
                point.index = hasGroupedData ?
                    (groupCropStartIndex + i) : cursor;
                points[i] = point;
                // Set point properties for convenient access in tooltip and
                // data labels
                point.category = (_c = categories === null || categories === void 0 ? void 0 : categories[point.x]) !== null && _c !== void 0 ? _c : point.x;
                point.key = (_d = point.name) !== null && _d !== void 0 ? _d : point.category;
            }
        }
        // Restore keys options (#6590)
        series.options.keys = keys;
        // Hide cropped-away points - this only runs when the number of
        // points is above cropThreshold, or when switching view from
        // non-grouped data to grouped data (#637)
        if (data &&
            (processedDataLength !== (dataLength = data.length) ||
                hasGroupedData)) {
            for (i = 0; i < dataLength; i++) {
                // When has grouped data, clear all points
                if (i === cropStart && !hasGroupedData) {
                    i += processedDataLength;
                }
                if (data[i]) {
                    data[i].destroyElements();
                    data[i].plotX = void 0; // #1003
                }
            }
        }
        /**
         * Read only. An array containing those values converted to points.
         * In case the series data length exceeds the `cropThreshold`, or if
         * the data is grouped, `series.data` doesn't contain all the
         * points. Also, in case a series is hidden, the `data` array may be
         * empty. In case of cropping, the `data` array may contain `undefined`
         * values, instead of points. To access raw values,
         * `series.options.data` will always be up to date. `Series.data` only
         * contains the points that have been created on demand. To modify the
         * data, use
         * {@link Highcharts.Series#setData} or
         * {@link Highcharts.Point#update}.
         *
         * @see Series.points
         *
         * @name Highcharts.Series#data
         * @type {Array<Highcharts.Point>}
         */
        series.data = data;
        /**
         * An array containing all currently visible point objects. In case
         * of cropping, the cropped-away points are not part of this array.
         * The `series.points` array starts at `series.cropStart` compared
         * to `series.data` and `series.options.data`. If however the series
         * data is grouped, these can't be correlated one to one. To modify
         * the data, use {@link Highcharts.Series#setData} or
         * {@link Highcharts.Point#update}.
         *
         * @name Highcharts.Series#points
         * @type {Array<Highcharts.Point>}
         */
        series.points = points;
        Series_fireEvent(this, 'afterGeneratePoints');
    };
    /**
     * Get current X extremes for the visible data.
     *
     * @private
     * @function Highcharts.Series#getXExtremes
     * @param {Array<number>} xData
     * The data to inspect. Defaults to the current data within the visible
     * range.
     */
    Series.prototype.getXExtremes = function (xData) {
        return {
            min: Series_arrayMin(xData),
            max: Series_arrayMax(xData)
        };
    };
    /**
     * Calculate Y extremes for the visible data. The result is returned
     * as an object with `dataMin` and `dataMax` properties.
     *
     * @private
     * @function Highcharts.Series#getExtremes
     * @param {Array<number>} [yData]
     * The data to inspect. Defaults to the current data within the visible
     * range.
     * @param {boolean} [forceExtremesFromAll]
     * Force getting extremes of a total series data range.
     */
    Series.prototype.getExtremes = function (yData, forceExtremesFromAll) {
        var _a;
        var _b = this, xAxis = _b.xAxis, yAxis = _b.yAxis, getExtremesFromAll = forceExtremesFromAll ||
                this.getExtremesFromAll ||
                this.options.getExtremesFromAll, // #4599, #21003
            table = getExtremesFromAll && this.cropped ?
                this.dataTable :
                this.dataTable.modified, rowCount = table.rowCount, customData = yData || this.stackedYData, yAxisData = customData ?
                [customData] :
                ((_a = (this.keysAffectYAxis || this.pointArrayMap || ['y'])) === null || _a === void 0 ? void 0 : _a.map(function (key) { return table.getColumn(key, true) || []; })) || [], xData = this.getColumn('x', true), activeYData = [], 
            // Handle X outside the viewed area. This does not work with
            // non-sorted data like scatter (#7639).
            shoulder = this.requireSorting && !this.is('column') ?
                1 : 0, 
            // #2117, need to compensate for log X axis
            positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false, doAll = getExtremesFromAll ||
                this.cropped ||
                !xAxis; // For colorAxis support
            var xExtremes, x, i, xMin = 0, xMax = 0;
        if (xAxis) {
            xExtremes = xAxis.getExtremes();
            xMin = xExtremes.min;
            xMax = xExtremes.max;
        }
        for (i = 0; i < rowCount; i++) {
            x = xData[i];
            // Check if it is within the selected x axis range
            if (doAll ||
                ((xData[i + shoulder] || x) >= xMin &&
                    (xData[i - shoulder] || x) <= xMax)) {
                for (var _c = 0, yAxisData_1 = yAxisData; _c < yAxisData_1.length; _c++) {
                    var values = yAxisData_1[_c];
                    var val = values[i];
                    // For points within the visible range, including the
                    // first point outside the visible range (#7061),
                    // consider y extremes.
                    if (Series_isNumber(val) &&
                        (val > 0 || !positiveValuesOnly)) {
                        activeYData.push(val);
                    }
                }
            }
        }
        var dataExtremes = {
                activeYData: activeYData, // Needed for Stock Cumulative Sum
                dataMin: Series_arrayMin(activeYData),
                dataMax: Series_arrayMax(activeYData)
            };
        Series_fireEvent(this, 'afterGetExtremes', { dataExtremes: dataExtremes });
        return dataExtremes;
    };
    /**
     * Set the current data extremes as `dataMin` and `dataMax` on the
     * Series item. Use this only when the series properties should be
     * updated.
     *
     * @private
     * @function Highcharts.Series#applyExtremes
     */
    Series.prototype.applyExtremes = function () {
        var dataExtremes = this.getExtremes();
        /**
         * Contains the minimum value of the series' data point. Some series
         * types like `networkgraph` do not support this property as they
         * lack a `y`-value.
         * @name Highcharts.Series#dataMin
         * @type {number|undefined}
         * @readonly
         */
        this.dataMin = dataExtremes.dataMin;
        /**
         * Contains the maximum value of the series' data point. Some series
         * types like `networkgraph` do not support this property as they
         * lack a `y`-value.
         * @name Highcharts.Series#dataMax
         * @type {number|undefined}
         * @readonly
         */
        this.dataMax = dataExtremes.dataMax;
        return dataExtremes;
    };
    /**
     * Find and return the first non nullish point in the data
     *
     * @private
     * @function Highcharts.Series.getFirstValidPoint
     * @param {Array<Highcharts.PointOptionsType>} data
     *        Array of options for points
     * @param {number} [start=0]
     *        Index to start searching from
     * @param {number} [increment=1]
     *        Index increment, set -1 to search backwards
     */
    Series.prototype.getFirstValidPoint = function (data, start, increment) {
        if (start === void 0) { start = 0; }
        if (increment === void 0) { increment = 1; }
        var dataLength = data.length;
        var i = start;
        while (i >= 0 && i < dataLength) {
            if (Series_defined(data[i])) {
                return data[i];
            }
            i += increment;
        }
    };
    /**
     * Translate data points from raw data values to chart specific
     * positioning data needed later in the `drawPoints` and `drawGraph`
     * functions. This function can be overridden in plugins and custom
     * series type implementations.
     *
     * @function Highcharts.Series#translate
     *
     * @emits Highcharts.Series#events:translate
     */
    Series.prototype.translate = function () {
        var _a;
        this.generatePoints();
        var series = this,
            options = series.options,
            stacking = options.stacking,
            xAxis = series.xAxis,
            enabledDataSorting = series.enabledDataSorting,
            yAxis = series.yAxis,
            points = series.points,
            dataLength = points.length,
            pointPlacement = series.pointPlacementToXValue(), // #7860
            dynamicallyPlaced = Boolean(pointPlacement),
            threshold = options.threshold,
            stackThreshold = options.startFromThreshold ? threshold : 0;
        var i,
            plotX,
            lastPlotX,
            stackIndicator,
            closestPointRangePx = Number.MAX_VALUE;
        /**
         * Plotted coordinates need to be within a limited range. Drawing
         * too far outside the viewport causes various rendering issues
         * (#3201, #3923, #7555).
         * @private
         */
        function limitedRange(val) {
            return Series_clamp(val, -1e9, 1e9);
        }
        // Translate each point
        for (i = 0; i < dataLength; i++) {
            var point = points[i],
                xValue = point.x;
            var stackItem = void 0,
                stackValues = void 0,
                yValue = point.y,
                lowValue = point.low;
            var stacks = stacking && ((_a = yAxis.stacking) === null || _a === void 0 ? void 0 : _a.stacks[(series.negStacks &&
                    yValue <
                        (stackThreshold ? 0 : threshold) ?
                    '-' :
                    '') + series.stackKey]);
            plotX = xAxis.translate(// #3923
            xValue, false, false, false, true, pointPlacement);
            /**
             * The translated X value for the point in terms of pixels. Relative
             * to the X axis position if the series has one, otherwise relative
             * to the plot area. Depending on the series type this value might
             * not be defined.
             *
             * In an inverted chart the x-axis is going from the bottom to the
             * top so the `plotX` value is the number of pixels from the bottom
             * of the axis.
             *
             * @see Highcharts.Point#pos
             * @name Highcharts.Point#plotX
             * @type {number|undefined}
             */
            point.plotX = Series_isNumber(plotX) ? Series_correctFloat(// #5236
            limitedRange(plotX) // #3923
            ) : void 0;
            // Calculate the bottom y value for stacked series
            if (stacking &&
                series.visible &&
                stacks &&
                stacks[xValue]) {
                stackIndicator = series.getStackIndicator(stackIndicator, xValue, series.index);
                if (!point.isNull && stackIndicator.key) {
                    stackItem = stacks[xValue];
                    stackValues = stackItem.points[stackIndicator.key];
                }
                if (stackItem && Series_isArray(stackValues)) {
                    lowValue = stackValues[0];
                    yValue = stackValues[1];
                    if (lowValue === stackThreshold &&
                        stackIndicator.key === stacks[xValue].base) {
                        lowValue = Series_pick(Series_isNumber(threshold) ? threshold : yAxis.min);
                    }
                    // #1200, #1232
                    if (yAxis.positiveValuesOnly &&
                        Series_defined(lowValue) &&
                        lowValue <= 0) {
                        lowValue = void 0;
                    }
                    point.total = point.stackTotal = Series_pick(stackItem.total);
                    point.percentage = Series_defined(point.y) && stackItem.total ?
                        (point.y / stackItem.total * 100) : void 0;
                    point.stackY = yValue;
                    // In case of variwide series (where widths of points are
                    // different in most cases), stack labels are positioned
                    // wrongly, so the call of the setOffset is omitted here and
                    // labels are correctly positioned later, at the end of the
                    // variwide's translate function (#10962)
                    if (!series.irregularWidths) {
                        stackItem.setOffset(series.pointXOffset || 0, series.barW || 0, void 0, void 0, void 0, series.xAxis);
                    }
                }
            }
            // Set translated yBottom or remove it
            point.yBottom = Series_defined(lowValue) ?
                limitedRange(yAxis.translate(lowValue, false, true, false, true)) :
                void 0;
            // General hook, used for Highcharts Stock compare and cumulative
            if (series.dataModify) {
                yValue = series.dataModify.modifyValue(yValue, i);
            }
            // Set the plotY value, reset it for redraws #3201, #18422
            var plotY = void 0;
            if (Series_isNumber(yValue) && point.plotX !== void 0) {
                plotY = yAxis.translate(yValue, false, true, false, true);
                plotY = Series_isNumber(plotY) ? limitedRange(plotY) : void 0;
            }
            /**
             * The translated Y value for the point in terms of pixels. Relative
             * to the Y axis position if the series has one, otherwise relative
             * to the plot area. Depending on the series type this value might
             * not be defined.
             *
             * In an inverted chart the y-axis is going from right to left
             * so the `plotY` value is the number of pixels from the right
             * of the `yAxis`.
             *
             * @see Highcharts.Point#pos
             * @name Highcharts.Point#plotY
             * @type {number|undefined}
             */
            point.plotY = plotY;
            point.isInside = this.isPointInside(point);
            // Set client related positions for mouse tracking
            point.clientX = dynamicallyPlaced ?
                Series_correctFloat(xAxis.translate(xValue, false, false, false, true, pointPlacement)) :
                plotX; // #1514, #5383, #5518
            // Negative points #19028
            point.negative = (point.y || 0) < (threshold || 0);
            // Determine auto enabling of markers (#3635, #5099)
            if (!point.isNull && point.visible !== false) {
                if (typeof lastPlotX !== 'undefined') {
                    closestPointRangePx = Math.min(closestPointRangePx, Math.abs(plotX - lastPlotX));
                }
                lastPlotX = plotX;
            }
            // Find point zone
            point.zone = this.zones.length ? point.getZone() : void 0;
            // Animate new points with data sorting
            if (!point.graphic && series.group && enabledDataSorting) {
                point.isNew = true;
            }
        }
        series.closestPointRangePx = closestPointRangePx;
        Series_fireEvent(this, 'afterTranslate');
    };
    /**
     * Return the series points with null points filtered out.
     *
     * @function Highcharts.Series#getValidPoints
     *
     * @param {Array<Highcharts.Point>} [points]
     * The points to inspect, defaults to {@link Series.points}.
     *
     * @param {boolean} [insideOnly=false]
     * Whether to inspect only the points that are inside the visible view.
     *
     * @param {boolean} [allowNull=false]
     * Whether to allow null points to pass as valid points.
     *
     * @return {Array<Highcharts.Point>}
     * The valid points.
     */
    Series.prototype.getValidPoints = function (points, insideOnly, allowNull) {
        var chart = this.chart;
        // #3916, #5029, #5085
        return (points || this.points || []).filter(function (point) {
            var plotX = point.plotX,
                plotY = point.plotY, 
                // Undefined plotY is treated as null when negative values
                // in log axis (#18422)
                asNull = !allowNull && (point.isNull || !Series_isNumber(plotY));
            if (asNull || (insideOnly && !chart.isInsidePlot(plotX, plotY, { inverted: chart.inverted }))) {
                return false;
            }
            return point.visible !== false;
        });
    };
    /**
     * Get the clipping for the series. Could be called for a series to
     * initiate animating the clip or to set the final clip (only width
     * and x).
     *
     * @private
     * @function Highcharts.Series#getClip
     */
    Series.prototype.getClipBox = function () {
        var _a;
        var _b = this,
            chart = _b.chart,
            xAxis = _b.xAxis,
            yAxis = _b.yAxis;
        // If no axes on the series, use global clipBox
        var _c = Series_merge(chart.clipBox),
            x = _c.x,
            y = _c.y,
            width = _c.width,
            height = _c.height;
        // Otherwise, use clipBox.width which is corrected for plotBorderWidth
        // and clipOffset
        if (xAxis && xAxis.len !== chart.plotSizeX) {
            width = xAxis.len;
        }
        if (yAxis && yAxis.len !== chart.plotSizeY) {
            height = yAxis.len;
        }
        // If the chart is inverted and the series is not invertible, the chart
        // clip box should be inverted, but not the series clip box (#20264)
        if (chart.inverted && !this.invertible) {
            _a = [height, width], width = _a[0], height = _a[1];
        }
        return { x: x, y: y, width: width, height: height };
    };
    /**
     * Get the shared clip key, creating it if it doesn't exist.
     *
     * @private
     * @function Highcharts.Series#getSharedClipKey
     */
    Series.prototype.getSharedClipKey = function () {
        this.sharedClipKey = (this.options.xAxis || 0) + ',' +
            (this.options.yAxis || 0);
        return this.sharedClipKey;
    };
    /**
     * Set the clipping for the series. For animated series the clip is later
     * modified.
     *
     * @private
     * @function Highcharts.Series#setClip
     */
    Series.prototype.setClip = function () {
        var _a = this,
            chart = _a.chart,
            group = _a.group,
            markerGroup = _a.markerGroup,
            sharedClips = chart.sharedClips,
            renderer = chart.renderer,
            clipBox = this.getClipBox(),
            sharedClipKey = this.getSharedClipKey(); // #4526
            var clipRect = sharedClips[sharedClipKey];
        // If a clipping rectangle for the same set of axes does not exist,
        // create it
        if (!clipRect) {
            sharedClips[sharedClipKey] = clipRect = renderer.clipRect(clipBox);
            // When setting chart size, or when the series is rendered again before
            // starting animating, in compliance to a responsive rule
        }
        else {
            clipRect.animate(clipBox);
        }
        if (group) {
            // When clip is false, reset to no clip after animation
            group.clip(this.options.clip === false ? void 0 : clipRect);
        }
        // Unclip temporary animation clip
        if (markerGroup) {
            markerGroup.clip();
        }
    };
    /**
     * Animate in the series. Called internally twice. First with the `init`
     * parameter set to true, which sets up the initial state of the
     * animation. Then when ready, it is called with the `init` parameter
     * undefined, in order to perform the actual animation.
     *
     * @function Highcharts.Series#animate
     *
     * @param {boolean} [init]
     * Initialize the animation.
     */
    Series.prototype.animate = function (init) {
        var _a = this, chart = _a.chart, group = _a.group, markerGroup = _a.markerGroup, inverted = chart.inverted, animation = Series_animObject(this.options.animation), 
            // The key for temporary animation clips
            animationClipKey = [
                this.getSharedClipKey(),
                animation.duration,
                animation.easing,
                animation.defer
            ].join(',');
        var animationClipRect = chart.sharedClips[animationClipKey],
            markerAnimationClipRect = chart.sharedClips[animationClipKey + 'm'];
        // Initialize the animation. Set up the clipping rectangle.
        if (init && group) {
            var clipBox = this.getClipBox();
            // Create temporary animation clips
            if (!animationClipRect) {
                clipBox.width = 0;
                if (inverted) {
                    clipBox.x = chart.plotHeight;
                }
                animationClipRect = chart.renderer.clipRect(clipBox);
                chart.sharedClips[animationClipKey] = animationClipRect;
                // The marker clip box. The number 99 is a safe margin to avoid
                // markers being clipped during animation.
                var markerClipBox = {
                        x: inverted ? -99 : -99,
                        y: inverted ? -99 : -99,
                        width: inverted ? chart.plotWidth + 199 : 99,
                        height: inverted ? 99 : chart.plotHeight + 199
                    };
                markerAnimationClipRect = chart.renderer.clipRect(markerClipBox);
                chart.sharedClips[animationClipKey + 'm'] = markerAnimationClipRect;
            }
            else {
                // When height changes during animation, typically due to
                // responsive settings
                animationClipRect.attr('height', clipBox.height);
            }
            group.clip(animationClipRect);
            markerGroup === null || markerGroup === void 0 ? void 0 : markerGroup.clip(markerAnimationClipRect);
            // Run the animation
        }
        else if (animationClipRect &&
            // Only first series in this pane
            !animationClipRect.hasClass('highcharts-animating')) {
            var finalBox = this.getClipBox(),
                step_1 = animation.step;
            // Only do this when there are actually markers, or we have multiple
            // series (#20473)
            if ((markerGroup === null || markerGroup === void 0 ? void 0 : markerGroup.element.childNodes.length) ||
                chart.series.length > 1) {
                // To provide as smooth animation as possible, update the marker
                // group clipping in steps of the main group animation
                animation.step = function (val, fx) {
                    if (step_1) {
                        step_1.apply(fx, arguments);
                    }
                    if (fx.prop === 'width' &&
                        (markerAnimationClipRect === null || markerAnimationClipRect === void 0 ? void 0 : markerAnimationClipRect.element)) {
                        markerAnimationClipRect.attr(inverted ? 'height' : 'width', val + 99);
                    }
                };
            }
            animationClipRect
                .addClass('highcharts-animating')
                .animate(finalBox, animation);
        }
    };
    /**
     * This runs after animation to land on the final plot clipping.
     *
     * @private
     * @function Highcharts.Series#afterAnimate
     *
     * @emits Highcharts.Series#event:afterAnimate
     */
    Series.prototype.afterAnimate = function () {
        var _this = this;
        this.setClip();
        // Destroy temporary clip rectangles that are no longer in use
        Series_objectEach(this.chart.sharedClips, function (clip, key, sharedClips) {
            if (clip && !_this.chart.container.querySelector("[clip-path=\"url(#".concat(clip.id, ")\"]"))) {
                clip.destroy();
                delete sharedClips[key];
            }
        });
        this.finishedAnimating = true;
        Series_fireEvent(this, 'afterAnimate');
    };
    /**
     * Draw the markers for line-like series types, and columns or other
     * graphical representation for {@link Point} objects for other series
     * types. The resulting element is typically stored as
     * {@link Point.graphic}, and is created on the first call and updated
     * and moved on subsequent calls.
     *
     * @function Highcharts.Series#drawPoints
     */
    Series.prototype.drawPoints = function (points) {
        if (points === void 0) { points = this.points; }
        var series = this,
            chart = series.chart,
            styledMode = chart.styledMode,
            colorAxis = series.colorAxis,
            options = series.options,
            seriesMarkerOptions = options.marker,
            markerGroup = series[series.specialGroup || 'markerGroup'],
            xAxis = series.xAxis,
            globallyEnabled = Series_pick(seriesMarkerOptions.enabled, !xAxis || xAxis.isRadial ? true : null, 
            // Use larger or equal as radius is null in bubbles (#6321)
            series.closestPointRangePx >= (seriesMarkerOptions.enabledThreshold *
                seriesMarkerOptions.radius));
        var i,
            point,
            graphic,
            verb,
            pointMarkerOptions,
            hasPointMarker,
            markerAttribs;
        if (seriesMarkerOptions.enabled !== false ||
            series._hasPointMarkers) {
            for (i = 0; i < points.length; i++) {
                point = points[i];
                graphic = point.graphic;
                verb = graphic ? 'animate' : 'attr';
                pointMarkerOptions = point.marker || {};
                hasPointMarker = !!point.marker;
                var shouldDrawMarker = ((globallyEnabled &&
                        typeof pointMarkerOptions.enabled === 'undefined') || pointMarkerOptions.enabled) && !point.isNull && point.visible !== false;
                // Only draw the point if y is defined
                if (shouldDrawMarker) {
                    // Shortcuts
                    var symbol = Series_pick(pointMarkerOptions.symbol,
                        series.symbol, 'rect');
                    markerAttribs = series.markerAttribs(point, (point.selected && 'select'));
                    // Set starting position for point sliding animation.
                    if (series.enabledDataSorting) {
                        point.startXPos = xAxis.reversed ?
                            -(markerAttribs.width || 0) :
                            xAxis.width;
                    }
                    var isInside = point.isInside !== false;
                    if (!graphic &&
                        isInside &&
                        ((markerAttribs.width || 0) > 0 || point.hasImage)) {
                        /**
                         * SVG graphic representing the point in the chart. In
                         * some cases it may be a hidden graphic to improve
                         * accessibility.
                         *
                         * Typically this is a simple shape, like a `rect`
                         * for column charts or `path` for line markers, but
                         * for some complex series types like boxplot or 3D
                         * charts, the graphic may be a `g` element
                         * containing other shapes. The graphic is generated
                         * the first time {@link Series#drawPoints} runs,
                         * and updated and moved on subsequent runs.
                         *
                         * @see Highcharts.Point#graphics
                         *
                         * @name Highcharts.Point#graphic
                         * @type {Highcharts.SVGElement|undefined}
                         */
                        point.graphic = graphic = chart.renderer
                            .symbol(symbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, hasPointMarker ?
                            pointMarkerOptions :
                            seriesMarkerOptions)
                            .add(markerGroup);
                        // Sliding animation for new points
                        if (series.enabledDataSorting &&
                            chart.hasRendered) {
                            graphic.attr({
                                x: point.startXPos
                            });
                            verb = 'animate';
                        }
                    }
                    if (graphic && verb === 'animate') { // Update
                        // Since the marker group isn't clipped, each
                        // individual marker must be toggled
                        graphic[isInside ? 'show' : 'hide'](isInside)
                            .animate(markerAttribs);
                    }
                    // Presentational attributes
                    if (graphic) {
                        var pointAttr = series.pointAttribs(point, ((styledMode || !point.selected) ?
                                void 0 :
                                'select'));
                        if (!styledMode) {
                            graphic[verb](pointAttr);
                        }
                        else if (colorAxis) { // #14114
                            graphic['css']({
                                fill: pointAttr.fill
                            });
                        }
                    }
                    if (graphic) {
                        graphic.addClass(point.getClassName(), true);
                    }
                }
                else if (graphic) {
                    point.graphic = graphic.destroy(); // #1269
                }
            }
        }
    };
    /**
     * Get non-presentational attributes for a point. Used internally for
     * both styled mode and classic. Can be overridden for different series
     * types.
     *
     * @see Series#pointAttribs
     *
     * @function Highcharts.Series#markerAttribs
     *
     * @param {Highcharts.Point} point
     * The Point to inspect.
     *
     * @param {string} [state]
     * The state, can be either `hover`, `select` or undefined.
     *
     * @return {Highcharts.SVGAttributes}
     * A hash containing those attributes that are not settable from CSS.
     */
    Series.prototype.markerAttribs = function (point, state) {
        var seriesOptions = this.options,
            seriesMarkerOptions = seriesOptions.marker,
            pointMarkerOptions = point.marker || {},
            symbol = (pointMarkerOptions.symbol ||
                seriesMarkerOptions.symbol),
            attribs = {};
        var seriesStateOptions,
            pointStateOptions,
            radius = Series_pick(pointMarkerOptions.radius,
            seriesMarkerOptions && seriesMarkerOptions.radius);
        // Handle hover and select states
        if (state) {
            seriesStateOptions = seriesMarkerOptions.states[state];
            pointStateOptions = pointMarkerOptions.states &&
                pointMarkerOptions.states[state];
            radius = Series_pick(pointStateOptions && pointStateOptions.radius, seriesStateOptions && seriesStateOptions.radius, radius && radius + (seriesStateOptions && seriesStateOptions.radiusPlus ||
                0));
        }
        point.hasImage = symbol && symbol.indexOf('url') === 0;
        if (point.hasImage) {
            radius = 0; // And subsequently width and height is not set
        }
        var pos = point.pos();
        if (Series_isNumber(radius) && pos) {
            if (seriesOptions.crisp) {
                pos[0] = Series_crisp(pos[0], point.hasImage ?
                    0 :
                    symbol === 'rect' ?
                        // Rectangle symbols need crisp edges, others don't
                        (seriesMarkerOptions === null || seriesMarkerOptions === void 0 ? void 0 : seriesMarkerOptions.lineWidth) || 0 :
                        1);
            }
            attribs.x = pos[0] - radius;
            attribs.y = pos[1] - radius;
        }
        if (radius) {
            attribs.width = attribs.height = 2 * radius;
        }
        return attribs;
    };
    /**
     * Internal function to get presentational attributes for each point.
     * Unlike {@link Series#markerAttribs}, this function should return
     * those attributes that can also be set in CSS. In styled mode,
     * `pointAttribs` won't be called.
     *
     * @private
     * @function Highcharts.Series#pointAttribs
     *
     * @param {Highcharts.Point} [point]
     * The point instance to inspect.
     *
     * @param {string} [state]
     * The point state, can be either `hover`, `select` or 'normal'. If
     * undefined, normal state is assumed.
     *
     * @return {Highcharts.SVGAttributes}
     * The presentational attributes to be set on the point.
     */
    Series.prototype.pointAttribs = function (point, state) {
        var seriesMarkerOptions = this.options.marker,
            pointOptions = point && point.options,
            pointMarkerOptions = ((pointOptions && pointOptions.marker) || {}),
            pointColorOption = pointOptions && pointOptions.color,
            pointColor = point && point.color,
            zoneColor = point && point.zone && point.zone.color;
        var seriesStateOptions,
            pointStateOptions,
            color = this.color,
            fill,
            stroke,
            strokeWidth = Series_pick(pointMarkerOptions.lineWidth,
            seriesMarkerOptions.lineWidth),
            opacity = 1;
        color = (pointColorOption ||
            zoneColor ||
            pointColor ||
            color);
        fill = (pointMarkerOptions.fillColor ||
            seriesMarkerOptions.fillColor ||
            color);
        stroke = (pointMarkerOptions.lineColor ||
            seriesMarkerOptions.lineColor ||
            color);
        // Handle hover and select states
        state = state || 'normal';
        if (state) {
            seriesStateOptions = (seriesMarkerOptions.states[state] || {});
            pointStateOptions = (pointMarkerOptions.states &&
                pointMarkerOptions.states[state]) || {};
            strokeWidth = Series_pick(pointStateOptions.lineWidth, seriesStateOptions.lineWidth, strokeWidth + Series_pick(pointStateOptions.lineWidthPlus, seriesStateOptions.lineWidthPlus, 0));
            fill = (pointStateOptions.fillColor ||
                seriesStateOptions.fillColor ||
                fill);
            stroke = (pointStateOptions.lineColor ||
                seriesStateOptions.lineColor ||
                stroke);
            opacity = Series_pick(pointStateOptions.opacity, seriesStateOptions.opacity, opacity);
        }
        return {
            'stroke': stroke,
            'stroke-width': strokeWidth,
            'fill': fill,
            'opacity': opacity
        };
    };
    /**
     * Clear DOM objects and free up memory.
     *
     * @private
     * @function Highcharts.Series#destroy
     *
     * @emits Highcharts.Series#event:destroy
     */
    Series.prototype.destroy = function (keepEventsForUpdate) {
        var series = this, chart = series.chart, issue134 = /AppleWebKit\/533/.test(Series_win.navigator.userAgent), data = series.data || [];
        var destroy,
            i,
            point,
            axis;
        // Add event hook
        Series_fireEvent(series, 'destroy', { keepEventsForUpdate: keepEventsForUpdate });
        // Remove events
        this.removeEvents(keepEventsForUpdate);
        // Erase from axes
        (series.axisTypes || []).forEach(function (AXIS) {
            axis = series[AXIS];
            if (axis && axis.series) {
                Series_erase(axis.series, series);
                axis.isDirty = axis.forceRedraw = true;
            }
        });
        // Remove legend items
        if (series.legendItem) {
            series.chart.legend.destroyItem(series);
        }
        // Destroy all points with their elements
        i = data.length;
        while (i--) {
            point = data[i];
            if (point && point.destroy) {
                point.destroy();
            }
        }
        for (var _a = 0, _b = series.zones; _a < _b.length; _a++) {
            var zone = _b[_a];
            // Destroy SVGElement's but preserve primitive props (#20426)
            Series_destroyObjectProperties(zone, void 0, true);
        }
        // Clear the animation timeout if we are destroying the series
        // during initial animation
        Core_Utilities.clearTimeout(series.animationTimeout);
        // Destroy all SVGElements associated to the series
        Series_objectEach(series, function (val, prop) {
            // Survive provides a hook for not destroying
            if (val instanceof SVG_SVGElement && !val.survive) {
                // Issue 134 workaround
                destroy = issue134 && prop === 'group' ?
                    'hide' :
                    'destroy';
                val[destroy]();
            }
        });
        // Remove from hoverSeries
        if (chart.hoverSeries === series) {
            chart.hoverSeries = void 0;
        }
        Series_erase(chart.series, series);
        chart.orderItems('series');
        // Clear all members
        Series_objectEach(series, function (val, prop) {
            if (!keepEventsForUpdate || prop !== 'hcEvents') {
                delete series[prop];
            }
        });
    };
    /**
     * Clip the graphs into zones for colors and styling.
     *
     * @private
     * @function Highcharts.Series#applyZones
     */
    Series.prototype.applyZones = function () {
        var series = this,
            area = series.area,
            chart = series.chart,
            graph = series.graph,
            zones = series.zones,
            points = series.points,
            xAxis = series.xAxis,
            yAxis = series.yAxis,
            zoneAxis = series.zoneAxis,
            inverted = chart.inverted,
            renderer = chart.renderer,
            axis = this["" + zoneAxis + "Axis"],
            _a = axis || {},
            isXAxis = _a.isXAxis,
            _b = _a.len,
            len = _b === void 0 ? 0 : _b,
            _c = _a.minPointOffset,
            minPointOffset = _c === void 0 ? 0 : _c,
            halfWidth = ((graph === null || graph === void 0 ? void 0 : graph.strokeWidth()) || 0) / 2 + 1, 
            // Avoid points that are so close to the threshold that the graph
            // line would be split
            avoidClose = function (zone,
            plotX,
            plotY) {
                if (plotX === void 0) { plotX = 0; }
                if (plotY === void 0) { plotY = 0; }
                if (inverted) {
                    plotY = len - plotY;
            }
            var _a = zone.translated,
                translated = _a === void 0 ? 0 : _a,
                lineClip = zone.lineClip,
                distance = plotY - translated;
            lineClip === null || lineClip === void 0 ? void 0 : lineClip.push([
                'L',
                plotX,
                Math.abs(distance) < halfWidth ?
                    plotY - halfWidth * (distance <= 0 ? -1 : 1) :
                    translated
            ]);
        };
        if (zones.length &&
            (graph || area) &&
            axis &&
            Series_isNumber(axis.min)) {
            var axisMax_1 = axis.getExtremes().max + minPointOffset, 
                // Invert the x and y coordinates of inverted charts
                invertPath_1 = function (path) {
                    path.forEach(function (segment,
                i) {
                        if (segment[0] === 'M' || segment[0] === 'L') {
                            path[i] = [
                                segment[0],
                                isXAxis ? len - segment[1] : segment[1],
                                isXAxis ? segment[2] : len - segment[2]
                            ];
                    }
                });
            };
            // Reset
            zones.forEach(function (zone) {
                zone.lineClip = [];
                zone.translated = Series_clamp(axis.toPixels(Series_pick(zone.value, axisMax_1), true) || 0, 0, len);
            });
            // The use of the Color Threshold assumes there are no gaps so it is
            // safe to hide the original graph and area unless it is not
            // waterfall series, then use showLine property to set lines between
            // columns to be visible (#7862)
            if (graph && !this.showLine) {
                graph.hide();
            }
            if (area) {
                area.hide();
            }
            // Prepare for adaptive clips, avoiding segments close to the
            // threshold (#19709)
            if (zoneAxis === 'y' &&
                // Overheat protection
                points.length < xAxis.len) {
                for (var _d = 0, points_1 = points; _d < points_1.length; _d++) {
                    var point = points_1[_d];
                    var plotX = point.plotX,
                        plotY = point.plotY,
                        zone = point.zone,
                        zoneBelow = zone && zones[zones.indexOf(zone) - 1];
                    // Close to upper boundary
                    if (zone) {
                        avoidClose(zone, plotX, plotY);
                    }
                    // Close to lower boundary
                    if (zoneBelow) {
                        avoidClose(zoneBelow, plotX, plotY);
                    }
                }
            }
            // Compute and apply the clips
            var lastLineClip_1 = [], 
                // Starting point of the first zone. Offset for category axis
                // (#22188).
                lastTranslated_1 = axis.toPixels(axis.getExtremes().min - minPointOffset,
                true);
            zones.forEach(function (zone) {
                var _a,
                    _b;
                var lineClip = zone.lineClip || [],
                    translated = Math.round(zone.translated || 0);
                if (xAxis.reversed) {
                    lineClip.reverse();
                }
                var clip = zone.clip,
                    simpleClip = zone.simpleClip,
                    x1 = 0,
                    y1 = 0,
                    x2 = xAxis.len,
                    y2 = yAxis.len;
                if (isXAxis) {
                    x1 = translated;
                    x2 = lastTranslated_1;
                }
                else {
                    y1 = translated;
                    y2 = lastTranslated_1;
                }
                // Adaptive clips
                var simplePath = [
                        ['M',
                    x1,
                    y1],
                        ['L',
                    x2,
                    y1],
                        ['L',
                    x2,
                    y2],
                        ['L',
                    x1,
                    y2],
                        ['Z']
                    ],
                    adaptivePath = Series_spreadArray(Series_spreadArray(Series_spreadArray(Series_spreadArray([
                        simplePath[0]
                    ],
                    lineClip,
                    true),
                    [
                        simplePath[1],
                        simplePath[2]
                    ],
                    false),
                    lastLineClip_1,
                    true),
                    [
                        simplePath[3],
                        simplePath[4]
                    ],
                    false);
                lastLineClip_1 = lineClip.reverse();
                lastTranslated_1 = translated;
                if (inverted) {
                    invertPath_1(adaptivePath);
                    if (area) {
                        invertPath_1(simplePath);
                    }
                }
                /* Debug clip paths
                zone.path?.destroy();
                zone.path = chart.renderer.path(adaptivePath)
                    .attr({
                        stroke: zone.color || this.color || 'gray',
                        'stroke-width': 1,
                        'dashstyle': 'Dash'
                    })
                    .add(series.group);
                // */
                if (clip) {
                    clip.animate({ d: adaptivePath });
                    simpleClip === null || simpleClip === void 0 ? void 0 : simpleClip.animate({ d: simplePath });
                }
                else {
                    clip = zone.clip = renderer.path(adaptivePath);
                    if (area) {
                        simpleClip = zone.simpleClip = renderer.path(simplePath);
                    }
                }
                // When no data, graph zone is not applied and after setData
                // clip was ignored. As a result, it should be applied each
                // time.
                if (graph) {
                    (_a = zone.graph) === null || _a === void 0 ? void 0 : _a.clip(clip);
                }
                if (area) {
                    (_b = zone.area) === null || _b === void 0 ? void 0 : _b.clip(simpleClip);
                }
            });
        }
        else if (series.visible) {
            // If zones were removed, restore graph and area
            if (graph) {
                graph.show();
            }
            if (area) {
                area.show();
            }
        }
    };
    /**
     * General abstraction for creating plot groups like series.group,
     * series.dataLabelsGroup and series.markerGroup. On subsequent calls,
     * the group will only be adjusted to the updated plot size.
     *
     * @private
     * @function Highcharts.Series#plotGroup
     */
    Series.prototype.plotGroup = function (prop, name, visibility, zIndex, parent) {
        var group = this[prop];
        var isNew = !group,
            attrs = {
                visibility: visibility,
                zIndex: zIndex || 0.1 // Pointer logic uses this
            };
        // Avoid setting undefined opacity, or in styled mode
        if (Series_defined(this.opacity) &&
            !this.chart.styledMode && this.state !== 'inactive' // #13719
        ) {
            attrs.opacity = this.opacity;
        }
        // Generate it on first call
        if (!group) {
            this[prop] = group = this.chart.renderer
                .g()
                .add(parent);
        }
        // Add the class names, and replace existing ones as response to
        // Series.update (#6660)
        group.addClass(('highcharts-' + name +
            ' highcharts-series-' + this.index +
            ' highcharts-' + this.type + '-series ' +
            (Series_defined(this.colorIndex) ?
                'highcharts-color-' + this.colorIndex + ' ' :
                '') +
            (this.options.className || '') +
            (group.hasClass('highcharts-tracker') ?
                ' highcharts-tracker' :
                '')), true);
        // Place it on first and subsequent (redraw) calls
        group.attr(attrs)[isNew ? 'attr' : 'animate'](this.getPlotBox(name));
        return group;
    };
    /**
     * Get the translation and scale for the plot area of this series.
     *
     * @function Highcharts.Series#getPlotBox
     */
    Series.prototype.getPlotBox = function (name) {
        var horAxis = this.xAxis,
            vertAxis = this.yAxis;
        var chart = this.chart,
            inverted = (chart.inverted &&
                !chart.polar &&
                horAxis &&
                this.invertible &&
                name === 'series');
        // Swap axes for inverted (#2339)
        if (chart.inverted) {
            horAxis = vertAxis;
            vertAxis = this.xAxis;
        }
        return {
            translateX: horAxis ? horAxis.left : chart.plotLeft,
            translateY: vertAxis ? vertAxis.top : chart.plotTop,
            rotation: inverted ? 90 : 0,
            rotationOriginX: inverted ?
                (horAxis.len - vertAxis.len) / 2 :
                0,
            rotationOriginY: inverted ?
                (horAxis.len + vertAxis.len) / 2 :
                0,
            scaleX: inverted ? -1 : 1, // #1623
            scaleY: 1
        };
    };
    /**
     * Removes the event handlers attached previously with addEvents.
     * @private
     * @function Highcharts.Series#removeEvents
     */
    Series.prototype.removeEvents = function (keepEventsForUpdate) {
        var eventsToUnbind = this.eventsToUnbind;
        if (!keepEventsForUpdate) {
            // Remove all events
            Series_removeEvent(this);
        }
        if (eventsToUnbind.length) {
            // Remove only internal events for proper update. #12355 solves
            // problem with multiple destroy events
            eventsToUnbind.forEach(function (unbind) {
                unbind();
            });
            eventsToUnbind.length = 0;
        }
    };
    /**
     * Render the graph and markers. Called internally when first rendering
     * and later when redrawing the chart. This function can be extended in
     * plugins, but normally shouldn't be called directly.
     *
     * @function Highcharts.Series#render
     *
     * @emits Highcharts.Series#event:afterRender
     */
    Series.prototype.render = function () {
        var _a,
            _b,
            _c,
            _d,
            _e;
        var series = this,
            chart = series.chart,
            options = series.options,
            hasRendered = series.hasRendered,
            animOptions = Series_animObject(options.animation),
            visibility = series.visible ?
                'inherit' : 'hidden', // #2597
            zIndex = options.zIndex,
            chartSeriesGroup = chart.seriesGroup;
        var animDuration = series.finishedAnimating ?
                0 : animOptions.duration;
        Series_fireEvent(this, 'render');
        // The group
        series.plotGroup('group', 'series', visibility, zIndex, chartSeriesGroup);
        series.markerGroup = series.plotGroup('markerGroup', 'markers', visibility, zIndex, chartSeriesGroup);
        // Initial clipping, applies to columns etc. (#3839).
        if (options.clip !== false) {
            series.setClip();
        }
        // Initialize the animation
        if (animDuration) {
            (_a = series.animate) === null || _a === void 0 ? void 0 : _a.call(series, true);
        }
        // Draw the graph if any
        if (series.drawGraph) {
            series.drawGraph();
            series.applyZones();
        }
        // Draw the points
        if (series.visible) {
            series.drawPoints();
        }
        // Draw the data labels
        (_b = series.drawDataLabels) === null || _b === void 0 ? void 0 : _b.call(series);
        // In pie charts, slices are added to the DOM, but actual rendering
        // is postponed until labels reserved their space
        (_c = series.redrawPoints) === null || _c === void 0 ? void 0 : _c.call(series);
        // Draw the mouse tracking area
        if (options.enableMouseTracking) {
            (_d = series.drawTracker) === null || _d === void 0 ? void 0 : _d.call(series);
        }
        // Run the animation
        if (animDuration) {
            (_e = series.animate) === null || _e === void 0 ? void 0 : _e.call(series);
        }
        // Call the afterAnimate function on animation complete (but don't
        // overwrite the animation.complete option which should be available
        // to the user).
        if (!hasRendered) {
            // Additional time if defer is defined before afterAnimate
            // will be triggered
            if (animDuration && animOptions.defer) {
                animDuration += animOptions.defer;
            }
            series.animationTimeout = Series_syncTimeout(function () {
                series.afterAnimate();
            }, animDuration || 0);
        }
        // Means data is in accordance with what you see
        series.isDirty = false;
        // (See #322) series.isDirty = series.isDirtyData = false; // means
        // data is in accordance with what you see
        series.hasRendered = true;
        Series_fireEvent(series, 'afterRender');
    };
    /**
     * Redraw the series. This function is called internally from
     * `chart.redraw` and normally shouldn't be called directly.
     * @private
     * @function Highcharts.Series#redraw
     */
    Series.prototype.redraw = function () {
        // Cache it here as it is set to false in render, but used after
        var wasDirty = this.isDirty || this.isDirtyData;
        this.translate();
        this.render();
        if (wasDirty) { // #3868, #3945
            delete this.kdTree;
        }
    };
    /**
     * Whether to reserve space for the series, either because it is visible or
     * because the `chart.ignoreHiddenSeries` option is false.
     *
     * @private
     */
    Series.prototype.reserveSpace = function () {
        return this.visible || !this.chart.options.chart.ignoreHiddenSeries;
    };
    /**
     * Find the nearest point from a pointer event. This applies to series that
     * use k-d-trees to get the nearest point. Native pointer events must be
     * normalized using `Pointer.normalize`, that adds `chartX` and `chartY`
     * properties.
     *
     * @sample highcharts/demo/synchronized-charts
     *         Synchronized charts with tooltips
     *
     * @function Highcharts.Series#searchPoint
     *
     * @param {Highcharts.PointerEvent} e
     *        The normalized pointer event
     * @param {boolean} [compareX=false]
     *        Search only by the X value, not Y
     *
     * @return {Point|undefined}
     *        The closest point to the pointer event
     */
    Series.prototype.searchPoint = function (e, compareX) {
        var _a = this,
            xAxis = _a.xAxis,
            yAxis = _a.yAxis,
            inverted = this.chart.inverted;
        return this.searchKDTree({
            clientX: inverted ?
                xAxis.len - e.chartY + xAxis.pos :
                e.chartX - xAxis.pos,
            plotY: inverted ?
                yAxis.len - e.chartX + yAxis.pos :
                e.chartY - yAxis.pos
        }, compareX, e);
    };
    /**
     * Build the k-d-tree that is used by mouse and touch interaction to get
     * the closest point. Line-like series typically have a one-dimensional
     * tree where points are searched along the X axis, while scatter-like
     * series typically search in two dimensions, X and Y.
     *
     * @private
     * @function Highcharts.Series#buildKDTree
     */
    Series.prototype.buildKDTree = function (e) {
        // Prevent multiple k-d-trees from being built simultaneously
        // (#6235)
        this.buildingKdTree = true;
        var series = this,
            dimensions = series.options.findNearestPointBy
                .indexOf('y') > -1 ? 2 : 1;
        /**
         * Internal function
         * @private
         */
        function kdtree(points, depth, dimensions) {
            var length = points === null || points === void 0 ? void 0 : points.length;
            var axis,
                median;
            if (length) {
                // Alternate between the axis
                axis = series.kdAxisArray[depth % dimensions];
                // Sort point array
                points.sort(function (a, b) { return (a[axis] || 0) - (b[axis] || 0); });
                median = Math.floor(length / 2);
                // Build and return node
                return {
                    point: points[median],
                    left: kdtree(points.slice(0, median), depth + 1, dimensions),
                    right: kdtree(points.slice(median + 1), depth + 1, dimensions)
                };
            }
        }
        /**
         * Start the recursive build process with a clone of the points
         * array and null points filtered out. (#3873)
         * @private
         */
        function startRecursive() {
            series.kdTree = kdtree(series.getValidPoints(void 0, 
            // For line-type series restrict to plot area, but
            // column-type series not (#3916, #4511)
            !series.directTouch), dimensions, dimensions);
            series.buildingKdTree = false;
        }
        delete series.kdTree;
        // For testing tooltips, don't build async. Also if touchstart, we may
        // be dealing with click events on mobile, so don't delay (#6817).
        Series_syncTimeout(startRecursive, series.options.kdNow || (e === null || e === void 0 ? void 0 : e.type) === 'touchstart' ? 0 : 1);
    };
    /**
     * @private
     * @function Highcharts.Series#searchKDTree
     */
    Series.prototype.searchKDTree = function (point, compareX, e, suppliedPointEvaluator, suppliedBSideCheckEvaluator) {
        var series = this, _a = this.kdAxisArray, kdX = _a[0], kdY = _a[1], kdComparer = compareX ? 'distX' : 'dist', kdDimensions = (series.options.findNearestPointBy || '')
                .indexOf('y') > -1 ? 2 : 1, useRadius = !!series.isBubble, pointEvaluator = suppliedPointEvaluator || (function (p1, p2, comparisonProp) { return [
                (p1[comparisonProp] || 0) < (p2[comparisonProp] || 0) ?
                    p1 :
                    p2,
                false
            ]; }), bSideCheckEvaluator = suppliedBSideCheckEvaluator || (function (a, b) { return a < b; });
        /**
         * Set the one and two dimensional distance on the point object.
         * @private
         */
        function setDistance(p1, p2) {
            var _a;
            var p1kdX = p1[kdX],
                p2kdX = p2[kdX],
                x = (Series_defined(p1kdX) && Series_defined(p2kdX)) ? p1kdX - p2kdX : null,
                p1kdY = p1[kdY],
                p2kdY = p2[kdY],
                y = (Series_defined(p1kdY) && Series_defined(p2kdY)) ? p1kdY - p2kdY : 0,
                radius = useRadius ? (((_a = p2.marker) === null || _a === void 0 ? void 0 : _a.radius) || 0) : 0;
            p2.dist = Math.sqrt(((x && x * x) || 0) + y * y) - radius;
            p2.distX = Series_defined(x) ? (Math.abs(x) - radius) : Number.MAX_VALUE;
        }
        /**
         * @private
         */
        function doSearch(search, tree, depth, dimensions) {
            var _a;
            var _b;
            var point = tree.point,
                axis = series.kdAxisArray[depth % dimensions];
            var ret = point,
                flip = false;
            setDistance(search, point);
            // Pick side based on distance to splitting point
            var tdist = (search[axis] || 0) - (point[axis] || 0) +
                    (useRadius ? (((_b = point.marker) === null || _b === void 0 ? void 0 : _b.radius) || 0) : 0), sideA = tdist < 0 ? 'left' : 'right', sideB = tdist < 0 ? 'right' : 'left';
            // End of tree
            if (tree[sideA]) {
                _a = pointEvaluator(point, doSearch(search, tree[sideA], depth + 1, dimensions), kdComparer), ret = _a[0], flip = _a[1];
            }
            if (tree[sideB]) {
                var sqrtTDist = Math.sqrt(tdist * tdist),
                    retDist = ret[kdComparer];
                // Compare distance to current best to splitting point to decide
                // whether to check side B or no
                if (bSideCheckEvaluator(sqrtTDist, retDist, flip)) {
                    ret = pointEvaluator(ret, doSearch(search, tree[sideB], depth + 1, dimensions), kdComparer)[0];
                }
            }
            return ret;
        }
        if (!this.kdTree && !this.buildingKdTree) {
            this.buildKDTree(e);
        }
        if (this.kdTree) {
            return doSearch(point, this.kdTree, kdDimensions, kdDimensions);
        }
    };
    /**
     * @private
     * @function Highcharts.Series#pointPlacementToXValue
     */
    Series.prototype.pointPlacementToXValue = function () {
        var _a = this,
            options = _a.options,
            xAxis = _a.xAxis;
        var factor = options.pointPlacement;
        // Point placement is relative to each series pointRange (#5889)
        if (factor === 'between') {
            factor = xAxis.reversed ? -0.5 : 0.5; // #11955
        }
        return Series_isNumber(factor) ?
            factor * (options.pointRange || xAxis.pointRange) :
            0;
    };
    /**
     * @private
     * @function Highcharts.Series#isPointInside
     */
    Series.prototype.isPointInside = function (point) {
        var _a = this,
            chart = _a.chart,
            xAxis = _a.xAxis,
            yAxis = _a.yAxis,
            _b = point.plotX,
            plotX = _b === void 0 ? -1 : _b,
            _c = point.plotY,
            plotY = _c === void 0 ? -1 : _c,
            isInside = (plotY >= 0 &&
                plotY <= (yAxis ? yAxis.len : chart.plotHeight) &&
                plotX >= 0 &&
                plotX <= (xAxis ? xAxis.len : chart.plotWidth));
        return isInside;
    };
    /**
     * Draw the tracker object that sits above all data labels and markers to
     * track mouse events on the graph or points. For the line type charts
     * the tracker uses the same graphPath, but with a greater stroke width
     * for better control.
     * @private
     */
    Series.prototype.drawTracker = function () {
        var _a;
        var series = this,
            options = series.options,
            trackByArea = options.trackByArea,
            trackerPath = [].concat((trackByArea ? series.areaPath : series.graphPath) || []),
            chart = series.chart,
            pointer = chart.pointer,
            renderer = chart.renderer,
            snap = ((_a = chart.options.tooltip) === null || _a === void 0 ? void 0 : _a.snap) || 0,
            onMouseOver = function () {
                if (options.enableMouseTracking &&
                    chart.hoverSeries !== series) {
                    series.onMouseOver();
            }
        }, 
        /*
         * Empirical lowest possible opacities for TRACKER_FILL for an
         * element to stay invisible but clickable
         * IE9: 0.00000000001 (unlimited)
         * IE10: 0.0001 (exporting only)
         * FF: 0.00000000001 (unlimited)
         * Chrome: 0.000001
         * Safari: 0.000001
         * Opera: 0.00000000001 (unlimited)
         */
        TRACKER_FILL = 'rgba(192,192,192,' + (Series_svg ? 0.0001 : 0.002) + ')';
        var tracker = series.tracker;
        // Draw the tracker
        if (tracker) {
            tracker.attr({ d: trackerPath });
        }
        else if (series.graph) { // Create
            series.tracker = tracker = renderer.path(trackerPath)
                .attr({
                visibility: series.visible ? 'inherit' : 'hidden',
                zIndex: 2
            })
                .addClass(trackByArea ?
                'highcharts-tracker-area' :
                'highcharts-tracker-line')
                .add(series.group);
            if (!chart.styledMode) {
                tracker.attr({
                    'stroke-linecap': 'round',
                    'stroke-linejoin': 'round', // #1225
                    stroke: TRACKER_FILL,
                    fill: trackByArea ? TRACKER_FILL : 'none',
                    'stroke-width': series.graph.strokeWidth() +
                        (trackByArea ? 0 : 2 * snap)
                });
            }
            // The tracker is added to the series group, which is clipped, but
            // is covered by the marker group. So the marker group also needs to
            // capture events.
            [
                series.tracker,
                series.markerGroup,
                series.dataLabelsGroup
            ].forEach(function (tracker) {
                if (tracker) {
                    tracker.addClass('highcharts-tracker')
                        .on('mouseover', onMouseOver)
                        .on('mouseout', function (e) {
                        pointer === null || pointer === void 0 ? void 0 : pointer.onTrackerMouseOut(e);
                    });
                    if (options.cursor && !chart.styledMode) {
                        tracker.css({ cursor: options.cursor });
                    }
                    tracker.on('touchstart', onMouseOver);
                }
            });
        }
        Series_fireEvent(this, 'afterDrawTracker');
    };
    /**
     * Add a point to the series after render time. The point can be added at
     * the end, or by giving it an X value, to the start or in the middle of the
     * series.
     *
     * @sample highcharts/members/series-addpoint-append/
     *         Append point
     * @sample highcharts/members/series-addpoint-append-and-shift/
     *         Append and shift
     * @sample highcharts/members/series-addpoint-x-and-y/
     *         Both X and Y values given
     * @sample highcharts/members/series-addpoint-pie/
     *         Append pie slice
     * @sample stock/members/series-addpoint/
     *         Append 100 points in Highcharts Stock
     * @sample stock/members/series-addpoint-shift/
     *         Append and shift in Highcharts Stock
     * @sample maps/members/series-addpoint/
     *         Add a point in Highmaps
     *
     * @function Highcharts.Series#addPoint
     *
     * @param {Highcharts.PointOptionsType} options
     *        The point options. If options is a single number, a point with
     *        that y value is appended to the series. If it is an array, it will
     *        be interpreted as x and y values respectively. If it is an
     *        object, advanced options as outlined under `series.data` are
     *        applied.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after the point is added. When adding
     *        more than one point, it is highly recommended that the redraw
     *        option be set to false, and instead {@link Chart#redraw} is
     *        explicitly called after the adding of points is finished.
     *        Otherwise, the chart will redraw after adding each point.
     *
     * @param {boolean} [shift=false]
     *        If true, a point is shifted off the start of the series as one is
     *        appended to the end.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether to apply animation, and optionally animation
     *        configuration.
     *
     * @param {boolean} [withEvent=true]
     *        Used internally, whether to fire the series `addPoint` event.
     *
     * @emits Highcharts.Series#event:addPoint
     */
    Series.prototype.addPoint = function (options, redraw, shift, animation, withEvent) {
        var series = this,
            seriesOptions = series.options,
            chart = series.chart,
            data = series.data,
            table = series.dataTable,
            xAxis = series.xAxis,
            names = xAxis && xAxis.hasNames && xAxis.names,
            dataOptions = seriesOptions.data,
            xData = series.getColumn('x');
        var isInTheMiddle,
            i;
        // Optional redraw, defaults to true
        redraw = Series_pick(redraw, true);
        // Get options and push the point to xData, yData and series.options. In
        // series.generatePoints the Point instance will be created on demand
        // and pushed to the series.data array.
        var point = { series: series };
        series.pointClass.prototype.applyOptions.apply(point, [options]);
        var x = point.x;
        // Get the insertion point
        i = xData.length;
        if (series.requireSorting && x < xData[i - 1]) {
            isInTheMiddle = true;
            while (i && xData[i - 1] > x) {
                i--;
            }
        }
        // Insert the row at the given index
        table.setRow(point, i, true, { addColumns: false });
        if (names && point.name) {
            names[x] = point.name;
        }
        dataOptions === null || dataOptions === void 0 ? void 0 : dataOptions.splice(i, 0, options);
        if (isInTheMiddle ||
            // When processedData is present we need to splice an empty slot
            // into series.data, otherwise generatePoints won't pick it up.
            series.processedData) {
            series.data.splice(i, 0, null);
            series.processData();
        }
        // Generate points to be added to the legend (#1329)
        if (seriesOptions.legendType === 'point') {
            series.generatePoints();
        }
        // Shift the first point off the parallel arrays
        if (shift) {
            if (data[0] && !!data[0].remove) {
                data[0].remove(false);
            }
            else {
                Series_spreadArray([
                    data,
                    dataOptions
                ], Object.values(table.getColumns()), true).filter(Series_defined).forEach(function (coll) {
                    coll.shift();
                });
                table.rowCount -= 1;
                Series_fireEvent(table, 'afterDeleteRows');
            }
        }
        // Fire event
        if (withEvent !== false) {
            Series_fireEvent(series, 'addPoint', { point: point });
        }
        // Redraw
        series.isDirty = true;
        series.isDirtyData = true;
        if (redraw) {
            chart.redraw(animation); // Animation is set anyway on redraw, #5665
        }
    };
    /**
     * Remove a point from the series. Unlike the
     * {@link Highcharts.Point#remove} method, this can also be done on a point
     * that is not instantiated because it is outside the view or subject to
     * Highcharts Stock data grouping.
     *
     * @sample highcharts/members/series-removepoint/
     *         Remove cropped point
     *
     * @function Highcharts.Series#removePoint
     *
     * @param {number} i
     *        The index of the point in the {@link Highcharts.Series.data|data}
     *        array.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after the point is added. When
     *        removing more than one point, it is highly recommended that the
     *        `redraw` option be set to `false`, and instead {@link
     *        Highcharts.Chart#redraw} is explicitly called after the adding of
     *        points is finished.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether and optionally how the series should be animated.
     *
     * @emits Highcharts.Point#event:remove
     */
    Series.prototype.removePoint = function (i, redraw, animation) {
        var series = this,
            chart = series.chart,
            data = series.data,
            points = series.points,
            table = series.dataTable,
            point = data[i],
            remove = function () {
                // Splice out the point's data from all parallel arrays
                Series_spreadArray([
                    // #4935
                    (points === null || points === void 0 ? void 0 : points.length) === data.length ? points : void 0,
                    data,
                    series.options.data
                ],
            Object.values(table.getColumns()),
            true).filter(Series_defined).forEach(function (coll) {
                    coll.splice(i, 1);
            });
            // Shorthand row deletion in order to avoid including the whole
            // `deleteRows` function in the DataTableCore module.
            table.rowCount -= 1;
            Series_fireEvent(table, 'afterDeleteRows');
            point === null || point === void 0 ? void 0 : point.destroy();
            // Redraw
            series.isDirty = true;
            series.isDirtyData = true;
            if (redraw) {
                chart.redraw();
            }
        };
        Series_setAnimation(animation, chart);
        redraw = Series_pick(redraw, true);
        // Fire the event with a default handler of removing the point
        if (point) {
            point.firePointEvent('remove', null, remove);
        }
        else {
            remove();
        }
    };
    /**
     * Remove a series and optionally redraw the chart.
     *
     * @sample highcharts/members/series-remove/
     *         Remove first series from a button
     *
     * @function Highcharts.Series#remove
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart or wait for an explicit call to
     *        {@link Highcharts.Chart#redraw}.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether to apply animation, and optionally animation
     *        configuration.
     *
     * @param {boolean} [withEvent=true]
     *        Used internally, whether to fire the series `remove` event.
     *
     * @emits Highcharts.Series#event:remove
     */
    Series.prototype.remove = function (redraw, animation, withEvent, keepEvents) {
        var series = this,
            chart = series.chart;
        /**
         * @private
         */
        function remove() {
            // Destroy elements
            series.destroy(keepEvents);
            // Redraw
            chart.isDirtyLegend = chart.isDirtyBox = true;
            chart.linkSeries(keepEvents);
            if (Series_pick(redraw, true)) {
                chart.redraw(animation);
            }
        }
        // Fire the event with a default handler of removing the point
        if (withEvent !== false) {
            Series_fireEvent(series, 'remove', null, remove);
        }
        else {
            remove();
        }
    };
    /**
     * Update the series with a new set of options. For a clean and precise
     * handling of new options, all methods and elements from the series are
     * removed, and it is initialized from scratch. Therefore, this method is
     * more performance expensive than some other utility methods like {@link
     * Series#setData} or {@link Series#setVisible}.
     *
     * Note that `Series.update` may mutate the passed `data` options.
     *
     * @sample highcharts/members/series-update/
     *         Updating series options
     * @sample maps/members/series-update/
     *         Update series options in Highmaps
     *
     * @function Highcharts.Series#update
     *
     * @param {Highcharts.SeriesOptionsType} options
     *        New options that will be merged with the series' existing options.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after the series is altered. If doing
     *        more operations on the chart, it is a good idea to set redraw to
     *        false and call {@link Chart#redraw} after.
     *
     * @emits Highcharts.Series#event:update
     * @emits Highcharts.Series#event:afterUpdate
     */
    Series.prototype.update = function (options, redraw) {
        var _a,
            _b,
            _c,
            _d;
        options = Series_diffObjects(options, this.userOptions);
        Series_fireEvent(this, 'update', { options: options });
        var series = this,
            chart = series.chart, 
            // Must use user options when changing type because series.options
            // is merged in with type specific plotOptions
            oldOptions = series.userOptions,
            initialType = series.initialType || series.type,
            plotOptions = chart.options.plotOptions,
            initialSeriesProto = seriesTypes[initialType].prototype,
            groups = [
                'group',
                'markerGroup',
                'dataLabelsGroup',
                'transformGroup'
            ],
            optionsToCheck = [
                'dataGrouping',
                'pointStart',
                'pointInterval',
                'pointIntervalUnit',
                'keys'
            ], 
            // Animation must be enabled when calling update before the initial
            // animation has first run. This happens when calling update
            // directly after chart initialization, or when applying responsive
            // rules (#6912).
            animation = series.finishedAnimating && { animation: false },
            kinds = {};
        var seriesOptions,
            n,
            preserve = [
                'colorIndex',
                'eventOptions',
                'navigatorSeries',
                'symbolIndex',
                'baseSeries'
            ],
            newType = (options.type ||
                oldOptions.type ||
                chart.options.chart.type);
        var keepPoints = !(
            // Indicators, histograms etc recalculate the data. It should be
            // possible to omit this.
            this.hasDerivedData ||
                // New type requires new point classes
                (newType && newType !== this.type) ||
                // New options affecting how the data points are built
                typeof options.keys !== 'undefined' ||
                typeof options.pointStart !== 'undefined' ||
                typeof options.pointInterval !== 'undefined' ||
                typeof options.relativeXValue !== 'undefined' ||
                options.joinBy ||
                options.mapData || // #11636
                // Changes to data grouping requires new points in new group
                optionsToCheck.some(function (option) { return series.hasOptionChanged(option); }));
        newType = newType || initialType;
        if (keepPoints) {
            preserve.push('data', 'isDirtyData', 
            // GeoHeatMap interpolation
            'isDirtyCanvas', 'points', 'dataTable', 'processedData', // #17057
            'xIncrement', 'cropped', '_hasPointMarkers', 'hasDataLabels', 
            // Networkgraph (#14397)
            'nodes', 'layout', 
            // Treemap
            'level', 
            // Map specific, consider moving it to series-specific preserve-
            // properties (#10617)
            'mapMap', 'mapData', 'minY', 'maxY', 'minX', 'maxX', 'transformGroups' // #18857
            );
            if (options.visible !== false) {
                preserve.push('area', 'graph');
            }
            series.parallelArrays.forEach(function (key) {
                preserve.push(key + 'Data');
            });
            if (options.data) {
                // `setData` uses `dataSorting` options so we need to update
                // them earlier
                if (options.dataSorting) {
                    Series_extend(series.options.dataSorting, options.dataSorting);
                }
                this.setData(options.data, false);
            }
        }
        else {
            this.dataTable.modified = this.dataTable;
        }
        // Do the merge, with some forced options
        options = Series_merge(oldOptions, {
            // When oldOptions.index is null it should't be cleared.
            // Otherwise navigator series will have wrong indexes (#10193).
            index: oldOptions.index === void 0 ?
                series.index : oldOptions.index,
            pointStart: 
            // When updating from blank (#7933)
            (_c = (_b = (_a = plotOptions === null || plotOptions === void 0 ? void 0 : plotOptions.series) === null || _a === void 0 ? void 0 : _a.pointStart) !== null && _b !== void 0 ? _b : oldOptions.pointStart) !== null && _c !== void 0 ? _c : 
            // When updating after addPoint
            series.getColumn('x')[0]
        }, !keepPoints && { data: series.options.data }, options, animation);
        // Merge does not merge arrays, but replaces them. Since points were
        // updated, `series.options.data` has correct merged options, use it:
        if (keepPoints && options.data) {
            options.data = series.options.data;
        }
        // Make sure preserved properties are not destroyed (#3094)
        preserve = groups.concat(preserve);
        preserve.forEach(function (prop) {
            preserve[prop] = series[prop];
            delete series[prop];
        });
        var casting = false;
        if (seriesTypes[newType]) {
            casting = newType !== series.type;
            // Destroy the series and delete all properties, it will be
            // reinserted within the `init` call below
            series.remove(false, false, false, true);
            if (casting) {
                // #20264: Re-detect a certain chart properties from new series
                chart.propFromSeries();
                // Modern browsers including IE11
                if (Object.setPrototypeOf) {
                    Object.setPrototypeOf(series, seriesTypes[newType].prototype);
                    // Legacy (IE < 11)
                }
                else {
                    var ownEvents = Object.hasOwnProperty.call(series, 'hcEvents') && series.hcEvents;
                    for (n in initialSeriesProto) { // eslint-disable-line guard-for-in
                        series[n] = void 0;
                    }
                    // Reinsert all methods and properties from the new type
                    // prototype (#2270, #3719).
                    Series_extend(series, seriesTypes[newType].prototype);
                    // The events are tied to the prototype chain, don't copy if
                    // they're not the series' own
                    if (ownEvents) {
                        series.hcEvents = ownEvents;
                    }
                    else {
                        delete series.hcEvents;
                    }
                }
            }
        }
        else {
            Series_error(17, true, chart, { missingModuleFor: newType });
        }
        // Re-register groups (#3094) and other preserved properties
        preserve.forEach(function (prop) {
            series[prop] = preserve[prop];
        });
        series.init(chart, options);
        // Remove particular elements of the points. Check `series.options`
        // because we need to consider the options being set on plotOptions as
        // well.
        if (keepPoints && this.points) {
            seriesOptions = series.options;
            // What kind of elements to destroy
            if (seriesOptions.visible === false) {
                kinds.graphic = 1;
                kinds.dataLabel = 1;
            }
            else {
                // If the marker got disabled or changed its symbol, width or
                // height - destroy
                if (this.hasMarkerChanged(seriesOptions, oldOptions)) {
                    kinds.graphic = 1;
                }
                if (!((_d = series.hasDataLabels) === null || _d === void 0 ? void 0 : _d.call(series))) {
                    kinds.dataLabel = 1;
                }
            }
            for (var _e = 0, _f = this.points; _e < _f.length; _e++) {
                var point = _f[_e];
                if (point && point.series) {
                    point.resolveColor();
                    // Destroy elements in order to recreate based on updated
                    // series options.
                    if (Object.keys(kinds).length) {
                        point.destroyElements(kinds);
                    }
                    if (seriesOptions.showInLegend === false &&
                        point.legendItem) {
                        chart.legend.destroyItem(point);
                    }
                }
            }
        }
        series.initialType = initialType;
        chart.linkSeries(); // Links are lost in series.remove (#3028)
        // Set data for series with sorting enabled if it isn't set yet (#19715)
        chart.setSortedData();
        // #15383: Fire updatedData if the type has changed to keep linked
        // series such as indicators updated
        if (casting && series.linkedSeries.length) {
            series.isDirtyData = true;
        }
        Series_fireEvent(this, 'afterUpdate');
        if (Series_pick(redraw, true)) {
            chart.redraw(keepPoints ? void 0 : false);
        }
    };
    /**
     * Used from within series.update
     * @private
     */
    Series.prototype.setName = function (name) {
        this.name = this.options.name = this.userOptions.name = name;
        this.chart.isDirtyLegend = true;
    };
    /**
     * Check if the option has changed.
     * @private
     */
    Series.prototype.hasOptionChanged = function (optionName) {
        var _a,
            _b;
        var chart = this.chart,
            option = this.options[optionName],
            plotOptions = chart.options.plotOptions,
            oldOption = this.userOptions[optionName],
            plotOptionsOption = Series_pick((_a = plotOptions === null || plotOptions === void 0 ? void 0 : plotOptions[this.type]) === null || _a === void 0 ? void 0 : _a[optionName], (_b = plotOptions === null || plotOptions === void 0 ? void 0 : plotOptions.series) === null || _b === void 0 ? void 0 : _b[optionName]);
        // Check if `plotOptions` are defined already, #19203
        if (oldOption && !Series_defined(plotOptionsOption)) {
            return option !== oldOption;
        }
        return option !== Series_pick(plotOptionsOption, option);
    };
    /**
     * Runs on mouse over the series graphical items.
     *
     * @function Highcharts.Series#onMouseOver
     * @emits Highcharts.Series#event:mouseOver
     */
    Series.prototype.onMouseOver = function () {
        var series = this,
            chart = series.chart,
            hoverSeries = chart.hoverSeries,
            pointer = chart.pointer;
        pointer === null || pointer === void 0 ? void 0 : pointer.setHoverChartIndex();
        // Set normal state to previous series
        if (hoverSeries && hoverSeries !== series) {
            hoverSeries.onMouseOut();
        }
        // Trigger the event, but to save processing time,
        // only if defined
        if (series.options.events.mouseOver) {
            Series_fireEvent(series, 'mouseOver');
        }
        // Hover this
        series.setState('hover');
        /**
         * Contains the original hovered series.
         *
         * @name Highcharts.Chart#hoverSeries
         * @type {Highcharts.Series|null}
         */
        chart.hoverSeries = series;
    };
    /**
     * Runs on mouse out of the series graphical items.
     *
     * @function Highcharts.Series#onMouseOut
     *
     * @emits Highcharts.Series#event:mouseOut
     */
    Series.prototype.onMouseOut = function () {
        // Trigger the event only if listeners exist
        var series = this,
            options = series.options,
            chart = series.chart,
            tooltip = chart.tooltip,
            hoverPoint = chart.hoverPoint;
        // #182, set to null before the mouseOut event fires
        chart.hoverSeries = null;
        // Trigger mouse out on the point, which must be in this series
        if (hoverPoint) {
            hoverPoint.onMouseOut();
        }
        // Fire the mouse out event
        if (series && options.events.mouseOut) {
            Series_fireEvent(series, 'mouseOut');
        }
        // Hide the tooltip
        if (tooltip &&
            !series.stickyTracking &&
            (!tooltip.shared || series.noSharedTooltip)) {
            tooltip.hide();
        }
        // Reset all inactive states
        chart.series.forEach(function (s) {
            s.setState('', true);
        });
    };
    /**
     * Set the state of the series. Called internally on mouse interaction
     * operations, but it can also be called directly to visually
     * highlight a series.
     *
     * @function Highcharts.Series#setState
     *
     * @param {Highcharts.SeriesStateValue|""} [state]
     *        The new state, can be either `'hover'`, `'inactive'`, `'select'`,
     *        or `''` (an empty string), `'normal'` or `undefined` to set to
     *        normal state.
     * @param {boolean} [inherit]
     *        Determines if state should be inherited by points too.
     */
    Series.prototype.setState = function (state, inherit) {
        var series = this, options = series.options, graph = series.graph, inactiveOtherPoints = options.inactiveOtherPoints, stateOptions = options.states, 
            // By default a quick animation to hover/inactive,
            // slower to un-hover
            stateAnimation = Series_pick((stateOptions[state || 'normal'] &&
                stateOptions[state || 'normal'].animation), series.chart.options.chart.animation);
        var lineWidth = options.lineWidth,
            opacity = options.opacity;
        state = state || '';
        if (series.state !== state) {
            // Toggle class names
            [
                series.group,
                series.markerGroup,
                series.dataLabelsGroup
            ].forEach(function (group) {
                if (group) {
                    // Old state
                    if (series.state) {
                        group.removeClass('highcharts-series-' + series.state);
                    }
                    // New state
                    if (state) {
                        group.addClass('highcharts-series-' + state);
                    }
                }
            });
            series.state = state;
            if (!series.chart.styledMode) {
                if (stateOptions[state] &&
                    stateOptions[state].enabled === false) {
                    return;
                }
                if (state) {
                    lineWidth = (stateOptions[state].lineWidth ||
                        lineWidth + (stateOptions[state].lineWidthPlus || 0)); // #4035
                    opacity = Series_pick(stateOptions[state].opacity, opacity);
                }
                if (graph && !graph.dashstyle && Series_isNumber(lineWidth)) {
                    // Animate the graph stroke-width
                    for (var _a = 0, _b = Series_spreadArray([
                        graph
                    ], this.zones.map(function (zone) { return zone.graph; }), true); _a < _b.length; _a++) {
                        var graphElement = _b[_a];
                        graphElement === null || graphElement === void 0 ? void 0 : graphElement.animate({
                            'stroke-width': lineWidth
                        }, stateAnimation);
                    }
                }
                // For some types (pie, networkgraph, sankey) opacity is
                // resolved on a point level
                if (!inactiveOtherPoints) {
                    [
                        series.group,
                        series.markerGroup,
                        series.dataLabelsGroup,
                        series.labelBySeries
                    ].forEach(function (group) {
                        if (group) {
                            group.animate({
                                opacity: opacity
                            }, stateAnimation);
                        }
                    });
                }
            }
        }
        // Don't loop over points on a series that doesn't apply inactive state
        // to siblings markers (e.g. line, column)
        if (inherit && inactiveOtherPoints && series.points) {
            series.setAllPointsToState(state || void 0);
        }
    };
    /**
     * Set the state for all points in the series.
     *
     * @function Highcharts.Series#setAllPointsToState
     *
     * @private
     *
     * @param {string} [state]
     *        Can be either `hover` or undefined to set to normal state.
     */
    Series.prototype.setAllPointsToState = function (state) {
        this.points.forEach(function (point) {
            if (point.setState) {
                point.setState(state);
            }
        });
    };
    /**
     * Show or hide the series.
     *
     * @function Highcharts.Series#setVisible
     *
     * @param {boolean} [visible]
     * True to show the series, false to hide. If undefined, the visibility is
     * toggled.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart after the series is altered. If doing more
     * operations on the chart, it is a good idea to set redraw to false and
     * call {@link Chart#redraw|chart.redraw()} after.
     *
     * @emits Highcharts.Series#event:hide
     * @emits Highcharts.Series#event:show
     */
    Series.prototype.setVisible = function (vis, redraw) {
        var _a;
        var series = this,
            chart = series.chart,
            ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,
            oldVisibility = series.visible;
        // If called without an argument, toggle visibility
        series.visible =
            vis =
                series.options.visible =
                    series.userOptions.visible =
                        typeof vis === 'undefined' ? !oldVisibility : vis; // #5618
        var showOrHide = vis ? 'show' : 'hide';
        // Show or hide elements
        [
            'group',
            'dataLabelsGroup',
            'markerGroup',
            'tracker',
            'tt'
        ].forEach(function (key) {
            var _a;
            (_a = series[key]) === null || _a === void 0 ? void 0 : _a[showOrHide]();
        });
        // Hide tooltip (#1361)
        if (chart.hoverSeries === series ||
            ((_a = chart.hoverPoint) === null || _a === void 0 ? void 0 : _a.series) === series) {
            series.onMouseOut();
        }
        if (series.legendItem) {
            chart.legend.colorizeItem(series, vis);
        }
        // Rescale or adapt to resized chart
        series.isDirty = true;
        // In a stack, all other series are affected
        if (series.options.stacking) {
            chart.series.forEach(function (otherSeries) {
                if (otherSeries.options.stacking && otherSeries.visible) {
                    otherSeries.isDirty = true;
                }
            });
        }
        // Show or hide linked series
        series.linkedSeries.forEach(function (otherSeries) {
            otherSeries.setVisible(vis, false);
        });
        if (ignoreHiddenSeries) {
            chart.isDirtyBox = true;
        }
        Series_fireEvent(series, showOrHide);
        if (redraw !== false) {
            chart.redraw();
        }
    };
    /**
     * Show the series if hidden.
     *
     * @sample highcharts/members/series-hide/
     *         Toggle visibility from a button
     *
     * @function Highcharts.Series#show
     * @emits Highcharts.Series#event:show
     */
    Series.prototype.show = function () {
        this.setVisible(true);
    };
    /**
     * Hide the series if visible. If the
     * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries)
     * option is true, the chart is redrawn without this series.
     *
     * @sample highcharts/members/series-hide/
     *         Toggle visibility from a button
     *
     * @function Highcharts.Series#hide
     * @emits Highcharts.Series#event:hide
     */
    Series.prototype.hide = function () {
        this.setVisible(false);
    };
    /**
     * Select or unselect the series. This means its
     * {@link Highcharts.Series.selected|selected}
     * property is set, the checkbox in the legend is toggled and when selected,
     * the series is returned by the {@link Highcharts.Chart#getSelectedSeries}
     * function.
     *
     * @sample highcharts/members/series-select/
     *         Select a series from a button
     *
     * @function Highcharts.Series#select
     *
     * @param {boolean} [selected]
     * True to select the series, false to unselect. If undefined, the selection
     * state is toggled.
     *
     * @emits Highcharts.Series#event:select
     * @emits Highcharts.Series#event:unselect
     */
    Series.prototype.select = function (selected) {
        var series = this;
        series.selected =
            selected =
                this.options.selected = (typeof selected === 'undefined' ?
                    !series.selected :
                    selected);
        if (series.checkbox) {
            series.checkbox.checked = selected;
        }
        Series_fireEvent(series, selected ? 'select' : 'unselect');
    };
    /**
     * Checks if a tooltip should be shown for a given point.
     *
     * @private
     */
    Series.prototype.shouldShowTooltip = function (plotX, plotY, options) {
        if (options === void 0) { options = {}; }
        options.series = this;
        options.visiblePlotOnly = true;
        return this.chart.isInsidePlot(plotX, plotY, options);
    };
    /**
     * Draws the legend symbol based on the legendSymbol user option.
     *
     * @private
     */
    Series.prototype.drawLegendSymbol = function (legend, item) {
        var _a;
        (_a = Legend_LegendSymbol[this.options.legendSymbol || 'rectangle']) === null || _a === void 0 ? void 0 : _a.call(this, legend, item);
    };
    Series.defaultOptions = SeriesDefaults;
    /**
     * Registry of all available series types.
     *
     * @name Highcharts.Series.types
     * @type {Highcharts.Dictionary<typeof_Highcharts.Series>}
     */
    Series.types = Series_SeriesRegistry.seriesTypes;
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * Registers a series class to be accessible via `Series.types`.
     *
     * @function Highcharts.Series.registerType
     *
     * @param {string} seriesType
     * The series type as an identifier string in lower case.
     *
     * @param {Function} SeriesClass
     * The series class as a class pattern or a constructor function with
     * prototype.
     */
    Series.registerType = Series_SeriesRegistry.registerSeriesType;
    return Series;
}());
Series_extend(Series.prototype, {
    axisTypes: ['xAxis', 'yAxis'],
    coll: 'series',
    colorCounter: 0,
    directTouch: false,
    invertible: true,
    isCartesian: true,
    kdAxisArray: ['clientX', 'plotY'],
    // Each point's x and y values are stored in this.xData and this.yData:
    parallelArrays: ['x', 'y'],
    pointClass: Series_Point,
    requireSorting: true,
    // Requires the data to be sorted:
    sorted: true
});
/* *
 *
 *  Registry
 *
 * */
Series_SeriesRegistry.series = Series;
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Series_Series = (Series);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * This is a placeholder type of the possible series options for
 * [Highcharts](../highcharts/series), [Highcharts Stock](../highstock/series),
 * [Highmaps](../highmaps/series), and [Gantt](../gantt/series).
 *
 * In TypeScript is this dynamically generated to reference all possible types
 * of series options.
 *
 * @ignore-declaration
 * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType
 */
/**
 * Options for `dataSorting`.
 *
 * @interface Highcharts.DataSortingOptionsObject
 * @since 8.0.0
 */ /**
* Enable or disable data sorting for the series.
* @name Highcharts.DataSortingOptionsObject#enabled
* @type {boolean|undefined}
*/ /**
* Whether to allow matching points by name in an update.
* @name Highcharts.DataSortingOptionsObject#matchByName
* @type {boolean|undefined}
*/ /**
* Determines what data value should be used to sort by.
* @name Highcharts.DataSortingOptionsObject#sortKey
* @type {string|undefined}
*/
/**
 * Function callback when a series has been animated.
 *
 * @callback Highcharts.SeriesAfterAnimateCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {Highcharts.SeriesAfterAnimateEventObject} event
 *        Event arguments.
 */
/**
 * Event information regarding completed animation of a series.
 *
 * @interface Highcharts.SeriesAfterAnimateEventObject
 */ /**
* Animated series.
* @name Highcharts.SeriesAfterAnimateEventObject#target
* @type {Highcharts.Series}
*/ /**
* Event type.
* @name Highcharts.SeriesAfterAnimateEventObject#type
* @type {"afterAnimate"}
*/
/**
 * Function callback when the checkbox next to the series' name in the legend is
 * clicked.
 *
 * @callback Highcharts.SeriesCheckboxClickCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {Highcharts.SeriesCheckboxClickEventObject} event
 *        Event arguments.
 */
/**
 * Event information regarding check of a series box.
 *
 * @interface Highcharts.SeriesCheckboxClickEventObject
 */ /**
* Whether the box has been checked.
* @name Highcharts.SeriesCheckboxClickEventObject#checked
* @type {boolean}
*/ /**
* Related series.
* @name Highcharts.SeriesCheckboxClickEventObject#item
* @type {Highcharts.Series}
*/ /**
* Related series.
* @name Highcharts.SeriesCheckboxClickEventObject#target
* @type {Highcharts.Series}
*/ /**
* Event type.
* @name Highcharts.SeriesCheckboxClickEventObject#type
* @type {"checkboxClick"}
*/
/**
 * Function callback when a series is clicked. Return false to cancel toogle
 * actions.
 *
 * @callback Highcharts.SeriesClickCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {Highcharts.SeriesClickEventObject} event
 *        Event arguments.
 */
/**
 * Common information for a click event on a series.
 *
 * @interface Highcharts.SeriesClickEventObject
 * @extends global.Event
 */ /**
* Nearest point on the graph.
* @name Highcharts.SeriesClickEventObject#point
* @type {Highcharts.Point}
*/
/**
 * Gets fired when the series is hidden after chart generation time, either by
 * clicking the legend item or by calling `.hide()`.
 *
 * @callback Highcharts.SeriesHideCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {global.Event} event
 *        The event that occurred.
 */
/**
 * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line
 * graph.
 *
 * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue
 */
/**
 * Gets fired when the legend item belonging to the series is clicked. The
 * default action is to toggle the visibility of the series. This can be
 * prevented by returning `false` or calling `event.preventDefault()`.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickCallbackFunction.
 *
 * @deprecated 11.4.4
 * @callback Highcharts.SeriesLegendItemClickCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {Highcharts.SeriesLegendItemClickEventObject} event
 *        The event that occurred.
 */
/**
 * Information about the event.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickEventObject.
 *
 * @deprecated 11.4.4
 * @interface Highcharts.SeriesLegendItemClickEventObject
 */ /**
* Related browser event.
* @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
* @type {global.PointerEvent}
*/ /**
* Prevent the default action of toggle the visibility of the series.
* @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
* @type {Function}
*/ /**
* Related series.
* @name Highcharts.SeriesCheckboxClickEventObject#target
* @type {Highcharts.Series}
*/ /**
* Event type.
* @name Highcharts.SeriesCheckboxClickEventObject#type
* @type {"checkboxClick"}
*/
/**
 * Gets fired when the mouse leaves the graph.
 *
 * @callback Highcharts.SeriesMouseOutCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        Series where the event occurred.
 *
 * @param {global.PointerEvent} event
 *        Event that occurred.
 */
/**
 * Gets fired when the mouse enters the graph.
 *
 * @callback Highcharts.SeriesMouseOverCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        Series where the event occurred.
 *
 * @param {global.PointerEvent} event
 *        Event that occurred.
 */
/**
 * Translation and scale for the plot area of a series.
 *
 * @interface Highcharts.SeriesPlotBoxObject
 */ /**
* @name Highcharts.SeriesPlotBoxObject#scaleX
* @type {number}
*/ /**
* @name Highcharts.SeriesPlotBoxObject#scaleY
* @type {number}
*/ /**
* @name Highcharts.SeriesPlotBoxObject#translateX
* @type {number}
*/ /**
* @name Highcharts.SeriesPlotBoxObject#translateY
* @type {number}
*/
/**
 * Gets fired when the series is shown after chart generation time, either by
 * clicking the legend item or by calling `.show()`.
 *
 * @callback Highcharts.SeriesShowCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        Series where the event occurred.
 *
 * @param {global.Event} event
 *        Event that occurred.
 */
/**
 * Possible key values for the series state options.
 *
 * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue
 */
''; // Detach doclets above
/* *
 *
 *  API Options
 *
 * */
/**
 * Series options for specific data and the data itself. In TypeScript you
 * have to cast the series options to specific series types, to get all
 * possible options for a series.
 *
 * @example
 * // TypeScript example
 * Highcharts.chart('container', {
 *     series: [{
 *         color: '#06C',
 *         data: [[0, 1], [2, 3]]
 *     } as Highcharts.SeriesLineOptions ]
 * });
 *
 * @type      {Array<*>}
 * @apioption series
 */
/**
 * An id for the series. This can be used after render time to get a pointer
 * to the series object through `chart.get()`.
 *
 * @sample {highcharts} highcharts/plotoptions/series-id/
 *         Get series by id
 *
 * @type      {string}
 * @since     1.2.0
 * @apioption series.id
 */
/**
 * The index of the series in the chart, affecting the internal index in the
 * `chart.series` array, the visible Z index as well as the order in the
 * legend.
 *
 * @type      {number}
 * @since     2.3.0
 * @apioption series.index
 */
/**
 * The sequential index of the series in the legend.
 *
 * @see [legend.reversed](#legend.reversed),
 *      [yAxis.reversedStacks](#yAxis.reversedStacks)
 *
 * @sample {highcharts|highstock} highcharts/series/legendindex/
 *         Legend in opposite order
 *
 * @type      {number}
 * @apioption series.legendIndex
 */
/**
 * The name of the series as shown in the legend, tooltip etc.
 *
 * @sample {highcharts} highcharts/series/name/
 *         Series name
 * @sample {highmaps} maps/demo/category-map/
 *         Series name
 *
 * @type      {string}
 * @apioption series.name
 */
/**
 * This option allows grouping series in a stacked chart. The stack option
 * can be a string or anything else, as long as the grouped series' stack
 * options match each other after conversion into a string.
 *
 * @sample {highcharts} highcharts/series/stack/
 *         Stacked and grouped columns
 * @sample {highcharts} highcharts/series/stack-centerincategory/
 *         Stacked and grouped, centered in category
 *
 * @type      {number|string}
 * @since     2.1
 * @product   highcharts highstock
 * @apioption series.stack
 */
/**
 * The type of series, for example `line` or `column`. By default, the
 * series type is inherited from [chart.type](#chart.type), so unless the
 * chart is a combination of series types, there is no need to set it on the
 * series level.
 *
 * @sample {highcharts} highcharts/series/type/
 *         Line and column in the same chart
 * @sample highcharts/series/type-dynamic/
 *         Dynamic types with button selector
 * @sample {highmaps} maps/demo/mapline-mappoint/
 *         Multiple types in the same map
 *
 * @type      {string}
 * @apioption series.type
 */
/**
 * When using dual or multiple x axes, this number defines which xAxis the
 * particular series is connected to. It refers to either the
 * {@link #xAxis.id|axis id}
 * or the index of the axis in the xAxis array, with 0 being the first.
 *
 * @type      {number|string}
 * @default   0
 * @product   highcharts highstock
 * @apioption series.xAxis
 */
/**
 * When using dual or multiple y axes, this number defines which yAxis the
 * particular series is connected to. It refers to either the
 * {@link #yAxis.id|axis id}
 * or the index of the axis in the yAxis array, with 0 being the first.
 *
 * @sample {highcharts} highcharts/series/yaxis/
 *         Apply the column series to the secondary Y axis
 *
 * @type      {number|string}
 * @default   0
 * @product   highcharts highstock
 * @apioption series.yAxis
 */
/**
 * Define the visual z index of the series.
 *
 * @sample {highcharts} highcharts/plotoptions/series-zindex-default/
 *         With no z index, the series defined last are on top
 * @sample {highcharts} highcharts/plotoptions/series-zindex/
 *         With a z index, the series with the highest z index is on top
 * @sample {highstock} highcharts/plotoptions/series-zindex-default/
 *         With no z index, the series defined last are on top
 * @sample {highstock} highcharts/plotoptions/series-zindex/
 *         With a z index, the series with the highest z index is on top
 *
 * @type      {number}
 * @product   highcharts highstock
 * @apioption series.zIndex
 */
''; // Include precedent doclets in transpiled

;// ./code/es5/es-modules/Core/Legend/Legend.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Legend_animObject = AnimationUtilities.animObject, Legend_setAnimation = AnimationUtilities.setAnimation;

var Legend_registerEventOptions = Core_Foundation.registerEventOptions;

var Legend_composed = Core_Globals.composed, marginNames = Core_Globals.marginNames;



var Legend_distribute = Renderer_RendererUtilities.distribute;

var Legend_format = Core_Templating.format;

var Legend_addEvent = Core_Utilities.addEvent, Legend_createElement = Core_Utilities.createElement, Legend_css = Core_Utilities.css, Legend_defined = Core_Utilities.defined, Legend_discardElement = Core_Utilities.discardElement, Legend_find = Core_Utilities.find, Legend_fireEvent = Core_Utilities.fireEvent, Legend_isNumber = Core_Utilities.isNumber, Legend_merge = Core_Utilities.merge, Legend_pick = Core_Utilities.pick, Legend_pushUnique = Core_Utilities.pushUnique, Legend_relativeLength = Core_Utilities.relativeLength, Legend_stableSort = Core_Utilities.stableSort, Legend_syncTimeout = Core_Utilities.syncTimeout;
/* *
 *
 *  Class
 *
 * */
/**
 * The overview of the chart's series. The legend object is instantiated
 * internally in the chart constructor, and is available from the `chart.legend`
 * property. Each chart has only one legend.
 *
 * @class
 * @name Highcharts.Legend
 *
 * @param {Highcharts.Chart} chart
 * The chart instance.
 *
 * @param {Highcharts.LegendOptions} options
 * Legend options.
 */
var Legend = /** @class */ (function () {
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Initialize the legend.
     *
     * @private
     * @function Highcharts.Legend#init
     *
     * @param {Highcharts.Chart} chart
     * The chart instance.
     *
     * @param {Highcharts.LegendOptions} options
     * Legend options.
     */
    function Legend(chart, options) {
        var _this = this;
        /* *
         *
         *  Properties
         *
         * */
        this.allItems = [];
        this.initialItemY = 0;
        this.itemHeight = 0;
        this.itemMarginBottom = 0;
        this.itemMarginTop = 0;
        this.itemX = 0;
        this.itemY = 0;
        this.lastItemY = 0;
        this.lastLineHeight = 0;
        this.legendHeight = 0;
        this.legendWidth = 0;
        this.maxItemWidth = 0;
        this.maxLegendWidth = 0;
        this.offsetWidth = 0;
        this.padding = 0;
        this.pages = [];
        this.symbolHeight = 0;
        this.symbolWidth = 0;
        this.titleHeight = 0;
        this.totalItemWidth = 0;
        this.widthOption = 0;
        /**
         * Chart of this legend.
         *
         * @readonly
         * @name Highcharts.Legend#chart
         * @type {Highcharts.Chart}
         */
        this.chart = chart;
        this.setOptions(options);
        if (options.enabled) {
            // Render it
            this.render();
            Legend_registerEventOptions(this, options);
            // Move checkboxes
            Legend_addEvent(this.chart, 'endResize', function () {
                this.legend.positionCheckboxes();
            });
        }
        // On Legend.init and Legend.update, make sure that proximate layout
        // events are either added or removed (#18362).
        Legend_addEvent(this.chart, 'render', function () {
            if (_this.options.enabled && _this.proximate) {
                _this.proximatePositions();
                _this.positionItems();
            }
        });
    }
    /**
     * @private
     * @function Highcharts.Legend#setOptions
     * @param {Highcharts.LegendOptions} options
     */
    Legend.prototype.setOptions = function (options) {
        var padding = Legend_pick(options.padding, 8);
        /**
         * Legend options.
         *
         * @readonly
         * @name Highcharts.Legend#options
         * @type {Highcharts.LegendOptions}
         */
        this.options = options;
        if (!this.chart.styledMode) {
            this.itemStyle = options.itemStyle;
            this.itemHiddenStyle = Legend_merge(this.itemStyle, options.itemHiddenStyle);
        }
        this.itemMarginTop = options.itemMarginTop;
        this.itemMarginBottom = options.itemMarginBottom;
        this.padding = padding;
        this.initialItemY = padding - 5; // 5 is pixels above the text
        this.symbolWidth = Legend_pick(options.symbolWidth, 16);
        this.pages = [];
        this.proximate = options.layout === 'proximate' && !this.chart.inverted;
        // #12705: baseline has to be reset on every update
        this.baseline = void 0;
    };
    /**
     * Update the legend with new options. Equivalent to running `chart.update`
     * with a legend configuration option.
     *
     * @sample highcharts/legend/legend-update/
     *         Legend update
     *
     * @function Highcharts.Legend#update
     *
     * @param {Highcharts.LegendOptions} options
     * Legend options.
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart after the axis is altered. If doing more
     * operations on the chart, it is a good idea to set redraw to false and
     * call {@link Chart#redraw} after. Whether to redraw the chart.
     *
     * @emits Highcharts.Legends#event:afterUpdate
     */
    Legend.prototype.update = function (options, redraw) {
        var chart = this.chart;
        this.setOptions(Legend_merge(true, this.options, options));
        if ('events' in this.options) {
            // Legend event handlers
            Legend_registerEventOptions(this, this.options);
        }
        this.destroy();
        chart.isDirtyLegend = chart.isDirtyBox = true;
        if (Legend_pick(redraw, true)) {
            chart.redraw();
        }
        Legend_fireEvent(this, 'afterUpdate', { redraw: redraw });
    };
    /**
     * Set the colors for the legend item.
     *
     * @private
     * @function Highcharts.Legend#colorizeItem
     * @param {Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series} item
     *        A Series or Point instance
     * @param {boolean} [visible=false]
     *        Dimmed or colored
     *
     * @todo
     * Make events official: Fires the event `afterColorizeItem`.
     */
    Legend.prototype.colorizeItem = function (item, visible) {
        var _a;
        var originalColor = item.color,
            _b = item.legendItem || {},
            area = _b.area,
            group = _b.group,
            label = _b.label,
            line = _b.line,
            symbol = _b.symbol;
        if (item instanceof Series_Series || item instanceof Series_Point) {
            item.color = ((_a = item.options) === null || _a === void 0 ? void 0 : _a.legendSymbolColor) || originalColor;
        }
        group === null || group === void 0 ? void 0 : group[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden');
        if (!this.chart.styledMode) {
            var _c = this.itemHiddenStyle,
                itemHiddenStyle = _c === void 0 ? {} : _c,
                hiddenColor_1 = itemHiddenStyle.color,
                _d = item.options,
                fillColor = _d.fillColor,
                fillOpacity = _d.fillOpacity,
                lineColor = _d.lineColor,
                marker = _d.marker,
                colorizeHidden = function (attr) {
                    if (!visible) {
                        if (attr.fill) {
                            attr.fill = hiddenColor_1;
                    }
                    if (attr.stroke) {
                        attr.stroke = hiddenColor_1;
                    }
                }
                return attr;
            };
            label === null || label === void 0 ? void 0 : label.css(Legend_merge(visible ? this.itemStyle : itemHiddenStyle));
            line === null || line === void 0 ? void 0 : line.attr(colorizeHidden({ stroke: lineColor || item.color }));
            if (symbol) {
                // Apply marker options
                symbol.attr(colorizeHidden(marker && symbol.isMarker ? // #585
                    item.pointAttribs() :
                    { fill: item.color }));
            }
            area === null || area === void 0 ? void 0 : area.attr(colorizeHidden({
                fill: fillColor || item.color,
                'fill-opacity': fillColor ? 1 : (fillOpacity !== null && fillOpacity !== void 0 ? fillOpacity : 0.75)
            }));
        }
        item.color = originalColor;
        Legend_fireEvent(this, 'afterColorizeItem', { item: item, visible: visible });
    };
    /**
     * @private
     * @function Highcharts.Legend#positionItems
     */
    Legend.prototype.positionItems = function () {
        // Now that the legend width and height are established, put the items
        // in the final position
        this.allItems.forEach(this.positionItem, this);
        if (!this.chart.isResizing) {
            this.positionCheckboxes();
        }
    };
    /**
     * Position the legend item.
     *
     * @private
     * @function Highcharts.Legend#positionItem
     * @param {Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series} item
     * The item to position
     */
    Legend.prototype.positionItem = function (item) {
        var _this = this;
        var legend = this,
            _a = item.legendItem || {},
            group = _a.group,
            _b = _a.x,
            x = _b === void 0 ? 0 : _b,
            _c = _a.y,
            y = _c === void 0 ? 0 : _c,
            options = legend.options,
            symbolPadding = options.symbolPadding,
            ltr = !options.rtl,
            checkbox = item.checkbox;
        if (group && group.element) {
            var attribs = {
                    translateX: ltr ?
                        x :
                        legend.legendWidth - x - 2 * symbolPadding - 4,
                    translateY: y
                };
            var complete = function () {
                    Legend_fireEvent(_this, 'afterPositionItem', { item: item });
            };
            group[Legend_defined(group.translateY) ? 'animate' : 'attr'](attribs, void 0, complete);
        }
        if (checkbox) {
            checkbox.x = x;
            checkbox.y = y;
        }
    };
    /**
     * Destroy a single legend item, used internally on removing series items.
     *
     * @private
     * @function Highcharts.Legend#destroyItem
     * @param {Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series} item
     * The item to remove
     */
    Legend.prototype.destroyItem = function (item) {
        var checkbox = item.checkbox,
            legendItem = item.legendItem || {};
        // Destroy SVG elements
        for (var _i = 0, _a = ['group', 'label', 'line', 'symbol']; _i < _a.length; _i++) {
            var key = _a[_i];
            if (legendItem[key]) {
                legendItem[key] = legendItem[key].destroy();
            }
        }
        if (checkbox) {
            Legend_discardElement(checkbox);
        }
        item.legendItem = void 0;
    };
    /**
     * Destroy the legend. Used internally. To reflow objects, `chart.redraw`
     * must be called after destruction.
     *
     * @private
     * @function Highcharts.Legend#destroy
     */
    Legend.prototype.destroy = function () {
        var legend = this;
        // Destroy items
        for (var _i = 0, _a = this.getAllItems(); _i < _a.length; _i++) {
            var item = _a[_i];
            this.destroyItem(item);
        }
        // Destroy legend elements
        for (var _b = 0, _c = [
            'clipRect',
            'up',
            'down',
            'pager',
            'nav',
            'box',
            'title',
            'group'
        ]; _b < _c.length; _b++) {
            var key = _c[_b];
            if (legend[key]) {
                legend[key] = legend[key].destroy();
            }
        }
        this.display = null; // Reset in .render on update.
    };
    /**
     * Position the checkboxes after the width is determined.
     *
     * @private
     * @function Highcharts.Legend#positionCheckboxes
     */
    Legend.prototype.positionCheckboxes = function () {
        var alignAttr = this.group && this.group.alignAttr,
            clipHeight = this.clipHeight || this.legendHeight,
            titleHeight = this.titleHeight;
        var translateY;
        if (alignAttr) {
            translateY = alignAttr.translateY;
            this.allItems.forEach(function (item) {
                var checkbox = item.checkbox;
                var top;
                if (checkbox) {
                    top = translateY + titleHeight + checkbox.y +
                        (this.scrollOffset || 0) + 3;
                    Legend_css(checkbox, {
                        left: (alignAttr.translateX + item.checkboxOffset +
                            checkbox.x - 20) + 'px',
                        top: top + 'px',
                        display: this.proximate || (top > translateY - 6 &&
                            top < translateY + clipHeight - 6) ?
                            '' :
                            'none'
                    });
                }
            }, this);
        }
    };
    /**
     * Render the legend title on top of the legend.
     *
     * @private
     * @function Highcharts.Legend#renderTitle
     */
    Legend.prototype.renderTitle = function () {
        var options = this.options,
            padding = this.padding,
            titleOptions = options.title;
        var bBox,
            titleHeight = 0;
        if (titleOptions.text) {
            if (!this.title) {
                /**
                 * SVG element of the legend title.
                 *
                 * @readonly
                 * @name Highcharts.Legend#title
                 * @type {Highcharts.SVGElement}
                 */
                this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, void 0, void 0, void 0, options.useHTML, void 0, 'legend-title')
                    .attr({ zIndex: 1 });
                if (!this.chart.styledMode) {
                    this.title.css(titleOptions.style);
                }
                this.title.add(this.group);
            }
            // Set the max title width (#7253)
            if (!titleOptions.width) {
                this.title.css({
                    width: this.maxLegendWidth + 'px'
                });
            }
            bBox = this.title.getBBox();
            titleHeight = bBox.height;
            this.offsetWidth = bBox.width; // #1717
            this.contentGroup.attr({ translateY: titleHeight });
        }
        this.titleHeight = titleHeight;
    };
    /**
     * Set the legend item text.
     *
     * @function Highcharts.Legend#setText
     * @param {Highcharts.Point|Highcharts.Series} item
     *        The item for which to update the text in the legend.
     */
    Legend.prototype.setText = function (item) {
        var options = this.options;
        item.legendItem.label.attr({
            text: options.labelFormat ?
                Legend_format(options.labelFormat, item, this.chart) :
                options.labelFormatter.call(item)
        });
    };
    /**
     * Render a single specific legend item. Called internally from the `render`
     * function.
     *
     * @private
     * @function Highcharts.Legend#renderItem
     * @param {Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series} item
     * The item to render.
     */
    Legend.prototype.renderItem = function (item) {
        var legend = this,
            legendItem = item.legendItem = item.legendItem || {},
            chart = legend.chart,
            renderer = chart.renderer,
            options = legend.options,
            horizontal = options.layout === 'horizontal',
            symbolWidth = legend.symbolWidth,
            symbolPadding = options.symbolPadding || 0,
            itemStyle = legend.itemStyle,
            itemHiddenStyle = legend.itemHiddenStyle,
            itemDistance = horizontal ? Legend_pick(options.itemDistance, 20) : 0,
            ltr = !options.rtl,
            isSeries = !item.series,
            series = !isSeries && item.series.drawLegendSymbol ?
                item.series :
                item,
            seriesOptions = series.options,
            showCheckbox = (!!legend.createCheckboxForItem &&
                seriesOptions &&
                seriesOptions.showCheckbox),
            useHTML = options.useHTML,
            itemClassName = item.options.className;
        var label = legendItem.label, 
            // Full width minus text width
            itemExtraWidth = symbolWidth + symbolPadding +
                itemDistance + (showCheckbox ? 20 : 0);
        if (!label) { // Generate it once, later move it
            // Generate the group box, a group to hold the symbol and text. Text
            // is to be appended in Legend class.
            legendItem.group = renderer
                .g('legend-item')
                .addClass('highcharts-' + series.type + '-series ' +
                'highcharts-color-' + item.colorIndex +
                (itemClassName ? ' ' + itemClassName : '') +
                (isSeries ?
                    ' highcharts-series-' + item.index :
                    ''))
                .attr({ zIndex: 1 })
                .add(legend.scrollGroup);
            // Generate the list item text and add it to the group
            legendItem.label = label = renderer.text('', ltr ?
                symbolWidth + symbolPadding :
                -symbolPadding, legend.baseline || 0, useHTML);
            if (!chart.styledMode) {
                // Merge to prevent modifying original (#1021)
                label.css(Legend_merge(item.visible ?
                    itemStyle :
                    itemHiddenStyle));
            }
            label
                .attr({
                align: ltr ? 'left' : 'right',
                zIndex: 2
            })
                .add(legendItem.group);
            // Get the baseline for the first item - the font size is equal for
            // all
            if (!legend.baseline) {
                legend.fontMetrics = renderer.fontMetrics(label);
                legend.baseline =
                    legend.fontMetrics.f + 3 + legend.itemMarginTop;
                label.attr('y', legend.baseline);
                legend.symbolHeight =
                    Legend_pick(options.symbolHeight, legend.fontMetrics.f);
                if (options.squareSymbol) {
                    legend.symbolWidth = Legend_pick(options.symbolWidth, Math.max(legend.symbolHeight, 16));
                    itemExtraWidth = legend.symbolWidth + symbolPadding +
                        itemDistance + (showCheckbox ? 20 : 0);
                    if (ltr) {
                        label.attr('x', legend.symbolWidth + symbolPadding);
                    }
                }
            }
            // Draw the legend symbol inside the group box
            series.drawLegendSymbol(legend, item);
            if (legend.setItemEvents) {
                legend.setItemEvents(item, label, useHTML);
            }
        }
        // Add the HTML checkbox on top
        if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) {
            legend.createCheckboxForItem(item);
        }
        // Colorize the items
        legend.colorizeItem(item, item.visible);
        // Take care of max width and text overflow (#6659)
        if (chart.styledMode || !itemStyle.width) {
            label.css({
                width: ((options.itemWidth ||
                    legend.widthOption ||
                    chart.spacingBox.width) - itemExtraWidth) + 'px'
            });
        }
        // Always update the text
        legend.setText(item);
        // Calculate the positions for the next line
        var bBox = label.getBBox();
        var fontMetricsH = (legend.fontMetrics && legend.fontMetrics.h) || 0;
        item.itemWidth = item.checkboxOffset =
            options.itemWidth ||
                legendItem.labelWidth ||
                bBox.width + itemExtraWidth;
        legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth);
        legend.totalItemWidth += item.itemWidth;
        legend.itemHeight = item.itemHeight = Math.round(legendItem.labelHeight ||
            // Use bBox for multiline (#16398)
            (bBox.height > fontMetricsH * 1.5 ? bBox.height : fontMetricsH));
    };
    /**
     * Get the position of the item in the layout. We now know the
     * maxItemWidth from the previous loop.
     *
     * @private
     * @function Highcharts.Legend#layoutItem
     * @param {Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series} item
     */
    Legend.prototype.layoutItem = function (item) {
        var options = this.options,
            padding = this.padding,
            horizontal = options.layout === 'horizontal',
            itemHeight = item.itemHeight,
            itemMarginBottom = this.itemMarginBottom,
            itemMarginTop = this.itemMarginTop,
            itemDistance = horizontal ? Legend_pick(options.itemDistance, 20) : 0,
            maxLegendWidth = this.maxLegendWidth,
            itemWidth = (options.alignColumns &&
                this.totalItemWidth > maxLegendWidth) ?
                this.maxItemWidth :
                item.itemWidth,
            legendItem = item.legendItem || {};
        // If the item exceeds the width, start a new line
        if (horizontal &&
            this.itemX - padding + itemWidth > maxLegendWidth) {
            this.itemX = padding;
            if (this.lastLineHeight) { // Not for the first line (#10167)
                this.itemY += (itemMarginTop +
                    this.lastLineHeight +
                    itemMarginBottom);
            }
            this.lastLineHeight = 0; // Reset for next line (#915, #3976)
        }
        // Set the edge positions
        this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom;
        this.lastLineHeight = Math.max(// #915
        itemHeight, this.lastLineHeight);
        // Cache the position of the newly generated or reordered items
        legendItem.x = this.itemX;
        legendItem.y = this.itemY;
        // Advance
        if (horizontal) {
            this.itemX += itemWidth;
        }
        else {
            this.itemY +=
                itemMarginTop + itemHeight + itemMarginBottom;
            this.lastLineHeight = itemHeight;
        }
        // The width of the widest item
        this.offsetWidth = this.widthOption || Math.max((horizontal ? this.itemX - padding - (item.checkbox ?
            // Decrease by itemDistance only when no checkbox #4853
            0 :
            itemDistance) : itemWidth) + padding, this.offsetWidth);
    };
    /**
     * Get all items, which is one item per series for most series and one
     * item per point for pie series and its derivatives. Fires the event
     * `afterGetAllItems`.
     *
     * @private
     * @function Highcharts.Legend#getAllItems
     * @return {Array<(Highcharts.BubbleLegendItem|Highcharts.Point|Highcharts.Series)>}
     * The current items in the legend.
     * @emits Highcharts.Legend#event:afterGetAllItems
     */
    Legend.prototype.getAllItems = function () {
        var allItems = [];
        this.chart.series.forEach(function (series) {
            var seriesOptions = series && series.options;
            // Handle showInLegend. If the series is linked to another series,
            // defaults to false.
            if (series && Legend_pick(seriesOptions.showInLegend, !Legend_defined(seriesOptions.linkedTo) ? void 0 : false, true)) {
                // Use points or series for the legend item depending on
                // legendType
                allItems = allItems.concat((series.legendItem || {}).labels ||
                    (seriesOptions.legendType === 'point' ?
                        series.data :
                        series));
            }
        });
        Legend_fireEvent(this, 'afterGetAllItems', { allItems: allItems });
        return allItems;
    };
    /**
     * Get a short, three letter string reflecting the alignment and layout.
     *
     * @private
     * @function Highcharts.Legend#getAlignment
     * @return {string}
     * The alignment, empty string if floating
     */
    Legend.prototype.getAlignment = function () {
        var options = this.options;
        // Use the first letter of each alignment option in order to detect
        // the side. (#4189 - use charAt(x) notation instead of [x] for IE7)
        if (this.proximate) {
            return options.align.charAt(0) + 'tv';
        }
        return options.floating ? '' : (options.align.charAt(0) +
            options.verticalAlign.charAt(0) +
            options.layout.charAt(0));
    };
    /**
     * Adjust the chart margins by reserving space for the legend on only one
     * side of the chart. If the position is set to a corner, top or bottom is
     * reserved for horizontal legends and left or right for vertical ones.
     *
     * @private
     * @function Highcharts.Legend#adjustMargins
     * @param {Array<number>} margin
     * @param {Array<number>} spacing
     */
    Legend.prototype.adjustMargins = function (margin, spacing) {
        var chart = this.chart,
            options = this.options,
            alignment = this.getAlignment();
        if (alignment) {
            ([
                /(lth|ct|rth)/,
                /(rtv|rm|rbv)/,
                /(rbh|cb|lbh)/,
                /(lbv|lm|ltv)/
            ]).forEach(function (alignments, side) {
                if (alignments.test(alignment) && !Legend_defined(margin[side])) {
                    // Now we have detected on which side of the chart we should
                    // reserve space for the legend
                    chart[marginNames[side]] = Math.max(chart[marginNames[side]], (chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] +
                        [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] +
                        Legend_pick(options.margin, 12) +
                        spacing[side] +
                        (chart.titleOffset[side] || 0)));
                }
            });
        }
    };
    /**
     * @private
     * @function Highcharts.Legend#proximatePositions
     */
    Legend.prototype.proximatePositions = function () {
        var chart = this.chart,
            boxes = [],
            alignLeft = this.options.align === 'left';
        this.allItems.forEach(function (item) {
            var lastPoint,
                height,
                useFirstPoint = alignLeft,
                target,
                top;
            if (item.yAxis) {
                if (item.xAxis.options.reversed) {
                    useFirstPoint = !useFirstPoint;
                }
                if (item.points) {
                    lastPoint = Legend_find(useFirstPoint ?
                        item.points :
                        item.points.slice(0).reverse(), function (item) {
                        return Legend_isNumber(item.plotY);
                    });
                }
                height = this.itemMarginTop +
                    item.legendItem.label.getBBox().height +
                    this.itemMarginBottom;
                top = item.yAxis.top - chart.plotTop;
                if (item.visible) {
                    target = lastPoint ?
                        lastPoint.plotY :
                        item.yAxis.height;
                    target += top - 0.3 * height;
                }
                else {
                    target = top + item.yAxis.height;
                }
                boxes.push({
                    target: target,
                    size: height,
                    item: item
                });
            }
        }, this);
        var legendItem;
        for (var _i = 0, _a = Legend_distribute(boxes, chart.plotHeight); _i < _a.length; _i++) {
            var box = _a[_i];
            legendItem = box.item.legendItem || {};
            if (Legend_isNumber(box.pos)) {
                legendItem.y = chart.plotTop - chart.spacing[0] + box.pos;
            }
        }
    };
    /**
     * Render the legend. This method can be called both before and after
     * `chart.render`. If called after, it will only rearrange items instead
     * of creating new ones. Called internally on initial render and after
     * redraws.
     *
     * @private
     * @function Highcharts.Legend#render
     */
    Legend.prototype.render = function () {
        var legend = this,
            chart = legend.chart,
            renderer = chart.renderer,
            options = legend.options,
            padding = legend.padding, 
            // Add each series or point
            allItems = legend.getAllItems();
        var display,
            legendWidth,
            legendHeight,
            legendGroup = legend.group,
            allowedWidth,
            box = legend.box;
        legend.itemX = padding;
        legend.itemY = legend.initialItemY;
        legend.offsetWidth = 0;
        legend.lastItemY = 0;
        legend.widthOption = Legend_relativeLength(options.width, chart.spacingBox.width - padding);
        // Compute how wide the legend is allowed to be
        allowedWidth = chart.spacingBox.width - 2 * padding - options.x;
        if (['rm', 'lm'].indexOf(legend.getAlignment().substring(0, 2)) > -1) {
            allowedWidth /= 2;
        }
        legend.maxLegendWidth = legend.widthOption || allowedWidth;
        if (!legendGroup) {
            /**
             * SVG group of the legend.
             *
             * @readonly
             * @name Highcharts.Legend#group
             * @type {Highcharts.SVGElement}
             */
            legend.group = legendGroup = renderer
                .g('legend')
                .addClass(options.className || '')
                .attr({ zIndex: 7 })
                .add();
            legend.contentGroup = renderer
                .g()
                .attr({ zIndex: 1 }) // Above background
                .add(legendGroup);
            legend.scrollGroup = renderer
                .g()
                .add(legend.contentGroup);
        }
        legend.renderTitle();
        // Sort by legendIndex
        Legend_stableSort(allItems, function (a, b) {
            return ((a.options && a.options.legendIndex) || 0) -
                ((b.options && b.options.legendIndex) || 0);
        });
        // Reversed legend
        if (options.reversed) {
            allItems.reverse();
        }
        /**
         * All items for the legend, which is an array of series for most series
         * and an array of points for pie series and its derivatives.
         *
         * @readonly
         * @name Highcharts.Legend#allItems
         * @type {Array<(Highcharts.Point|Highcharts.Series)>}
         */
        legend.allItems = allItems;
        legend.display = display = !!allItems.length;
        // Render the items. First we run a loop to set the text and properties
        // and read all the bounding boxes. The next loop computes the item
        // positions based on the bounding boxes.
        legend.lastLineHeight = 0;
        legend.maxItemWidth = 0;
        legend.totalItemWidth = 0;
        legend.itemHeight = 0;
        allItems.forEach(legend.renderItem, legend);
        allItems.forEach(legend.layoutItem, legend);
        // Get the box
        legendWidth = (legend.widthOption || legend.offsetWidth) + padding;
        legendHeight = legend.lastItemY + legend.lastLineHeight +
            legend.titleHeight;
        legendHeight = legend.handleOverflow(legendHeight);
        legendHeight += padding;
        // Draw the border and/or background
        if (!box) {
            /**
             * SVG element of the legend box.
             *
             * @readonly
             * @name Highcharts.Legend#box
             * @type {Highcharts.SVGElement}
             */
            legend.box = box = renderer.rect()
                .addClass('highcharts-legend-box')
                .attr({
                r: options.borderRadius
            })
                .add(legendGroup);
        }
        // Presentational
        if (!chart.styledMode) {
            box
                .attr({
                stroke: options.borderColor,
                'stroke-width': options.borderWidth || 0,
                fill: options.backgroundColor || 'none'
            })
                .shadow(options.shadow);
        }
        if (legendWidth > 0 && legendHeight > 0) {
            box[box.placed ? 'animate' : 'attr'](box.crisp.call({}, {
                x: 0,
                y: 0,
                width: legendWidth,
                height: legendHeight
            }, box.strokeWidth()));
        }
        // Hide the border if no items
        legendGroup[display ? 'show' : 'hide']();
        // Open for responsiveness
        if (chart.styledMode && legendGroup.getStyle('display') === 'none') {
            legendWidth = legendHeight = 0;
        }
        legend.legendWidth = legendWidth;
        legend.legendHeight = legendHeight;
        if (display) {
            legend.align();
        }
        if (!this.proximate) {
            this.positionItems();
        }
        Legend_fireEvent(this, 'afterRender');
    };
    /**
     * Align the legend to chart's box.
     *
     * @private
     * @function Highcharts.align
     * @param {Highcharts.BBoxObject} alignTo
     */
    Legend.prototype.align = function (alignTo) {
        if (alignTo === void 0) { alignTo = this.chart.spacingBox; }
        var chart = this.chart,
            options = this.options;
        // If aligning to the top and the layout is horizontal, adjust for
        // the title (#7428)
        var y = alignTo.y;
        if (/(lth|ct|rth)/.test(this.getAlignment()) &&
            chart.titleOffset[0] > 0) {
            y += chart.titleOffset[0];
        }
        else if (/(lbh|cb|rbh)/.test(this.getAlignment()) &&
            chart.titleOffset[2] > 0) {
            y -= chart.titleOffset[2];
        }
        if (y !== alignTo.y) {
            alignTo = Legend_merge(alignTo, { y: y });
        }
        if (!chart.hasRendered) {
            // Avoid animation when adjusting alignment for responsiveness and
            // colorAxis label layout
            this.group.placed = false;
        }
        this.group.align(Legend_merge(options, {
            width: this.legendWidth,
            height: this.legendHeight,
            verticalAlign: this.proximate ? 'top' : options.verticalAlign
        }), true, alignTo);
    };
    /**
     * Set up the overflow handling by adding navigation with up and down arrows
     * below the legend.
     *
     * @private
     * @function Highcharts.Legend#handleOverflow
     */
    Legend.prototype.handleOverflow = function (legendHeight) {
        var legend = this,
            chart = this.chart,
            renderer = chart.renderer,
            options = this.options,
            optionsY = options.y,
            alignTop = options.verticalAlign === 'top',
            padding = this.padding,
            maxHeight = options.maxHeight,
            navOptions = options.navigation,
            animation = Legend_pick(navOptions.animation,
            true),
            arrowSize = navOptions.arrowSize || 12,
            pages = this.pages,
            allItems = this.allItems,
            clipToHeight = function (height) {
                if (typeof height === 'number') {
                    clipRect.attr({
                        height: height
                    });
            }
            else if (clipRect) { // Reset (#5912)
                legend.clipRect = clipRect.destroy();
                legend.contentGroup.clip();
            }
            // Use HTML
            if (legend.contentGroup.div) {
                legend.contentGroup.div.style.clip = height ?
                    'rect(' + padding + 'px,9999px,' +
                        (padding + height) + 'px,0)' :
                    'auto';
            }
        }, addTracker = function (key) {
            legend[key] = renderer
                .circle(0, 0, arrowSize * 1.3)
                .translate(arrowSize / 2, arrowSize / 2)
                .add(nav);
            if (!chart.styledMode) {
                legend[key].attr('fill', 'rgba(0,0,0,0.0001)');
            }
            return legend[key];
        };
        var clipHeight,
            lastY,
            legendItem,
            spaceHeight = (chart.spacingBox.height +
                (alignTop ? -optionsY : optionsY) - padding),
            nav = this.nav,
            clipRect = this.clipRect;
        // Adjust the height
        if (options.layout === 'horizontal' &&
            options.verticalAlign !== 'middle' &&
            !options.floating) {
            spaceHeight /= 2;
        }
        if (maxHeight) {
            spaceHeight = Math.min(spaceHeight, maxHeight);
        }
        // Reset the legend height and adjust the clipping rectangle
        pages.length = 0;
        if (legendHeight &&
            spaceHeight > 0 &&
            legendHeight > spaceHeight &&
            navOptions.enabled !== false) {
            this.clipHeight = clipHeight =
                Math.max(spaceHeight - 20 - this.titleHeight - padding, 0);
            this.currentPage = Legend_pick(this.currentPage, 1);
            this.fullHeight = legendHeight;
            // Fill pages with Y positions so that the top of each a legend item
            // defines the scroll top for each page (#2098)
            allItems.forEach(function (item, i) {
                legendItem = item.legendItem || {};
                var y = legendItem.y || 0,
                    h = Math.round(legendItem.label.getBBox().height);
                var len = pages.length;
                if (!len || (y - pages[len - 1] > clipHeight &&
                    (lastY || y) !== pages[len - 1])) {
                    pages.push(lastY || y);
                    len++;
                }
                // Keep track of which page each item is on
                legendItem.pageIx = len - 1;
                if (lastY) {
                    (allItems[i - 1].legendItem || {}).pageIx = len - 1;
                }
                // Add the last page if needed (#2617, #13683)
                if (
                // Check the last item
                i === allItems.length - 1 &&
                    // If adding next page is needed (#18768)
                    y + h - pages[len - 1] > clipHeight &&
                    y > pages[len - 1]) {
                    pages.push(y);
                    legendItem.pageIx = len;
                }
                if (y !== lastY) {
                    lastY = y;
                }
            });
            // Only apply clipping if needed. Clipping causes blurred legend in
            // PDF export (#1787)
            if (!clipRect) {
                clipRect = legend.clipRect =
                    renderer.clipRect(0, padding - 2, 9999, 0);
                legend.contentGroup.clip(clipRect);
            }
            clipToHeight(clipHeight);
            // Add navigation elements
            if (!nav) {
                this.nav = nav = renderer.g()
                    .attr({ zIndex: 1 })
                    .add(this.group);
                this.up = renderer
                    .symbol('triangle', 0, 0, arrowSize, arrowSize)
                    .add(nav);
                addTracker('upTracker')
                    .on('click', function () {
                    legend.scroll(-1, animation);
                });
                this.pager = renderer.text('', 15, 10)
                    .addClass('highcharts-legend-navigation');
                if (!chart.styledMode && navOptions.style) {
                    this.pager.css(navOptions.style);
                }
                this.pager.add(nav);
                this.down = renderer
                    .symbol('triangle-down', 0, 0, arrowSize, arrowSize)
                    .add(nav);
                addTracker('downTracker')
                    .on('click', function () {
                    legend.scroll(1, animation);
                });
            }
            // Set initial position
            legend.scroll(0);
            legendHeight = spaceHeight;
            // Reset
        }
        else if (nav) {
            clipToHeight();
            this.nav = nav.destroy(); // #6322
            this.scrollGroup.attr({
                translateY: 1
            });
            this.clipHeight = 0; // #1379
        }
        return legendHeight;
    };
    /**
     * Scroll the legend by a number of pages.
     *
     * @private
     * @function Highcharts.Legend#scroll
     *
     * @param {number} scrollBy
     *        The number of pages to scroll.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether and how to apply animation.
     *
     */
    Legend.prototype.scroll = function (scrollBy, animation) {
        var _this = this;
        var chart = this.chart,
            pages = this.pages,
            pageCount = pages.length,
            clipHeight = this.clipHeight,
            navOptions = this.options.navigation,
            pager = this.pager,
            padding = this.padding;
        var currentPage = this.currentPage + scrollBy;
        // When resizing while looking at the last page
        if (currentPage > pageCount) {
            currentPage = pageCount;
        }
        if (currentPage > 0) {
            if (typeof animation !== 'undefined') {
                Legend_setAnimation(animation, chart);
            }
            this.nav.attr({
                translateX: padding,
                translateY: clipHeight + this.padding + 7 + this.titleHeight,
                visibility: 'inherit'
            });
            [this.up, this.upTracker].forEach(function (elem) {
                elem.attr({
                    'class': currentPage === 1 ?
                        'highcharts-legend-nav-inactive' :
                        'highcharts-legend-nav-active'
                });
            });
            pager.attr({
                text: currentPage + '/' + pageCount
            });
            [this.down, this.downTracker].forEach(function (elem) {
                elem.attr({
                    // Adjust to text width
                    x: 18 + this.pager.getBBox().width,
                    'class': currentPage === pageCount ?
                        'highcharts-legend-nav-inactive' :
                        'highcharts-legend-nav-active'
                });
            }, this);
            if (!chart.styledMode) {
                this.up
                    .attr({
                    fill: currentPage === 1 ?
                        navOptions.inactiveColor :
                        navOptions.activeColor
                });
                this.upTracker
                    .css({
                    cursor: currentPage === 1 ? 'default' : 'pointer'
                });
                this.down
                    .attr({
                    fill: currentPage === pageCount ?
                        navOptions.inactiveColor :
                        navOptions.activeColor
                });
                this.downTracker
                    .css({
                    cursor: currentPage === pageCount ?
                        'default' :
                        'pointer'
                });
            }
            this.scrollOffset = -pages[currentPage - 1] + this.initialItemY;
            this.scrollGroup.animate({
                translateY: this.scrollOffset
            });
            this.currentPage = currentPage;
            this.positionCheckboxes();
            // Fire event after scroll animation is complete
            var animOptions = Legend_animObject(Legend_pick(animation,
                chart.renderer.globalAnimation,
                true));
            Legend_syncTimeout(function () {
                Legend_fireEvent(_this, 'afterScroll', { currentPage: currentPage });
            }, animOptions.duration);
        }
    };
    /**
     * @private
     * @function Highcharts.Legend#setItemEvents
     * @param {Highcharts.BubbleLegendItem|Point|Highcharts.Series} item
     * @param {Highcharts.SVGElement} legendLabel
     * @param {boolean} [useHTML=false]
     * @emits Highcharts.Legend#event:itemClick
     */
    Legend.prototype.setItemEvents = function (item, legendLabel, useHTML) {
        var legend = this,
            legendItem = item.legendItem || {},
            boxWrapper = legend.chart.renderer.boxWrapper,
            isPoint = item instanceof Series_Point,
            isSeries = item instanceof Series_Series,
            activeClass = 'highcharts-legend-' +
                (isPoint ? 'point' : 'series') + '-active',
            styledMode = legend.chart.styledMode, 
            // When `useHTML`, the symbol is rendered in other group, so
            // we need to apply events listeners to both places
            legendElements = useHTML ?
                [legendLabel,
            legendItem.symbol] :
                [legendItem.group];
        var setOtherItemsState = function (state) {
                legend.allItems.forEach(function (otherItem) {
                    if (item !== otherItem) {
                        [otherItem]
                            .concat(otherItem.linkedSeries || [])
                            .forEach(function (otherItem) {
                            otherItem.setState(state, !isPoint);
                    });
                }
            });
        };
        // Set the events on the item group, or in case of useHTML, the item
        // itself (#1249)
        for (var _i = 0, legendElements_1 = legendElements; _i < legendElements_1.length; _i++) {
            var element = legendElements_1[_i];
            if (element) {
                element
                    .on('mouseover', function () {
                    if (item.visible) {
                        setOtherItemsState('inactive');
                    }
                    item.setState('hover');
                    // A CSS class to dim or hide other than the hovered
                    // series.
                    // Works only if hovered series is visible (#10071).
                    if (item.visible) {
                        boxWrapper.addClass(activeClass);
                    }
                    if (!styledMode) {
                        legendLabel.css(legend.options.itemHoverStyle);
                    }
                })
                    .on('mouseout', function () {
                    if (!legend.chart.styledMode) {
                        legendLabel.css(Legend_merge(item.visible ?
                            legend.itemStyle :
                            legend.itemHiddenStyle));
                    }
                    setOtherItemsState('');
                    // A CSS class to dim or hide other than the hovered
                    // series.
                    boxWrapper.removeClass(activeClass);
                    item.setState();
                })
                    .on('click', function (event) {
                    var defaultItemClick = function () {
                            if (item.setVisible) {
                                item.setVisible();
                        }
                        // Reset inactive state
                        setOtherItemsState(item.visible ? 'inactive' : '');
                    };
                    // A CSS class to dim or hide other than the hovered
                    // series. Event handling in iOS causes the activeClass
                    // to be added prior to click in some cases (#7418).
                    boxWrapper.removeClass(activeClass);
                    Legend_fireEvent(legend, 'itemClick', {
                        // Pass over the click/touch event. #4.
                        browserEvent: event,
                        legendItem: item
                    }, defaultItemClick);
                    // Deprecated logic
                    // Click the name or symbol
                    if (isPoint) {
                        item.firePointEvent('legendItemClick', {
                            browserEvent: event
                        });
                    }
                    else if (isSeries) {
                        Legend_fireEvent(item, 'legendItemClick', {
                            browserEvent: event
                        });
                    }
                });
            }
        }
    };
    /**
     * @private
     * @function Highcharts.Legend#createCheckboxForItem
     * @param {Highcharts.BubbleLegendItem|Point|Highcharts.Series} item
     * @emits Highcharts.Series#event:checkboxClick
     */
    Legend.prototype.createCheckboxForItem = function (item) {
        var legend = this;
        item.checkbox = Legend_createElement('input', {
            type: 'checkbox',
            className: 'highcharts-legend-checkbox',
            checked: item.selected,
            defaultChecked: item.selected // Required by IE7
        }, legend.options.itemCheckboxStyle, legend.chart.container);
        Legend_addEvent(item.checkbox, 'click', function (event) {
            var target = event.target;
            Legend_fireEvent(item.series || item, 'checkboxClick', {
                checked: target.checked,
                item: item
            }, function () {
                item.select();
            });
        });
    };
    return Legend;
}());
/* *
 *
 *  Class Namespace
 *
 * */
(function (Legend) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    function compose(ChartClass) {
        if (Legend_pushUnique(Legend_composed, 'Core.Legend')) {
            Legend_addEvent(ChartClass, 'beforeMargins', function () {
                /**
                 * The legend contains an interactive overview over chart items,
                 * usually individual series or points depending on the series
                 * type. The color axis and bubble legend are also rendered in
                 * the chart legend.
                 *
                 * @name Highcharts.Chart#legend
                 * @type {Highcharts.Legend}
                 */
                this.legend = new Legend(this, this.options.legend);
            });
        }
    }
    Legend.compose = compose;
})(Legend || (Legend = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Legend_Legend = (Legend);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * @interface Highcharts.LegendItemObject
 */ /**
* @name Highcharts.LegendItemObject#item
* @type {Highcharts.SVGElement|undefined}
*/ /**
* @name Highcharts.LegendItemObject#line
* @type {Highcharts.SVGElement|undefined}
*/ /**
* @name Highcharts.LegendItemObject#symbol
* @type {Highcharts.SVGElement|undefined}
*/
/**
 * Gets fired when the legend item is clicked. The default
 * action is to toggle the visibility of the series or point. This can be
 * prevented by returning `false` or calling `event.preventDefault()`.
 *
 * @callback Highcharts.LegendItemClickCallbackFunction
 *
 * @param {Highcharts.Legend} this
 *        The legend on which the event occurred.
 *
 * @param {Highcharts.LegendItemClickEventObject} event
 *        The event that occurred.
 */
/**
 * Information about the legend click event.
 *
 * @interface Highcharts.LegendItemClickEventObject
 */ /**
* Related browser event.
* @name Highcharts.LegendItemClickEventObject#browserEvent
* @type {Highcharts.PointerEvent}
*/ /**
* Prevent the default action of toggle the visibility of the series or point.
* @name Highcharts.LegendItemClickEventObject#preventDefault
* @type {Function}
* */ /**
* Related legend item, it can be series, point, color axis or data class from
* color axis.
* @name Highcharts.LegendItemClickEventObject#legendItem
* @type {Highcharts.Series|Highcharts.Point|Highcharts.LegendItemObject}
* */ /**
* Related legend.
* @name Highcharts.LegendItemClickEventObject#target
* @type {Highcharts.Legend}
*/ /**
* Event type.
* @name Highcharts.LegendItemClickEventObject#type
* @type {"itemClick"}
*/
/**
 * Gets fired when the legend item belonging to a point is clicked. The default
 * action is to toggle the visibility of the point. This can be prevented by
 * returning `false` or calling `event.preventDefault()`.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickCallbackFunction.
 *
 * @deprecated 11.4.4
 * @callback Highcharts.PointLegendItemClickCallbackFunction
 *
 * @param {Highcharts.Point} this
 *        The point on which the event occurred.
 *
 * @param {Highcharts.PointLegendItemClickEventObject} event
 *        The event that occurred.
 */
/**
 * Information about the legend click event.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickEventObject.
 *
 * @deprecated 11.4.4
 * @interface Highcharts.PointLegendItemClickEventObject
 */ /**
* Related browser event.
* @name Highcharts.PointLegendItemClickEventObject#browserEvent
* @type {Highcharts.PointerEvent}
*/ /**
* Prevent the default action of toggle the visibility of the point.
* @name Highcharts.PointLegendItemClickEventObject#preventDefault
* @type {Function}
*/ /**
* Related point.
* @name Highcharts.PointLegendItemClickEventObject#target
* @type {Highcharts.Point}
*/ /**
* Event type.
* @name Highcharts.PointLegendItemClickEventObject#type
* @type {"legendItemClick"}
*/
/**
 * Series color as used by the legend and some series types.
 * @name Highcharts.Series#color
 * @type {Highcharts.ColorType|undefined}
 */ /**
* Legend data for the series.
* @name Highcharts.Series#legendItem
* @type {Highcharts.LegendItemObject|undefined}
* @since 10.3.0
*/
/**
 * Gets fired when the legend item belonging to a series is clicked. The default
 * action is to toggle the visibility of the series. This can be prevented by
 * returning `false` or calling `event.preventDefault()`.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickCallbackFunction.
 *
 * @deprecated 11.4.4
 * @callback Highcharts.SeriesLegendItemClickCallbackFunction
 *
 * @param {Highcharts.Series} this
 *        The series where the event occurred.
 *
 * @param {Highcharts.SeriesLegendItemClickEventObject} event
 *        The event that occurred.
 */
/**
 * Information about the legend click event.
 *
 * **Note:** This option is deprecated in favor of
 * Highcharts.LegendItemClickEventObject.
 *
 * @deprecated 11.4.4
 * @interface Highcharts.SeriesLegendItemClickEventObject
 */ /**
* Related browser event.
* @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
* @type {Highcharts.PointerEvent}
*/ /**
* Prevent the default action of toggle the visibility of the series.
* @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
* @type {Function}
*/ /**
* Related series.
* @name Highcharts.SeriesLegendItemClickEventObject#target
* @type {Highcharts.Series}
*/ /**
* Event type.
* @name Highcharts.SeriesLegendItemClickEventObject#type
* @type {"legendItemClick"}
*/
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Chart/Chart.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var Chart_assign = (undefined && undefined.__assign) || function () {
    Chart_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 Chart_assign.apply(this, arguments);
};
var Chart_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};

var Chart_animate = AnimationUtilities.animate, Chart_animObject = AnimationUtilities.animObject, Chart_setAnimation = AnimationUtilities.setAnimation;


var Chart_defaultOptions = Defaults.defaultOptions;

var Chart_numberFormat = Core_Templating.numberFormat;

var Chart_registerEventOptions = Core_Foundation.registerEventOptions;

var Chart_charts = Core_Globals.charts, Chart_doc = Core_Globals.doc, Chart_marginNames = Core_Globals.marginNames, Chart_svg = Core_Globals.svg, Chart_win = Core_Globals.win;



var Chart_seriesTypes = Series_SeriesRegistry.seriesTypes;





var Chart_addEvent = Core_Utilities.addEvent, Chart_attr = Core_Utilities.attr, Chart_createElement = Core_Utilities.createElement, Chart_css = Core_Utilities.css, Chart_defined = Core_Utilities.defined, Chart_diffObjects = Core_Utilities.diffObjects, Chart_discardElement = Core_Utilities.discardElement, Chart_erase = Core_Utilities.erase, Chart_error = Core_Utilities.error, Chart_extend = Core_Utilities.extend, Chart_find = Core_Utilities.find, Chart_fireEvent = Core_Utilities.fireEvent, Chart_getAlignFactor = Core_Utilities.getAlignFactor, Chart_getStyle = Core_Utilities.getStyle, Chart_isArray = Core_Utilities.isArray, Chart_isNumber = Core_Utilities.isNumber, Chart_isObject = Core_Utilities.isObject, Chart_isString = Core_Utilities.isString, Chart_merge = Core_Utilities.merge, Chart_objectEach = Core_Utilities.objectEach, Chart_pick = Core_Utilities.pick, Chart_pInt = Core_Utilities.pInt, Chart_relativeLength = Core_Utilities.relativeLength, Chart_removeEvent = Core_Utilities.removeEvent, Chart_splat = Core_Utilities.splat, Chart_syncTimeout = Core_Utilities.syncTimeout, Chart_uniqueKey = Core_Utilities.uniqueKey;
/* *
 *
 *  Class
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * The Chart class. The recommended constructor is {@link Highcharts#chart}.
 *
 * @example
 * let chart = Highcharts.chart('container', {
 *        title: {
 *               text: 'My chart'
 *        },
 *        series: [{
 *            data: [1, 3, 2, 4]
 *        }]
 * })
 *
 * @class
 * @name Highcharts.Chart
 *
 * @param {string|Highcharts.HTMLDOMElement} [renderTo]
 *        The DOM element to render to, or its id.
 *
 * @param {Highcharts.Options} options
 *        The chart options structure.
 *
 * @param {Highcharts.ChartCallbackFunction} [callback]
 *        Function to run when the chart has loaded and all external images
 *        are loaded. Defining a
 *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
 *        handler is equivalent.
 */
var Chart = /** @class */ (function () {
    // Implementation
    function Chart(a, 
    /* eslint-disable @typescript-eslint/no-unused-vars */
    b, c
    /* eslint-enable @typescript-eslint/no-unused-vars */
    ) {
        this.sharedClips = {};
        var args = Chart_spreadArray([],
            arguments,
            true);
        // Remove the optional first argument, renderTo, and set it on this.
        if (Chart_isString(a) || a.nodeName) {
            this.renderTo = args.shift();
        }
        this.init(args[0], args[1]);
    }
    /**
     * Factory function for basic charts.
     *
     * @example
     * // Render a chart in to div#container
     * let chart = Highcharts.chart('container', {
     *     title: {
     *         text: 'My chart'
     *     },
     *     series: [{
     *         data: [1, 3, 2, 4]
     *     }]
     * });
     *
     * @function Highcharts.chart
     *
     * @param {string|Highcharts.HTMLDOMElement} [renderTo]
     * The DOM element to render to, or its id.
     *
     * @param {Highcharts.Options} options
     * The chart options structure.
     *
     * @param {Highcharts.ChartCallbackFunction} [callback]
     * Function to run when the chart has loaded and all external images are
     * loaded. Defining a
     * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
     * handler is equivalent.
     *
     * @return {Highcharts.Chart}
     * Returns the Chart object.
     */
    Chart.chart = function (a, b, c) {
        return new Chart(a, b, c);
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Function setting zoom options after chart init and after chart update.
     * Offers support for deprecated options.
     *
     * @private
     * @function Highcharts.Chart#setZoomOptions
     */
    Chart.prototype.setZoomOptions = function () {
        var chart = this,
            options = chart.options.chart,
            zooming = options.zooming;
        chart.zooming = Chart_assign(Chart_assign({}, zooming), { type: Chart_pick(options.zoomType, zooming.type), key: Chart_pick(options.zoomKey, zooming.key), pinchType: Chart_pick(options.pinchType, zooming.pinchType), singleTouch: Chart_pick(options.zoomBySingleTouch, zooming.singleTouch, false), resetButton: Chart_merge(zooming.resetButton, options.resetZoomButton) });
    };
    /**
     * Overridable function that initializes the chart. The constructor's
     * arguments are passed on directly.
     *
     * @function Highcharts.Chart#init
     *
     * @param {Highcharts.Options} userOptions
     *        Custom options.
     *
     * @param {Function} [callback]
     *        Function to run when the chart has loaded and all external
     *        images are loaded.
     *
     *
     * @emits Highcharts.Chart#event:init
     * @emits Highcharts.Chart#event:afterInit
     */
    Chart.prototype.init = function (userOptions, callback) {
        // Fire the event with a default function
        Chart_fireEvent(this, 'init', { args: arguments }, function () {
            var _a,
                _b;
            var options = Chart_merge(Chart_defaultOptions,
                userOptions), // Do the merge
                optionsChart = options.chart,
                renderTo = this.renderTo || optionsChart.renderTo;
            /**
             * The original options given to the constructor or a chart factory
             * like {@link Highcharts.chart} and {@link Highcharts.stockChart}.
             * The original options are shallow copied to avoid mutation. The
             * copy, `chart.userOptions`, may later be mutated to reflect
             * updated options throughout the lifetime of the chart.
             *
             * For collections, like `series`, `xAxis` and `yAxis`, the chart
             * user options should always be reflected by the item user option,
             * so for example the following should always be true:
             *
             * `chart.xAxis[0].userOptions === chart.userOptions.xAxis[0]`
             *
             * @name Highcharts.Chart#userOptions
             * @type {Highcharts.Options}
             */
            this.userOptions = Chart_extend({}, userOptions);
            if (!(this.renderTo = (Chart_isString(renderTo) ?
                Chart_doc.getElementById(renderTo) :
                renderTo))) {
                // Display an error if the renderTo is wrong
                Chart_error(13, true, this);
            }
            this.margin = [];
            this.spacing = [];
            // An array of functions that returns labels that should be
            // considered for anti-collision
            this.labelCollectors = [];
            this.callback = callback;
            this.isResizing = 0;
            /**
             * The options structure for the chart after merging
             * {@link #defaultOptions} and {@link #userOptions}. It contains
             * members for the sub elements like series, legend, tooltip etc.
             *
             * @name Highcharts.Chart#options
             * @type {Highcharts.Options}
             */
            this.options = options;
            /**
             * All the axes in the chart.
             *
             * @see  Highcharts.Chart.xAxis
             * @see  Highcharts.Chart.yAxis
             *
             * @name Highcharts.Chart#axes
             * @type {Array<Highcharts.Axis>}
             */
            this.axes = [];
            /**
             * All the current series in the chart.
             *
             * @name Highcharts.Chart#series
             * @type {Array<Highcharts.Series>}
             */
            this.series = [];
            this.locale = (_a = options.lang.locale) !== null && _a !== void 0 ? _a : (_b = this.renderTo.closest('[lang]')) === null || _b === void 0 ? void 0 : _b.lang;
            /**
             * The `Time` object associated with the chart. Since v6.0.5,
             * time settings can be applied individually for each chart. If
             * no individual settings apply, the `Time` object is shared by
             * all instances.
             *
             * @name Highcharts.Chart#time
             * @type {Highcharts.Time}
             */
            this.time = new Core_Time(Chart_extend(options.time || {}, {
                locale: this.locale
            }));
            options.time = this.time.options;
            /**
             * Callback function to override the default function that formats
             * all the numbers in the chart. Returns a string with the formatted
             * number.
             *
             * @name Highcharts.Chart#numberFormatter
             * @type {Highcharts.NumberFormatterCallbackFunction}
             */
            this.numberFormatter = (optionsChart.numberFormatter || Chart_numberFormat).bind(this);
            /**
             * Whether the chart is in styled mode, meaning all presentational
             * attributes are avoided.
             *
             * @name Highcharts.Chart#styledMode
             * @type {boolean}
             */
            this.styledMode = optionsChart.styledMode;
            this.hasCartesianSeries = optionsChart.showAxes;
            var chart = this;
            /**
             * Index position of the chart in the {@link Highcharts#charts}
             * property.
             *
             * @name Highcharts.Chart#index
             * @type {number}
             * @readonly
             */
            chart.index = Chart_charts.length; // Add the chart to the global lookup
            Chart_charts.push(chart);
            Core_Globals.chartCount++;
            // Chart event handlers
            Chart_registerEventOptions(this, optionsChart);
            /**
             * A collection of the X axes in the chart.
             *
             * @name Highcharts.Chart#xAxis
             * @type {Array<Highcharts.Axis>}
             */
            chart.xAxis = [];
            /**
             * A collection of the Y axes in the chart.
             *
             * @name Highcharts.Chart#yAxis
             * @type {Array<Highcharts.Axis>}
             *
             * @todo
             * Make events official: Fire the event `afterInit`.
             */
            chart.yAxis = [];
            chart.pointCount = chart.colorCounter = chart.symbolCounter = 0;
            this.setZoomOptions();
            // Fire after init but before first render, before axes and series
            // have been initialized.
            Chart_fireEvent(chart, 'afterInit');
            chart.firstRender();
        });
    };
    /**
     * Internal function to unitialize an individual series.
     *
     * @private
     * @function Highcharts.Chart#initSeries
     */
    Chart.prototype.initSeries = function (options) {
        var chart = this,
            optionsChart = chart.options.chart,
            type = (options.type ||
                optionsChart.type),
            SeriesClass = Chart_seriesTypes[type];
        // No such series type
        if (!SeriesClass) {
            Chart_error(17, true, chart, { missingModuleFor: type });
        }
        var series = new SeriesClass();
        if (typeof series.init === 'function') {
            series.init(chart, options);
        }
        return series;
    };
    /**
     * Internal function to set data for all series with enabled sorting.
     *
     * @private
     * @function Highcharts.Chart#setSortedData
     */
    Chart.prototype.setSortedData = function () {
        this.getSeriesOrderByLinks().forEach(function (series) {
            // We need to set data for series with sorting after series init
            if (!series.points && !series.data && series.enabledDataSorting) {
                series.setData(series.options.data, false);
            }
        });
    };
    /**
     * Sort and return chart series in order depending on the number of linked
     * series.
     *
     * @private
     * @function Highcharts.Series#getSeriesOrderByLinks
     */
    Chart.prototype.getSeriesOrderByLinks = function () {
        return this.series.concat().sort(function (a, b) {
            if (a.linkedSeries.length || b.linkedSeries.length) {
                return b.linkedSeries.length - a.linkedSeries.length;
            }
            return 0;
        });
    };
    /**
     * Order all series or axes above a given index. When series or axes are
     * added and ordered by configuration, only the last series is handled
     * (#248, #1123, #2456, #6112). This function is called on series and axis
     * initialization and destroy.
     *
     * @private
     * @function Highcharts.Chart#orderItems
     * @param {string} coll The collection name
     * @param {number} [fromIndex=0]
     * If this is given, only the series above this index are handled.
     */
    Chart.prototype.orderItems = function (coll, fromIndex) {
        if (fromIndex === void 0) { fromIndex = 0; }
        var collection = this[coll], 
            // Item options should be reflected in chart.options.series,
            // chart.options.yAxis etc
            optionsArray = this.options[coll] = Chart_splat(this.options[coll])
                .slice(),
            userOptionsArray = this.userOptions[coll] = this.userOptions[coll] ?
                Chart_splat(this.userOptions[coll]).slice() :
                [];
        if (this.hasRendered) {
            // Remove all above index
            optionsArray.splice(fromIndex);
            userOptionsArray.splice(fromIndex);
        }
        if (collection) {
            for (var i = fromIndex, iEnd = collection.length; i < iEnd; ++i) {
                var item = collection[i];
                if (item) {
                    /**
                     * Contains the series' index in the `Chart.series` array.
                     *
                     * @name Highcharts.Series#index
                     * @type {number}
                     * @readonly
                     */
                    item.index = i;
                    if (item instanceof Series_Series) {
                        item.name = item.getName();
                    }
                    if (!item.options.isInternal) {
                        optionsArray[i] = item.options;
                        userOptionsArray[i] = item.userOptions;
                    }
                }
            }
        }
    };
    /**
     * Check whether a given point is within the plot area.
     *
     * @function Highcharts.Chart#isInsidePlot
     *
     * @param {number} plotX
     * Pixel x relative to the plot area.
     *
     * @param {number} plotY
     * Pixel y relative to the plot area.
     *
     * @param {Highcharts.ChartIsInsideOptionsObject} [options]
     * Options object.
     *
     * @return {boolean}
     * Returns true if the given point is inside the plot area.
     */
    Chart.prototype.isInsidePlot = function (plotX, plotY, options) {
        var _a;
        if (options === void 0) { options = {}; }
        var _b = this,
            inverted = _b.inverted,
            plotBox = _b.plotBox,
            plotLeft = _b.plotLeft,
            plotTop = _b.plotTop,
            scrollablePlotBox = _b.scrollablePlotBox,
            _c = (options.visiblePlotOnly &&
                ((_a = this.scrollablePlotArea) === null || _a === void 0 ? void 0 : _a.scrollingContainer)) || {},
            _d = _c.scrollLeft,
            scrollLeft = _d === void 0 ? 0 : _d,
            _e = _c.scrollTop,
            scrollTop = _e === void 0 ? 0 : _e,
            series = options.series,
            box = (options.visiblePlotOnly && scrollablePlotBox) || plotBox,
            x = options.inverted ? plotY : plotX,
            y = options.inverted ? plotX : plotY,
            e = {
                x: x,
                y: y,
                isInsidePlot: true,
                options: options
            };
        if (!options.ignoreX) {
            var xAxis = (series &&
                    (inverted && !this.polar ? series.yAxis : series.xAxis)) || {
                    pos: plotLeft,
                    len: Infinity
                };
            var chartX = options.paneCoordinates ?
                    xAxis.pos + x : plotLeft + x;
            if (!(chartX >= Math.max(scrollLeft + plotLeft, xAxis.pos) &&
                chartX <= Math.min(scrollLeft + plotLeft + box.width, xAxis.pos + xAxis.len))) {
                e.isInsidePlot = false;
            }
        }
        if (!options.ignoreY && e.isInsidePlot) {
            var yAxis = (!inverted && options.axis &&
                    !options.axis.isXAxis && options.axis) || (series && (inverted ? series.xAxis : series.yAxis)) || {
                    pos: plotTop,
                    len: Infinity
                };
            var chartY = options.paneCoordinates ?
                    yAxis.pos + y : plotTop + y;
            if (!(chartY >= Math.max(scrollTop + plotTop, yAxis.pos) &&
                chartY <= Math.min(scrollTop + plotTop + box.height, yAxis.pos + yAxis.len))) {
                e.isInsidePlot = false;
            }
        }
        Chart_fireEvent(this, 'afterIsInsidePlot', e);
        return e.isInsidePlot;
    };
    /**
     * Redraw the chart after changes have been done to the data, axis extremes
     * chart size or chart elements. All methods for updating axes, series or
     * points have a parameter for redrawing the chart. This is `true` by
     * default. But in many cases you want to do more than one operation on the
     * chart before redrawing, for example add a number of points. In those
     * cases it is a waste of resources to redraw the chart for each new point
     * added. So you add the points and call `chart.redraw()` after.
     *
     * @function Highcharts.Chart#redraw
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     * If or how to apply animation to the redraw. When `undefined`, it applies
     * the animation that is set in the `chart.animation` option.
     *
     * @emits Highcharts.Chart#event:afterSetExtremes
     * @emits Highcharts.Chart#event:beforeRedraw
     * @emits Highcharts.Chart#event:predraw
     * @emits Highcharts.Chart#event:redraw
     * @emits Highcharts.Chart#event:render
     * @emits Highcharts.Chart#event:updatedData
     */
    Chart.prototype.redraw = function (animation) {
        Chart_fireEvent(this, 'beforeRedraw');
        var chart = this,
            axes = chart.hasCartesianSeries ? chart.axes : chart.colorAxis || [],
            series = chart.series,
            pointer = chart.pointer,
            legend = chart.legend,
            legendUserOptions = chart.userOptions.legend,
            renderer = chart.renderer,
            isHiddenChart = renderer.isHidden(),
            afterRedraw = [];
        var hasDirtyStacks,
            hasStackedSeries,
            i,
            isDirtyBox = chart.isDirtyBox,
            redrawLegend = chart.isDirtyLegend,
            serie;
        renderer.rootFontSize = renderer.boxWrapper.getStyle('font-size');
        // Handle responsive rules, not only on resize (#6130)
        if (chart.setResponsive) {
            chart.setResponsive(false);
        }
        // Set the global animation. When chart.hasRendered is not true, the
        // redraw call comes from a responsive rule and animation should not
        // occur.
        Chart_setAnimation(chart.hasRendered ? animation : false, chart);
        if (isHiddenChart) {
            chart.temporaryDisplay();
        }
        // Adjust title layout (reflow multiline text)
        chart.layOutTitles(false);
        // Link stacked series
        i = series.length;
        while (i--) {
            serie = series[i];
            if (serie.options.stacking || serie.options.centerInCategory) {
                hasStackedSeries = true;
                if (serie.isDirty) {
                    hasDirtyStacks = true;
                    break;
                }
            }
        }
        if (hasDirtyStacks) { // Mark others as dirty
            i = series.length;
            while (i--) {
                serie = series[i];
                if (serie.options.stacking) {
                    serie.isDirty = true;
                }
            }
        }
        // Handle updated data in the series
        series.forEach(function (serie) {
            if (serie.isDirty) {
                if (serie.options.legendType === 'point') {
                    if (typeof serie.updateTotals === 'function') {
                        serie.updateTotals();
                    }
                    redrawLegend = true;
                }
                else if (legendUserOptions &&
                    (!!legendUserOptions.labelFormatter ||
                        legendUserOptions.labelFormat)) {
                    redrawLegend = true; // #2165
                }
            }
            if (serie.isDirtyData) {
                Chart_fireEvent(serie, 'updatedData');
            }
        });
        // Handle added or removed series
        if (redrawLegend && legend && legend.options.enabled) {
            // Draw legend graphics
            legend.render();
            chart.isDirtyLegend = false;
        }
        // Reset stacks
        if (hasStackedSeries) {
            chart.getStacks();
        }
        // Set axes scales
        axes.forEach(function (axis) {
            axis.updateNames();
            axis.setScale();
        });
        chart.getMargins(); // #3098
        // If one axis is dirty, all axes must be redrawn (#792, #2169)
        axes.forEach(function (axis) {
            if (axis.isDirty) {
                isDirtyBox = true;
            }
        });
        // Redraw axes
        axes.forEach(function (axis) {
            // Fire 'afterSetExtremes' only if extremes are set
            var key = axis.min + ',' + axis.max;
            if (axis.extKey !== key) { // #821, #4452
                axis.extKey = key;
                // Prevent a recursive call to chart.redraw() (#1119)
                afterRedraw.push(function () {
                    Chart_fireEvent(axis, 'afterSetExtremes', Chart_extend(axis.eventArgs, axis.getExtremes())); // #747, #751
                    delete axis.eventArgs;
                });
            }
            if (isDirtyBox || hasStackedSeries) {
                axis.redraw();
            }
        });
        // The plot areas size has changed
        if (isDirtyBox) {
            chart.drawChartBox();
        }
        // Fire an event before redrawing series, used by the boost module to
        // clear previous series renderings.
        Chart_fireEvent(chart, 'predraw');
        // Redraw affected series
        series.forEach(function (serie) {
            if ((isDirtyBox || serie.isDirty) && serie.visible) {
                serie.redraw();
            }
            // Set it here, otherwise we will have unlimited 'updatedData' calls
            // for a hidden series after setData(). Fixes #6012
            serie.isDirtyData = false;
        });
        // Move tooltip or reset
        if (pointer) {
            pointer.reset(true);
        }
        // Redraw if canvas
        renderer.draw();
        // Fire the events
        Chart_fireEvent(chart, 'redraw');
        Chart_fireEvent(chart, 'render');
        if (isHiddenChart) {
            chart.temporaryDisplay(true);
        }
        // Fire callbacks that are put on hold until after the redraw
        afterRedraw.forEach(function (callback) {
            callback.call();
        });
    };
    /**
     * Get an axis, series or point object by `id` as given in the configuration
     * options. Returns `undefined` if no item is found.
     *
     * @sample highcharts/plotoptions/series-id/
     *         Get series by id
     *
     * @function Highcharts.Chart#get
     *
     * @param {string} id
     * The id as given in the configuration options.
     *
     * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined}
     * The retrieved item.
     */
    Chart.prototype.get = function (id) {
        var series = this.series;
        /**
         * @private
         */
        function itemById(item) {
            return (item.id === id ||
                (item.options && item.options.id === id));
        }
        var ret = 
            // Search axes
            Chart_find(this.axes,
            itemById) ||
                // Search series
                Chart_find(this.series,
            itemById);
        // Search points
        for (var i = 0; !ret && i < series.length; i++) {
            ret = Chart_find(series[i].points || [], itemById);
        }
        return ret;
    };
    /**
     * Create the Axis instances based on the config options.
     *
     * @private
     * @function Highcharts.Chart#createAxes
     * @emits Highcharts.Chart#event:afterCreateAxes
     * @emits Highcharts.Chart#event:createAxes
     */
    Chart.prototype.createAxes = function () {
        var options = this.userOptions;
        Chart_fireEvent(this, 'createAxes');
        for (var _i = 0, _a = ['xAxis', 'yAxis']; _i < _a.length; _i++) {
            var coll = _a[_i];
            var arr = options[coll] = Chart_splat(options[coll] || {});
            for (var _b = 0, arr_1 = arr; _b < arr_1.length; _b++) {
                var axisOptions = arr_1[_b];
                // eslint-disable-next-line no-new
                new Axis_Axis(this, axisOptions, coll);
            }
        }
        Chart_fireEvent(this, 'afterCreateAxes');
    };
    /**
     * Returns an array of all currently selected points in the chart. Points
     * can be selected by clicking or programmatically by the
     * {@link Highcharts.Point#select}
     * function.
     *
     * @sample highcharts/plotoptions/series-allowpointselect-line/
     *         Get selected points
     * @sample highcharts/members/point-select-lasso/
     *         Lasso selection
     * @sample highcharts/chart/events-selection-points/
     *         Rectangle selection
     *
     * @function Highcharts.Chart#getSelectedPoints
     *
     * @return {Array<Highcharts.Point>}
     *         The currently selected points.
     */
    Chart.prototype.getSelectedPoints = function () {
        return this.series.reduce(function (acc, series) {
            // For one-to-one points inspect series.data in order to retrieve
            // points outside the visible range (#6445). For grouped data,
            // inspect the generated series.points.
            series.getPointsCollection()
                .forEach(function (point) {
                if (Chart_pick(point.selectedStaging, point.selected)) {
                    acc.push(point);
                }
            });
            return acc;
        }, []);
    };
    /**
     * Returns an array of all currently selected series in the chart. Series
     * can be selected either programmatically by the
     * {@link Highcharts.Series#select}
     * function or by checking the checkbox next to the legend item if
     * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox)
     * is true.
     *
     * @sample highcharts/members/chart-getselectedseries/
     *         Get selected series
     *
     * @function Highcharts.Chart#getSelectedSeries
     *
     * @return {Array<Highcharts.Series>}
     *         The currently selected series.
     */
    Chart.prototype.getSelectedSeries = function () {
        return this.series.filter(function (s) { return s.selected; });
    };
    /**
     * Set a new title or subtitle for the chart.
     *
     * @sample highcharts/members/chart-settitle/
     *         Set title text and styles
     *
     * @function Highcharts.Chart#setTitle
     *
     * @param {Highcharts.TitleOptions} [titleOptions]
     *        New title options. The title text itself is set by the
     *        `titleOptions.text` property.
     *
     * @param {Highcharts.SubtitleOptions} [subtitleOptions]
     *        New subtitle options. The subtitle text itself is set by the
     *        `subtitleOptions.text` property.
     *
     * @param {boolean} [redraw]
     *        Whether to redraw the chart or wait for a later call to
     *        `chart.redraw()`.
     */
    Chart.prototype.setTitle = function (titleOptions, subtitleOptions, redraw) {
        this.applyDescription('title', titleOptions);
        this.applyDescription('subtitle', subtitleOptions);
        // The initial call also adds the caption. On update, chart.update will
        // relay to Chart.setCaption.
        this.applyDescription('caption', void 0);
        this.layOutTitles(redraw);
    };
    /**
     * Apply a title, subtitle or caption for the chart
     *
     * @private
     * @function Highcharts.Chart#applyDescription
     * @param key {string}
     * Either title, subtitle or caption
     * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions
     * The options to set, will be merged with default options.
     */
    Chart.prototype.applyDescription = function (key, explicitOptions) {
        var _a;
        var chart = this;
        // Merge default options with explicit options
        var options = this.options[key] = Chart_merge(this.options[key],
            explicitOptions);
        var elem = this[key];
        if (elem && explicitOptions) {
            this[key] = elem = elem.destroy(); // Remove old
        }
        if (options && !elem) {
            elem = this.renderer.text(options.text, 0, 0, options.useHTML)
                .attr({
                align: options.align,
                'class': 'highcharts-' + key,
                zIndex: options.zIndex || 4
            })
                .css({
                textOverflow: 'ellipsis',
                whiteSpace: 'nowrap'
            })
                .add();
            // Update methods, relay to `applyDescription`
            elem.update = function (updateOptions, redraw) {
                chart.applyDescription(key, updateOptions);
                chart.layOutTitles(redraw);
            };
            // Presentational
            if (!this.styledMode) {
                elem.css(Chart_extend(key === 'title' ? {
                    // #2944
                    fontSize: this.options.isStock ? '1em' : '1.2em'
                } : {}, options.style));
            }
            // Get unwrapped text length and reset
            elem.textPxLength = elem.getBBox().width;
            elem.css({ whiteSpace: (_a = options.style) === null || _a === void 0 ? void 0 : _a.whiteSpace });
            /**
             * The chart title. The title has an `update` method that allows
             * modifying the options directly or indirectly via
             * `chart.update`.
             *
             * @sample highcharts/members/title-update/
             *         Updating titles
             *
             * @name Highcharts.Chart#title
             * @type {Highcharts.TitleObject}
             */
            /**
             * The chart subtitle. The subtitle has an `update` method that
             * allows modifying the options directly or indirectly via
             * `chart.update`.
             *
             * @name Highcharts.Chart#subtitle
             * @type {Highcharts.SubtitleObject}
             */
            this[key] = elem;
        }
    };
    /**
     * Internal function to lay out the chart title, subtitle and caption, and
     * cache the full offset height for use in `getMargins`. The result is
     * stored in `this.titleOffset`.
     *
     * @private
     * @function Highcharts.Chart#layOutTitles
     *
     * @param {boolean} [redraw=true]
     * @emits Highcharts.Chart#event:afterLayOutTitles
     */
    Chart.prototype.layOutTitles = function (redraw) {
        var _this = this;
        var _a,
            _b,
            _c,
            _d;
        if (redraw === void 0) { redraw = true; }
        var titleOffset = [0, 0, 0],
            _e = this,
            options = _e.options,
            renderer = _e.renderer,
            spacingBox = _e.spacingBox;
        // Lay out the title, subtitle and caption respectively
        ['title', 'subtitle', 'caption'].forEach(function (key) {
            var _a;
            var desc = _this[key],
                descOptions = _this.options[key],
                alignTo = Chart_merge(spacingBox),
                textPxLength = (desc === null || desc === void 0 ? void 0 : desc.textPxLength) || 0;
            if (desc && descOptions) {
                // Provide a hook for the exporting button to shift the title
                Chart_fireEvent(_this, 'layOutTitle', { alignTo: alignTo, key: key, textPxLength: textPxLength });
                var fontMetrics = renderer.fontMetrics(desc), baseline = fontMetrics.b, lineHeight = fontMetrics.h, verticalAlign = descOptions.verticalAlign || 'top', topAligned = verticalAlign === 'top', 
                    // Use minScale only for top-aligned titles. It is not
                    // likely that we will need scaling for other positions, but
                    // if it is requested, we need to adjust the vertical
                    // position to the scale.
                    minScale = topAligned && descOptions.minScale || 1, offset = key === 'title' ?
                        topAligned ? -3 : 0 :
                        // Floating subtitle (#6574)
                        topAligned ? titleOffset[0] + 2 : 0, uncappedScale = Math.min(alignTo.width / textPxLength, 1), scale = Math.max(minScale, uncappedScale), alignAttr = Chart_merge({
                        y: verticalAlign === 'bottom' ?
                            baseline :
                            offset + baseline
                    }, {
                        align: key === 'title' ?
                            // Title defaults to center for short titles,
                            // left for word-wrapped titles
                            (uncappedScale < minScale ? 'left' : 'center') :
                            // Subtitle defaults to the title.align
                            (_a = _this.title) === null || _a === void 0 ? void 0 : _a.alignValue
                    }, descOptions), width = descOptions.width || ((uncappedScale > minScale ?
                        // One line
                        _this.chartWidth :
                        // Allow word wrap
                        alignTo.width) / scale);
                // No animation when switching alignment
                if (desc.alignValue !== alignAttr.align) {
                    desc.placed = false;
                }
                // Set the width and read the height
                var height = Math.round(desc
                        .css({ width: "" + width + "px" })
                        // Skip the cache for HTML (#3481, #11666)
                        .getBBox(descOptions.useHTML).height);
                alignAttr.height = height;
                // Perform scaling and alignment
                desc
                    .align(alignAttr, false, alignTo)
                    .attr({
                    align: alignAttr.align,
                    scaleX: scale,
                    scaleY: scale,
                    'transform-origin': "" + (alignTo.x +
                        textPxLength *
                            scale *
                            Chart_getAlignFactor(alignAttr.align)) + " ".concat(lineHeight)
                });
                // Adjust the rendered title offset
                if (!descOptions.floating) {
                    var offset_1 = height * (
                        // When scaling down the title, preserve the offset as
                        // long as it's only one line, but scale down the offset
                        // if the title wraps to multiple lines.
                        height < lineHeight * 1.2 ? 1 : scale);
                    if (verticalAlign === 'top') {
                        titleOffset[0] = Math.ceil(titleOffset[0] + offset_1);
                    }
                    else if (verticalAlign === 'bottom') {
                        titleOffset[2] = Math.ceil(titleOffset[2] + offset_1);
                    }
                }
            }
        }, this);
        // Handle title.margin and caption.margin
        if (titleOffset[0] &&
            (((_a = options.title) === null || _a === void 0 ? void 0 : _a.verticalAlign) || 'top') === 'top') {
            titleOffset[0] += ((_b = options.title) === null || _b === void 0 ? void 0 : _b.margin) || 0;
        }
        if (titleOffset[2] &&
            ((_c = options.caption) === null || _c === void 0 ? void 0 : _c.verticalAlign) === 'bottom') {
            titleOffset[2] += ((_d = options.caption) === null || _d === void 0 ? void 0 : _d.margin) || 0;
        }
        var requiresDirtyBox = (!this.titleOffset ||
                this.titleOffset.join(',') !== titleOffset.join(','));
        // Used in getMargins
        this.titleOffset = titleOffset;
        Chart_fireEvent(this, 'afterLayOutTitles');
        if (!this.isDirtyBox && requiresDirtyBox) {
            this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox;
            // Redraw if necessary (#2719, #2744)
            if (this.hasRendered && redraw && this.isDirtyBox) {
                this.redraw();
            }
        }
    };
    /**
     * Internal function to get the available size of the container element
     *
     * @private
     * @function Highcharts.Chart#getContainerBox
     */
    Chart.prototype.getContainerBox = function () {
        var _this = this;
        // Temporarily hide support divs from a11y and others, #21888
        var nonContainers = [].map.call(this.renderTo.children,
            function (child) {
                if (child !== _this.container) {
                    var display = child.style.display;
                child.style.display = 'none';
                return [child, display];
            }
        }), box = {
            width: Chart_getStyle(this.renderTo, 'width', true) || 0,
            height: (Chart_getStyle(this.renderTo, 'height', true) || 0)
        };
        // Restore the non-containers
        nonContainers.filter(Boolean).forEach(function (_a) {
            var div = _a[0],
                display = _a[1];
            div.style.display = display;
        });
        return box;
    };
    /**
     * Internal function to get the chart width and height according to options
     * and container size. Sets {@link Chart.chartWidth} and
     * {@link Chart.chartHeight}.
     *
     * @private
     * @function Highcharts.Chart#getChartSize
     */
    Chart.prototype.getChartSize = function () {
        var _a;
        var chart = this,
            optionsChart = chart.options.chart,
            widthOption = optionsChart.width,
            heightOption = optionsChart.height,
            containerBox = chart.getContainerBox(),
            enableDefaultHeight = containerBox.height <= 1 ||
                ( // #21510, prevent infinite reflow
                !((_a = chart.renderTo.parentElement) === null || _a === void 0 ? void 0 : _a.style.height) &&
                    chart.renderTo.style.height === '100%');
        /**
         * The current pixel width of the chart.
         *
         * @name Highcharts.Chart#chartWidth
         * @type {number}
         */
        chart.chartWidth = Math.max(// #1393
        0, widthOption || containerBox.width || 600 // #1460
        );
        /**
         * The current pixel height of the chart.
         *
         * @name Highcharts.Chart#chartHeight
         * @type {number}
         */
        chart.chartHeight = Math.max(0, Chart_relativeLength(heightOption, chart.chartWidth) ||
            (enableDefaultHeight ? 400 : containerBox.height));
        chart.containerBox = containerBox;
    };
    /**
     * If the renderTo element has no offsetWidth, most likely one or more of
     * its parents are hidden. Loop up the DOM tree to temporarily display the
     * parents, then save the original display properties, and when the true
     * size is retrieved, reset them. Used on first render and on redraws.
     *
     * @private
     * @function Highcharts.Chart#temporaryDisplay
     *
     * @param {boolean} [revert]
     * Revert to the saved original styles.
     */
    Chart.prototype.temporaryDisplay = function (revert) {
        var node = this.renderTo,
            tempStyle;
        if (!revert) {
            while (node && node.style) {
                // When rendering to a detached node, it needs to be temporarily
                // attached in order to read styling and bounding boxes (#5783,
                // #7024).
                if (!Chart_doc.body.contains(node) && !node.parentNode) {
                    node.hcOrigDetached = true;
                    Chart_doc.body.appendChild(node);
                }
                if (Chart_getStyle(node, 'display', false) === 'none' ||
                    node.hcOricDetached) {
                    node.hcOrigStyle = {
                        display: node.style.display,
                        height: node.style.height,
                        overflow: node.style.overflow
                    };
                    tempStyle = {
                        display: 'block',
                        overflow: 'hidden'
                    };
                    if (node !== this.renderTo) {
                        tempStyle.height = 0;
                    }
                    Chart_css(node, tempStyle);
                    // If it still doesn't have an offset width after setting
                    // display to block, it probably has an !important priority
                    // #2631, 6803
                    if (!node.offsetWidth) {
                        node.style.setProperty('display', 'block', 'important');
                    }
                }
                node = node.parentNode;
                if (node === Chart_doc.body) {
                    break;
                }
            }
        }
        else {
            while (node && node.style) {
                if (node.hcOrigStyle) {
                    Chart_css(node, node.hcOrigStyle);
                    delete node.hcOrigStyle;
                }
                if (node.hcOrigDetached) {
                    Chart_doc.body.removeChild(node);
                    node.hcOrigDetached = false;
                }
                node = node.parentNode;
            }
        }
    };
    /**
     * Set the {@link Chart.container|chart container's} class name, in
     * addition to `highcharts-container`.
     *
     * @function Highcharts.Chart#setClassName
     *
     * @param {string} [className]
     * The additional class name.
     */
    Chart.prototype.setClassName = function (className) {
        this.container.className = 'highcharts-container ' + (className || '');
    };
    /**
     * Get the containing element, determine the size and create the inner
     * container div to hold the chart.
     *
     * @private
     * @function Highcharts.Chart#afterGetContainer
     * @emits Highcharts.Chart#event:afterGetContainer
     */
    Chart.prototype.getContainer = function () {
        var _a;
        var chart = this,
            options = chart.options,
            optionsChart = options.chart,
            indexAttrName = 'data-highcharts-chart',
            containerId = Chart_uniqueKey(),
            renderTo = chart.renderTo;
        var containerStyle;
        // If the container already holds a chart, destroy it. The check for
        // hasRendered is there because web pages that are saved to disk from
        // the browser, will preserve the data-highcharts-chart attribute and
        // the SVG contents, but not an interactive chart. So in this case,
        // charts[oldChartIndex] will point to the wrong chart if any (#2609).
        var oldChartIndex = Chart_pInt(Chart_attr(renderTo,
            indexAttrName));
        if (Chart_isNumber(oldChartIndex) &&
            Chart_charts[oldChartIndex] &&
            Chart_charts[oldChartIndex].hasRendered) {
            Chart_charts[oldChartIndex].destroy();
        }
        // Make a reference to the chart from the div
        Chart_attr(renderTo, indexAttrName, chart.index);
        // Remove previous chart
        renderTo.innerHTML = HTML_AST.emptyHTML;
        // If the container doesn't have an offsetWidth, it has or is a child of
        // a node that has display:none. We need to temporarily move it out to a
        // visible state to determine the size, else the legend and tooltips
        // won't render properly. The skipClone option is used in sparklines as
        // a micro optimization, saving about 1-2 ms each chart.
        if (!optionsChart.skipClone && !renderTo.offsetWidth) {
            chart.temporaryDisplay();
        }
        // Get the width and height
        chart.getChartSize();
        var chartHeight = chart.chartHeight;
        var chartWidth = chart.chartWidth;
        // Allow table cells and flex-boxes to shrink without the chart blocking
        // them out (#6427)
        Chart_css(renderTo, { overflow: 'hidden' });
        // Create the inner container
        if (!chart.styledMode) {
            containerStyle = Chart_extend({
                position: 'relative',
                // Needed for context menu (avoidscrollbars) and content
                // overflow in IE
                overflow: 'hidden',
                width: chartWidth + 'px',
                height: chartHeight + 'px',
                textAlign: 'left',
                lineHeight: 'normal', // #427
                zIndex: 0, // #1072
                '-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
                userSelect: 'none', // #13503
                'touch-action': 'manipulation',
                outline: 'none',
                padding: '0px'
            }, optionsChart.style || {});
        }
        /**
         * The containing HTML element of the chart. The container is
         * dynamically inserted into the element given as the `renderTo`
         * parameter in the {@link Highcharts#chart} constructor.
         *
         * @name Highcharts.Chart#container
         * @type {Highcharts.HTMLDOMElement}
         */
        var container = Chart_createElement('div', {
                id: containerId
            },
            containerStyle,
            renderTo);
        chart.container = container;
        // Adjust width if setting height affected it (#20334)
        chart.getChartSize();
        if (chartWidth !== chart.chartWidth) {
            chartWidth = chart.chartWidth;
            if (!chart.styledMode) {
                Chart_css(container, {
                    width: Chart_pick((_a = optionsChart.style) === null || _a === void 0 ? void 0 : _a.width, chartWidth + 'px')
                });
            }
        }
        chart.containerBox = chart.getContainerBox();
        // Cache the cursor (#1650)
        chart._cursor = container.style.cursor;
        // Initialize the renderer
        var Renderer = optionsChart.renderer || !Chart_svg ?
                Renderer_RendererRegistry.getRendererType(optionsChart.renderer) :
                SVG_SVGRenderer;
        /**
         * The renderer instance of the chart. Each chart instance has only one
         * associated renderer.
         *
         * @name Highcharts.Chart#renderer
         * @type {Highcharts.SVGRenderer}
         */
        chart.renderer = new Renderer(container, chartWidth, chartHeight, void 0, optionsChart.forExport, options.exporting && options.exporting.allowHTML, chart.styledMode);
        // Set the initial animation from the options
        Chart_setAnimation(void 0, chart);
        chart.setClassName(optionsChart.className);
        if (!chart.styledMode) {
            chart.renderer.setStyle(optionsChart.style);
        }
        else {
            // Initialize definitions
            for (var key in options.defs) { // eslint-disable-line guard-for-in
                this.renderer.definition(options.defs[key]);
            }
        }
        // Add a reference to the charts index
        chart.renderer.chartIndex = chart.index;
        Chart_fireEvent(this, 'afterGetContainer');
    };
    /**
     * Calculate margins by rendering axis labels in a preliminary position.
     * Title, subtitle and legend have already been rendered at this stage, but
     * will be moved into their final positions.
     *
     * @private
     * @function Highcharts.Chart#getMargins
     * @emits Highcharts.Chart#event:getMargins
     */
    Chart.prototype.getMargins = function (skipAxes) {
        var _a = this,
            spacing = _a.spacing,
            margin = _a.margin,
            titleOffset = _a.titleOffset;
        this.resetMargins();
        // Adjust for title and subtitle
        if (titleOffset[0] && !Chart_defined(margin[0])) {
            this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]);
        }
        if (titleOffset[2] && !Chart_defined(margin[2])) {
            this.marginBottom = Math.max(this.marginBottom, titleOffset[2] + spacing[2]);
        }
        // Adjust for legend
        if (this.legend && this.legend.display) {
            this.legend.adjustMargins(margin, spacing);
        }
        Chart_fireEvent(this, 'getMargins');
        if (!skipAxes) {
            this.getAxisMargins();
        }
    };
    /**
     * @private
     * @function Highcharts.Chart#getAxisMargins
     */
    Chart.prototype.getAxisMargins = function () {
        var chart = this, 
            // [top, right, bottom, left]
            axisOffset = chart.axisOffset = [0, 0, 0, 0],
            colorAxis = chart.colorAxis,
            margin = chart.margin,
            getOffset = function (axes) {
                axes.forEach(function (axis) {
                    if (axis.visible) {
                        axis.getOffset();
                }
            });
        };
        // Pre-render axes to get labels offset width
        if (chart.hasCartesianSeries) {
            getOffset(chart.axes);
        }
        else if (colorAxis && colorAxis.length) {
            getOffset(colorAxis);
        }
        // Add the axis offsets
        Chart_marginNames.forEach(function (m, side) {
            if (!Chart_defined(margin[side])) {
                chart[m] += axisOffset[side];
            }
        });
        chart.setChartSize();
    };
    /**
     * Return the current options of the chart, but only those that differ from
     * default options. Items that can be either an object or an array of
     * objects, like `series`, `xAxis` and `yAxis`, are always returned as
     * array.
     *
     * @sample highcharts/members/chart-getoptions
     *
     * @function Highcharts.Chart#getOptions
     *
     * @since 11.1.0
     */
    Chart.prototype.getOptions = function () {
        return Chart_diffObjects(this.userOptions, Chart_defaultOptions);
    };
    /**
     * Reflows the chart to its container. By default, the Resize Observer is
     * attached to the chart's div which allows to reflows the chart
     * automatically to its container, as per the
     * [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow)
     * option.
     *
     * @sample highcharts/chart/events-container/
     *         Pop up and reflow
     *
     * @function Highcharts.Chart#reflow
     *
     * @param {global.Event} [e]
     *        Event arguments. Used primarily when the function is called
     *        internally as a response to window resize.
     */
    Chart.prototype.reflow = function (e) {
        var _a;
        var chart = this,
            oldBox = chart.containerBox,
            containerBox = chart.getContainerBox();
        (_a = chart.pointer) === null || _a === void 0 ? true : delete _a.chartPosition;
        // Width and height checks for display:none. Target is doc in Opera
        // and win in Firefox, Chrome and IE9.
        if (!chart.isPrinting &&
            !chart.isResizing &&
            oldBox &&
            // When fired by resize observer inside hidden container
            containerBox.width) {
            if (containerBox.width !== oldBox.width ||
                containerBox.height !== oldBox.height) {
                Core_Utilities.clearTimeout(chart.reflowTimeout);
                // When called from window.resize, e is set, else it's called
                // directly (#2224)
                chart.reflowTimeout = Chart_syncTimeout(function () {
                    // Set size, it may have been destroyed in the meantime
                    // (#1257)
                    if (chart.container) {
                        chart.setSize(void 0, void 0, false);
                    }
                }, e ? 100 : 0);
            }
            chart.containerBox = containerBox;
        }
    };
    /**
     * Toggle the event handlers necessary for auto resizing, depending on the
     * `chart.reflow` option.
     *
     * @private
     * @function Highcharts.Chart#setReflow
     */
    Chart.prototype.setReflow = function () {
        var chart = this;
        var runReflow = function (e) {
                var _a;
            if (((_a = chart.options) === null || _a === void 0 ? void 0 : _a.chart.reflow) && chart.hasLoaded) {
                chart.reflow(e);
            }
        };
        if (typeof ResizeObserver === 'function') {
            (new ResizeObserver(runReflow)).observe(chart.renderTo);
            // Fallback for more legacy browser versions.
        }
        else {
            var unbind = Chart_addEvent(Chart_win, 'resize',
                runReflow);
            Chart_addEvent(this, 'destroy', unbind);
        }
    };
    /**
     * Resize the chart to a given width and height. In order to set the width
     * only, the height argument may be skipped. To set the height only, pass
     * `undefined` for the width.
     *
     * @sample highcharts/members/chart-setsize-button/
     *         Test resizing from buttons
     * @sample highcharts/members/chart-setsize-jquery-resizable/
     *         Add a jQuery UI resizable
     * @sample stock/members/chart-setsize/
     *         Highcharts Stock with UI resizable
     *
     * @function Highcharts.Chart#setSize
     *
     * @param {number|null} [width]
     *        The new pixel width of the chart. Since v4.2.6, the argument can
     *        be `undefined` in order to preserve the current value (when
     *        setting height only), or `null` to adapt to the width of the
     *        containing element.
     *
     * @param {number|null} [height]
     *        The new pixel height of the chart. Since v4.2.6, the argument can
     *        be `undefined` in order to preserve the current value, or `null`
     *        in order to adapt to the height of the containing element.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether and how to apply animation. When `undefined`, it applies
     *        the animation that is set in the `chart.animation` option.
     *
     *
     * @emits Highcharts.Chart#event:endResize
     * @emits Highcharts.Chart#event:resize
     */
    Chart.prototype.setSize = function (width, height, animation) {
        var chart = this,
            renderer = chart.renderer;
        // Handle the isResizing counter
        chart.isResizing += 1;
        // Set the animation for the current process
        Chart_setAnimation(animation, chart);
        var globalAnimation = renderer.globalAnimation;
        chart.oldChartHeight = chart.chartHeight;
        chart.oldChartWidth = chart.chartWidth;
        if (typeof width !== 'undefined') {
            chart.options.chart.width = width;
        }
        if (typeof height !== 'undefined') {
            chart.options.chart.height = height;
        }
        chart.getChartSize();
        var chartWidth = chart.chartWidth,
            chartHeight = chart.chartHeight,
            _a = chart.scrollablePixelsX,
            scrollablePixelsX = _a === void 0 ? 0 : _a,
            _b = chart.scrollablePixelsY,
            scrollablePixelsY = _b === void 0 ? 0 : _b;
        // Avoid expensive redrawing if the computed size didn't change
        if (chart.isDirtyBox ||
            chartWidth !== chart.oldChartWidth ||
            chartHeight !== chart.oldChartHeight) {
            // Resize the container with the global animation applied if enabled
            // (#2503)
            if (!chart.styledMode) {
                (globalAnimation ? Chart_animate : Chart_css)(chart.container, {
                    width: "" + (chartWidth + scrollablePixelsX) + "px",
                    height: "" + (chartHeight + scrollablePixelsY) + "px"
                }, globalAnimation);
            }
            chart.setChartSize(true);
            renderer.setSize(chartWidth, chartHeight, globalAnimation);
            // Handle axes
            chart.axes.forEach(function (axis) {
                axis.isDirty = true;
                axis.setScale();
            });
            chart.isDirtyLegend = true; // Force legend redraw
            chart.isDirtyBox = true; // Force redraw of plot and chart border
            chart.layOutTitles(); // #2857
            chart.getMargins();
            chart.redraw(globalAnimation);
            chart.oldChartHeight = void 0;
            Chart_fireEvent(chart, 'resize');
            // Fire endResize and set isResizing back. If animation is disabled,
            // fire without delay, but in a new thread to avoid triggering the
            // resize observer (#19027).
            setTimeout(function () {
                if (chart) {
                    Chart_fireEvent(chart, 'endResize');
                }
            }, Chart_animObject(globalAnimation).duration);
        }
        // Handle resizing counter even if we've re-rendered or not (#20548).
        chart.isResizing -= 1;
    };
    /**
     * Set the public chart properties. This is done before and after the
     * pre-render to determine margin sizes.
     *
     * @private
     * @function Highcharts.Chart#setChartSize
     * @emits Highcharts.Chart#event:afterSetChartSize
     */
    Chart.prototype.setChartSize = function (skipAxes) {
        var chart = this,
            chartHeight = chart.chartHeight,
            chartWidth = chart.chartWidth,
            inverted = chart.inverted,
            spacing = chart.spacing,
            renderer = chart.renderer,
            clipOffset = chart.clipOffset,
            clipRoundFunc = Math[inverted ? 'floor' : 'round'];
        var plotLeft,
            plotTop,
            plotWidth,
            plotHeight;
        /**
         * The current left position of the plot area in pixels.
         *
         * @name Highcharts.Chart#plotLeft
         * @type {number}
         */
        chart.plotLeft = plotLeft = Math.round(chart.plotLeft);
        /**
         * The current top position of the plot area in pixels.
         *
         * @name Highcharts.Chart#plotTop
         * @type {number}
         */
        chart.plotTop = plotTop = Math.round(chart.plotTop);
        /**
         * The current width of the plot area in pixels.
         *
         * @name Highcharts.Chart#plotWidth
         * @type {number}
         */
        chart.plotWidth = plotWidth = Math.max(0, Math.round(chartWidth - plotLeft - chart.marginRight));
        /**
         * The current height of the plot area in pixels.
         *
         * @name Highcharts.Chart#plotHeight
         * @type {number}
         */
        chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom));
        chart.plotSizeX = inverted ? plotHeight : plotWidth;
        chart.plotSizeY = inverted ? plotWidth : plotHeight;
        // Set boxes used for alignment
        chart.spacingBox = renderer.spacingBox = {
            x: spacing[3],
            y: spacing[0],
            width: chartWidth - spacing[3] - spacing[1],
            height: chartHeight - spacing[0] - spacing[2]
        };
        chart.plotBox = renderer.plotBox = {
            x: plotLeft,
            y: plotTop,
            width: plotWidth,
            height: plotHeight
        };
        // Compute the clipping box
        if (clipOffset) {
            chart.clipBox = {
                x: clipRoundFunc(clipOffset[3]),
                y: clipRoundFunc(clipOffset[0]),
                width: clipRoundFunc(chart.plotSizeX - clipOffset[1] - clipOffset[3]),
                height: clipRoundFunc(chart.plotSizeY - clipOffset[0] - clipOffset[2])
            };
        }
        if (!skipAxes) {
            chart.axes.forEach(function (axis) {
                axis.setAxisSize();
                axis.setAxisTranslation();
            });
            renderer.alignElements();
        }
        Chart_fireEvent(chart, 'afterSetChartSize', { skipAxes: skipAxes });
    };
    /**
     * Initial margins before auto size margins are applied.
     *
     * @private
     * @function Highcharts.Chart#resetMargins
     */
    Chart.prototype.resetMargins = function () {
        Chart_fireEvent(this, 'resetMargins');
        var chart = this,
            chartOptions = chart.options.chart,
            plotBorderWidth = chartOptions.plotBorderWidth || 0,
            halfWidth = plotBorderWidth / 2;
        // Create margin and spacing array
        ['margin', 'spacing'].forEach(function splashArrays(target) {
            var value = chartOptions[target],
                values = Chart_isObject(value) ? value : [value,
                value,
                value,
                value];
            [
                'Top',
                'Right',
                'Bottom',
                'Left'
            ].forEach(function (sideName, side) {
                chart[target][side] = Chart_pick(chartOptions[target + sideName], values[side]);
            });
        });
        // Set margin names like chart.plotTop, chart.plotLeft,
        // chart.marginRight, chart.marginBottom.
        Chart_marginNames.forEach(function (m, side) {
            chart[m] = Chart_pick(chart.margin[side], chart.spacing[side]);
        });
        chart.axisOffset = [0, 0, 0, 0]; // Top, right, bottom, left
        chart.clipOffset = [
            halfWidth,
            halfWidth,
            halfWidth,
            halfWidth
        ];
        chart.plotBorderWidth = plotBorderWidth;
    };
    /**
     * Internal function to draw or redraw the borders and backgrounds for chart
     * and plot area.
     *
     * @private
     * @function Highcharts.Chart#drawChartBox
     * @emits Highcharts.Chart#event:afterDrawChartBox
     */
    Chart.prototype.drawChartBox = function () {
        var chart = this,
            optionsChart = chart.options.chart,
            renderer = chart.renderer,
            chartWidth = chart.chartWidth,
            chartHeight = chart.chartHeight,
            styledMode = chart.styledMode,
            plotBGImage = chart.plotBGImage,
            chartBackgroundColor = optionsChart.backgroundColor,
            plotBackgroundColor = optionsChart.plotBackgroundColor,
            plotBackgroundImage = optionsChart.plotBackgroundImage,
            plotLeft = chart.plotLeft,
            plotTop = chart.plotTop,
            plotWidth = chart.plotWidth,
            plotHeight = chart.plotHeight,
            plotBox = chart.plotBox,
            clipRect = chart.clipRect,
            clipBox = chart.clipBox;
        var chartBackground = chart.chartBackground,
            plotBackground = chart.plotBackground,
            plotBorder = chart.plotBorder,
            chartBorderWidth,
            mgn,
            bgAttr,
            verb = 'animate';
        // Chart area
        if (!chartBackground) {
            chart.chartBackground = chartBackground = renderer.rect()
                .addClass('highcharts-background')
                .add();
            verb = 'attr';
        }
        if (!styledMode) {
            // Presentational
            chartBorderWidth = optionsChart.borderWidth || 0;
            mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0);
            bgAttr = {
                fill: chartBackgroundColor || 'none'
            };
            if (chartBorderWidth || chartBackground['stroke-width']) { // #980
                bgAttr.stroke = optionsChart.borderColor;
                bgAttr['stroke-width'] = chartBorderWidth;
            }
            chartBackground
                .attr(bgAttr)
                .shadow(optionsChart.shadow);
        }
        else {
            chartBorderWidth = mgn = chartBackground.strokeWidth();
        }
        chartBackground[verb]({
            x: mgn / 2,
            y: mgn / 2,
            width: chartWidth - mgn - chartBorderWidth % 2,
            height: chartHeight - mgn - chartBorderWidth % 2,
            r: optionsChart.borderRadius
        });
        // Plot background
        verb = 'animate';
        if (!plotBackground) {
            verb = 'attr';
            chart.plotBackground = plotBackground = renderer.rect()
                .addClass('highcharts-plot-background')
                .add();
        }
        plotBackground[verb](plotBox);
        if (!styledMode) {
            // Presentational attributes for the background
            plotBackground
                .attr({
                fill: plotBackgroundColor || 'none'
            })
                .shadow(optionsChart.plotShadow);
            // Create the background image
            if (plotBackgroundImage) {
                if (!plotBGImage) {
                    chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight).add();
                }
                else {
                    if (plotBackgroundImage !== plotBGImage.attr('href')) {
                        plotBGImage.attr('href', plotBackgroundImage);
                    }
                    plotBGImage.animate(plotBox);
                }
            }
        }
        // Plot clip
        if (!clipRect) {
            chart.clipRect = renderer.clipRect(clipBox);
        }
        else {
            clipRect.animate({
                width: clipBox.width,
                height: clipBox.height
            });
        }
        // Plot area border
        verb = 'animate';
        if (!plotBorder) {
            verb = 'attr';
            chart.plotBorder = plotBorder = renderer.rect()
                .addClass('highcharts-plot-border')
                .attr({
                zIndex: 1 // Above the grid
            })
                .add();
        }
        if (!styledMode) {
            // Presentational
            plotBorder.attr({
                stroke: optionsChart.plotBorderColor,
                'stroke-width': optionsChart.plotBorderWidth || 0,
                fill: 'none'
            });
        }
        plotBorder[verb](plotBorder.crisp({
            x: plotLeft,
            y: plotTop,
            width: plotWidth,
            height: plotHeight
        }, -plotBorder.strokeWidth())); // #3282 plotBorder should be negative;
        // reset
        chart.isDirtyBox = false;
        Chart_fireEvent(this, 'afterDrawChartBox');
    };
    /**
     * Detect whether a certain chart property is needed based on inspecting its
     * options and series. This mainly applies to the chart.inverted property,
     * and in extensions to the chart.angular and chart.polar properties.
     *
     * @private
     * @function Highcharts.Chart#propFromSeries
     */
    Chart.prototype.propFromSeries = function () {
        var chart = this,
            optionsChart = chart.options.chart,
            seriesOptions = chart.options.series;
        var i,
            klass,
            value;
        /**
         * The flag is set to `true` if a series of the chart is inverted.
         *
         * @name Highcharts.Chart#inverted
         * @type {boolean|undefined}
         */
        ['inverted', 'angular', 'polar'].forEach(function (key) {
            // The default series type's class
            klass = Chart_seriesTypes[optionsChart.type];
            // Get the value from available chart-wide properties
            value =
                // It is set in the options:
                optionsChart[key] ||
                    // The default series class:
                    (klass && klass.prototype[key]);
            // Requires it
            // 4. Check if any the chart's series require it
            i = seriesOptions && seriesOptions.length;
            while (!value && i--) {
                klass = Chart_seriesTypes[seriesOptions[i].type];
                if (klass && klass.prototype[key]) {
                    value = true;
                }
            }
            // Set the chart property
            chart[key] = value;
        });
    };
    /**
     * Internal function to link two or more series together, based on the
     * `linkedTo` option. This is done from `Chart.render`, and after
     * `Chart.addSeries` and `Series.remove`.
     *
     * @private
     * @function Highcharts.Chart#linkSeries
     * @emits Highcharts.Chart#event:afterLinkSeries
     */
    Chart.prototype.linkSeries = function (isUpdating) {
        var chart = this,
            chartSeries = chart.series;
        // Reset links
        chartSeries.forEach(function (series) {
            series.linkedSeries.length = 0;
        });
        // Apply new links
        chartSeries.forEach(function (series) {
            var linkedTo = series.options.linkedTo;
            if (Chart_isString(linkedTo)) {
                var linkedParent = void 0;
                if (linkedTo === ':previous') {
                    linkedParent = chart.series[series.index - 1];
                }
                else {
                    linkedParent = chart.get(linkedTo);
                }
                // #3341 avoid mutual linking
                if (linkedParent &&
                    linkedParent.linkedParent !== series) {
                    linkedParent.linkedSeries.push(series);
                    /**
                     * The parent series of the current series, if the current
                     * series has a [linkedTo](https://api.highcharts.com/highcharts/series.line.linkedTo)
                     * setting.
                     *
                     * @name Highcharts.Series#linkedParent
                     * @type {Highcharts.Series}
                     * @readonly
                     */
                    series.linkedParent = linkedParent;
                    if (linkedParent.enabledDataSorting) {
                        series.setDataSortingOptions();
                    }
                    series.visible = Chart_pick(series.options.visible, linkedParent.options.visible, series.visible); // #3879
                }
            }
        });
        Chart_fireEvent(this, 'afterLinkSeries', { isUpdating: isUpdating });
    };
    /**
     * Render series for the chart.
     *
     * @private
     * @function Highcharts.Chart#renderSeries
     */
    Chart.prototype.renderSeries = function () {
        this.series.forEach(function (serie) {
            serie.translate();
            serie.render();
        });
    };
    /**
     * Render all graphics for the chart. Runs internally on initialization.
     *
     * @private
     * @function Highcharts.Chart#render
     */
    Chart.prototype.render = function () {
        var _a;
        var chart = this,
            axes = chart.axes,
            colorAxis = chart.colorAxis,
            renderer = chart.renderer,
            axisLayoutRuns = chart.options.chart.axisLayoutRuns || 2,
            renderAxes = function (axes) {
                axes.forEach(function (axis) {
                    if (axis.visible) {
                        axis.render();
                }
            });
        };
        var expectedSpace = 0, // Correction for X axis labels
            // If the plot area size has changed significantly, calculate tick
            // positions again
            redoHorizontal = true,
            redoVertical,
            run = 0;
        // Title
        chart.setTitle();
        // Fire an event before the margins are computed. This is where the
        // legend is assigned.
        Chart_fireEvent(chart, 'beforeMargins');
        // Get stacks
        (_a = chart.getStacks) === null || _a === void 0 ? void 0 : _a.call(chart);
        // Get chart margins
        chart.getMargins(true);
        chart.setChartSize();
        for (var _i = 0, axes_1 = axes; _i < axes_1.length; _i++) {
            var axis = axes_1[_i];
            var options = axis.options,
                labels = options.labels;
            if (chart.hasCartesianSeries && // #20948
                axis.horiz &&
                axis.visible &&
                labels.enabled &&
                axis.series.length &&
                axis.coll !== 'colorAxis' &&
                !chart.polar) {
                expectedSpace = options.tickLength;
                axis.createGroups();
                // Calculate expected space based on dummy tick
                var mockTick = new Axis_Tick(axis, 0, '', true), label = mockTick.createLabel('x', labels);
                mockTick.destroy();
                if (label &&
                    Chart_pick(labels.reserveSpace, !Chart_isNumber(options.crossing))) {
                    expectedSpace = label.getBBox().height +
                        labels.distance +
                        Math.max(options.offset || 0, 0);
                }
                if (expectedSpace) {
                    label === null || label === void 0 ? void 0 : label.destroy();
                    break;
                }
            }
        }
        // Use Math.max to prevent negative plotHeight
        chart.plotHeight = Math.max(chart.plotHeight - expectedSpace, 0);
        while ((redoHorizontal || redoVertical || axisLayoutRuns > 1) &&
            run < axisLayoutRuns // #19794
        ) {
            var tempWidth = chart.plotWidth,
                tempHeight = chart.plotHeight;
            for (var _b = 0, axes_2 = axes; _b < axes_2.length; _b++) {
                var axis = axes_2[_b];
                if (run === 0) {
                    // Get margins by pre-rendering axes
                    axis.setScale();
                }
                else if ((axis.horiz && redoHorizontal) ||
                    (!axis.horiz && redoVertical)) {
                    // Update to reflect the new margins
                    axis.setTickInterval(true);
                }
            }
            if (run === 0) {
                chart.getAxisMargins();
            }
            else {
                // Check again for new, rotated or moved labels
                chart.getMargins();
            }
            redoHorizontal = (tempWidth / chart.plotWidth) > (run ? 1 : 1.1);
            redoVertical = (tempHeight / chart.plotHeight) > (run ? 1 : 1.05);
            run++;
        }
        // Draw the borders and backgrounds
        chart.drawChartBox();
        // Axes
        if (chart.hasCartesianSeries) {
            renderAxes(axes);
        }
        else if (colorAxis && colorAxis.length) {
            renderAxes(colorAxis);
        }
        // The series
        if (!chart.seriesGroup) {
            chart.seriesGroup = renderer.g('series-group')
                .attr({ zIndex: 3 })
                .shadow(chart.options.chart.seriesGroupShadow)
                .add();
        }
        chart.renderSeries();
        // Credits
        chart.addCredits();
        // Handle responsiveness
        if (chart.setResponsive) {
            chart.setResponsive();
        }
        // Set flag
        chart.hasRendered = true;
    };
    /**
     * Set a new credits label for the chart.
     *
     * @sample highcharts/credits/credits-update/
     *         Add and update credits
     *
     * @function Highcharts.Chart#addCredits
     *
     * @param {Highcharts.CreditsOptions} [credits]
     * A configuration object for the new credits.
     */
    Chart.prototype.addCredits = function (credits) {
        var chart = this,
            creds = Chart_merge(true,
            this.options.credits,
            credits);
        if (creds.enabled && !this.credits) {
            /**
             * The chart's credits label. The label has an `update` method that
             * allows setting new options as per the
             * [credits options set](https://api.highcharts.com/highcharts/credits).
             *
             * @name Highcharts.Chart#credits
             * @type {Highcharts.SVGElement}
             */
            this.credits = this.renderer.text(creds.text + (this.mapCredits || ''), 0, 0)
                .addClass('highcharts-credits')
                .on('click', function () {
                if (creds.href) {
                    Chart_win.location.href = creds.href;
                }
            })
                .attr({
                align: creds.position.align,
                zIndex: 8
            });
            if (!chart.styledMode) {
                this.credits.css(creds.style);
            }
            this.credits
                .add()
                .align(creds.position);
            // Dynamically update
            this.credits.update = function (options) {
                chart.credits = chart.credits.destroy();
                chart.addCredits(options);
            };
        }
    };
    /**
     * Remove the chart and purge memory. This method is called internally
     * before adding a second chart into the same container, as well as on
     * window unload to prevent leaks.
     *
     * @sample highcharts/members/chart-destroy/
     *         Destroy the chart from a button
     * @sample stock/members/chart-destroy/
     *         Destroy with Highcharts Stock
     *
     * @function Highcharts.Chart#destroy
     *
     * @emits Highcharts.Chart#event:destroy
     */
    Chart.prototype.destroy = function () {
        var chart = this,
            axes = chart.axes,
            series = chart.series,
            container = chart.container,
            parentNode = container && container.parentNode;
        var i;
        // Fire the chart.destroy event
        Chart_fireEvent(chart, 'destroy');
        // Delete the chart from charts lookup array
        if (chart.renderer.forExport) {
            Chart_erase(Chart_charts, chart); // #6569
        }
        else {
            Chart_charts[chart.index] = void 0;
        }
        Core_Globals.chartCount--;
        chart.renderTo.removeAttribute('data-highcharts-chart');
        // Remove events
        Chart_removeEvent(chart);
        // ==== Destroy collections:
        // Destroy axes
        i = axes.length;
        while (i--) {
            axes[i] = axes[i].destroy();
        }
        // Destroy scroller & scroller series before destroying base series
        if (this.scroller && this.scroller.destroy) {
            this.scroller.destroy();
        }
        // Destroy each series
        i = series.length;
        while (i--) {
            series[i] = series[i].destroy();
        }
        // ==== Destroy chart properties:
        [
            'title', 'subtitle', 'chartBackground', 'plotBackground',
            'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits',
            'pointer', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip',
            'renderer'
        ].forEach(function (name) {
            var prop = chart[name];
            if (prop && prop.destroy) {
                chart[name] = prop.destroy();
            }
        });
        // Remove container and all SVG, check container as it can break in IE
        // when destroyed before finished loading
        if (container) {
            container.innerHTML = HTML_AST.emptyHTML;
            Chart_removeEvent(container);
            if (parentNode) {
                Chart_discardElement(container);
            }
        }
        // Clean it all up
        Chart_objectEach(chart, function (val, key) {
            delete chart[key];
        });
    };
    /**
     * Prepare for first rendering after all data are loaded.
     *
     * @private
     * @function Highcharts.Chart#firstRender
     * @emits Highcharts.Chart#event:beforeRender
     */
    Chart.prototype.firstRender = function () {
        var _a;
        var chart = this,
            options = chart.options;
        // Create the container
        chart.getContainer();
        chart.resetMargins();
        chart.setChartSize();
        // Set the common chart properties (mainly invert) from the given series
        chart.propFromSeries();
        // Get axes
        chart.createAxes();
        // Initialize the series
        var series = Chart_isArray(options.series) ? options.series : [];
        options.series = []; // Avoid mutation
        series.forEach(
        // #9680
        function (serieOptions) {
            chart.initSeries(serieOptions);
        });
        chart.linkSeries();
        chart.setSortedData();
        // Run an event after axes and series are initialized, but before
        // render. At this stage, the series data is indexed and cached in the
        // xData and yData arrays, so we can access those before rendering. Used
        // in Highcharts Stock.
        Chart_fireEvent(chart, 'beforeRender');
        chart.render();
        (_a = chart.pointer) === null || _a === void 0 ? void 0 : _a.getChartPosition(); // #14973
        // Fire the load event if there are no external images
        if (!chart.renderer.imgCount && !chart.hasLoaded) {
            chart.onload();
        }
        // If the chart was rendered outside the top container, put it back in
        // (#3679)
        chart.temporaryDisplay(true);
    };
    /**
     * Internal function that runs on chart load, async if any images are loaded
     * in the chart. Runs the callbacks and triggers the `load` and `render`
     * events.
     *
     * @private
     * @function Highcharts.Chart#onload
     * @emits Highcharts.Chart#event:load
     * @emits Highcharts.Chart#event:render
     */
    Chart.prototype.onload = function () {
        // Run callbacks, first the ones registered by modules, then user's one
        this.callbacks.concat([this.callback]).forEach(function (fn) {
            // Chart destroyed in its own callback (#3600)
            if (fn && typeof this.index !== 'undefined') {
                fn.apply(this, [this]);
            }
        }, this);
        Chart_fireEvent(this, 'load');
        Chart_fireEvent(this, 'render');
        // Set up auto resize, check for not destroyed (#6068)
        if (Chart_defined(this.index)) {
            this.setReflow();
        }
        this.warnIfA11yModuleNotLoaded();
        // Don't run again
        this.hasLoaded = true;
    };
    /**
     * Emit console warning if the a11y module is not loaded.
     * @private
     */
    Chart.prototype.warnIfA11yModuleNotLoaded = function () {
        var _a = this,
            options = _a.options,
            title = _a.title;
        if (options && !this.accessibility) {
            // Make chart behave as an image with the title as alt text
            this.renderer.boxWrapper.attr({
                role: 'img',
                'aria-label': ((title && title.element.textContent) || ''
                // #17753, < is not allowed in SVG attributes
                ).replace(/</g, '&lt;')
            });
            if (!(options.accessibility && options.accessibility.enabled === false)) {
                Chart_error('Highcharts warning: Consider including the ' +
                    '"accessibility.js" module to make your chart more ' +
                    'usable for people with disabilities. Set the ' +
                    '"accessibility.enabled" option to false to remove this ' +
                    'warning. See https://www.highcharts.com/docs/accessibility/accessibility-module.', false, this);
            }
        }
    };
    /**
     * Add a series to the chart after render time. Note that this method should
     * never be used when adding data synchronously at chart render time, as it
     * adds expense to the calculations and rendering. When adding data at the
     * same time as the chart is initialized, add the series as a configuration
     * option instead. With multiple axes, the `offset` is dynamically adjusted.
     *
     * @sample highcharts/members/chart-addseries/
     *         Add a series from a button
     * @sample stock/members/chart-addseries/
     *         Add a series in Highcharts Stock
     *
     * @function Highcharts.Chart#addSeries
     *
     * @param {Highcharts.SeriesOptionsType} options
     *        The config options for the series.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after adding.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether to apply animation, and optionally animation
     *        configuration. When `undefined`, it applies the animation that is
     *        set in the `chart.animation` option.
     *
     * @return {Highcharts.Series}
     *         The newly created series object.
     *
     * @emits Highcharts.Chart#event:addSeries
     * @emits Highcharts.Chart#event:afterAddSeries
     */
    Chart.prototype.addSeries = function (options, redraw, animation) {
        var chart = this;
        var series;
        if (options) { // <- not necessary
            redraw = Chart_pick(redraw, true); // Defaults to true
            Chart_fireEvent(chart, 'addSeries', { options: options }, function () {
                series = chart.initSeries(options);
                chart.isDirtyLegend = true;
                chart.linkSeries();
                if (series.enabledDataSorting) {
                    // We need to call `setData` after `linkSeries`
                    series.setData(options.data, false);
                }
                Chart_fireEvent(chart, 'afterAddSeries', { series: series });
                if (redraw) {
                    chart.redraw(animation);
                }
            });
        }
        return series;
    };
    /**
     * Add an axis to the chart after render time. Note that this method should
     * never be used when adding data synchronously at chart render time, as it
     * adds expense to the calculations and rendering. When adding data at the
     * same time as the chart is initialized, add the axis as a configuration
     * option instead.
     *
     * @sample highcharts/members/chart-addaxis/
     *         Add and remove axes
     *
     * @function Highcharts.Chart#addAxis
     *
     * @param {Highcharts.AxisOptions} options
     *        The axis options.
     *
     * @param {boolean} [isX=false]
     *        Whether it is an X axis or a value axis.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after adding.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether and how to apply animation in the redraw. When
     *        `undefined`, it applies the animation that is set in the
     *        `chart.animation` option.
     *
     * @return {Highcharts.Axis}
     *         The newly generated Axis object.
     */
    Chart.prototype.addAxis = function (options, isX, redraw, animation) {
        return this.createAxis(isX ? 'xAxis' : 'yAxis', { axis: options, redraw: redraw, animation: animation });
    };
    /**
     * Add a color axis to the chart after render time. Note that this method
     * should never be used when adding data synchronously at chart render time,
     * as it adds expense to the calculations and rendering. When adding data at
     * the same time as the chart is initialized, add the axis as a
     * configuration option instead.
     *
     * @sample highcharts/members/chart-addaxis/
     *         Add and remove axes
     *
     * @function Highcharts.Chart#addColorAxis
     *
     * @param {Highcharts.ColorAxisOptions} options
     *        The axis options.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart after adding.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether and how to apply animation in the redraw. When
     *        `undefined`, it applies the animation that is set in the
     *        `chart.animation` option.
     *
     * @return {Highcharts.Axis}
     *         The newly generated Axis object.
     */
    Chart.prototype.addColorAxis = function (options, redraw, animation) {
        return this.createAxis('colorAxis', { axis: options, redraw: redraw, animation: animation });
    };
    /**
     * Factory for creating different axis types.
     *
     * @private
     * @function Highcharts.Chart#createAxis
     *
     * @param {string} coll
     *        An axis type.
     *
     * @param {...Array<*>} arguments
     *        All arguments for the constructor.
     *
     * @return {Highcharts.Axis}
     *         The newly generated Axis object.
     */
    Chart.prototype.createAxis = function (coll, options) {
        var axis = new Axis_Axis(this,
            options.axis,
            coll);
        if (Chart_pick(options.redraw, true)) {
            this.redraw(options.animation);
        }
        return axis;
    };
    /**
     * Dim the chart and show a loading text or symbol. Options for the loading
     * screen are defined in {@link
     * https://api.highcharts.com/highcharts/loading|the loading options}.
     *
     * @sample highcharts/members/chart-hideloading/
     *         Show and hide loading from a button
     * @sample highcharts/members/chart-showloading/
     *         Apply different text labels
     * @sample stock/members/chart-show-hide-loading/
     *         Toggle loading in Highcharts Stock
     *
     * @function Highcharts.Chart#showLoading
     *
     * @param {string} [str]
     *        An optional text to show in the loading label instead of the
     *        default one. The default text is set in
     *        [lang.loading](https://api.highcharts.com/highcharts/lang.loading).
     */
    Chart.prototype.showLoading = function (str) {
        var chart = this,
            options = chart.options,
            loadingOptions = options.loading,
            setLoadingSize = function () {
                if (loadingDiv) {
                    Chart_css(loadingDiv, {
                        left: chart.plotLeft + 'px',
                        top: chart.plotTop + 'px',
                        width: chart.plotWidth + 'px',
                        height: chart.plotHeight + 'px'
                    });
            }
        };
        var loadingDiv = chart.loadingDiv,
            loadingSpan = chart.loadingSpan;
        // Create the layer at the first call
        if (!loadingDiv) {
            chart.loadingDiv = loadingDiv = Chart_createElement('div', {
                className: 'highcharts-loading highcharts-loading-hidden'
            }, null, chart.container);
        }
        if (!loadingSpan) {
            chart.loadingSpan = loadingSpan = Chart_createElement('span', { className: 'highcharts-loading-inner' }, null, loadingDiv);
            Chart_addEvent(chart, 'redraw', setLoadingSize); // #1080
        }
        loadingDiv.className = 'highcharts-loading';
        // Update text
        HTML_AST.setElementHTML(loadingSpan, Chart_pick(str, options.lang.loading, ''));
        if (!chart.styledMode) {
            // Update visuals
            Chart_css(loadingDiv, Chart_extend(loadingOptions.style, {
                zIndex: 10
            }));
            Chart_css(loadingSpan, loadingOptions.labelStyle);
            // Show it
            if (!chart.loadingShown) {
                Chart_css(loadingDiv, {
                    opacity: 0,
                    display: ''
                });
                Chart_animate(loadingDiv, {
                    opacity: loadingOptions.style.opacity || 0.5
                }, {
                    duration: loadingOptions.showDuration || 0
                });
            }
        }
        chart.loadingShown = true;
        setLoadingSize();
    };
    /**
     * Hide the loading layer.
     *
     * @see Highcharts.Chart#showLoading
     *
     * @sample highcharts/members/chart-hideloading/
     *         Show and hide loading from a button
     * @sample stock/members/chart-show-hide-loading/
     *         Toggle loading in Highcharts Stock
     *
     * @function Highcharts.Chart#hideLoading
     */
    Chart.prototype.hideLoading = function () {
        var options = this.options,
            loadingDiv = this.loadingDiv;
        if (loadingDiv) {
            loadingDiv.className =
                'highcharts-loading highcharts-loading-hidden';
            if (!this.styledMode) {
                Chart_animate(loadingDiv, {
                    opacity: 0
                }, {
                    duration: options.loading.hideDuration || 100,
                    complete: function () {
                        Chart_css(loadingDiv, { display: 'none' });
                    }
                });
            }
        }
        this.loadingShown = false;
    };
    /**
     * A generic function to update any element of the chart. Elements can be
     * enabled and disabled, moved, re-styled, re-formatted etc.
     *
     * A special case is configuration objects that take arrays, for example
     * [xAxis](https://api.highcharts.com/highcharts/xAxis),
     * [yAxis](https://api.highcharts.com/highcharts/yAxis) or
     * [series](https://api.highcharts.com/highcharts/series). For these
     * collections, an `id` option is used to map the new option set to an
     * existing object. If an existing object of the same id is not found, the
     * corresponding item is updated. So for example, running `chart.update`
     * with a series item without an id, will cause the existing chart's series
     * with the same index in the series array to be updated. When the
     * `oneToOne` parameter is true, `chart.update` will also take care of
     * adding and removing items from the collection. Read more under the
     * parameter description below.
     *
     * Note that when changing series data, `chart.update` may mutate the passed
     * data options.
     *
     * See also the
     * [responsive option set](https://api.highcharts.com/highcharts/responsive).
     * Switching between `responsive.rules` basically runs `chart.update` under
     * the hood.
     *
     * @sample highcharts/members/chart-update/
     *         Update chart geometry
     *
     * @function Highcharts.Chart#update
     *
     * @param {Highcharts.Options} options
     *        A configuration object for the new chart options.
     *
     * @param {boolean} [redraw=true]
     *        Whether to redraw the chart.
     *
     * @param {boolean} [oneToOne=false]
     *        When `true`, the `series`, `xAxis`, `yAxis` and `annotations`
     *        collections will be updated one to one, and items will be either
     *        added or removed to match the new updated options. For example,
     *        if the chart has two series and we call `chart.update` with a
     *        configuration containing three series, one will be added. If we
     *        call `chart.update` with one series, one will be removed. Setting
     *        an empty `series` array will remove all series, but leaving out
     *        the`series` property will leave all series untouched. If the
     *        series have id's, the new series options will be matched by id,
     *        and the remaining ones removed.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Whether to apply animation, and optionally animation
     *        configuration. When `undefined`, it applies the animation that is
     *        set in the `chart.animation` option.
     *
     * @emits Highcharts.Chart#event:update
     * @emits Highcharts.Chart#event:afterUpdate
     */
    Chart.prototype.update = function (options, redraw, oneToOne, animation) {
        var chart = this,
            adders = {
                credits: 'addCredits',
                title: 'setTitle',
                subtitle: 'setSubtitle',
                caption: 'setCaption'
            },
            isResponsiveOptions = options.isResponsiveOptions,
            itemsForRemoval = [];
        var updateAllAxes,
            updateAllSeries,
            runSetSize;
        Chart_fireEvent(chart, 'update', { options: options });
        // If there are responsive rules in action, undo the responsive rules
        // before we apply the updated options and replay the responsive rules
        // on top from the chart.redraw function (#9617).
        if (!isResponsiveOptions) {
            chart.setResponsive(false, true);
        }
        options = Chart_diffObjects(options, chart.options);
        chart.userOptions = Chart_merge(chart.userOptions, options);
        // If the top-level chart option is present, some special updates are
        // required
        var optionsChart = options.chart;
        if (optionsChart) {
            Chart_merge(true, chart.options.chart, optionsChart);
            // Add support for deprecated zooming options like zoomType, #17861
            this.setZoomOptions();
            // Setter function
            if ('className' in optionsChart) {
                chart.setClassName(optionsChart.className);
            }
            if ('inverted' in optionsChart ||
                'polar' in optionsChart ||
                'type' in optionsChart) {
                // Parse options.chart.inverted and options.chart.polar together
                // with the available series.
                chart.propFromSeries();
                updateAllAxes = true;
            }
            if ('alignTicks' in optionsChart) { // #6452
                updateAllAxes = true;
            }
            if ('events' in optionsChart) {
                // Chart event handlers
                Chart_registerEventOptions(this, optionsChart);
            }
            Chart_objectEach(optionsChart, function (val, key) {
                if (chart.propsRequireUpdateSeries.indexOf('chart.' + key) !==
                    -1) {
                    updateAllSeries = true;
                }
                // Only dirty box
                if (chart.propsRequireDirtyBox.indexOf(key) !== -1) {
                    chart.isDirtyBox = true;
                }
                // Chart setSize
                if (chart.propsRequireReflow.indexOf(key) !== -1) {
                    chart.isDirtyBox = true;
                    if (!isResponsiveOptions) {
                        runSetSize = true;
                    }
                }
            });
            if (!chart.styledMode && optionsChart.style) {
                chart.renderer.setStyle(chart.options.chart.style || {});
            }
        }
        // Moved up, because tooltip needs updated plotOptions (#6218)
        if (!chart.styledMode && options.colors) {
            this.options.colors = options.colors;
        }
        // Some option structures correspond one-to-one to chart objects that
        // have update methods, for example
        // options.credits => chart.credits
        // options.legend => chart.legend
        // options.title => chart.title
        // options.tooltip => chart.tooltip
        // options.subtitle => chart.subtitle
        // options.mapNavigation => chart.mapNavigation
        // options.navigator => chart.navigator
        // options.scrollbar => chart.scrollbar
        Chart_objectEach(options, function (val, key) {
            if (chart[key] &&
                typeof chart[key].update === 'function') {
                chart[key].update(val, false);
                // If a one-to-one object does not exist, look for an adder function
            }
            else if (typeof chart[adders[key]] === 'function') {
                chart[adders[key]](val);
                // Else, just merge the options. For nodes like loading, noData,
                // plotOptions
            }
            else if (key !== 'colors' &&
                chart.collectionsWithUpdate.indexOf(key) === -1) {
                Chart_merge(true, chart.options[key], options[key]);
            }
            if (key !== 'chart' &&
                chart.propsRequireUpdateSeries.indexOf(key) !== -1) {
                updateAllSeries = true;
            }
        });
        // Setters for collections. For axes and series, each item is referred
        // by an id. If the id is not found, it defaults to the corresponding
        // item in the collection, so setting one series without an id, will
        // update the first series in the chart. Setting two series without
        // an id will update the first and the second respectively (#6019)
        // chart.update and responsive.
        this.collectionsWithUpdate.forEach(function (coll) {
            if (options[coll]) {
                Chart_splat(options[coll]).forEach(function (newOptions, i) {
                    var hasId = Chart_defined(newOptions.id);
                    var item;
                    // Match by id
                    if (hasId) {
                        item = chart.get(newOptions.id);
                    }
                    // No match by id found, match by index instead
                    if (!item && chart[coll]) {
                        item = chart[coll][Chart_pick(newOptions.index, i)];
                        // Check if we grabbed an item with an existing but
                        // different id (#13541). Check that the item in this
                        // position is not internal (navigator).
                        if (item && ((hasId && Chart_defined(item.options.id)) ||
                            item.options.isInternal)) {
                            item = void 0;
                        }
                    }
                    if (item && item.coll === coll) {
                        item.update(newOptions, false);
                        if (oneToOne) {
                            item.touched = true;
                        }
                    }
                    // If oneToOne and no matching item is found, add one
                    if (!item && oneToOne && chart.collectionsWithInit[coll]) {
                        chart.collectionsWithInit[coll][0].apply(chart, 
                        // [newOptions, ...extraArguments, redraw=false]
                        [
                            newOptions
                        ].concat(
                        // Not all initializers require extra args
                        chart.collectionsWithInit[coll][1] || []).concat([
                            false
                        ])).touched = true;
                    }
                });
                // Add items for removal
                if (oneToOne) {
                    chart[coll].forEach(function (item) {
                        if (!item.touched && !item.options.isInternal) {
                            itemsForRemoval.push(item);
                        }
                        else {
                            delete item.touched;
                        }
                    });
                }
            }
        });
        itemsForRemoval.forEach(function (item) {
            if (item.chart && item.remove) { // #9097, avoid removing twice
                item.remove(false);
            }
        });
        if (updateAllAxes) {
            chart.axes.forEach(function (axis) {
                axis.update({}, false);
            });
        }
        // Certain options require the whole series structure to be thrown away
        // and rebuilt
        if (updateAllSeries) {
            chart.getSeriesOrderByLinks().forEach(function (series) {
                // Avoid removed navigator series
                if (series.chart) {
                    series.update({}, false);
                }
            }, this);
        }
        // Update size. Redraw is forced.
        var newWidth = optionsChart && optionsChart.width;
        var newHeight = optionsChart && (Chart_isString(optionsChart.height) ?
                Chart_relativeLength(optionsChart.height,
            newWidth || chart.chartWidth) :
                optionsChart.height);
        if (
        // In this case, run chart.setSize with newWidth and newHeight which
        // are undefined, only for reflowing chart elements because margin
        // or spacing has been set (#8190)
        runSetSize ||
            // In this case, the size is actually set
            (Chart_isNumber(newWidth) && newWidth !== chart.chartWidth) ||
            (Chart_isNumber(newHeight) && newHeight !== chart.chartHeight)) {
            chart.setSize(newWidth, newHeight, animation);
        }
        else if (Chart_pick(redraw, true)) {
            chart.redraw(animation);
        }
        Chart_fireEvent(chart, 'afterUpdate', {
            options: options,
            redraw: redraw,
            animation: animation
        });
    };
    /**
     * Shortcut to set the subtitle options. This can also be done from {@link
     * Chart#update} or {@link Chart#setTitle}.
     *
     * @function Highcharts.Chart#setSubtitle
     *
     * @param {Highcharts.SubtitleOptions} options
     *        New subtitle options. The subtitle text itself is set by the
     *        `options.text` property.
     */
    Chart.prototype.setSubtitle = function (options, redraw) {
        this.applyDescription('subtitle', options);
        this.layOutTitles(redraw);
    };
    /**
     * Set the caption options. This can also be done from {@link
     * Chart#update}.
     *
     * @function Highcharts.Chart#setCaption
     *
     * @param {Highcharts.CaptionOptions} options
     *        New caption options. The caption text itself is set by the
     *        `options.text` property.
     */
    Chart.prototype.setCaption = function (options, redraw) {
        this.applyDescription('caption', options);
        this.layOutTitles(redraw);
    };
    /**
     * Display the zoom button, so users can reset zoom to the default view
     * settings.
     *
     * @function Highcharts.Chart#showResetZoom
     *
     * @emits Highcharts.Chart#event:afterShowResetZoom
     * @emits Highcharts.Chart#event:beforeShowResetZoom
     */
    Chart.prototype.showResetZoom = function () {
        var chart = this,
            lang = Chart_defaultOptions.lang,
            btnOptions = chart.zooming.resetButton,
            theme = btnOptions.theme,
            alignTo = (btnOptions.relativeTo === 'chart' ||
                btnOptions.relativeTo === 'spacingBox' ?
                null :
                'plotBox');
        /**
         * @private
         */
        function zoomOut() {
            chart.zoomOut();
        }
        Chart_fireEvent(this, 'beforeShowResetZoom', null, function () {
            chart.resetZoomButton = chart.renderer
                .button(lang.resetZoom, null, null, zoomOut, theme)
                .attr({
                align: btnOptions.position.align,
                title: lang.resetZoomTitle
            })
                .addClass('highcharts-reset-zoom')
                .add()
                .align(btnOptions.position, false, alignTo);
        });
        Chart_fireEvent(this, 'afterShowResetZoom');
    };
    /**
     * Zoom the chart out after a user has zoomed in. See also
     * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes).
     *
     * @function Highcharts.Chart#zoomOut
     *
     * @emits Highcharts.Chart#event:selection
     */
    Chart.prototype.zoomOut = function () {
        var _this = this;
        Chart_fireEvent(this, 'selection', { resetSelection: true }, function () { return _this.transform({ reset: true, trigger: 'zoom' }); });
    };
    /**
     * Pan the chart by dragging the mouse across the pane. This function is
     * called on mouse move, and the distance to pan is computed from chartX
     * compared to the first chartX position in the dragging operation.
     *
     * @private
     * @function Highcharts.Chart#pan
     * @param {Highcharts.PointerEventObject} event
     * @param {string} panning
     */
    Chart.prototype.pan = function (event, panning) {
        var chart = this,
            panningOptions = (typeof panning === 'object' ?
                panning :
                {
                    enabled: panning,
                    type: 'x'
                }),
            type = panningOptions.type,
            axes = type && chart[{
                x: 'xAxis',
                xy: 'axes',
                y: 'yAxis'
            }[type]]
                .filter(function (axis) {
                return axis.options.panningEnabled && !axis.options.isInternal;
        }), chartOptions = chart.options.chart;
        if (chartOptions === null || chartOptions === void 0 ? void 0 : chartOptions.panning) {
            chartOptions.panning = panningOptions;
        }
        Chart_fireEvent(this, 'pan', { originalEvent: event }, function () {
            chart.transform({
                axes: axes,
                event: event,
                to: {
                    x: event.chartX - (chart.mouseDownX || 0),
                    y: event.chartY - (chart.mouseDownY || 0)
                },
                trigger: 'pan'
            });
            Chart_css(chart.container, { cursor: 'move' });
        });
    };
    /**
     * Pan and scale the chart. Used internally by mouse-pan, touch-pan,
     * touch-zoom, and mousewheel zoom.
     *
     * The main positioning logic is created around two imaginary boxes. What is
     * currently within the `from` rectangle, should be transformed to fill up
     * the `to` rectangle.
     * - In a mouse zoom, the `from` rectangle is the selection, while the `to`
     *   rectangle is the full plot area.
     * - In a touch zoom, the `from` rectangle is made up of the last two-finger
     *   touch, while the `to`` rectangle is the current touch.
     * - In a mousewheel zoom, the `to` rectangle is a 10x10 px square,
     *   while the `to` rectangle reflects the scale around that.
     *
     * @private
     * @function Highcharts.Chart#transform
     */
    Chart.prototype.transform = function (params) {
        var _a;
        var _this = this;
        var _b,
            _c,
            _d;
        var _e = params.axes,
            axes = _e === void 0 ? this.axes : _e,
            event = params.event,
            _f = params.from,
            from = _f === void 0 ? {} : _f,
            reset = params.reset,
            selection = params.selection,
            _g = params.to,
            to = _g === void 0 ? {} : _g,
            trigger = params.trigger,
            _h = this,
            inverted = _h.inverted,
            time = _h.time;
        var hasZoomed = false,
            displayButton,
            isAnyAxisPanning;
        // Remove active points for shared tooltip
        (_b = this.hoverPoints) === null || _b === void 0 ? void 0 : _b.forEach(function (point) { return point.setState(); });
        for (var _i = 0, axes_3 = axes; _i < axes_3.length; _i++) {
            var axis = axes_3[_i];
            var horiz = axis.horiz, len = axis.len, _j = axis.minPointOffset, minPointOffset = _j === void 0 ? 0 : _j, options = axis.options, reversed = axis.reversed, wh = horiz ? 'width' : 'height', xy = horiz ? 'x' : 'y', toLength = Chart_pick(to[wh], axis.len), fromLength = Chart_pick(from[wh], axis.len), 
                // If fingers pinched very close on this axis, treat as pan
                scale = Math.abs(toLength) < 10 ?
                    1 :
                    toLength / fromLength, fromCenter = (from[xy] || 0) + fromLength / 2 - axis.pos, toCenter = ((_c = to[xy]) !== null && _c !== void 0 ? _c : axis.pos) +
                    toLength / 2 - axis.pos, move = fromCenter - toCenter / scale, pointRangeDirection = (reversed && !inverted) ||
                    (!reversed && inverted) ?
                    -1 :
                    1, minPx = move;
            // Zooming in multiple panes, zoom only in the pane that receives
            // the input
            if (!reset && (fromCenter < 0 || fromCenter > axis.len)) {
                continue;
            }
            var newMin = axis.toValue(minPx,
                true) +
                    // Don't apply offset for selection (#20784)
                    (selection || axis.isOrdinal ?
                        0 : minPointOffset * pointRangeDirection),
                newMax = axis.toValue(minPx + len / scale,
                true) -
                    (
                    // Don't apply offset for selection (#20784)
                    selection || axis.isOrdinal ?
                        0 :
                        ((minPointOffset * pointRangeDirection) ||
                            // Polar zoom tests failed when this was not
                            // commented:
                            // (axis.isXAxis && axis.pointRangePadding) ||
                            0)),
                allExtremes = axis.allExtremes;
            if (newMin > newMax) {
                _a = [newMax, newMin], newMin = _a[0], newMax = _a[1];
            }
            // General calculations of the full data extremes. It is calculated
            // on the first call to transform, then reused for subsequent
            // touch/pan calls. (#11315).
            if (scale === 1 &&
                !reset &&
                axis.coll === 'yAxis' &&
                !allExtremes) {
                for (var _k = 0, _l = axis.series; _k < _l.length; _k++) {
                    var series = _l[_k];
                    var seriesExtremes = series.getExtremes(series.getProcessedData(true).modified
                            .getColumn('y') || [],
                        true);
                    allExtremes !== null && allExtremes !== void 0 ? allExtremes : (allExtremes = {
                        dataMin: Number.MAX_VALUE,
                        dataMax: -Number.MAX_VALUE
                    });
                    if (Chart_isNumber(seriesExtremes.dataMin) &&
                        Chart_isNumber(seriesExtremes.dataMax)) {
                        allExtremes.dataMin = Math.min(seriesExtremes.dataMin, allExtremes.dataMin);
                        allExtremes.dataMax = Math.max(seriesExtremes.dataMax, allExtremes.dataMax);
                    }
                }
                axis.allExtremes = allExtremes;
            }
            var _m = Chart_extend(axis.getExtremes(), allExtremes || {}), dataMin = _m.dataMin, dataMax = _m.dataMax, min = _m.min, max = _m.max, optionsMin = time.parse(options.min), optionsMax = time.parse(options.max), 
                // For boosted chart where data extremes are skipped
                safeDataMin = dataMin !== null && dataMin !== void 0 ? dataMin : optionsMin, safeDataMax = dataMax !== null && dataMax !== void 0 ? dataMax : optionsMax, range = newMax - newMin, padRange = axis.categories ? 0 : Math.min(range, safeDataMax - safeDataMin), paddedMin = safeDataMin - padRange * (Chart_defined(optionsMin) ? 0 : options.minPadding), paddedMax = safeDataMax + padRange * (Chart_defined(optionsMax) ? 0 : options.maxPadding), 
                // We're allowed to zoom outside the data extremes if we're
                // dealing with a bubble chart, if we're panning, or if we're
                // pinching or mousewheeling in.
                allowZoomOutside = axis.allowZoomOutside ||
                    scale === 1 ||
                    (trigger !== 'zoom' && scale > 1), 
                // Calculate the floor and the ceiling
                floor = Math.min(optionsMin !== null && optionsMin !== void 0 ? optionsMin : paddedMin, paddedMin, allowZoomOutside ? min : paddedMin), ceiling = Math.max(optionsMax !== null && optionsMax !== void 0 ? optionsMax : paddedMax, paddedMax, allowZoomOutside ? max : paddedMax);
            // It is not necessary to calculate extremes on ordinal axis,
            // because they are already calculated, so we don't want to override
            // them.
            if (!axis.isOrdinal ||
                axis.options.overscroll || // #21316
                scale !== 1 ||
                reset) {
                // If the new range spills over, either to the min or max,
                // adjust it.
                if (newMin < floor) {
                    newMin = floor;
                    if (scale >= 1) {
                        newMax = newMin + range;
                    }
                }
                if (newMax > ceiling) {
                    newMax = ceiling;
                    if (scale >= 1) {
                        newMin = newMax - range;
                    }
                }
                // Set new extremes if they are actually new
                if (reset || (axis.series.length &&
                    (newMin !== min || newMax !== max) &&
                    newMin >= floor &&
                    newMax <= ceiling)) {
                    if (selection) {
                        selection[axis.coll].push({
                            axis: axis,
                            min: newMin,
                            max: newMax
                        });
                    }
                    else {
                        // Temporarily flag the axis as `isPanning` in order to
                        // disallow certain axis padding options that would make
                        // panning/zooming hard. Reset and redraw after the
                        // operation has finished.
                        axis.isPanning = trigger !== 'zoom';
                        if (axis.isPanning) {
                            isAnyAxisPanning = true; // #21319
                        }
                        axis.setExtremes(reset ? void 0 : newMin, reset ? void 0 : newMax, false, false, { move: move, trigger: trigger, scale: scale });
                        if (!reset &&
                            (newMin > floor || newMax < ceiling) &&
                            trigger !== 'mousewheel') {
                            displayButton = true;
                        }
                    }
                    hasZoomed = true;
                }
                if (event) {
                    this[horiz ? 'mouseDownX' : 'mouseDownY'] =
                        event[horiz ? 'chartX' : 'chartY'];
                }
            }
        }
        if (hasZoomed) {
            if (selection) {
                Chart_fireEvent(this, 'selection', selection, 
                // Run transform again, this time without the selection data
                // so that the transform is applied.
                function () {
                    delete params.selection;
                    params.trigger = 'zoom';
                    _this.transform(params);
                });
            }
            else {
                // Show or hide the Reset zoom button, but not while panning
                if (displayButton &&
                    !isAnyAxisPanning &&
                    !this.resetZoomButton) {
                    this.showResetZoom();
                }
                else if (!displayButton && this.resetZoomButton) {
                    this.resetZoomButton = this.resetZoomButton.destroy();
                }
                this.redraw(trigger === 'zoom' &&
                    ((_d = this.options.chart.animation) !== null && _d !== void 0 ? _d : this.pointCount < 100));
            }
        }
        return hasZoomed;
    };
    return Chart;
}());
Chart_extend(Chart.prototype, {
    // Hook for adding callbacks in modules
    callbacks: [],
    /**
     * These collections (arrays) implement `Chart.addSomething` method used in
     * chart.update() to create new object in the collection. Equivalent for
     * deleting is resolved by simple `Something.remove()`.
     *
     * Note: We need to define these references after initializers are bound to
     * chart's prototype.
     *
     * @private
     */
    collectionsWithInit: {
        // CollectionName: [ initializingMethod, [extraArguments] ]
        xAxis: [Chart.prototype.addAxis, [true]],
        yAxis: [Chart.prototype.addAxis, [false]],
        series: [Chart.prototype.addSeries]
    },
    /**
     * These collections (arrays) implement update() methods with support for
     * one-to-one option.
     * @private
     */
    collectionsWithUpdate: [
        'xAxis',
        'yAxis',
        'series'
    ],
    /**
     * These properties cause isDirtyBox to be set to true when updating. Can be
     * extended from plugins.
     * @private
     */
    propsRequireDirtyBox: [
        'backgroundColor',
        'borderColor',
        'borderWidth',
        'borderRadius',
        'plotBackgroundColor',
        'plotBackgroundImage',
        'plotBorderColor',
        'plotBorderWidth',
        'plotShadow',
        'shadow'
    ],
    /**
     * These properties require a full reflow of chart elements, best
     * implemented through running `Chart.setSize` internally (#8190).
     * @private
     */
    propsRequireReflow: [
        'margin',
        'marginTop',
        'marginRight',
        'marginBottom',
        'marginLeft',
        'spacing',
        'spacingTop',
        'spacingRight',
        'spacingBottom',
        'spacingLeft'
    ],
    /**
     * These properties cause all series to be updated when updating. Can be
     * extended from plugins.
     * @private
     */
    propsRequireUpdateSeries: [
        'chart.inverted',
        'chart.polar',
        'chart.ignoreHiddenSeries',
        'chart.type',
        'colors',
        'plotOptions',
        'time',
        'tooltip'
    ]
});
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Chart_Chart = (Chart);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Callback for chart constructors.
 *
 * @callback Highcharts.ChartCallbackFunction
 *
 * @param {Highcharts.Chart} chart
 *        Created chart.
 */
/**
 * Format a number and return a string based on input settings.
 *
 * @callback Highcharts.NumberFormatterCallbackFunction
 *
 * @param {number} number
 *        The input number to format.
 *
 * @param {number} decimals
 *        The amount of decimals. A value of -1 preserves the amount in the
 *        input number.
 *
 * @param {string} [decimalPoint]
 *        The decimal point, defaults to the one given in the lang options, or
 *        a dot.
 *
 * @param {string} [thousandsSep]
 *        The thousands separator, defaults to the one given in the lang
 *        options, or a space character.
 *
 * @return {string} The formatted number.
 */
/**
 * The chart title. The title has an `update` method that allows modifying the
 * options directly or indirectly via `chart.update`.
 *
 * @interface Highcharts.TitleObject
 * @extends Highcharts.SVGElement
 */ /**
* Modify options for the title.
*
* @function Highcharts.TitleObject#update
*
* @param {Highcharts.TitleOptions} titleOptions
*        Options to modify.
*
* @param {boolean} [redraw=true]
*        Whether to redraw the chart after the title is altered. If doing more
*        operations on the chart, it is a good idea to set redraw to false and
*        call {@link Chart#redraw} after.
*/
/**
 * The chart subtitle. The subtitle has an `update` method that
 * allows modifying the options directly or indirectly via
 * `chart.update`.
 *
 * @interface Highcharts.SubtitleObject
 * @extends Highcharts.SVGElement
 */ /**
* Modify options for the subtitle.
*
* @function Highcharts.SubtitleObject#update
*
* @param {Highcharts.SubtitleOptions} subtitleOptions
*        Options to modify.
*
* @param {boolean} [redraw=true]
*        Whether to redraw the chart after the subtitle is altered. If doing
*        more operations on the chart, it is a good idea to set redraw to false
*        and call {@link Chart#redraw} after.
*/
/**
 * The chart caption. The caption has an `update` method that
 * allows modifying the options directly or indirectly via
 * `chart.update`.
 *
 * @interface Highcharts.CaptionObject
 * @extends Highcharts.SVGElement
 */ /**
* Modify options for the caption.
*
* @function Highcharts.CaptionObject#update
*
* @param {Highcharts.CaptionOptions} captionOptions
*        Options to modify.
*
* @param {boolean} [redraw=true]
*        Whether to redraw the chart after the caption is altered. If doing
*        more operations on the chart, it is a good idea to set redraw to false
*        and call {@link Chart#redraw} after.
*/
/**
 * @interface Highcharts.ChartIsInsideOptionsObject
 */ /**
* @name Highcharts.ChartIsInsideOptionsObject#axis
* @type {Highcharts.Axis|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#ignoreX
* @type {boolean|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#ignoreY
* @type {boolean|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#inverted
* @type {boolean|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#paneCoordinates
* @type {boolean|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#series
* @type {Highcharts.Series|undefined}
*/ /**
* @name Highcharts.ChartIsInsideOptionsObject#visiblePlotOnly
* @type {boolean|undefined}
*/
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Extensions/ScrollablePlotArea.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 *  Highcharts feature to make the Y axis stay fixed when scrolling the chart
 *  horizontally on mobile devices. Supports left and right side axes.
 */


var ScrollablePlotArea_stop = AnimationUtilities.stop;

var ScrollablePlotArea_composed = Core_Globals.composed;


var ScrollablePlotArea_addEvent = Core_Utilities.addEvent, ScrollablePlotArea_createElement = Core_Utilities.createElement, ScrollablePlotArea_css = Core_Utilities.css, ScrollablePlotArea_defined = Core_Utilities.defined, ScrollablePlotArea_erase = Core_Utilities.erase, ScrollablePlotArea_merge = Core_Utilities.merge, ScrollablePlotArea_pushUnique = Core_Utilities.pushUnique;
/* *
 *
 *  Functions
 *
 * */
/** @private */
function onChartRender() {
    var scrollablePlotArea = this.scrollablePlotArea;
    if ((this.scrollablePixelsX || this.scrollablePixelsY) &&
        !scrollablePlotArea) {
        this.scrollablePlotArea = scrollablePlotArea = new ScrollablePlotArea(this);
    }
    scrollablePlotArea === null || scrollablePlotArea === void 0 ? void 0 : scrollablePlotArea.applyFixed();
}
/** @private */
function markDirty() {
    if (this.chart.scrollablePlotArea) {
        this.chart.scrollablePlotArea.isDirty = true;
    }
}
var ScrollablePlotArea = /** @class */ (function () {
    function ScrollablePlotArea(chart) {
        var _a,
            _b;
        var chartOptions = chart.options.chart,
            Renderer = Renderer_RendererRegistry.getRendererType(),
            scrollableOptions = chartOptions.scrollablePlotArea || {},
            moveFixedElements = this.moveFixedElements.bind(this),
            styles = {
                WebkitOverflowScrolling: 'touch',
                overflowX: 'hidden',
                overflowY: 'hidden'
            };
        if (chart.scrollablePixelsX) {
            styles.overflowX = 'auto';
        }
        if (chart.scrollablePixelsY) {
            styles.overflowY = 'auto';
        }
        this.chart = chart;
        // Insert a container with relative position that scrolling and fixed
        // container renders to (#10555)
        var parentDiv = this.parentDiv = ScrollablePlotArea_createElement('div', {
                className: 'highcharts-scrolling-parent'
            }, {
                position: 'relative'
            },
            chart.renderTo), 
            // Add the necessary divs to provide scrolling
            scrollingContainer = this.scrollingContainer = ScrollablePlotArea_createElement('div', {
                'className': 'highcharts-scrolling'
            },
            styles,
            parentDiv),
            innerContainer = this.innerContainer = ScrollablePlotArea_createElement('div', {
                'className': 'highcharts-inner-container'
            },
            void 0,
            scrollingContainer),
            fixedDiv = this.fixedDiv = ScrollablePlotArea_createElement('div', {
                className: 'highcharts-fixed'
            }, {
                position: 'absolute',
                overflow: 'hidden',
                pointerEvents: 'none',
                zIndex: (((_a = chartOptions.style) === null || _a === void 0 ? void 0 : _a.zIndex) || 0) + 2,
                top: 0
            },
            void 0,
            true),
            fixedRenderer = this.fixedRenderer = new Renderer(fixedDiv,
            chart.chartWidth,
            chart.chartHeight,
            chartOptions.style);
        // Mask
        this.mask = fixedRenderer
            .path()
            .attr({
            fill: chartOptions.backgroundColor || '#fff',
            'fill-opacity': (_b = scrollableOptions.opacity) !== null && _b !== void 0 ? _b : 0.85,
            zIndex: -1
        })
            .addClass('highcharts-scrollable-mask')
            .add();
        scrollingContainer.parentNode.insertBefore(fixedDiv, scrollingContainer);
        ScrollablePlotArea_css(chart.renderTo, { overflow: 'visible' });
        ScrollablePlotArea_addEvent(chart, 'afterShowResetZoom', moveFixedElements);
        ScrollablePlotArea_addEvent(chart, 'afterApplyDrilldown', moveFixedElements);
        ScrollablePlotArea_addEvent(chart, 'afterLayOutTitles', moveFixedElements);
        // On scroll, reset the chart position because it applies to the
        // scrolled container
        var lastHoverPoint;
        ScrollablePlotArea_addEvent(scrollingContainer, 'scroll', function () {
            var pointer = chart.pointer,
                hoverPoint = chart.hoverPoint;
            if (pointer) {
                delete pointer.chartPosition;
                if (hoverPoint) {
                    lastHoverPoint = hoverPoint;
                }
                pointer.runPointActions(void 0, lastHoverPoint, true);
            }
        });
        // Now move the container inside
        innerContainer.appendChild(chart.container);
    }
    ScrollablePlotArea.compose = function (AxisClass, ChartClass, SeriesClass) {
        var _this = this;
        if (ScrollablePlotArea_pushUnique(ScrollablePlotArea_composed, this.compose)) {
            ScrollablePlotArea_addEvent(AxisClass, 'afterInit', markDirty);
            ScrollablePlotArea_addEvent(ChartClass, 'afterSetChartSize', function (e) {
                return _this.afterSetSize(e.target, e);
            });
            ScrollablePlotArea_addEvent(ChartClass, 'render', onChartRender);
            ScrollablePlotArea_addEvent(SeriesClass, 'show', markDirty);
        }
    };
    ScrollablePlotArea.afterSetSize = function (chart, e) {
        var _a = chart.options.chart.scrollablePlotArea || {},
            minWidth = _a.minWidth,
            minHeight = _a.minHeight,
            clipBox = chart.clipBox,
            plotBox = chart.plotBox,
            inverted = chart.inverted,
            renderer = chart.renderer;
        var scrollablePixelsX,
            scrollablePixelsY,
            recalculateHoriz;
        if (!renderer.forExport) {
            // The amount of pixels to scroll, the difference between chart
            // width and scrollable width
            if (minWidth) {
                chart.scrollablePixelsX = scrollablePixelsX = Math.max(0, minWidth - chart.chartWidth);
                if (scrollablePixelsX) {
                    chart.scrollablePlotBox = ScrollablePlotArea_merge(chart.plotBox);
                    plotBox.width = chart.plotWidth += scrollablePixelsX;
                    clipBox[inverted ? 'height' : 'width'] += scrollablePixelsX;
                    recalculateHoriz = true;
                }
                // Currently we can only do either X or Y
            }
            else if (minHeight) {
                chart.scrollablePixelsY = scrollablePixelsY = Math.max(0, minHeight - chart.chartHeight);
                if (ScrollablePlotArea_defined(scrollablePixelsY)) {
                    chart.scrollablePlotBox = ScrollablePlotArea_merge(chart.plotBox);
                    plotBox.height = chart.plotHeight += scrollablePixelsY;
                    clipBox[inverted ? 'width' : 'height'] += scrollablePixelsY;
                    recalculateHoriz = false;
                }
            }
            if (ScrollablePlotArea_defined(recalculateHoriz) && !e.skipAxes) {
                for (var _i = 0, _b = chart.axes; _i < _b.length; _i++) {
                    var axis = _b[_i];
                    // Apply the corrected plot size to the axes of the other
                    // orientation than the scrolling direction
                    if (axis.horiz === recalculateHoriz ||
                        // Or parallel axes
                        (chart.hasParallelCoordinates && axis.coll === 'yAxis')) {
                        axis.setAxisSize();
                        axis.setAxisTranslation();
                    }
                }
            }
        }
    };
    ScrollablePlotArea.prototype.applyFixed = function () {
        var _a;
        var _b = this,
            chart = _b.chart,
            fixedRenderer = _b.fixedRenderer,
            isDirty = _b.isDirty,
            scrollingContainer = _b.scrollingContainer,
            axisOffset = chart.axisOffset,
            chartWidth = chart.chartWidth,
            chartHeight = chart.chartHeight,
            container = chart.container,
            plotHeight = chart.plotHeight,
            plotLeft = chart.plotLeft,
            plotTop = chart.plotTop,
            plotWidth = chart.plotWidth,
            _c = chart.scrollablePixelsX,
            scrollablePixelsX = _c === void 0 ? 0 : _c,
            _d = chart.scrollablePixelsY,
            scrollablePixelsY = _d === void 0 ? 0 : _d,
            chartOptions = chart.options.chart,
            scrollableOptions = chartOptions.scrollablePlotArea || {},
            _e = scrollableOptions.scrollPositionX,
            scrollPositionX = _e === void 0 ? 0 : _e,
            _f = scrollableOptions.scrollPositionY,
            scrollPositionY = _f === void 0 ? 0 : _f,
            scrollableWidth = chartWidth + scrollablePixelsX,
            scrollableHeight = chartHeight + scrollablePixelsY;
        // Set the size of the fixed renderer to the visible width
        fixedRenderer.setSize(chartWidth, chartHeight);
        if (isDirty !== null && isDirty !== void 0 ? isDirty : true) {
            this.isDirty = false;
            this.moveFixedElements();
        }
        // Increase the size of the scrollable renderer and background
        ScrollablePlotArea_stop(chart.container);
        ScrollablePlotArea_css(container, {
            width: "" + scrollableWidth + "px",
            height: "" + scrollableHeight + "px"
        });
        chart.renderer.boxWrapper.attr({
            width: scrollableWidth,
            height: scrollableHeight,
            viewBox: [0, 0, scrollableWidth, scrollableHeight].join(' ')
        });
        (_a = chart.chartBackground) === null || _a === void 0 ? void 0 : _a.attr({
            width: scrollableWidth,
            height: scrollableHeight
        });
        ScrollablePlotArea_css(scrollingContainer, {
            width: "" + chartWidth + "px",
            height: "" + chartHeight + "px"
        });
        // Set scroll position the first time (this.isDirty was undefined at
        // the top of this function)
        if (!ScrollablePlotArea_defined(isDirty)) {
            scrollingContainer.scrollLeft = scrollablePixelsX * scrollPositionX;
            scrollingContainer.scrollTop = scrollablePixelsY * scrollPositionY;
        }
        // Mask behind the left and right side
        var maskTop = plotTop - axisOffset[0] - 1,
            maskLeft = plotLeft - axisOffset[3] - 1,
            maskBottom = plotTop + plotHeight + axisOffset[2] + 1,
            maskRight = plotLeft + plotWidth + axisOffset[1] + 1,
            maskPlotRight = plotLeft + plotWidth - scrollablePixelsX,
            maskPlotBottom = plotTop + plotHeight - scrollablePixelsY;
        var d = [['M', 0, 0]];
        if (scrollablePixelsX) {
            d = [
                // Left side
                ['M', 0, maskTop],
                ['L', plotLeft - 1, maskTop],
                ['L', plotLeft - 1, maskBottom],
                ['L', 0, maskBottom],
                ['Z'],
                // Right side
                ['M', maskPlotRight, maskTop],
                ['L', chartWidth, maskTop],
                ['L', chartWidth, maskBottom],
                ['L', maskPlotRight, maskBottom],
                ['Z']
            ];
        }
        else if (scrollablePixelsY) {
            d = [
                // Top side
                ['M', maskLeft, 0],
                ['L', maskLeft, plotTop - 1],
                ['L', maskRight, plotTop - 1],
                ['L', maskRight, 0],
                ['Z'],
                // Bottom side
                ['M', maskLeft, maskPlotBottom],
                ['L', maskLeft, chartHeight],
                ['L', maskRight, chartHeight],
                ['L', maskRight, maskPlotBottom],
                ['Z']
            ];
        }
        if (chart.redrawTrigger !== 'adjustHeight') {
            this.mask.attr({ d: d });
        }
    };
    /**
     * These elements are moved over to the fixed renderer and stay fixed when
     * the user scrolls the chart
     * @private
     */
    ScrollablePlotArea.prototype.moveFixedElements = function () {
        var _a = this.chart,
            container = _a.container,
            inverted = _a.inverted,
            scrollablePixelsX = _a.scrollablePixelsX,
            scrollablePixelsY = _a.scrollablePixelsY,
            fixedRenderer = this.fixedRenderer,
            fixedSelectors = ScrollablePlotArea.fixedSelectors;
        var axisClass;
        if (scrollablePixelsX && !inverted) {
            axisClass = '.highcharts-yaxis';
        }
        else if (scrollablePixelsX && inverted) {
            axisClass = '.highcharts-xaxis';
        }
        else if (scrollablePixelsY && !inverted) {
            axisClass = '.highcharts-xaxis';
        }
        else if (scrollablePixelsY && inverted) {
            axisClass = '.highcharts-yaxis';
        }
        if (axisClass && !(this.chart.hasParallelCoordinates &&
            axisClass === '.highcharts-yaxis')) {
            // Add if not added yet
            for (var _i = 0, _b = [
                "" + axisClass + ":not(.highcharts-radial-axis)",
                "" + axisClass + "-labels:not(.highcharts-radial-axis-labels)"
            ]; _i < _b.length; _i++) {
                var className = _b[_i];
                ScrollablePlotArea_pushUnique(fixedSelectors, className);
            }
        }
        else {
            // Clear all axis related selectors
            for (var _c = 0, _d = [
                '.highcharts-xaxis',
                '.highcharts-yaxis'
            ]; _c < _d.length; _c++) {
                var classBase = _d[_c];
                for (var _e = 0, _f = [
                    "" + classBase + ":not(.highcharts-radial-axis)",
                    "" + classBase + "-labels:not(.highcharts-radial-axis-labels)"
                ]; _e < _f.length; _e++) {
                    var className = _f[_e];
                    ScrollablePlotArea_erase(fixedSelectors, className);
                }
            }
        }
        for (var _g = 0, fixedSelectors_1 = fixedSelectors; _g < fixedSelectors_1.length; _g++) {
            var className = fixedSelectors_1[_g];
            [].forEach.call(container.querySelectorAll(className), function (elem) {
                (elem.namespaceURI === fixedRenderer.SVG_NS ?
                    fixedRenderer.box :
                    fixedRenderer.box.parentNode).appendChild(elem);
                elem.style.pointerEvents = 'auto';
            });
        }
    };
    ScrollablePlotArea.fixedSelectors = [
        '.highcharts-breadcrumbs-group',
        '.highcharts-contextbutton',
        '.highcharts-caption',
        '.highcharts-credits',
        '.highcharts-drillup-button',
        '.highcharts-legend',
        '.highcharts-legend-checkbox',
        '.highcharts-navigator-series',
        '.highcharts-navigator-xaxis',
        '.highcharts-navigator-yaxis',
        '.highcharts-navigator',
        '.highcharts-range-selector-group',
        '.highcharts-reset-zoom',
        '.highcharts-scrollbar',
        '.highcharts-subtitle',
        '.highcharts-title'
    ];
    return ScrollablePlotArea;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Extensions_ScrollablePlotArea = (ScrollablePlotArea);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Options for a scrollable plot area. This feature provides a minimum size for
 * the plot area of the chart. If the size gets smaller than this, typically
 * on mobile devices, a native browser scrollbar is presented. This scrollbar
 * provides smooth scrolling for the contents of the plot area, whereas the
 * title, legend and unaffected axes are fixed.
 *
 * Since v7.1.2, a scrollable plot area can be defined for either horizontal or
 * vertical scrolling, depending on whether the `minWidth` or `minHeight`
 * option is set.
 *
 * @sample highcharts/chart/scrollable-plotarea
 *         Scrollable plot area
 * @sample highcharts/chart/scrollable-plotarea-vertical
 *         Vertically scrollable plot area
 * @sample {gantt} gantt/chart/scrollable-plotarea-vertical
 *         Gantt chart with vertically scrollable plot area
 *
 * @since     6.1.0
 * @product   highcharts gantt
 * @apioption chart.scrollablePlotArea
 */
/**
 * The minimum height for the plot area. If it gets smaller than this, the plot
 * area will become scrollable.
 *
 * @type      {number}
 * @since     7.1.2
 * @apioption chart.scrollablePlotArea.minHeight
 */
/**
 * The minimum width for the plot area. If it gets smaller than this, the plot
 * area will become scrollable.
 *
 * @type      {number}
 * @since     6.1.0
 * @apioption chart.scrollablePlotArea.minWidth
 */
/**
 * The initial scrolling position of the scrollable plot area. Ranges from 0 to
 * 1, where 0 aligns the plot area to the left and 1 aligns it to the right.
 * Typically we would use 1 if the chart has right aligned Y axes.
 *
 * @type      {number}
 * @since     6.1.0
 * @apioption chart.scrollablePlotArea.scrollPositionX
 */
/**
 * The initial scrolling position of the scrollable plot area. Ranges from 0 to
 * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom.
 *
 * @type      {number}
 * @since     7.1.2
 * @apioption chart.scrollablePlotArea.scrollPositionY
 */
/**
 * The opacity of mask applied on one of the sides of the plot
 * area.
 *
 * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity
 *         Disabled opacity for the mask
 *
 * @type        {number}
 * @default     0.85
 * @since       7.1.1
 * @apioption   chart.scrollablePlotArea.opacity
 */
(''); // Keep doclets above in transpiled file

;// ./code/es5/es-modules/Core/Axis/Stacking/StackItem.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var StackItem_format = Core_Templating.format;

var StackItem_Series = Series_SeriesRegistry.series;

var StackItem_destroyObjectProperties = Core_Utilities.destroyObjectProperties, StackItem_fireEvent = Core_Utilities.fireEvent, StackItem_getAlignFactor = Core_Utilities.getAlignFactor, StackItem_isNumber = Core_Utilities.isNumber, StackItem_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * The class for stacks. Each stack, on a specific X value and either negative
 * or positive, has its own stack item.
 * @private
 */
var StackItem = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function StackItem(axis, options, negativeValue, x, stackOption) {
        var inverted = axis.chart.inverted,
            reversed = axis.reversed;
        this.axis = axis;
        // The stack goes to the left either if the stack has negative value
        // or when axis is reversed. XOR operator.
        var isNegative = (this.isNegative = !!negativeValue !== !!reversed);
        // Save the options to be able to style the label
        this.options = options = options || {};
        // Save the x value to be able to position the label later
        this.x = x;
        // Initialize total value
        this.total = null;
        this.cumulative = null;
        // This will keep each points' extremes stored by series.index and point
        // index
        this.points = {};
        this.hasValidPoints = false;
        // Save the stack option on the series configuration object,
        // and whether to treat it as percent
        this.stack = stackOption;
        this.leftCliff = 0;
        this.rightCliff = 0;
        // The align options and text align varies on whether the stack is
        // negative and if the chart is inverted or not.
        // First test the user supplied value, then use the dynamic.
        this.alignOptions = {
            align: options.align ||
                (inverted ? (isNegative ? 'left' : 'right') : 'center'),
            verticalAlign: options.verticalAlign ||
                (inverted ? 'middle' : isNegative ? 'bottom' : 'top'),
            y: options.y,
            x: options.x
        };
        this.textAlign =
            options.textAlign ||
                (inverted ? (!isNegative ? 'left' : 'right') : 'center');
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    StackItem.prototype.destroy = function () {
        StackItem_destroyObjectProperties(this, this.axis);
    };
    /**
     * Renders the stack total label and adds it to the stack label group.
     * @private
     */
    StackItem.prototype.render = function (group) {
        var chart = this.axis.chart,
            options = this.options,
            formatOption = options.format, 
            // Format the text in the label.
            str = formatOption ?
                StackItem_format(formatOption,
            this,
            chart) :
                options.formatter.call(this);
        // Change the text to reflect the new total and set visibility to hidden
        // in case the series is hidden
        if (this.label) {
            this.label.attr({ text: str, visibility: 'hidden' });
        }
        else {
            // Create new label
            this.label = chart.renderer.label(str, null, void 0, options.shape, void 0, void 0, options.useHTML, false, 'stack-labels');
            var attr = {
                    r: options.borderRadius || 0,
                    text: str,
                    // Set default padding to 5 as it is in datalabels #12308
                    padding: StackItem_pick(options.padding, 5),
                    visibility: 'hidden' // Hidden until setOffset is called
                };
            if (!chart.styledMode) {
                attr.fill = options.backgroundColor;
                attr.stroke = options.borderColor;
                attr['stroke-width'] = options.borderWidth;
                this.label.css(options.style || {});
            }
            this.label.attr(attr);
            if (!this.label.added) {
                this.label.add(group); // Add to the labels-group
            }
        }
        // Rank it higher than data labels (#8742)
        this.label.labelrank = chart.plotSizeY;
        StackItem_fireEvent(this, 'afterRender');
    };
    /**
     * Sets the offset that the stack has from the x value and repositions the
     * label.
     * @private
     */
    StackItem.prototype.setOffset = function (xOffset, width, boxBottom, boxTop, defaultX, xAxis) {
        var _a = this,
            alignOptions = _a.alignOptions,
            axis = _a.axis,
            label = _a.label,
            options = _a.options,
            textAlign = _a.textAlign,
            chart = axis.chart,
            stackBox = this.getStackBox({
                xOffset: xOffset,
                width: width,
                boxBottom: boxBottom,
                boxTop: boxTop,
                defaultX: defaultX,
                xAxis: xAxis
            }),
            verticalAlign = alignOptions.verticalAlign;
        if (label && stackBox) {
            var labelBox = label.getBBox(void 0, 0),
                padding = label.padding;
            var isJustify = StackItem_pick(options.overflow, 'justify') === 'justify',
                visible = void 0;
            // Reset alignOptions property after justify #12337
            alignOptions.x = options.x || 0;
            alignOptions.y = options.y || 0;
            // Calculate the adjusted Stack position, to take into consideration
            // The size if the labelBox and vertical alignment as
            // well as the text alignment. It's need to be done to work with
            // default SVGLabel.align/justify methods.
            var _b = this.adjustStackPosition({
                    labelBox: labelBox,
                    verticalAlign: verticalAlign,
                    textAlign: textAlign
                }),
                x = _b.x,
                y = _b.y;
            stackBox.x -= x;
            stackBox.y -= y;
            // Align the label to the adjusted box.
            label.align(alignOptions, false, stackBox);
            // Check if label is inside the plotArea #12294
            visible = chart.isInsidePlot(label.alignAttr.x + alignOptions.x + x, label.alignAttr.y + alignOptions.y + y);
            if (!visible) {
                isJustify = false;
            }
            if (isJustify) {
                // Justify stackLabel into the alignBox
                StackItem_Series.prototype.justifyDataLabel.call(axis, label, alignOptions, label.alignAttr, labelBox, stackBox);
            }
            // Add attr to avoid the default animation of justifyDataLabel.
            // Also add correct rotation with its rotation origin. #15129
            label.attr({
                x: label.alignAttr.x,
                y: label.alignAttr.y,
                rotation: options.rotation,
                rotationOriginX: labelBox.width *
                    StackItem_getAlignFactor(options.textAlign || 'center'),
                rotationOriginY: labelBox.height / 2
            });
            // Check if the dataLabel should be visible.
            if (StackItem_pick(!isJustify && options.crop, true)) {
                visible =
                    StackItem_isNumber(label.x) &&
                        StackItem_isNumber(label.y) &&
                        chart.isInsidePlot(label.x - padding + (label.width || 0), label.y) &&
                        chart.isInsidePlot(label.x + padding, label.y);
            }
            label[visible ? 'show' : 'hide']();
        }
        StackItem_fireEvent(this, 'afterSetOffset', { xOffset: xOffset, width: width });
    };
    /**
     * Adjust the stack BBox position, to take into consideration the alignment
     * of the dataLabel. This is necessary to make the stackDataLabel work with
     * core methods like `SVGLabel.adjust` and `Series.justifyDataLabel`.
     * @param AdjustStackPositionProps
     * @return {{x: number, y: number}} Adjusted BBox position of the stack.
     */
    StackItem.prototype.adjustStackPosition = function (_a) {
        var labelBox = _a.labelBox,
            verticalAlign = _a.verticalAlign,
            textAlign = _a.textAlign;
        return {
            x: labelBox.width / 2 +
                (labelBox.width / 2) * (2 * StackItem_getAlignFactor(textAlign) - 1),
            y: (labelBox.height / 2) * 2 * (1 - StackItem_getAlignFactor(verticalAlign))
        };
    };
    /**
     * Get the bbox of the stack.
     * @private
     * @function Highcharts.StackItem#getStackBox
     * @return {BBoxObject} The x, y, height, width of the stack.
     */
    StackItem.prototype.getStackBox = function (stackBoxProps) {
        var stackItem = this,
            axis = this.axis,
            chart = axis.chart,
            boxTop = stackBoxProps.boxTop,
            defaultX = stackBoxProps.defaultX,
            xOffset = stackBoxProps.xOffset,
            width = stackBoxProps.width,
            boxBottom = stackBoxProps.boxBottom,
            totalStackValue = axis.stacking.usePercentage ?
                100 :
                StackItem_pick(boxTop,
            this.total, 0),
            y = axis.toPixels(totalStackValue),
            xAxis = stackBoxProps.xAxis || chart.xAxis[0],
            x = StackItem_pick(defaultX,
            xAxis.translate(this.x)) + xOffset,
            yZero = axis.toPixels(boxBottom ||
                (StackItem_isNumber(axis.min) &&
                    axis.logarithmic &&
                    axis.logarithmic.lin2log(axis.min)) ||
                0),
            height = Math.abs(y - yZero),
            inverted = chart.inverted,
            neg = stackItem.isNegative;
        return inverted ?
            {
                x: (neg ? y : y - height) - chart.plotLeft,
                y: xAxis.height - x - width + xAxis.top - chart.plotTop,
                width: height,
                height: width
            } : {
            x: x + xAxis.transB - chart.plotLeft,
            y: (neg ? y - height : y) - chart.plotTop,
            width: width,
            height: height
        };
    };
    return StackItem;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Stacking_StackItem = (StackItem);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Stack of data points
 *
 * @product highcharts
 *
 * @interface Highcharts.StackItemObject
 */ /**
* Alignment settings
* @name Highcharts.StackItemObject#alignOptions
* @type {Highcharts.AlignObject}
*/ /**
* Related axis
* @name Highcharts.StackItemObject#axis
* @type {Highcharts.Axis}
*/ /**
* Cumulative value of the stacked data points
* @name Highcharts.StackItemObject#cumulative
* @type {number}
*/ /**
* True if on the negative side
* @name Highcharts.StackItemObject#isNegative
* @type {boolean}
*/ /**
* Related SVG element
* @name Highcharts.StackItemObject#label
* @type {Highcharts.SVGElement}
*/ /**
* Related stack options
* @name Highcharts.StackItemObject#options
* @type {Highcharts.YAxisStackLabelsOptions}
*/ /**
* Total value of the stacked data points
* @name Highcharts.StackItemObject#total
* @type {number}
*/ /**
* Shared x value of the stack
* @name Highcharts.StackItemObject#x
* @type {number}
*/
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Axis/Stacking/StackingAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var StackingAxis_getDeferredAnimation = AnimationUtilities.getDeferredAnimation;


var seriesProto = Series_SeriesRegistry.series.prototype;


var StackingAxis_addEvent = Core_Utilities.addEvent, StackingAxis_correctFloat = Core_Utilities.correctFloat, StackingAxis_defined = Core_Utilities.defined, StackingAxis_destroyObjectProperties = Core_Utilities.destroyObjectProperties, StackingAxis_fireEvent = Core_Utilities.fireEvent, StackingAxis_isNumber = Core_Utilities.isNumber, StackingAxis_objectEach = Core_Utilities.objectEach, StackingAxis_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/**
 * Generate stacks for each series and calculate stacks total values
 *
 * @private
 * @function Highcharts.Chart#getStacks
 */
function chartGetStacks() {
    var chart = this,
        inverted = chart.inverted;
    // Reset stacks for each axis
    chart.axes.forEach(function (axis) {
        if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) {
            axis.stacking.oldStacks = axis.stacking.stacks;
        }
    });
    chart.series.forEach(function (series) {
        var xAxisOptions = series.xAxis && series.xAxis.options || {};
        if (series.options.stacking && series.reserveSpace()) {
            series.stackKey = [
                series.type,
                StackingAxis_pick(series.options.stack, ''),
                inverted ? xAxisOptions.top : xAxisOptions.left,
                inverted ? xAxisOptions.height : xAxisOptions.width
            ].join(',');
        }
    });
}
/**
 * @private
 */
function onAxisDestroy() {
    var _a;
    var stacking = this.stacking;
    if (stacking) {
        var stacks_1 = stacking.stacks;
        // Destroy each stack total
        StackingAxis_objectEach(stacks_1, function (stack, stackKey) {
            StackingAxis_destroyObjectProperties(stack);
            delete stacks_1[stackKey];
        });
        (_a = stacking.stackTotalGroup) === null || _a === void 0 ? void 0 : _a.destroy();
    }
}
/**
 * @private
 */
function onAxisInit() {
    if (!this.stacking) {
        this.stacking = new AxisAdditions(this);
    }
}
/**
 * Get stack indicator, according to it's x-value, to determine points with the
 * same x-value
 *
 * @private
 * @function Highcharts.Series#getStackIndicator
 */
function seriesGetStackIndicator(stackIndicator, x, index, key) {
    // Update stack indicator, when:
    // first point in a stack || x changed || stack type (negative vs positive)
    // changed:
    if (!StackingAxis_defined(stackIndicator) ||
        stackIndicator.x !== x ||
        (key && stackIndicator.stackKey !== key)) {
        stackIndicator = {
            x: x,
            index: 0,
            key: key,
            stackKey: key
        };
    }
    else {
        stackIndicator.index++;
    }
    stackIndicator.key = [index, x, stackIndicator.index].join(',');
    return stackIndicator;
}
/**
 * Iterate over all stacks and compute the absolute values to percent
 *
 * @private
 * @function Highcharts.Series#modifyStacks
 */
function seriesModifyStacks() {
    var series = this, yAxis = series.yAxis, stackKey = series.stackKey || '', stacks = yAxis.stacking.stacks, processedXData = series.getColumn('x', true), stacking = series.options.stacking, stacker = series[stacking + 'Stacker'];
    var stackIndicator;
    if (stacker) { // Modifier function exists (Series.percentStacker etc.)
        [stackKey, '-' + stackKey].forEach(function (key) {
            var _a;
            var i = processedXData.length,
                x,
                stackItem,
                pointExtremes;
            while (i--) {
                x = processedXData[i];
                stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key);
                stackItem = (_a = stacks[key]) === null || _a === void 0 ? void 0 : _a[x];
                pointExtremes = stackItem === null || stackItem === void 0 ? void 0 : stackItem.points[stackIndicator.key || ''];
                if (pointExtremes) {
                    stacker.call(series, pointExtremes, stackItem, i);
                }
            }
        });
    }
}
/**
 * Modifier function for percent stacks. Blows up the stack to 100%.
 *
 * @private
 * @function Highcharts.Series#percentStacker
 */
function seriesPercentStacker(pointExtremes, stack, i) {
    var totalFactor = stack.total ? 100 / stack.total : 0;
    // Y bottom value
    pointExtremes[0] = StackingAxis_correctFloat(pointExtremes[0] * totalFactor);
    // Y value
    pointExtremes[1] = StackingAxis_correctFloat(pointExtremes[1] * totalFactor);
    this.stackedYData[i] = pointExtremes[1];
}
/**
 * Set grouped points in a stack-like object. When `centerInCategory` is true,
 * and `stacking` is not enabled, we need a pseudo (horizontal) stack in order
 * to handle grouping of points within the same category.
 *
 * @private
 * @function Highcharts.Series#setGroupedPoints
 * @return {void}
 */
function seriesSetGroupedPoints(axis) {
    // Only series types supporting centerInCategory need to do this. That also
    // applies to resetting (#20221).
    if (this.is('column') || this.is('columnrange')) {
        if (this.options.centerInCategory &&
            // With only one series, we don't need to consider centerInCategory
            this.chart.series.length > 1) {
            seriesProto.setStackedPoints.call(this, axis, 'group');
            // After updating, if we now have proper stacks, we must delete the
            // group pseudo stacks (#14980)
        }
        else {
            axis.stacking.resetStacks();
        }
    }
}
/**
 * Adds series' points value to corresponding stack
 *
 * @private
 * @function Highcharts.Series#setStackedPoints
 */
function seriesSetStackedPoints(axis, stackingParam) {
    var _a,
        _b;
    var type = stackingParam || this.options.stacking;
    if (!type ||
        !this.reserveSpace() ||
        // Group stacks (centerInCategory) belong on the x-axis, other stacks on
        // the y-axis.
        ({ group: 'xAxis' }[type] || 'yAxis') !== axis.coll) {
        return;
    }
    var series = this, xData = series.getColumn('x', true), yData = series.getColumn(series.pointValKey || 'y', true), stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold || 0, stackThreshold = seriesOptions.startFromThreshold ? threshold : 0, stackOption = seriesOptions.stack, stackKey = stackingParam ?
            "" + series.type + ",".concat(type) : (series.stackKey || ''), negKey = '-' + stackKey, negStacks = series.negStacks, stacking = axis.stacking, stacks = stacking.stacks, oldStacks = stacking.oldStacks;
    var stackIndicator,
        isNegative,
        stack,
        other,
        key,
        pointKey,
        i;
    stacking.stacksTouched += 1;
    // Loop over the non-null y values and read them into a local array
    for (i = 0; i < yDataLength; i++) {
        var x = xData[i] || 0,
            y = yData[i],
            yNumber = StackingAxis_isNumber(y) && y || 0;
        stackIndicator = series.getStackIndicator(stackIndicator, x, series.index);
        pointKey = stackIndicator.key || '';
        // Read stacked values into a stack based on the x value,
        // the sign of y and the stack key. Stacking is also handled for null
        // values (#739)
        isNegative = negStacks && yNumber < (stackThreshold ? 0 : threshold);
        key = isNegative ? negKey : stackKey;
        // Create empty object for this stack if it doesn't exist yet
        if (!stacks[key]) {
            stacks[key] = {};
        }
        // Initialize StackItem for this x
        if (!stacks[key][x]) {
            if ((_a = oldStacks[key]) === null || _a === void 0 ? void 0 : _a[x]) {
                stacks[key][x] = oldStacks[key][x];
                stacks[key][x].total = null;
            }
            else {
                stacks[key][x] = new Stacking_StackItem(axis, axis.options.stackLabels, !!isNegative, x, stackOption);
            }
        }
        // If the StackItem doesn't exist, create it first
        stack = stacks[key][x];
        if (y !== null) {
            stack.points[pointKey] = stack.points[series.index] = [
                StackingAxis_pick(stack.cumulative, stackThreshold)
            ];
            // Record the base of the stack
            if (!StackingAxis_defined(stack.cumulative)) {
                stack.base = pointKey;
            }
            stack.touched = stacking.stacksTouched;
            // In area charts, if there are multiple points on the same X value,
            // let the area fill the full span of those points
            if (stackIndicator.index > 0 && series.singleStacks === false) {
                stack.points[pointKey][0] = stack.points[series.index + ',' + x + ',0'][0];
            }
            // When updating to null, reset the point stack (#7493)
        }
        else {
            delete stack.points[pointKey];
            delete stack.points[series.index];
        }
        // Add value to the stack total
        var total = stack.total || 0;
        if (type === 'percent') {
            // Percent stacked column, totals are the same for the positive and
            // negative stacks
            other = isNegative ? stackKey : negKey;
            if (negStacks && ((_b = stacks[other]) === null || _b === void 0 ? void 0 : _b[x])) {
                other = stacks[other][x];
                total = other.total = Math.max(other.total || 0, total) +
                    Math.abs(yNumber);
                // Percent stacked areas
            }
            else {
                total = StackingAxis_correctFloat(total + Math.abs(yNumber));
            }
        }
        else if (type === 'group') {
            // In this stack, the total is the number of valid points
            if (StackingAxis_isNumber(y)) {
                total++;
            }
        }
        else {
            total = StackingAxis_correctFloat(total + yNumber);
        }
        if (type === 'group') {
            // This point's index within the stack, pushed to stack.points[1]
            stack.cumulative = (total || 1) - 1;
        }
        else {
            stack.cumulative = StackingAxis_correctFloat(StackingAxis_pick(stack.cumulative, stackThreshold) + yNumber);
        }
        stack.total = total;
        if (y !== null) {
            stack.points[pointKey].push(stack.cumulative);
            stackedYData[i] = stack.cumulative;
            stack.hasValidPoints = true;
        }
    }
    if (type === 'percent') {
        stacking.usePercentage = true;
    }
    if (type !== 'group') {
        this.stackedYData = stackedYData; // To be used in getExtremes
    }
    // Reset old stacks
    stacking.oldStacks = {};
}
/* *
 *
 *  Classes
 *
 * */
/**
 * Adds stacking support to axes.
 * @private
 * @class
 */
var AxisAdditions = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function AxisAdditions(axis) {
        this.oldStacks = {};
        this.stacks = {};
        this.stacksTouched = 0;
        this.axis = axis;
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Build the stacks from top down
     * @private
     */
    AxisAdditions.prototype.buildStacks = function () {
        var stacking = this,
            axis = stacking.axis,
            axisSeries = axis.series,
            isXAxis = axis.coll === 'xAxis',
            reversedStacks = axis.options.reversedStacks,
            len = axisSeries.length;
        var actualSeries,
            i;
        this.resetStacks();
        stacking.usePercentage = false;
        i = len;
        while (i--) {
            actualSeries = axisSeries[reversedStacks ? i : len - i - 1];
            if (isXAxis) {
                actualSeries.setGroupedPoints(axis);
            }
            actualSeries.setStackedPoints(axis);
        }
        // Loop up again to compute percent and stream stack
        if (!isXAxis) {
            for (i = 0; i < len; i++) {
                axisSeries[i].modifyStacks();
            }
        }
        StackingAxis_fireEvent(axis, 'afterBuildStacks');
    };
    /**
     * @private
     */
    AxisAdditions.prototype.cleanStacks = function () {
        if (this.oldStacks) {
            this.stacks = this.oldStacks;
            // Reset stacks
            StackingAxis_objectEach(this.stacks, function (type) {
                StackingAxis_objectEach(type, function (stack) {
                    stack.cumulative = stack.total;
                });
            });
        }
    };
    /**
     * Set all the stacks to initial states and destroy unused ones.
     * @private
     */
    AxisAdditions.prototype.resetStacks = function () {
        var _this = this;
        StackingAxis_objectEach(this.stacks, function (type) {
            StackingAxis_objectEach(type, function (stack, x) {
                // Clean up memory after point deletion (#1044, #4320)
                if (StackingAxis_isNumber(stack.touched) &&
                    stack.touched < _this.stacksTouched) {
                    stack.destroy();
                    delete type[x];
                    // Reset stacks
                }
                else {
                    stack.total = null;
                    stack.cumulative = null;
                }
            });
        });
    };
    /**
     * @private
     */
    AxisAdditions.prototype.renderStackTotals = function () {
        var _a;
        var stacking = this,
            axis = stacking.axis,
            chart = axis.chart,
            renderer = chart.renderer,
            stacks = stacking.stacks,
            stackLabelsAnim = (_a = axis.options.stackLabels) === null || _a === void 0 ? void 0 : _a.animation,
            animationConfig = StackingAxis_getDeferredAnimation(chart,
            stackLabelsAnim || false),
            stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup ||
                renderer
                    .g('stack-labels')
                    .attr({
                    zIndex: 6,
                    opacity: 0
                })
                    .add());
        // The plotLeft/Top will change when y axis gets wider so we need to
        // translate the stackTotalGroup at every render call. See bug #506
        // and #516
        stackTotalGroup.translate(chart.plotLeft, chart.plotTop);
        // Render each stack total
        StackingAxis_objectEach(stacks, function (type) {
            StackingAxis_objectEach(type, function (stack) {
                stack.render(stackTotalGroup);
            });
        });
        stackTotalGroup.animate({
            opacity: 1
        }, animationConfig);
    };
    return AxisAdditions;
}());
/* *
 *
 *  Composition
 *
 * */
var StackingAxis;
(function (StackingAxis) {
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Extends axis with stacking support.
     * @private
     */
    function compose(AxisClass, ChartClass, SeriesClass) {
        var chartProto = ChartClass.prototype,
            seriesProto = SeriesClass.prototype;
        if (!chartProto.getStacks) {
            StackingAxis_addEvent(AxisClass, 'init', onAxisInit);
            StackingAxis_addEvent(AxisClass, 'destroy', onAxisDestroy);
            chartProto.getStacks = chartGetStacks;
            seriesProto.getStackIndicator = seriesGetStackIndicator;
            seriesProto.modifyStacks = seriesModifyStacks;
            seriesProto.percentStacker = seriesPercentStacker;
            seriesProto.setGroupedPoints = seriesSetGroupedPoints;
            seriesProto.setStackedPoints = seriesSetStackedPoints;
        }
    }
    StackingAxis.compose = compose;
})(StackingAxis || (StackingAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Stacking_StackingAxis = (StackingAxis);

;// ./code/es5/es-modules/Series/Line/LineSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var LineSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var LineSeries_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};



var LineSeries_defined = Core_Utilities.defined, LineSeries_merge = Core_Utilities.merge, LineSeries_isObject = Core_Utilities.isObject;
/* *
 *
 *  Class
 *
 * */
/**
 * The line series is the base type and is therefor the series base prototype.
 *
 * @private
 */
var LineSeries = /** @class */ (function (_super) {
    LineSeries_extends(LineSeries, _super);
    function LineSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Draw the graph. Called internally when rendering line-like series
     * types. The first time it generates the `series.graph` item and
     * optionally other series-wide items like `series.area` for area
     * charts. On subsequent calls these items are updated with new
     * positions and attributes.
     *
     * @function Highcharts.Series#drawGraph
     */
    LineSeries.prototype.drawGraph = function () {
        var _this = this;
        var options = this.options,
            graphPath = (this.gappedPath || this.getGraphPath).call(this),
            styledMode = this.chart.styledMode;
        // Draw the graph
        LineSeries_spreadArray([this], this.zones, true).forEach(function (owner, i) {
            var attribs,
                graph = owner.graph;
            var verb = graph ? 'animate' : 'attr',
                dashStyle = owner.dashStyle ||
                    options.dashStyle;
            if (graph) {
                graph.endX = _this.preventGraphAnimation ?
                    null :
                    graphPath.xMap;
                graph.animate({ d: graphPath });
            }
            else if (graphPath.length) { // #1487
                /**
                 * SVG element of line-based charts. Can be used for styling
                 * purposes. If zones are configured, this element will be
                 * hidden and replaced by multiple zone lines, accessible
                 * via `series.zones[i].graph`.
                 *
                 * @name Highcharts.Series#graph
                 * @type {Highcharts.SVGElement|undefined}
                 */
                owner.graph = graph = _this.chart.renderer
                    .path(graphPath)
                    .addClass('highcharts-graph' +
                    (i ? " highcharts-zone-graph-".concat(i - 1, " ") : ' ') +
                    ((i && owner.className) || ''))
                    .attr({ zIndex: 1 }) // #1069
                    .add(_this.group);
            }
            if (graph && !styledMode) {
                attribs = {
                    'stroke': ((!i && options.lineColor) || // Series only
                        owner.color ||
                        _this.color ||
                        "#cccccc" /* Palette.neutralColor20 */),
                    'stroke-width': options.lineWidth || 0,
                    // Polygon series use filled graph
                    'fill': (_this.fillGraph && _this.color) || 'none'
                };
                // Apply dash style
                if (dashStyle) {
                    attribs.dashstyle = dashStyle;
                    // The reason for the `else if` is that linecaps don't mix well
                    // with dashstyle. The gaps get partially filled by the
                    // linecap.
                }
                else if (options.linecap !== 'square') {
                    attribs['stroke-linecap'] =
                        attribs['stroke-linejoin'] = 'round';
                }
                graph[verb](attribs)
                    // Add shadow to normal series as well as zones
                    .shadow(options.shadow &&
                    // If shadow is defined, call function with
                    // `filterUnits: 'userSpaceOnUse'` to avoid known
                    // SVG filter bug (#19093)
                    LineSeries_merge({ filterUnits: 'userSpaceOnUse' }, LineSeries_isObject(options.shadow) ? options.shadow : {}));
            }
            // Helpers for animation
            if (graph) {
                graph.startX = graphPath.xMap;
                graph.isArea = graphPath.isArea; // For arearange animation
            }
        });
    };
    // eslint-disable-next-line valid-jsdoc
    /**
     * Get the graph path.
     *
     * @private
     */
    LineSeries.prototype.getGraphPath = function (points, nullsAsZeroes, connectCliffs) {
        var series = this,
            options = series.options,
            graphPath = [],
            xMap = [];
        var gap,
            step = options.step;
        points = points || series.points;
        // Bottom of a stack is reversed
        var reversed = points.reversed;
        if (reversed) {
            points.reverse();
        }
        // Reverse the steps (#5004)
        step = {
            right: 1,
            center: 2
        }[step] || (step && 3);
        if (step && reversed) {
            step = 4 - step;
        }
        // Remove invalid points, especially in spline (#5015)
        points = this.getValidPoints(points, false, !(options.connectNulls && !nullsAsZeroes && !connectCliffs));
        // Build the line
        points.forEach(function (point, i) {
            var plotX = point.plotX,
                plotY = point.plotY,
                lastPoint = points[i - 1],
                isNull = point.isNull || typeof plotY !== 'number';
            // The path to this point from the previous
            var pathToPoint;
            if ((point.leftCliff || (lastPoint && lastPoint.rightCliff)) &&
                !connectCliffs) {
                gap = true; // ... and continue
            }
            // Line series, nullsAsZeroes is not handled
            if (isNull && !LineSeries_defined(nullsAsZeroes) && i > 0) {
                gap = !options.connectNulls;
                // Area series, nullsAsZeroes is set
            }
            else if (isNull && !nullsAsZeroes) {
                gap = true;
            }
            else {
                if (i === 0 || gap) {
                    pathToPoint = [[
                            'M',
                            point.plotX,
                            point.plotY
                        ]];
                    // Generate the spline as defined in the SplineSeries object
                }
                else if (series.getPointSpline) {
                    pathToPoint = [series.getPointSpline(points, point, i)];
                }
                else if (step) {
                    if (step === 1) { // Right
                        pathToPoint = [[
                                'L',
                                lastPoint.plotX,
                                plotY
                            ]];
                    }
                    else if (step === 2) { // Center
                        pathToPoint = [[
                                'L',
                                (lastPoint.plotX + plotX) / 2,
                                lastPoint.plotY
                            ], [
                                'L',
                                (lastPoint.plotX + plotX) / 2,
                                plotY
                            ]];
                    }
                    else {
                        pathToPoint = [[
                                'L',
                                plotX,
                                lastPoint.plotY
                            ]];
                    }
                    pathToPoint.push([
                        'L',
                        plotX,
                        plotY
                    ]);
                }
                else {
                    // Normal line to next point
                    pathToPoint = [[
                            'L',
                            plotX,
                            plotY
                        ]];
                }
                // Prepare for animation. When step is enabled, there are
                // two path nodes for each x value.
                xMap.push(point.x);
                if (step) {
                    xMap.push(point.x);
                    if (step === 2) { // Step = center (#8073)
                        xMap.push(point.x);
                    }
                }
                graphPath.push.apply(graphPath, pathToPoint);
                gap = false;
            }
        });
        graphPath.xMap = xMap;
        series.graphPath = graphPath;
        return graphPath;
    };
    /* *
     *
     *  Static Functions
     *
     * */
    LineSeries.defaultOptions = LineSeries_merge(Series_Series.defaultOptions, 
    /**
     * General options for all series types.
     *
     * @optionparent plotOptions.series
     */
    {
        legendSymbol: 'lineMarker'
    });
    return LineSeries;
}(Series_Series));
Series_SeriesRegistry.registerSeriesType('line', LineSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Line_LineSeries = ((/* unused pure expression or super */ null && (LineSeries)));
/* *
 *
 *  API Options
 *
 * */
/**
 * A line series displays information as a series of data points connected by
 * straight line segments.
 *
 * @sample {highcharts} highcharts/demo/line-chart/
 *         Line chart
 * @sample {highstock} stock/demo/basic-line/
 *         Line chart
 *
 * @extends   plotOptions.series
 * @product   highcharts highstock
 * @apioption plotOptions.line
 */
/**
 * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
 * of a line graph. Round means that lines are rounded in the ends and
 * bends.
 *
 * @type       {Highcharts.SeriesLinecapValue}
 * @default    round
 * @since      3.0.7
 * @apioption  plotOptions.line.linecap
 */
/**
 * A `line` series. If the [type](#series.line.type) option is not
 * specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.line
 * @excluding dataParser,dataURL
 * @product   highcharts highstock
 * @apioption series.line
 */
/**
 * An array of data points for the series. For the `line` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 1],
 *        [1, 2],
 *        [2, 8]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.line.turboThreshold),
 *    this option is not available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 9,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 6,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * **Note:** In TypeScript you have to extend `PointOptionsObject` with an
 * additional declaration to allow custom data types:
 * ```ts
 * declare module `highcharts` {
 *   interface PointOptionsObject {
 *     custom: Record<string, (boolean|number|string)>;
 *   }
 * }
 * ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @declare   Highcharts.PointOptionsObject
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @apioption series.line.data
 */
/**
 * An additional, individual class name for the data point's graphic
 * representation. Changes to a point's color will also be reflected in a
 * chart's legend and tooltip.
 *
 * @sample {highcharts} highcharts/css/point-series-classname
 *         Series and point class name
 *
 * @type      {string}
 * @since     5.0.0
 * @product   highcharts gantt
 * @apioption series.line.data.className
 */
/**
 * Individual color for the point. By default the color is pulled from
 * the global `colors` array.
 *
 * In styled mode, the `color` option doesn't take effect. Instead, use
 * `colorIndex`.
 *
 * @sample {highcharts} highcharts/point/color/
 *         Mark the highest point
 *
 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
 * @product   highcharts highstock gantt
 * @apioption series.line.data.color
 */
/**
 * A specific color index to use for the point, so its graphic representations
 * are given the class name `highcharts-color-{n}`. In styled mode this will
 * change the color of the graphic. In non-styled mode, the color is set by the
 * `fill` attribute, so the change in class name won't have a visual effect by
 * default.
 *
 * Since v11, CSS variables on the form `--highcharts-color-{n}` make changing
 * the color scheme very convenient.
 *
 * @sample    {highcharts} highcharts/css/colorindex/
 *            Series and point color index
 *
 * @type      {number}
 * @since     5.0.0
 * @product   highcharts gantt
 * @apioption series.line.data.colorIndex
 */
/**
 * A reserved subspace to store options and values for customized functionality.
 * Here you can add additional data for your own event callbacks and formatter
 * callbacks.
 *
 * @sample {highcharts} highcharts/point/custom/
 *         Point and series with custom data
 *
 * @type      {Highcharts.Dictionary<*>}
 * @apioption series.line.data.custom
 */
/**
 * Individual data label for each point. The options are the same as
 * the ones for [plotOptions.series.dataLabels](
 * #plotOptions.series.dataLabels).
 *
 * @sample highcharts/point/datalabels/
 *         Show a label for the last value
 *
 * @type      {*|Array<*>}
 * @declare   Highcharts.DataLabelsOptions
 * @extends   plotOptions.line.dataLabels
 * @product   highcharts highstock gantt
 * @apioption series.line.data.dataLabels
 */
/**
 * A description of the point to add to the screen reader information
 * about the point.
 *
 * @type      {string}
 * @since     5.0.0
 * @requires  modules/accessibility
 * @apioption series.line.data.description
 */
/**
 * An id for the point. This can be used after render time to get a
 * pointer to the point object through `chart.get()`.
 *
 * @sample {highcharts} highcharts/point/id/
 *         Remove an id'd point
 *
 * @type      {string}
 * @since     1.2.0
 * @product   highcharts highstock gantt
 * @apioption series.line.data.id
 */
/**
 * The rank for this point's data label in case of collision. If two
 * data labels are about to overlap, only the one with the highest `labelrank`
 * will be drawn.
 *
 * @type      {number}
 * @apioption series.line.data.labelrank
 */
/**
 * The name of the point as shown in the legend, tooltip, dataLabels, etc.
 *
 * @see [xAxis.uniqueNames](#xAxis.uniqueNames)
 *
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Point names
 *
 * @type      {string}
 * @apioption series.line.data.name
 */
/**
 * Whether the data point is selected initially.
 *
 * @type      {boolean}
 * @default   false
 * @product   highcharts highstock gantt
 * @apioption series.line.data.selected
 */
/**
 * The x value of the point.
 *
 * For datetime axes, a number value is the timestamp in milliseconds since
 * 1970, while a date string is parsed according to the [current time zone]
 * (https://api.highcharts.com/highcharts/time.timezone) of the
 * chart. Date strings are supported since v12.
 *
 * @type      {number|string}
 * @product   highcharts highstock
 * @apioption series.line.data.x
 */
/**
 * The y value of the point.
 *
 * @type      {number|null}
 * @product   highcharts highstock
 * @apioption series.line.data.y
 */
/**
 * The individual point events.
 *
 * @extends   plotOptions.series.point.events
 * @product   highcharts highstock gantt
 * @apioption series.line.data.events
 */
/**
 * Options for the point markers of line-like series.
 *
 * @declare   Highcharts.PointMarkerOptionsObject
 * @extends   plotOptions.series.marker
 * @product   highcharts highstock
 * @apioption series.line.data.marker
 */
''; // Include precedent doclets in transpiled

;// ./code/es5/es-modules/Series/Area/AreaSeriesDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * The area series type.
 *
 * @sample {highcharts} highcharts/demo/area-chart/
 *         Area chart
 * @sample {highstock} stock/demo/area/
 *         Area chart
 *
 * @extends      plotOptions.line
 * @excluding    useOhlcData
 * @product      highcharts highstock
 * @optionparent plotOptions.area
 */
var AreaSeriesDefaults = {
    /**
     * @see [fillColor](#plotOptions.area.fillColor)
     * @see [fillOpacity](#plotOptions.area.fillOpacity)
     *
     * @apioption plotOptions.area.color
     */
    /**
     * Fill color or gradient for the area. When `undefined`, the series'
     * `color` is used with the series' `fillOpacity`.
     *
     * In styled mode, the fill color can be set with the `.highcharts-area`
     * class name.
     *
     * @see [color](#plotOptions.area.color)
     * @see [fillOpacity](#plotOptions.area.fillOpacity)
     *
     * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/
     *         Undefined by default
     * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/
     *         Gradient
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @product   highcharts highstock
     * @apioption plotOptions.area.fillColor
     */
    /**
     * Fill opacity for the area. When you set an explicit `fillColor`,
     * the `fillOpacity` is not applied. Instead, you should define the
     * opacity in the `fillColor` with an rgba color definition. The
     * `fillOpacity` setting, also the default setting, overrides the alpha
     * component of the `color` setting.
     *
     * In styled mode, the fill opacity can be set with the
     * `.highcharts-area` class name.
     *
     * @see [color](#plotOptions.area.color)
     * @see [fillColor](#plotOptions.area.fillColor)
     *
     * @sample {highcharts} highcharts/plotoptions/area-fillopacity/
     *         Automatic fill color and fill opacity of 0.1
     *
     * @type      {number}
     * @default   {highcharts} 0.75
     * @default   {highstock} 0.75
     * @product   highcharts highstock
     * @apioption plotOptions.area.fillOpacity
     */
    /**
     * A separate color for the graph line. By default the line takes the
     * `color` of the series, but the lineColor setting allows setting a
     * separate color for the line without altering the `fillColor`.
     *
     * In styled mode, the line stroke can be set with the
     * `.highcharts-graph` class name.
     *
     * @sample {highcharts} highcharts/plotoptions/area-linecolor/
     *         Dark gray line
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @product   highcharts highstock
     * @apioption plotOptions.area.lineColor
     */
    /**
     * A separate color for the negative part of the area. Note that `zones`
     * takes precedence over the negative fill color.
     *
     * In styled mode, a negative color is set with the
     * `.highcharts-negative` class name.
     *
     * @see [negativeColor](#plotOptions.area.negativeColor)
     *
     * @sample {highcharts} highcharts/css/series-negative-color/
     *         Negative color in styled mode
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @since     3.0
     * @product   highcharts
     * @apioption plotOptions.area.negativeFillColor
     */
    /**
     * Whether the whole area or just the line should respond to mouseover
     * tooltips and other mouse or touch events.
     *
     * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/
     *         Display the tooltip when the area is hovered
     *
     * @type      {boolean}
     * @default   false
     * @since     1.1.6
     * @product   highcharts highstock
     * @apioption plotOptions.area.trackByArea
     */
    /**
     * The Y axis value to serve as the base for the area, for
     * distinguishing between values above and below a threshold. The area
     * between the graph and the threshold is filled.
     *
     * * If a number is given, the Y axis will scale to the threshold.
     * * If `null`, the scaling behaves like a line series with fill between
     *   the graph and the Y axis minimum.
     * * If `Infinity` or `-Infinity`, the area between the graph and the
     *   corresponding Y axis extreme is filled (since v6.1.0).
     *
     * @sample {highcharts} highcharts/plotoptions/area-threshold/
     *         A threshold of 100
     * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/
     *         A threshold of Infinity
     *
     * @type    {number|null}
     * @since   2.0
     * @product highcharts highstock
     */
    threshold: 0,
    legendSymbol: 'areaMarker'
};
/**
 * A `area` series. If the [type](#series.area.type) option is not
 * specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.area
 * @excluding dataParser, dataURL, useOhlcData
 * @product   highcharts highstock
 * @apioption series.area
 */
/**
 * @see [fillColor](#series.area.fillColor)
 * @see [fillOpacity](#series.area.fillOpacity)
 *
 * @apioption series.area.color
 */
/**
 * An array of data points for the series. For the `area` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` * and `pointInterval` given in the series options. If the
 *    axis has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 9],
 *        [1, 7],
 *        [2, 6]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.area.turboThreshold), this option is not
 *    available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 9,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 6,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.line.data
 * @product   highcharts highstock
 * @apioption series.area.data
 */
/**
 * @see [color](#series.area.color)
 * @see [fillOpacity](#series.area.fillOpacity)
 *
 * @apioption series.area.fillColor
 */
/**
 * @see [color](#series.area.color)
 * @see [fillColor](#series.area.fillColor)
 *
 * @default   {highcharts} 0.75
 * @default   {highstock} 0.75
 * @apioption series.area.fillOpacity
 */
''; // Adds doclets above to transpiled
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Area_AreaSeriesDefaults = (AreaSeriesDefaults);

;// ./code/es5/es-modules/Series/Area/AreaSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var AreaSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var AreaSeries_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};


var AreaSeries_LineSeries = Series_SeriesRegistry.seriesTypes.line;

var AreaSeries_extend = Core_Utilities.extend, AreaSeries_merge = Core_Utilities.merge, AreaSeries_objectEach = Core_Utilities.objectEach, AreaSeries_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * Area series type.
 *
 * @private
 * @class
 * @name AreaSeries
 *
 * @augments LineSeries
 */
var AreaSeries = /** @class */ (function (_super) {
    AreaSeries_extends(AreaSeries, _super);
    function AreaSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Draw the graph and the underlying area. This method calls the Series
     * base function and adds the area. The areaPath is calculated in the
     * getSegmentPath method called from Series.prototype.drawGraph.
     * @private
     */
    AreaSeries.prototype.drawGraph = function () {
        var _this = this;
        // Define or reset areaPath
        this.areaPath = [];
        // Call the base method
        _super.prototype.drawGraph.apply(this);
        // Define local variables
        var _a = this,
            areaPath = _a.areaPath,
            options = _a.options;
        AreaSeries_spreadArray([this], this.zones, true).forEach(function (owner, i) {
            var _a;
            var attribs = {},
                fillColor = owner.fillColor || options.fillColor;
            var area = owner.area;
            var verb = area ? 'animate' : 'attr';
            // Create or update the area
            if (area) { // Update
                area.endX = _this.preventGraphAnimation ?
                    null :
                    areaPath.xMap;
                area.animate({ d: areaPath });
            }
            else { // Create
                attribs.zIndex = 0; // #1069
                /**
                 * SVG element of area-based charts. Can be used for styling
                 * purposes. If zones are configured, this element will be
                 * hidden and replaced by multiple zone areas, accessible
                 * via `series.zones[i].area`.
                 *
                 * @name Highcharts.Series#area
                 * @type {Highcharts.SVGElement|undefined}
                 */
                area = owner.area = _this.chart.renderer
                    .path(areaPath)
                    .addClass('highcharts-area' +
                    (i ? " highcharts-zone-area-".concat(i - 1, " ") : ' ') +
                    ((i && owner.className) || ''))
                    .add(_this.group);
                area.isArea = true;
            }
            if (!_this.chart.styledMode) {
                // If there is fillColor defined for the area, set it.
                // Otherwise, we set it to the zone/series color and add
                // fill-opacity (#18939).
                attribs.fill = fillColor || owner.color || _this.color;
                attribs['fill-opacity'] = fillColor ?
                    1 : ((_a = options.fillOpacity) !== null && _a !== void 0 ? _a : 0.75);
                // Allow clicking through the area if sticky tracking is true
                // (#18744)
                area.css({
                    pointerEvents: _this.stickyTracking ? 'none' : 'auto'
                });
            }
            area[verb](attribs);
            area.startX = areaPath.xMap;
            area.shiftUnit = options.step ? 2 : 1;
        });
    };
    /**
     * @private
     */
    AreaSeries.prototype.getGraphPath = function (points) {
        var getGraphPath = AreaSeries_LineSeries.prototype.getGraphPath, options = this.options, stacking = options.stacking, yAxis = this.yAxis, bottomPoints = [], graphPoints = [], seriesIndex = this.index, stacks = yAxis.stacking.stacks[this.stackKey], threshold = options.threshold, translatedThreshold = Math.round(// #10909
            yAxis.getThreshold(options.threshold)), connectNulls = AreaSeries_pick(// #10574
            options.connectNulls, stacking === 'percent'), 
            // To display null points in underlying stacked series, this
            // series graph must be broken, and the area also fall down to
            // fill the gap left by the null point. #2069
            addDummyPoints = function (i, otherI, side) {
                var point = points[i], stackedValues = stacking &&
                    stacks[point.x].points[seriesIndex], nullVal = point[side + 'Null'] || 0, cliffVal = point[side + 'Cliff'] || 0;
            var top,
                bottom,
                isNull = true;
            if (cliffVal || nullVal) {
                top = (nullVal ?
                    stackedValues[0] :
                    stackedValues[1]) + cliffVal;
                bottom = stackedValues[0] + cliffVal;
                isNull = !!nullVal;
            }
            else if (!stacking &&
                points[otherI] &&
                points[otherI].isNull) {
                top = bottom = threshold;
            }
            // Add to the top and bottom line of the area
            if (typeof top !== 'undefined') {
                graphPoints.push({
                    plotX: plotX,
                    plotY: top === null ?
                        translatedThreshold :
                        yAxis.getThreshold(top),
                    isNull: isNull,
                    isCliff: true
                });
                bottomPoints.push({
                    plotX: plotX,
                    plotY: bottom === null ?
                        translatedThreshold :
                        yAxis.getThreshold(bottom),
                    doCurve: false // #1041, gaps in areaspline areas
                });
            }
        };
        var plotX,
            isNull,
            yBottom;
        // Find what points to use
        points = points || this.points;
        // Fill in missing points
        if (stacking) {
            points = this.getStackPoints(points);
        }
        for (var i = 0, iEnd = points.length; i < iEnd; ++i) {
            // Reset after series.update of stacking property (#12033)
            if (!stacking) {
                points[i].leftCliff = points[i].rightCliff =
                    points[i].leftNull = points[i].rightNull = void 0;
            }
            isNull = points[i].isNull;
            plotX = AreaSeries_pick(points[i].rectPlotX, points[i].plotX);
            yBottom = stacking ?
                AreaSeries_pick(points[i].yBottom, translatedThreshold) :
                translatedThreshold;
            if (!isNull || connectNulls) {
                if (!connectNulls) {
                    addDummyPoints(i, i - 1, 'left');
                }
                // Skip null point when stacking is false and connectNulls
                // true
                if (!(isNull && !stacking && connectNulls)) {
                    graphPoints.push(points[i]);
                    bottomPoints.push({
                        x: i,
                        plotX: plotX,
                        plotY: yBottom
                    });
                }
                if (!connectNulls) {
                    addDummyPoints(i, i + 1, 'right');
                }
            }
        }
        var topPath = getGraphPath.call(this,
            graphPoints,
            true,
            true);
        bottomPoints.reversed = true;
        var bottomPath = getGraphPath.call(this,
            bottomPoints,
            true,
            true);
        var firstBottomPoint = bottomPath[0];
        if (firstBottomPoint && firstBottomPoint[0] === 'M') {
            bottomPath[0] = ['L', firstBottomPoint[1], firstBottomPoint[2]];
        }
        var areaPath = topPath.concat(bottomPath);
        if (areaPath.length) {
            areaPath.push(['Z']);
        }
        // TODO: don't set leftCliff and rightCliff when connectNulls?
        var graphPath = getGraphPath
                .call(this,
            graphPoints,
            false,
            connectNulls);
        if (this.chart.series.length > 1 &&
            stacking &&
            graphPoints.some(function (point) { return point.isCliff; })) {
            areaPath.hasStackedCliffs = graphPath.hasStackedCliffs = true;
        }
        areaPath.xMap = topPath.xMap;
        this.areaPath = areaPath;
        return graphPath;
    };
    /**
     * Return an array of stacked points, where null and missing points are
     * replaced by dummy points in order for gaps to be drawn correctly in
     * stacks.
     * @private
     */
    AreaSeries.prototype.getStackPoints = function (points) {
        var series = this,
            segment = [],
            keys = [],
            xAxis = this.xAxis,
            yAxis = this.yAxis,
            stack = yAxis.stacking.stacks[this.stackKey],
            pointMap = {},
            yAxisSeries = yAxis.series,
            seriesLength = yAxisSeries.length,
            upOrDown = yAxis.options.reversedStacks ? 1 : -1,
            seriesIndex = yAxisSeries.indexOf(series);
        points = points || this.points;
        if (this.options.stacking) {
            for (var i = 0; i < points.length; i++) {
                // Reset after point update (#7326)
                points[i].leftNull = points[i].rightNull = void 0;
                // Create a map where we can quickly look up the points by
                // their X values.
                pointMap[points[i].x] = points[i];
            }
            // Sort the keys (#1651)
            AreaSeries_objectEach(stack, function (stackX, x) {
                // Nulled after switching between
                // grouping and not (#1651, #2336)
                if (stackX.total !== null) {
                    keys.push(x);
                }
            });
            keys.sort(function (a, b) {
                return a - b;
            });
            var visibleSeries_1 = yAxisSeries.map(function (s) { return s.visible; });
            keys.forEach(function (x, idx) {
                var y = 0,
                    stackPoint,
                    stackedValues;
                if (pointMap[x] && !pointMap[x].isNull) {
                    segment.push(pointMap[x]);
                    // Find left and right cliff. -1 goes left, 1 goes
                    // right.
                    [-1, 1].forEach(function (direction) {
                        var nullName = direction === 1 ?
                                'rightNull' :
                                'leftNull',
                            cliffName = direction === 1 ?
                                'rightCliff' :
                                'leftCliff',
                            otherStack = stack[keys[idx + direction]];
                        var cliff = 0;
                        // If there is a stack next to this one,
                        // to the left or to the right...
                        if (otherStack) {
                            var i = seriesIndex;
                            // Can go either up or down,
                            // depending on reversedStacks
                            while (i >= 0 && i < seriesLength) {
                                var si = yAxisSeries[i].index;
                                stackPoint = otherStack.points[si];
                                if (!stackPoint) {
                                    // If the next point in this series is
                                    // missing, mark the point with
                                    // point.leftNull or point.rightNull = true.
                                    if (si === series.index) {
                                        pointMap[x][nullName] = true;
                                        // If there are missing points in the next
                                        // stack in any of the series below this
                                        // one, we need to subtract the missing
                                        // values and add a hiatus to the left or
                                        // right.
                                    }
                                    else if (visibleSeries_1[i]) {
                                        stackedValues = stack[x].points[si];
                                        if (stackedValues) {
                                            cliff -= (stackedValues[1] -
                                                stackedValues[0]);
                                        }
                                    }
                                }
                                // When reversedStacks is true, loop up,
                                // else loop down
                                i += upOrDown;
                            }
                        }
                        pointMap[x][cliffName] = cliff;
                    });
                    // There is no point for this X value in this series, so we
                    // insert a dummy point in order for the areas to be drawn
                    // correctly.
                }
                else {
                    // Loop down the stack to find the series below this
                    // one that has a value (#1991)
                    var i = seriesIndex;
                    while (i >= 0 && i < seriesLength) {
                        var si = yAxisSeries[i].index;
                        stackPoint = stack[x].points[si];
                        if (stackPoint) {
                            y = stackPoint[1];
                            break;
                        }
                        // When reversedStacks is true, loop up, else loop
                        // down
                        i += upOrDown;
                    }
                    y = AreaSeries_pick(y, 0);
                    y = yAxis.translate(// #6272
                    y, 0, 1, 0, 1);
                    segment.push({
                        isNull: true,
                        plotX: xAxis.translate(// #6272
                        x, 0, 0, 0, 1),
                        x: x,
                        plotY: y,
                        yBottom: y
                    });
                }
            });
        }
        return segment;
    };
    /* *
     *
     *  Static Properties
     *
     * */
    AreaSeries.defaultOptions = AreaSeries_merge(AreaSeries_LineSeries.defaultOptions, Area_AreaSeriesDefaults);
    return AreaSeries;
}(AreaSeries_LineSeries));
AreaSeries_extend(AreaSeries.prototype, {
    singleStacks: false
});
Series_SeriesRegistry.registerSeriesType('area', AreaSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Area_AreaSeries = ((/* unused pure expression or super */ null && (AreaSeries)));

;// ./code/es5/es-modules/Series/Spline/SplineSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var SplineSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var SplineSeries_LineSeries = Series_SeriesRegistry.seriesTypes.line;

var SplineSeries_merge = Core_Utilities.merge, SplineSeries_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * Spline series type.
 *
 * @private
 */
var SplineSeries = /** @class */ (function (_super) {
    SplineSeries_extends(SplineSeries, _super);
    function SplineSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Get the spline segment from a given point's previous neighbour to the
     * given point.
     *
     * @private
     * @function Highcharts.seriesTypes.spline#getPointSpline
     */
    SplineSeries.prototype.getPointSpline = function (points, point, i) {
        var 
            // 1 means control points midway between points, 2 means 1/3
            // from the point, 3 is 1/4 etc
            smoothing = 1.5, denom = smoothing + 1, plotX = point.plotX || 0, plotY = point.plotY || 0, lastPoint = points[i - 1], nextPoint = points[i + 1];
        var leftContX,
            leftContY,
            rightContX,
            rightContY;
        /**
         * @private
         */
        function doCurve(otherPoint) {
            return otherPoint &&
                !otherPoint.isNull &&
                otherPoint.doCurve !== false &&
                // #6387, area splines next to null:
                !point.isCliff;
        }
        // Find control points
        if (doCurve(lastPoint) && doCurve(nextPoint)) {
            var lastX = lastPoint.plotX || 0,
                lastY = lastPoint.plotY || 0,
                nextX = nextPoint.plotX || 0,
                nextY = nextPoint.plotY || 0;
            var correction = 0;
            leftContX = (smoothing * plotX + lastX) / denom;
            leftContY = (smoothing * plotY + lastY) / denom;
            rightContX = (smoothing * plotX + nextX) / denom;
            rightContY = (smoothing * plotY + nextY) / denom;
            // Have the two control points make a straight line through main
            // point
            if (rightContX !== leftContX) { // #5016, division by zero
                correction = (((rightContY - leftContY) *
                    (rightContX - plotX)) /
                    (rightContX - leftContX) + plotY - rightContY);
            }
            leftContY += correction;
            rightContY += correction;
            // To prevent false extremes, check that control points are
            // between neighbouring points' y values
            if (leftContY > lastY && leftContY > plotY) {
                leftContY = Math.max(lastY, plotY);
                // Mirror of left control point
                rightContY = 2 * plotY - leftContY;
            }
            else if (leftContY < lastY && leftContY < plotY) {
                leftContY = Math.min(lastY, plotY);
                rightContY = 2 * plotY - leftContY;
            }
            if (rightContY > nextY && rightContY > plotY) {
                rightContY = Math.max(nextY, plotY);
                leftContY = 2 * plotY - rightContY;
            }
            else if (rightContY < nextY && rightContY < plotY) {
                rightContY = Math.min(nextY, plotY);
                leftContY = 2 * plotY - rightContY;
            }
            // Record for drawing in next point
            point.rightContX = rightContX;
            point.rightContY = rightContY;
            // Visualize control points for debugging
            /*
            if (leftContX) {
                this.chart.renderer
                    .circle(
                        leftContX + this.chart.plotLeft,
                        leftContY + this.chart.plotTop,
                        2
                    )
                    .attr({
                        stroke: 'red',
                        'stroke-width': 2,
                        fill: 'none',
                        zIndex: 9
                    })
                    .add();
                this.chart.renderer
                    .path([['M', leftContX + this.chart.plotLeft,
                        leftContY + this.chart.plotTop
                    ], ['L', plotX + this.chart.plotLeft,
                        plotY + this.chart.plotTop
                    ]])
                    .attr({
                        stroke: 'red',
                        'stroke-width': 2,
                        zIndex: 9
                    })
                    .add();
            }
            if (rightContX) {
                this.chart.renderer
                    .circle(
                        rightContX + this.chart.plotLeft,
                        rightContY + this.chart.plotTop,
                        2
                    )
                    .attr({
                        stroke: 'green',
                        'stroke-width': 2,
                        fill: 'none',
                        zIndex: 9
                    })
                    .add();
                this.chart.renderer
                    .path([[
                        'M', rightContX + this.chart.plotLeft,
                        rightContY + this.chart.plotTop
                    ], [
                        'L', plotX + this.chart.plotLeft,
                        plotY + this.chart.plotTop
                    ]])
                    .attr({
                        stroke: 'green',
                        'stroke-width': 2,
                        zIndex: 9
                    })
                    .add();
            }
            // */
            point.controlPoints = {
                low: [leftContX, leftContY],
                high: [rightContX, rightContY]
            };
        }
        var ret = [
                'C',
                SplineSeries_pick(lastPoint.rightContX,
            lastPoint.plotX, 0),
                SplineSeries_pick(lastPoint.rightContY,
            lastPoint.plotY, 0),
                SplineSeries_pick(leftContX,
            plotX, 0),
                SplineSeries_pick(leftContY,
            plotY, 0),
                plotX,
                plotY
            ];
        // Reset for updating series later
        lastPoint.rightContX = lastPoint.rightContY = void 0;
        return ret;
    };
    /* *
     *
     *  Static Properties
     *
     * */
    /**
     * A spline series is a special type of line series, where the segments
     * between the data points are smoothed.
     *
     * @sample {highcharts} highcharts/demo/spline-irregular-time/
     *         Spline chart
     * @sample {highstock} stock/demo/spline/
     *         Spline chart
     *
     * @extends      plotOptions.series
     * @excluding    step, boostThreshold, boostBlending
     * @product      highcharts highstock
     * @optionparent plotOptions.spline
     */
    SplineSeries.defaultOptions = SplineSeries_merge(SplineSeries_LineSeries.defaultOptions);
    return SplineSeries;
}(SplineSeries_LineSeries));
Series_SeriesRegistry.registerSeriesType('spline', SplineSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Spline_SplineSeries = (SplineSeries);
/* *
 *
 *  API Options
 *
 * */
/**
 * A `spline` series. If the [type](#series.spline.type) option is
 * not specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.spline
 * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
 * @product   highcharts highstock
 * @apioption series.spline
 */
/**
 * An array of data points for the series. For the `spline` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 9],
 *        [1, 2],
 *        [2, 8]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.spline.turboThreshold),
 *    this option is not available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 9,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 0,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.line.data
 * @product   highcharts highstock
 * @apioption series.spline.data
 */
''; // Adds doclets above intro transpiled

;// ./code/es5/es-modules/Series/AreaSpline/AreaSplineSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var AreaSplineSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();


var _a = Series_SeriesRegistry.seriesTypes, AreaSplineSeries_AreaSeries = _a.area, areaProto = _a.area.prototype;

var AreaSplineSeries_extend = Core_Utilities.extend, AreaSplineSeries_merge = Core_Utilities.merge;
/* *
 *
 *  Class
 *
 * */
/**
 * AreaSpline series type.
 *
 * @private
 * @class
 * @name Highcharts.seriesTypes.areaspline
 *
 * @augments Highcharts.Series
 */
var AreaSplineSeries = /** @class */ (function (_super) {
    AreaSplineSeries_extends(AreaSplineSeries, _super);
    function AreaSplineSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Static Properties
     *
     * */
    AreaSplineSeries.defaultOptions = AreaSplineSeries_merge(Spline_SplineSeries.defaultOptions, AreaSplineSeries_AreaSeries.defaultOptions);
    return AreaSplineSeries;
}(Spline_SplineSeries));
AreaSplineSeries_extend(AreaSplineSeries.prototype, {
    getGraphPath: areaProto.getGraphPath,
    getStackPoints: areaProto.getStackPoints,
    drawGraph: areaProto.drawGraph
});
Series_SeriesRegistry.registerSeriesType('areaspline', AreaSplineSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var AreaSpline_AreaSplineSeries = ((/* unused pure expression or super */ null && (AreaSplineSeries)));
/* *
 *
 *  API Options
 *
 * */
/**
 * The area spline series is an area series where the graph between the
 * points is smoothed into a spline.
 *
 * @sample {highcharts} highcharts/demo/areaspline/
 *         Area spline chart
 * @sample {highstock} stock/demo/areaspline/
 *         Area spline chart
 *
 * @extends   plotOptions.area
 * @excluding step, boostThreshold, boostBlending
 * @product   highcharts highstock
 * @apioption plotOptions.areaspline
 */
/**
 * @see [fillColor](#plotOptions.areaspline.fillColor)
 * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
 *
 * @apioption plotOptions.areaspline.color
 */
/**
 * @see [color](#plotOptions.areaspline.color)
 * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
 *
 * @apioption plotOptions.areaspline.fillColor
 */
/**
 * @see [color](#plotOptions.areaspline.color)
 * @see [fillColor](#plotOptions.areaspline.fillColor)
 *
 * @default   0.75
 * @apioption plotOptions.areaspline.fillOpacity
 */
/**
 * A `areaspline` series. If the [type](#series.areaspline.type) option
 * is not specified, it is inherited from [chart.type](#chart.type).
 *
 *
 * @extends   series,plotOptions.areaspline
 * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
 * @product   highcharts highstock
 * @apioption series.areaspline
 */
/**
 * @see [fillColor](#series.areaspline.fillColor)
 * @see [fillOpacity](#series.areaspline.fillOpacity)
 *
 * @apioption series.areaspline.color
 */
/**
 * An array of data points for the series. For the `areaspline` series
 * type, points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 10],
 *        [1, 9],
 *        [2, 3]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.areaspline.turboThreshold), this option is not
 *    available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 4,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 4,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.line.data
 * @product   highcharts highstock
 * @apioption series.areaspline.data
 */
/**
 * @see [color](#series.areaspline.color)
 * @see [fillOpacity](#series.areaspline.fillOpacity)
 *
 * @apioption series.areaspline.fillColor
 */
/**
 * @see [color](#series.areaspline.color)
 * @see [fillColor](#series.areaspline.fillColor)
 *
 * @default   0.75
 * @apioption series.areaspline.fillOpacity
 */
''; // Adds doclets above into transpiled

;// ./code/es5/es-modules/Series/Column/ColumnSeriesDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * Column series display one column per value along an X axis.
 *
 * @sample {highcharts} highcharts/demo/column-basic/
 *         Column chart
 * @sample {highstock} stock/demo/column/
 *         Column chart
 *
 * @extends      plotOptions.line
 * @excluding    connectEnds, connectNulls, gapSize, gapUnit, linecap,
 *               lineWidth, marker, step, useOhlcData
 * @product      highcharts highstock
 * @optionparent plotOptions.column
 */
var ColumnSeriesDefaults = {
    /**
     * The corner radius of the border surrounding each column or bar. A number
     * signifies pixels. A percentage string, like for example `50%`, signifies
     * a relative size. For columns this is relative to the column width, for
     * pies it is relative to the radius and the inner radius.
     *
     * @sample  {highcharts} highcharts/plotoptions/column-borderradius/
     *          Rounded columns
     * @sample  highcharts/plotoptions/series-border-radius
     *          Column and pie with rounded border
     *
     * @type    {number|string|Highcharts.BorderRadiusOptionsObject}
     * @product highcharts highstock gantt
     */
    borderRadius: 3,
    /**
     * When using automatic point colors pulled from the global
     * [colors](colors) or series-specific
     * [plotOptions.column.colors](series.colors) collections, this option
     * determines whether the chart should receive one color per series or
     * one color per point.
     *
     * In styled mode, the `colors` or `series.colors` arrays are not
     * supported, and instead this option gives the points individual color
     * class names on the form `highcharts-color-{n}`.
     *
     * @see [series colors](#plotOptions.column.colors)
     *
     * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/
     *         False by default
     * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/
     *         True
     *
     * @type      {boolean}
     * @default   false
     * @since     2.0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.colorByPoint
     */
    /**
     * A series specific or series type specific color set to apply instead
     * of the global [colors](#colors) when [colorByPoint](
     * #plotOptions.column.colorByPoint) is true.
     *
     * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
     * @since     3.0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.colors
     */
    /**
     * When `true`, the columns will center in the category, ignoring null
     * or missing points. When `false`, space will be reserved for null or
     * missing points.
     *
     * @sample {highcharts} highcharts/series-column/centerincategory/
     *         Center in category
     * @sample {highcharts} highcharts/series/stack-centerincategory/
     *         Center in category, stacked and grouped
     *
     * @since   8.0.1
     * @product highcharts highstock gantt
     */
    centerInCategory: false,
    /**
     * Padding between each value groups, in x axis units.
     *
     * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/
     *         0.2 by default
     * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/
     *         No group padding - all columns are evenly spaced
     *
     * @product highcharts highstock gantt
     */
    groupPadding: 0.2,
    /**
     * Whether to group non-stacked columns or to let them render
     * independent of each other. Non-grouped columns will be laid out
     * individually and overlap each other.
     *
     * @sample {highcharts} highcharts/plotoptions/column-grouping-false/
     *         Grouping disabled
     * @sample {highstock} highcharts/plotoptions/column-grouping-false/
     *         Grouping disabled
     *
     * @type      {boolean}
     * @default   true
     * @since     2.3.0
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.grouping
     */
    /** @ignore-option */
    marker: null, // Point options are specified in the base options
    /**
     * The maximum allowed pixel width for a column, translated to the
     * height of a bar in a bar chart. This prevents the columns from
     * becoming too wide when there is a small number of points in the
     * chart.
     *
     * @see [pointWidth](#plotOptions.column.pointWidth)
     *
     * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/
     *         Limited to 50
     * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/
     *         Limited to 50
     *
     * @type      {number}
     * @since     4.1.8
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.maxPointWidth
     */
    /**
     * Padding between each column or bar, in x axis units.
     *
     * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/
     *         0.1 by default
     * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/
     *          0.25
     * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/
     *         0 for tightly packed columns
     *
     * @product highcharts highstock gantt
     */
    pointPadding: 0.1,
    /**
     * A pixel value specifying a fixed width for each column or bar point.
     * When set to `undefined`, the width is calculated from the
     * `pointPadding` and `groupPadding`. The width effects the dimension
     * that is not based on the point value. For column series it is the
     * horizontal length and for bar series it is the vertical length.
     *
     * @see [maxPointWidth](#plotOptions.column.maxPointWidth)
     *
     * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/
     *         20px wide columns regardless of chart width or the amount of
     *         data points
     *
     * @type      {number}
     * @since     1.2.5
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.pointWidth
     */
    /**
     * A pixel value specifying a fixed width for the column or bar.
     * Overrides pointWidth on the series.
     *
     * @see [series.pointWidth](#plotOptions.column.pointWidth)
     *
     * @type      {number}
     * @default   undefined
     * @since     7.0.0
     * @product   highcharts highstock gantt
     * @apioption series.column.data.pointWidth
     */
    /**
     * The minimal height for a column or width for a bar. By default,
     * 0 values are not shown. To visualize a 0 (or close to zero) point,
     * set the minimal point length to a pixel value like 3\. In stacked
     * column charts, minPointLength might not be respected for tightly
     * packed values.
     *
     * @sample {highcharts} highcharts/plotoptions/column-minpointlength/
     *         Zero base value
     * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/
     *         Positive and negative close to zero values
     *
     * @product highcharts highstock gantt
     */
    minPointLength: 0,
    /**
     * When the series contains less points than the crop threshold, all
     * points are drawn, event if the points fall outside the visible plot
     * area at the current zoom. The advantage of drawing all points
     * (including markers and columns), is that animation is performed on
     * updates. On the other hand, when the series contains more points than
     * the crop threshold, the series data is cropped to only contain points
     * that fall within the plot area. The advantage of cropping away
     * invisible points is to increase performance on large series.
     *
     * @product highcharts highstock gantt
     */
    cropThreshold: 50,
    /**
     * The X axis range that each point is valid for. This determines the
     * width of the column. On a categorized axis, the range will be 1
     * by default (one category unit). On linear and datetime axes, the
     * range will be computed as the distance between the two closest data
     * points.
     *
     * The default `null` means it is computed automatically, but this
     * option can be used to override the automatic value.
     *
     * This option is set by default to 1 if data sorting is enabled.
     *
     * @sample {highcharts} highcharts/plotoptions/column-pointrange/
     *         Set the point range to one day on a data set with one week
     *         between the points
     *
     * @type    {number|null}
     * @since   2.3
     * @product highcharts highstock gantt
     */
    pointRange: null,
    states: {
        /**
         * Options for the hovered point. These settings override the normal
         * state options when a point is moused over or touched.
         *
         * @extends   plotOptions.series.states.hover
         * @excluding halo, lineWidth, lineWidthPlus, marker
         * @product   highcharts highstock gantt
         */
        hover: {
            /** @ignore-option */
            halo: false,
            /**
             * A specific border color for the hovered point. Defaults to
             * inherit the normal state border color.
             *
             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @product   highcharts gantt
             * @apioption plotOptions.column.states.hover.borderColor
             */
            /**
             * A specific color for the hovered point.
             *
             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @product   highcharts gantt
             * @apioption plotOptions.column.states.hover.color
             */
            /**
             * How much to brighten the point on interaction. Requires the
             * main color to be defined in hex or rgb(a) format.
             *
             * In styled mode, the hover brightening is by default replaced
             * with a fill-opacity set in the `.highcharts-point:hover`
             * rule.
             *
             * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/
             *         Brighten by 0.5
             *
             * @product highcharts highstock gantt
             */
            brightness: 0.1
        },
        /**
         * Options for the selected point. These settings override the
         * normal state options when a point is selected.
         *
         * @extends   plotOptions.series.states.select
         * @excluding halo, lineWidth, lineWidthPlus, marker
         * @product   highcharts highstock gantt
         */
        select: {
            /**
             * A specific color for the selected point.
             *
             * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @default #cccccc
             * @product highcharts highstock gantt
             */
            color: "#cccccc" /* Palette.neutralColor20 */,
            /**
             * A specific border color for the selected point.
             *
             * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @default #000000
             * @product highcharts highstock gantt
             */
            borderColor: "#000000" /* Palette.neutralColor100 */
        }
    },
    dataLabels: {
        align: void 0,
        verticalAlign: void 0,
        /**
         * The y position offset of the label relative to the point in
         * pixels.
         *
         * @type {number}
         */
        y: void 0
    },
    // False doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/
    /** @ignore-option */
    startFromThreshold: true,
    stickyTracking: false,
    tooltip: {
        distance: 6
    },
    /**
     * The Y axis value to serve as the base for the columns, for
     * distinguishing between values above and below a threshold. If `null`,
     * the columns extend from the padding Y axis minimum.
     *
     * @type    {number|null}
     * @since   2.0
     * @product highcharts
     */
    threshold: 0,
    /**
     * The width of the border surrounding each column or bar. Defaults to
     * `1` when there is room for a border, but to `0` when the columns are
     * so dense that a border would cover the next column.
     *
     * In styled mode, the stroke width can be set with the
     * `.highcharts-point` rule.
     *
     * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
     *         2px black border
     *
     * @type      {number}
     * @default   undefined
     * @product   highcharts highstock gantt
     * @apioption plotOptions.column.borderWidth
     */
    /**
     * The color of the border surrounding each column or bar.
     *
     * In styled mode, the border stroke can be set with the
     * `.highcharts-point` rule.
     *
     * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
     *         Dark gray border
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default   #ffffff
     * @product   highcharts highstock gantt
     */
    borderColor: "#ffffff" /* Palette.backgroundColor */
};
/**
 * A `column` series. If the [type](#series.column.type) option is
 * not specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.column
 * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap,
 *            lineWidth, marker, connectEnds, step
 * @product   highcharts highstock
 * @apioption series.column
 */
/**
 * An array of data points for the series. For the `column` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 6],
 *        [1, 2],
 *        [2, 6]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.column.turboThreshold), this option is not
 *    available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 9,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 6,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.line.data
 * @excluding marker
 * @product   highcharts highstock
 * @apioption series.column.data
 */
/**
 * The color of the border surrounding the column or bar.
 *
 * In styled mode, the border stroke can be set with the `.highcharts-point`
 * rule.
 *
 * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
 *         Dark gray border
 *
 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
 * @product   highcharts highstock
 * @apioption series.column.data.borderColor
 */
/**
 * The width of the border surrounding the column or bar.
 *
 * In styled mode, the stroke width can be set with the `.highcharts-point`
 * rule.
 *
 * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
 *         2px black border
 *
 * @type      {number}
 * @product   highcharts highstock
 * @apioption series.column.data.borderWidth
 */
/**
 * A name for the dash style to use for the column or bar. Overrides
 * dashStyle on the series.
 *
 * In styled mode, the stroke dash-array can be set with the same classes as
 * listed under [data.color](#series.column.data.color).
 *
 * @see [series.pointWidth](#plotOptions.column.dashStyle)
 *
 * @type      {Highcharts.DashStyleValue}
 * @apioption series.column.data.dashStyle
 */
/**
 * A pixel value specifying a fixed width for the column or bar. Overrides
 * pointWidth on the series. The width effects the dimension that is not based
 * on the point value.
 *
 * @see [series.pointWidth](#plotOptions.column.pointWidth)
 *
 * @type      {number}
 * @apioption series.column.data.pointWidth
 */
/**
 * @excluding halo, lineWidth, lineWidthPlus, marker
 * @product   highcharts highstock
 * @apioption series.column.states.hover
 */
/**
 * @excluding halo, lineWidth, lineWidthPlus, marker
 * @product   highcharts highstock
 * @apioption series.column.states.select
 */
''; // Keeps doclets above in JS file
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Column_ColumnSeriesDefaults = (ColumnSeriesDefaults);

;// ./code/es5/es-modules/Series/Column/ColumnSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var ColumnSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var ColumnSeries_animObject = AnimationUtilities.animObject;

var ColumnSeries_color = Color_Color.parse;


var ColumnSeries_noop = Core_Globals.noop;



var ColumnSeries_clamp = Core_Utilities.clamp, ColumnSeries_crisp = Core_Utilities.crisp, ColumnSeries_defined = Core_Utilities.defined, ColumnSeries_extend = Core_Utilities.extend, ColumnSeries_fireEvent = Core_Utilities.fireEvent, ColumnSeries_isArray = Core_Utilities.isArray, ColumnSeries_isNumber = Core_Utilities.isNumber, ColumnSeries_merge = Core_Utilities.merge, ColumnSeries_pick = Core_Utilities.pick, ColumnSeries_objectEach = Core_Utilities.objectEach;
/* *
 *
 *  Class
 *
 * */
/**
 * The column series type.
 *
 * @private
 * @class
 * @name Highcharts.seriesTypes.column
 *
 * @augments Highcharts.Series
 */
var ColumnSeries = /** @class */ (function (_super) {
    ColumnSeries_extends(ColumnSeries, _super);
    function ColumnSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Animate the column heights one by one from zero.
     *
     * @private
     * @function Highcharts.seriesTypes.column#animate
     *
     * @param {boolean} init
     *        Whether to initialize the animation or run it
     */
    ColumnSeries.prototype.animate = function (init) {
        var series = this,
            yAxis = this.yAxis,
            yAxisPos = yAxis.pos,
            reversed = yAxis.reversed,
            options = series.options,
            _a = this.chart,
            clipOffset = _a.clipOffset,
            inverted = _a.inverted,
            attr = {},
            translateProp = inverted ?
                'translateX' :
                'translateY';
        var translateStart,
            translatedThreshold;
        if (init && clipOffset) {
            attr.scaleY = 0.001;
            translatedThreshold = ColumnSeries_clamp(yAxis.toPixels(options.threshold || 0), yAxisPos, yAxisPos + yAxis.len);
            if (inverted) {
                // Make sure the columns don't cover the axis line during
                // entrance animation
                translatedThreshold += reversed ?
                    -Math.floor(clipOffset[0]) :
                    Math.ceil(clipOffset[2]);
                attr.translateX = translatedThreshold - yAxis.len;
            }
            else {
                // Make sure the columns don't cover the axis line during
                // entrance animation
                translatedThreshold += reversed ?
                    Math.ceil(clipOffset[0]) :
                    -Math.floor(clipOffset[2]);
                attr.translateY = translatedThreshold;
            }
            // Apply final clipping (used in Highcharts Stock) (#7083)
            // animation is done by scaleY, so clipping is for panes
            if (series.clipBox) {
                series.setClip();
            }
            series.group.attr(attr);
        }
        else { // Run the animation
            translateStart = Number(series.group.attr(translateProp));
            series.group.animate({ scaleY: 1 }, ColumnSeries_extend(ColumnSeries_animObject(series.options.animation), {
                // Do the scale synchronously to ensure smooth
                // updating (#5030, #7228)
                step: function (val, fx) {
                    if (series.group) {
                        attr[translateProp] = translateStart +
                            fx.pos * (yAxisPos - translateStart);
                        series.group.attr(attr);
                    }
                }
            }));
        }
    };
    /**
     * Initialize the series. Extends the basic Series.init method by
     * marking other series of the same type as dirty.
     *
     * @private
     * @function Highcharts.seriesTypes.column#init
     */
    ColumnSeries.prototype.init = function (chart, 
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    options) {
        _super.prototype.init.apply(this, arguments);
        var series = this;
        chart = series.chart;
        // If the series is added dynamically, force redraw of other
        // series affected by a new column
        if (chart.hasRendered) {
            chart.series.forEach(function (otherSeries) {
                if (otherSeries.type === series.type) {
                    otherSeries.isDirty = true;
                }
            });
        }
    };
    /**
     * Return the width and x offset of the columns adjusted for grouping,
     * groupPadding, pointPadding, pointWidth etc.
     *
     * @private
     * @function Highcharts.seriesTypes.column#getColumnMetrics
     */
    ColumnSeries.prototype.getColumnMetrics = function () {
        var _a,
            _b;
        var series = this,
            options = series.options,
            xAxis = series.xAxis,
            yAxis = series.yAxis,
            reversedStacks = xAxis.options.reversedStacks, 
            // Keep backward compatibility: reversed xAxis had reversed
            // stacks
            reverseStacks = (xAxis.reversed && !reversedStacks) ||
                (!xAxis.reversed && reversedStacks),
            stackGroups = {};
        var stackKey,
            columnCount = 0;
        // Get the total number of column type series. This is called on
        // every series. Consider moving this logic to a chart.orderStacks()
        // function and call it on init, addSeries and removeSeries
        if (options.grouping === false) {
            columnCount = 1;
        }
        else {
            series.chart.series.forEach(function (otherSeries) {
                var otherYAxis = otherSeries.yAxis,
                    otherOptions = otherSeries.options;
                var columnIndex;
                if (otherSeries.type === series.type &&
                    otherSeries.reserveSpace() &&
                    yAxis.len === otherYAxis.len &&
                    yAxis.pos === otherYAxis.pos) { // #642, #2086
                    if (otherOptions.stacking &&
                        otherOptions.stacking !== 'group') {
                        stackKey = otherSeries.stackKey;
                        if (typeof stackGroups[stackKey] ===
                            'undefined') {
                            stackGroups[stackKey] = columnCount++;
                        }
                        columnIndex = stackGroups[stackKey];
                    }
                    else if (otherOptions.grouping !== false) { // #1162
                        columnIndex = columnCount++;
                    }
                    otherSeries.columnIndex = columnIndex;
                }
            });
        }
        var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((!((_a = xAxis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks) && ((_b = xAxis.ordinal) === null || _b === void 0 ? void 0 : _b.slope)) ||
                options.pointRange ||
                xAxis.closestPointRange ||
                xAxis.tickInterval ||
                1), // #2610
            xAxis.len // #1535
            ), groupPadding = categoryWidth * options.groupPadding, groupWidth = categoryWidth - 2 * groupPadding, pointOffsetWidth = groupWidth / (columnCount || 1), pointWidth = Math.min(options.maxPointWidth || xAxis.len, ColumnSeries_pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))), pointPadding = (pointOffsetWidth - pointWidth) / 2, 
            // #1251, #3737
            colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0), pointXOffset = pointPadding +
                (groupPadding +
                    colIndex * pointOffsetWidth -
                    (categoryWidth / 2)) * (reverseStacks ? -1 : 1);
        // Save it for reading in linked series (Error bars particularly)
        series.columnMetrics = {
            width: pointWidth,
            offset: pointXOffset,
            paddedWidth: pointOffsetWidth,
            columnCount: columnCount
        };
        return series.columnMetrics;
    };
    /**
     * Make the columns crisp. The edges are rounded to the nearest full
     * pixel.
     *
     * @private
     * @function Highcharts.seriesTypes.column#crispCol
     */
    ColumnSeries.prototype.crispCol = function (x, y, width, height) {
        var borderWidth = this.borderWidth,
            inverted = this.chart.inverted,
            bottom = ColumnSeries_crisp(y + height,
            borderWidth,
            inverted);
        // Vertical
        y = ColumnSeries_crisp(y, borderWidth, inverted);
        height = bottom - y;
        // Horizontal. We need to first compute the exact right edge, then
        // round it and compute the width from there.
        if (this.options.crisp) {
            var right = ColumnSeries_crisp(x + width,
                borderWidth);
            x = ColumnSeries_crisp(x, borderWidth);
            width = right - x;
        }
        return { x: x, y: y, width: width, height: height };
    };
    /**
     * Adjust for missing columns, according to the `centerInCategory`
     * option. Missing columns are either single points or stacks where the
     * point or points are either missing or null.
     *
     * @private
     * @function Highcharts.seriesTypes.column#adjustForMissingColumns
     * @param {number} x
     * The x coordinate of the column, left side
     *
     * @param {number} pointWidth
     * The pointWidth, already computed upstream
     *
     * @param {Highcharts.ColumnPoint} point
     * The point instance
     *
     * @param {Highcharts.ColumnMetricsObject} metrics
     * The series-wide column metrics
     *
     * @return {number}
     * The adjusted x position, or the original if not adjusted
     */
    ColumnSeries.prototype.adjustForMissingColumns = function (x, pointWidth, point, metrics) {
        var _this = this;
        var _a;
        if (!point.isNull && metrics.columnCount > 1) {
            var visibleSeries_1 = this.xAxis.series
                    .filter(function (s) { return s.visible; })
                    .map(function (s) { return s.index; });
            var indexInCategory_1 = 0,
                totalInCategory_1 = 0;
            // Loop over all the stacks on the Y axis. When stacking is enabled,
            // these are real point stacks. When stacking is not enabled, but
            // `centerInCategory` is true, there is one stack handling the
            // grouping of points in each category. This is done in the
            // `setGroupedPoints` function.
            ColumnSeries_objectEach((_a = this.xAxis.stacking) === null || _a === void 0 ? void 0 : _a.stacks, function (stack) {
                var _a;
                var points = typeof point.x === 'number' ?
                        (_a = stack[point.x.toString()]) === null || _a === void 0 ? void 0 : _a.points :
                        void 0,
                    pointValues = points === null || points === void 0 ? void 0 : points[_this.index],
                    yStackMap = {};
                // Look for the index
                if (points && ColumnSeries_isArray(pointValues)) {
                    var baseIndex_1 = _this.index;
                    // If there are multiple points with the same X then
                    // gather all series in category, and assign index
                    var seriesIndexes = Object
                            .keys(points)
                            .filter(function (pointKey) {
                            // Filter out duplicate X's
                            return !pointKey.match(',') &&
                                // Filter out null points
                                points[pointKey] &&
                                points[pointKey].length > 1;
                    })
                        .map(parseFloat)
                        .filter(function (index) {
                        return visibleSeries_1.indexOf(index) !== -1;
                    })
                        // When the series `stack` option is defined, assign
                        // all subsequent column of the same stack to the
                        // same index as the base column of the stack, then
                        // filter out the original series index so that
                        // `seriesIndexes` is shortened to the amount of
                        // stacks, not the amount of series (#20550).
                        .filter(function (index) {
                        var otherOptions = _this.chart.series[index]
                                .options,
                            yStack = otherOptions.stacking &&
                                otherOptions.stack;
                        if (ColumnSeries_defined(yStack)) {
                            if (ColumnSeries_isNumber(yStackMap[yStack])) {
                                if (baseIndex_1 === index) {
                                    baseIndex_1 = yStackMap[yStack];
                                }
                                return false;
                            }
                            yStackMap[yStack] = index;
                        }
                        return true;
                    })
                        .sort(function (a, b) { return b - a; });
                    indexInCategory_1 = seriesIndexes.indexOf(baseIndex_1);
                    totalInCategory_1 = seriesIndexes.length;
                }
            });
            indexInCategory_1 = this.xAxis.reversed ?
                totalInCategory_1 - 1 - indexInCategory_1 : indexInCategory_1;
            // Compute the adjusted x position
            var boxWidth = (totalInCategory_1 - 1) * metrics.paddedWidth +
                    pointWidth;
            x = (point.plotX || 0) + boxWidth / 2 - pointWidth -
                indexInCategory_1 * metrics.paddedWidth;
        }
        return x;
    };
    /**
     * Translate each point to the plot area coordinate system and find
     * shape positions
     *
     * @private
     * @function Highcharts.seriesTypes.column#translate
     */
    ColumnSeries.prototype.translate = function () {
        var series = this,
            chart = series.chart,
            options = series.options,
            dense = series.dense =
                series.closestPointRange * series.xAxis.transA < 2,
            borderWidth = series.borderWidth = ColumnSeries_pick(options.borderWidth,
            dense ? 0 : 1 // #3635
            ),
            xAxis = series.xAxis,
            yAxis = series.yAxis,
            threshold = options.threshold,
            minPointLength = ColumnSeries_pick(options.minPointLength, 5),
            metrics = series.getColumnMetrics(),
            seriesPointWidth = metrics.width,
            seriesXOffset = series.pointXOffset = metrics.offset,
            dataMin = series.dataMin,
            dataMax = series.dataMax,
            translatedThreshold = series.translatedThreshold =
                yAxis.getThreshold(threshold);
        // Postprocessed for border width
        var seriesBarW = series.barW =
                Math.max(seriesPointWidth, 1 + 2 * borderWidth);
        // When the pointPadding is 0, we want the columns to be packed
        // tightly, so we allow individual columns to have individual sizes.
        // When pointPadding is greater, we strive for equal-width columns
        // (#2694).
        if (options.pointPadding && options.crisp) {
            seriesBarW = Math.ceil(seriesBarW);
        }
        Series_Series.prototype.translate.apply(series);
        // Record the new values
        series.points.forEach(function (point) {
            var yBottom = ColumnSeries_pick(point.yBottom,
                translatedThreshold),
                safeDistance = 999 + Math.abs(yBottom),
                plotX = point.plotX || 0, 
                // Don't draw too far outside plot area (#1303, #2241,
                // #4264)
                plotY = ColumnSeries_clamp(point.plotY, -safeDistance,
                yAxis.len + safeDistance);
            var up,
                barY = Math.min(plotY,
                yBottom),
                barH = Math.max(plotY,
                yBottom) - barY,
                pointWidth = seriesPointWidth,
                barX = plotX + seriesXOffset,
                barW = seriesBarW;
            // Handle options.minPointLength
            if (minPointLength && Math.abs(barH) < minPointLength) {
                barH = minPointLength;
                up = (!yAxis.reversed && !point.negative) ||
                    (yAxis.reversed && point.negative);
                // Reverse zeros if there's no positive value in the series
                // in visible range (#7046)
                if (ColumnSeries_isNumber(threshold) &&
                    ColumnSeries_isNumber(dataMax) &&
                    point.y === threshold &&
                    dataMax <= threshold &&
                    // And if there's room for it (#7311)
                    (yAxis.min || 0) < threshold &&
                    // If all points are the same value (i.e zero) not draw
                    // as negative points (#10646), but only if there's room
                    // for it (#14876)
                    (dataMin !== dataMax || (yAxis.max || 0) <= threshold)) {
                    up = !up;
                    point.negative = !point.negative;
                }
                // If stacked...
                barY = (Math.abs(barY - translatedThreshold) > minPointLength ?
                    // ...keep position
                    yBottom - minPointLength :
                    // #1485, #4051
                    translatedThreshold -
                        (up ? minPointLength : 0));
            }
            // Handle point.options.pointWidth
            // @todo Handle grouping/stacking too. Calculate offset properly
            if (ColumnSeries_defined(point.options.pointWidth)) {
                pointWidth = barW =
                    Math.ceil(point.options.pointWidth);
                barX -= Math.round((pointWidth - seriesPointWidth) / 2);
            }
            // Adjust for null or missing points
            if (options.centerInCategory) {
                barX = series.adjustForMissingColumns(barX, pointWidth, point, metrics);
            }
            // Cache for access in polar
            point.barX = barX;
            point.pointWidth = pointWidth;
            // Fix the tooltip on center of grouped columns (#1216, #424,
            // #3648)
            point.tooltipPos = chart.inverted ?
                [
                    ColumnSeries_clamp(yAxis.len + yAxis.pos - chart.plotLeft - plotY, yAxis.pos - chart.plotLeft, yAxis.len + yAxis.pos - chart.plotLeft),
                    xAxis.len + xAxis.pos - chart.plotTop - barX - barW / 2,
                    barH
                ] :
                [
                    xAxis.left - chart.plotLeft + barX + barW / 2,
                    ColumnSeries_clamp(plotY + yAxis.pos -
                        chart.plotTop, yAxis.pos - chart.plotTop, yAxis.len + yAxis.pos - chart.plotTop),
                    barH
                ];
            // Register shape type and arguments to be used in drawPoints. Allow
            // `shapeType` defined on `pointClass` level.
            point.shapeType = series.pointClass.prototype.shapeType ||
                'roundedRect';
            point.shapeArgs = series.crispCol(barX, 
            // #3169, drilldown from null must have a position to work from.
            // #6585, dataLabel should be placed on xAxis, not floating in
            // the middle of the chart.
            point.isNull ? translatedThreshold : barY, barW, point.isNull ? 0 : barH);
        });
        // Fire a specific event after column translate. We could instead apply
        // all the column logic in an `afterTranslate` event handler, but there
        // are so many other series types that use the column translation, that
        // it is more convenient to have a specific event for it.
        ColumnSeries_fireEvent(this, 'afterColumnTranslate');
    };
    /**
     * Columns have no graph
     *
     * @private
     * @function Highcharts.seriesTypes.column#drawGraph
     */
    ColumnSeries.prototype.drawGraph = function () {
        this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data');
    };
    /**
     * Get presentational attributes
     *
     * @private
     * @function Highcharts.seriesTypes.column#pointAttribs
     */
    ColumnSeries.prototype.pointAttribs = function (point, state) {
        var options = this.options, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth';
        var stateOptions,
            zone,
            brightness,
            fill = (point && point.color) || this.color, 
            // Set to fill when borderColor null:
            stroke = ((point && point[strokeOption]) ||
                options[strokeOption] ||
                fill),
            dashstyle = (point && point.options.dashStyle) || options.dashStyle,
            strokeWidth = (point && point[strokeWidthOption]) ||
                options[strokeWidthOption] ||
                this[strokeWidthOption] || 0,
            opacity = ColumnSeries_pick(point && point.opacity,
            options.opacity, 1);
        // Handle zone colors
        if (point && this.zones.length) {
            zone = point.getZone();
            // When zones are present, don't use point.color (#4267).
            // Changed order (#6527), added support for colorAxis (#10670)
            fill = (point.options.color ||
                (zone && (zone.color || point.nonZonedColor)) ||
                this.color);
            if (zone) {
                stroke = zone.borderColor || stroke;
                dashstyle = zone.dashStyle || dashstyle;
                strokeWidth = zone.borderWidth || strokeWidth;
            }
        }
        // Select or hover states
        if (state && point) {
            stateOptions = ColumnSeries_merge(options.states[state], 
            // #6401
            point.options.states &&
                point.options.states[state] ||
                {});
            brightness = stateOptions.brightness;
            fill =
                stateOptions.color || (typeof brightness !== 'undefined' &&
                    ColumnSeries_color(fill)
                        .brighten(stateOptions.brightness)
                        .get()) || fill;
            stroke = stateOptions[strokeOption] || stroke;
            strokeWidth =
                stateOptions[strokeWidthOption] || strokeWidth;
            dashstyle = stateOptions.dashStyle || dashstyle;
            opacity = ColumnSeries_pick(stateOptions.opacity, opacity);
        }
        var ret = {
                fill: fill,
                stroke: stroke,
                'stroke-width': strokeWidth,
                opacity: opacity
            };
        if (dashstyle) {
            ret.dashstyle = dashstyle;
        }
        return ret;
    };
    /**
     * Draw the columns. For bars, the series.group is rotated, so the same
     * coordinates apply for columns and bars. This method is inherited by
     * scatter series.
     *
     * @private
     * @function Highcharts.seriesTypes.column#drawPoints
     */
    ColumnSeries.prototype.drawPoints = function (points) {
        if (points === void 0) { points = this.points; }
        var series = this,
            chart = this.chart,
            options = series.options,
            renderer = chart.renderer,
            animationLimit = options.animationLimit || 250;
        var shapeArgs;
        // Draw the columns
        points.forEach(function (point) {
            var plotY = point.plotY;
            var graphic = point.graphic,
                hasGraphic = !!graphic,
                verb = graphic && chart.pointCount < animationLimit ?
                    'animate' : 'attr';
            if (ColumnSeries_isNumber(plotY) && point.y !== null) {
                shapeArgs = point.shapeArgs;
                // When updating a series between 2d and 3d or cartesian and
                // polar, the shape type changes.
                if (graphic && point.hasNewShapeType()) {
                    graphic = graphic.destroy();
                }
                // Set starting position for point sliding animation.
                if (series.enabledDataSorting) {
                    point.startXPos = series.xAxis.reversed ?
                        -(shapeArgs ? (shapeArgs.width || 0) : 0) :
                        series.xAxis.width;
                }
                if (!graphic) {
                    point.graphic = graphic =
                        renderer[point.shapeType](shapeArgs)
                            .add(point.group || series.group);
                    if (graphic &&
                        series.enabledDataSorting &&
                        chart.hasRendered &&
                        chart.pointCount < animationLimit) {
                        graphic.attr({
                            x: point.startXPos
                        });
                        hasGraphic = true;
                        verb = 'animate';
                    }
                }
                if (graphic && hasGraphic) { // Update
                    graphic[verb](ColumnSeries_merge(shapeArgs));
                }
                // Presentational
                if (!chart.styledMode) {
                    graphic[verb](series.pointAttribs(point, (point.selected && 'select')))
                        .shadow(point.allowShadow !== false && options.shadow);
                }
                if (graphic) {
                    graphic.addClass(point.getClassName(), true);
                    graphic.attr({
                        visibility: point.visible ? 'inherit' : 'hidden'
                    });
                }
            }
            else if (graphic) {
                point.graphic = graphic.destroy(); // #1269
            }
        });
    };
    /**
     * Draw the tracker for a point.
     * @private
     */
    ColumnSeries.prototype.drawTracker = function (points) {
        if (points === void 0) { points = this.points; }
        var series = this,
            chart = series.chart,
            pointer = chart.pointer,
            onMouseOver = function (e) {
                pointer === null || pointer === void 0 ? void 0 : pointer.normalize(e);
            var point = pointer === null || pointer === void 0 ? void 0 : pointer.getPointFromEvent(e), 
                // Run point events only for points inside plot area, #21136
                isInsidePlot = chart.scrollablePlotArea ?
                    chart.isInsidePlot(e.chartX - chart.plotLeft,
                e.chartY - chart.plotTop, {
                        visiblePlotOnly: true
                    }) : true;
            // Undefined on graph in scatterchart
            if (pointer &&
                point &&
                series.options.enableMouseTracking &&
                isInsidePlot) {
                pointer.isDirectTouch = true;
                point.onMouseOver(e);
            }
        };
        var dataLabels;
        // Add reference to the point
        points.forEach(function (point) {
            dataLabels = (ColumnSeries_isArray(point.dataLabels) ?
                point.dataLabels :
                (point.dataLabel ? [point.dataLabel] : []));
            if (point.graphic) {
                point.graphic.element.point = point;
            }
            dataLabels.forEach(function (dataLabel) {
                (dataLabel.div || dataLabel.element).point = point;
            });
        });
        // Add the event listeners, we need to do this only once
        if (!series._hasTracking) {
            series.trackerGroups.forEach(function (key) {
                if (series[key]) {
                    // We don't always have dataLabelsGroup
                    series[key]
                        .addClass('highcharts-tracker')
                        .on('mouseover', onMouseOver)
                        .on('mouseout', function (e) {
                        pointer === null || pointer === void 0 ? void 0 : pointer.onTrackerMouseOut(e);
                    })
                        .on('touchstart', onMouseOver);
                    if (!chart.styledMode && series.options.cursor) {
                        series[key]
                            .css({ cursor: series.options.cursor });
                    }
                }
            });
            series._hasTracking = true;
        }
        ColumnSeries_fireEvent(this, 'afterDrawTracker');
    };
    /**
     * Remove this series from the chart
     *
     * @private
     * @function Highcharts.seriesTypes.column#remove
     */
    ColumnSeries.prototype.remove = function () {
        var series = this,
            chart = series.chart;
        // Column and bar series affects other series of the same type
        // as they are either stacked or grouped
        if (chart.hasRendered) {
            chart.series.forEach(function (otherSeries) {
                if (otherSeries.type === series.type) {
                    otherSeries.isDirty = true;
                }
            });
        }
        Series_Series.prototype.remove.apply(series, arguments);
    };
    /* *
     *
     *  Static Properties
     *
     * */
    ColumnSeries.defaultOptions = ColumnSeries_merge(Series_Series.defaultOptions, Column_ColumnSeriesDefaults);
    return ColumnSeries;
}(Series_Series));
ColumnSeries_extend(ColumnSeries.prototype, {
    // When tooltip is not shared, this series (and derivatives) requires
    // direct touch/hover. KD-tree does not apply.
    directTouch: true,
    getSymbol: ColumnSeries_noop,
    // Use separate negative stacks, unlike area stacks where a negative
    // point is subtracted from previous (#1910)
    negStacks: true,
    trackerGroups: ['group', 'dataLabelsGroup']
});
Series_SeriesRegistry.registerSeriesType('column', ColumnSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Column_ColumnSeries = (ColumnSeries);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Adjusted width and x offset of the columns for grouping.
 *
 * @private
 * @interface Highcharts.ColumnMetricsObject
 */ /**
* Width of the columns.
* @name Highcharts.ColumnMetricsObject#width
* @type {number}
*/ /**
* Offset of the columns.
* @name Highcharts.ColumnMetricsObject#offset
* @type {number}
*/
''; // Detach doclets above

;// ./code/es5/es-modules/Core/Series/DataLabel.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var DataLabel_getDeferredAnimation = AnimationUtilities.getDeferredAnimation;

var DataLabel_format = Core_Templating.format;

var DataLabel_defined = Core_Utilities.defined, DataLabel_extend = Core_Utilities.extend, DataLabel_fireEvent = Core_Utilities.fireEvent, DataLabel_getAlignFactor = Core_Utilities.getAlignFactor, DataLabel_isArray = Core_Utilities.isArray, DataLabel_isString = Core_Utilities.isString, DataLabel_merge = Core_Utilities.merge, DataLabel_objectEach = Core_Utilities.objectEach, DataLabel_pick = Core_Utilities.pick, DataLabel_pInt = Core_Utilities.pInt, DataLabel_splat = Core_Utilities.splat;
/* *
 *
 *  Composition
 *
 * */
var DataLabel;
(function (DataLabel) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Check if this series has data labels, either a series-level setting, or
     * individual. In case of individual point labels, this method is overridden
     * to always return true.
     * @private
     */
    function hasDataLabels() {
        return mergedDataLabelOptions(this)
            .some(function (o) {
            return o === null || o === void 0 ? void 0 : o.enabled;
        });
    }
    /**
     * Align each individual data label.
     * @private
     */
    function alignDataLabel(point, dataLabel, options, alignTo, isNew) {
        var _a;
        var series = this,
            _b = this,
            chart = _b.chart,
            enabledDataSorting = _b.enabledDataSorting,
            inverted = this.isCartesian && chart.inverted,
            plotX = point.plotX,
            plotY = point.plotY,
            rotation = options.rotation || 0,
            isInsidePlot = DataLabel_defined(plotX) &&
                DataLabel_defined(plotY) &&
                chart.isInsidePlot(plotX,
            Math.round(plotY), {
                    inverted: inverted,
                    paneCoordinates: true,
                    series: series
                }),
            setStartPos = function (alignOptions) {
                if (enabledDataSorting && series.xAxis && !justify) {
                    series.setDataLabelStartPos(point,
            dataLabel,
            isNew,
            isInsidePlot,
            alignOptions);
            }
        }, justify = rotation === 0 ? DataLabel_pick(options.overflow, (enabledDataSorting ? 'none' : 'justify')) === 'justify' : false;
        // Math.round for rounding errors (#2683), alignTo to allow column
        // labels (#2700)
        var visible = this.visible &&
                point.visible !== false &&
                DataLabel_defined(plotX) &&
                (point.series.forceDL ||
                    (enabledDataSorting && !justify) ||
                    isInsidePlot ||
                    (
                    // If the data label is inside the align box, it is enough
                    // that parts of the align box is inside the plot area
                    // (#12370). When stacking, it is always inside regardless
                    // of the option (#15148).
                    DataLabel_pick(options.inside, !!this.options.stacking) &&
                        alignTo &&
                        chart.isInsidePlot(plotX,
            inverted ?
                            alignTo.x + 1 :
                            alignTo.y + alignTo.height - 1, {
                            inverted: inverted,
                            paneCoordinates: true,
                            series: series
                        })));
        var pos = point.pos();
        if (visible && pos) {
            var bBox = dataLabel.getBBox(),
                unrotatedbBox = dataLabel.getBBox(void 0, 0);
            // The alignment box is a singular point
            alignTo = DataLabel_extend({
                x: pos[0],
                y: Math.round(pos[1]),
                width: 0,
                height: 0
            }, alignTo || {});
            // Align to plot edges
            if (options.alignTo === 'plotEdges' && series.isCartesian) {
                alignTo[inverted ? 'x' : 'y'] = 0;
                alignTo[inverted ? 'width' : 'height'] = ((_a = this.yAxis) === null || _a === void 0 ? void 0 : _a.len) || 0;
            }
            // Add the text size for alignment calculation
            DataLabel_extend(options, {
                width: bBox.width,
                height: bBox.height
            });
            setStartPos(alignTo); // Data sorting
            // Align the label to the adjusted box with for unrotated bBox due
            // to rotationOrigin, which is based on unrotated label
            dataLabel.align(DataLabel_merge(options, {
                width: unrotatedbBox.width,
                height: unrotatedbBox.height
            }), false, alignTo, false);
            dataLabel.alignAttr.x += DataLabel_getAlignFactor(options.align) *
                (unrotatedbBox.width - bBox.width);
            dataLabel.alignAttr.y += DataLabel_getAlignFactor(options.verticalAlign) *
                (unrotatedbBox.height - bBox.height);
            dataLabel[dataLabel.placed ? 'animate' : 'attr']({
                'text-align': dataLabel.alignAttr['text-align'] || 'center',
                x: dataLabel.alignAttr.x +
                    (bBox.width - unrotatedbBox.width) / 2,
                y: dataLabel.alignAttr.y +
                    (bBox.height - unrotatedbBox.height) / 2,
                rotationOriginX: (dataLabel.width || 0) / 2,
                rotationOriginY: (dataLabel.height || 0) / 2
            });
            // Uncomment this block to visualize the bounding boxes used for
            // determining visibility
            // chart.renderer.rect(
            //     (dataLabel.alignAttr.x || 0) + chart.plotLeft,
            //     (dataLabel.alignAttr.y || 0) + chart.plotTop,
            //     bBox.width,
            //     bBox.height
            // ).attr({
            //     stroke: 'rgba(0, 0, 0, 0.3)',
            //     'stroke-width': 1,
            //     zIndex: 20
            // }).add();
            // chart.renderer.circle(
            //     chart.plotLeft + pick(dataLabel.alignAttr.x, 0),
            //     chart.plotTop + pick(dataLabel.alignAttr.y, 0),
            //     2
            // ).attr({
            //     fill: 'red',
            //     zIndex: 20
            // }).add();
            if (justify && alignTo.height >= 0) { // #8830
                this.justifyDataLabel(dataLabel, options, dataLabel.alignAttr, bBox, alignTo, isNew);
            }
            else if (DataLabel_pick(options.crop, true)) {
                var _c = dataLabel.alignAttr,
                    x = _c.x,
                    y = _c.y,
                    correction = 1;
                // Check if the dataLabel should be visible.
                visible =
                    chart.isInsidePlot(x, y, {
                        paneCoordinates: true,
                        series: series
                    }) &&
                        chart.isInsidePlot(x + bBox.width - correction, y + bBox.height - correction, {
                            paneCoordinates: true,
                            series: series
                        });
            }
            // When we're using a shape, make it possible with a connector or an
            // arrow pointing to this point
            if (options.shape && !rotation) {
                dataLabel[isNew ? 'attr' : 'animate']({
                    anchorX: pos[0],
                    anchorY: pos[1]
                });
            }
        }
        // To use alignAttr property in hideOverlappingLabels
        if (isNew && enabledDataSorting) {
            dataLabel.placed = false;
        }
        // Show or hide based on the final aligned position
        if (!visible && (!enabledDataSorting || justify)) {
            dataLabel.hide();
            dataLabel.placed = false; // Don't animate back in
        }
        else {
            dataLabel.show();
            dataLabel.placed = true; // Flag for overlapping logic
        }
    }
    /**
     * Handle the dataLabels.filter option.
     * @private
     */
    function applyFilter(point, options) {
        var filter = options.filter;
        if (filter) {
            var op = filter.operator,
                prop = point[filter.property],
                val = filter.value;
            if ((op === '>' && prop > val) ||
                (op === '<' && prop < val) ||
                (op === '>=' && prop >= val) ||
                (op === '<=' && prop <= val) ||
                (op === '==' && prop == val) || // eslint-disable-line eqeqeq
                (op === '===' && prop === val) ||
                (op === '!=' && prop != val) || // eslint-disable-line eqeqeq
                (op === '!==' && prop !== val)) {
                return true;
            }
            return false;
        }
        return true;
    }
    /**
     * @private
     */
    function compose(SeriesClass) {
        var seriesProto = SeriesClass.prototype;
        if (!seriesProto.initDataLabels) {
            seriesProto.initDataLabels = initDataLabels;
            seriesProto.initDataLabelsGroup = initDataLabelsGroup;
            seriesProto.alignDataLabel = alignDataLabel;
            seriesProto.drawDataLabels = drawDataLabels;
            seriesProto.justifyDataLabel = justifyDataLabel;
            seriesProto.setDataLabelStartPos = setDataLabelStartPos;
            seriesProto.hasDataLabels = hasDataLabels;
        }
    }
    DataLabel.compose = compose;
    /**
     * Create the SVGElement group for dataLabels
     * @private
     */
    function initDataLabelsGroup() {
        return this.plotGroup('dataLabelsGroup', 'data-labels', this.hasRendered ? 'inherit' : 'hidden', // #5133, #10220
        this.options.dataLabels.zIndex || 6);
    }
    /**
     * Init the data labels with the correct animation
     * @private
     */
    function initDataLabels(animationConfig) {
        var series = this,
            hasRendered = series.hasRendered || 0;
        // Create a separate group for the data labels to avoid rotation
        var dataLabelsGroup = this.initDataLabelsGroup()
                .attr({ opacity: +hasRendered }); // #3300
            if (!hasRendered && dataLabelsGroup) {
                if (series.visible) { // #2597, #3023, #3024
                    dataLabelsGroup.show();
            }
            if (series.options.animation) {
                dataLabelsGroup.animate({ opacity: 1 }, animationConfig);
            }
            else {
                dataLabelsGroup.attr({ opacity: 1 });
            }
        }
        return dataLabelsGroup;
    }
    /**
     * Draw the data labels
     * @private
     */
    function drawDataLabels(points) {
        var _a;
        points = points || this.points;
        var series = this, chart = series.chart, seriesOptions = series.options, renderer = chart.renderer, _b = chart.options.chart, backgroundColor = _b.backgroundColor, plotBackgroundColor = _b.plotBackgroundColor, contrastColor = renderer.getContrast((DataLabel_isString(plotBackgroundColor) && plotBackgroundColor) ||
                (DataLabel_isString(backgroundColor) && backgroundColor) ||
                "#000000" /* Palette.neutralColor100 */), seriesDlOptions = mergedDataLabelOptions(series);
        var pointOptions,
            dataLabelsGroup;
        // Resolve the animation
        var _c = seriesDlOptions[0],
            animation = _c.animation,
            defer = _c.defer,
            animationConfig = defer ?
                DataLabel_getDeferredAnimation(chart,
            animation,
            series) :
                { defer: 0,
            duration: 0 };
        DataLabel_fireEvent(this, 'drawDataLabels');
        if ((_a = series.hasDataLabels) === null || _a === void 0 ? void 0 : _a.call(series)) {
            dataLabelsGroup = this.initDataLabels(animationConfig);
            // Make the labels for each point
            points.forEach(function (point) {
                var _a,
                    _b;
                var dataLabels = point.dataLabels || [];
                // Merge in series options for the point.
                // @note dataLabelAttribs (like pointAttribs) would eradicate
                // the need for dlOptions, and simplify the section below.
                pointOptions = DataLabel_splat(mergeArrays(seriesDlOptions, 
                // The dlOptions prop is used in treemaps
                point.dlOptions || ((_a = point.options) === null || _a === void 0 ? void 0 : _a.dataLabels)));
                // Handle each individual data label for this point
                pointOptions.forEach(function (labelOptions, i) {
                    // Options for one datalabel
                    var labelEnabled = (labelOptions.enabled &&
                            (point.visible || point.dataLabelOnHidden) &&
                            // #2282, #4641, #7112, #10049
                            (!point.isNull || point.dataLabelOnNull) &&
                            applyFilter(point,
                        labelOptions)),
                        backgroundColor = labelOptions.backgroundColor,
                        borderColor = labelOptions.borderColor,
                        distance = labelOptions.distance,
                        _a = labelOptions.style,
                        style = _a === void 0 ? {} : _a;
                    var formatString,
                        labelText,
                        rotation,
                        attr = {},
                        dataLabel = dataLabels[i],
                        isNew = !dataLabel,
                        labelBgColor;
                    if (labelEnabled) {
                        // Create individual options structure that can be
                        // extended without affecting others
                        formatString = DataLabel_pick(labelOptions[point.formatPrefix + 'Format'], labelOptions.format);
                        labelText = DataLabel_defined(formatString) ?
                            DataLabel_format(formatString, point, chart) :
                            (labelOptions[point.formatPrefix + 'Formatter'] ||
                                labelOptions.formatter).call(point, labelOptions);
                        rotation = labelOptions.rotation;
                        if (!chart.styledMode) {
                            // Determine the color
                            style.color = DataLabel_pick(labelOptions.color, style.color, DataLabel_isString(series.color) ? series.color : void 0, "#000000" /* Palette.neutralColor100 */);
                            // Get automated contrast color
                            if (style.color === 'contrast') {
                                if (backgroundColor !== 'none') {
                                    labelBgColor = backgroundColor;
                                }
                                point.contrastColor = renderer.getContrast(labelBgColor !== 'auto' && labelBgColor ||
                                    (point.color || series.color));
                                style.color = (labelBgColor || // #20007
                                    (!DataLabel_defined(distance) &&
                                        labelOptions.inside) ||
                                    DataLabel_pInt(distance || 0) < 0 ||
                                    seriesOptions.stacking) ?
                                    point.contrastColor :
                                    contrastColor;
                            }
                            else {
                                delete point.contrastColor;
                            }
                            if (seriesOptions.cursor) {
                                style.cursor = seriesOptions.cursor;
                            }
                        }
                        attr = {
                            r: labelOptions.borderRadius || 0,
                            rotation: rotation,
                            padding: labelOptions.padding,
                            zIndex: 1
                        };
                        if (!chart.styledMode) {
                            attr.fill = backgroundColor === 'auto' ?
                                point.color :
                                backgroundColor;
                            attr.stroke = borderColor === 'auto' ?
                                point.color :
                                borderColor;
                            attr['stroke-width'] = labelOptions.borderWidth;
                        }
                        // Remove unused attributes (#947)
                        DataLabel_objectEach(attr, function (val, name) {
                            if (typeof val === 'undefined') {
                                delete attr[name];
                            }
                        });
                    }
                    // If the point is outside the plot area, or the label
                    // changes properties that we cannot change, destroy it and
                    // build a new one below. #678, #820.
                    if (dataLabel && (!labelEnabled ||
                        !DataLabel_defined(labelText) ||
                        !!dataLabel.div !== !!labelOptions.useHTML ||
                        (
                        // Change from no rotation to rotation and
                        // vice versa. Don't use defined() because
                        // rotation = 0 means also rotation = undefined
                        (!dataLabel.rotation ||
                            !labelOptions.rotation) &&
                            dataLabel.rotation !== labelOptions.rotation))) {
                        dataLabel = void 0;
                        isNew = true;
                    }
                    // Individual labels are disabled if the are explicitly
                    // disabled in the point options, or if they fall outside
                    // the plot area.
                    if (labelEnabled && DataLabel_defined(labelText)) {
                        if (!dataLabel) {
                            // Create new label element
                            dataLabel = renderer.label(labelText, 0, 0, labelOptions.shape, void 0, void 0, labelOptions.useHTML, void 0, 'data-label');
                            dataLabel.addClass(' highcharts-data-label-color-' +
                                point.colorIndex +
                                ' ' + (labelOptions.className || '') +
                                ( // #3398
                                labelOptions.useHTML ?
                                    ' highcharts-tracker' :
                                    ''));
                        }
                        else {
                            // Use old element and just update text
                            attr.text = labelText;
                        }
                        // Store data label options for later access
                        if (dataLabel) {
                            dataLabel.options = labelOptions;
                            dataLabel.attr(attr);
                            if (!chart.styledMode) {
                                // Styles must be applied before add in order to
                                // read text bounding box
                                dataLabel.css(style).shadow(labelOptions.shadow);
                            }
                            else if (style.width) {
                                // In styled mode with a width property set,
                                // the width should be applied to the
                                // dataLabel. (#20499). These properties affect
                                // layout and must be applied also in styled
                                // mode.
                                dataLabel.css({
                                    width: style.width,
                                    textOverflow: style.textOverflow,
                                    whiteSpace: style.whiteSpace
                                });
                            }
                            DataLabel_fireEvent(dataLabel, 'beforeAddingDataLabel', { labelOptions: labelOptions, point: point });
                            if (!dataLabel.added) {
                                dataLabel.add(dataLabelsGroup);
                            }
                            // Now the data label is created and placed at 0,0,
                            // so we need to align it
                            series.alignDataLabel(point, dataLabel, labelOptions, void 0, isNew);
                            dataLabel.isActive = true;
                            if (dataLabels[i] && dataLabels[i] !== dataLabel) {
                                dataLabels[i].destroy();
                            }
                            dataLabels[i] = dataLabel;
                        }
                    }
                });
                // Destroy and remove the inactive ones
                var j = dataLabels.length;
                while (j--) {
                    // The item can be undefined if a disabled data label is
                    // succeeded by an enabled one (#19457)
                    if (!dataLabels[j] || !dataLabels[j].isActive) {
                        (_b = dataLabels[j]) === null || _b === void 0 ? void 0 : _b.destroy();
                        dataLabels.splice(j, 1);
                    }
                    else {
                        dataLabels[j].isActive = false;
                    }
                }
                // Write back
                point.dataLabel = dataLabels[0];
                point.dataLabels = dataLabels;
            });
        }
        DataLabel_fireEvent(this, 'afterDrawDataLabels');
    }
    /**
     * If data labels fall partly outside the plot area, align them back in, in
     * a way that doesn't hide the point.
     * @private
     */
    function justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew) {
        var chart = this.chart,
            align = options.align,
            verticalAlign = options.verticalAlign,
            padding = dataLabel.box ? 0 : (dataLabel.padding || 0),
            horizontalAxis = chart.inverted ? this.yAxis : this.xAxis,
            horizontalAxisShift = horizontalAxis ?
                horizontalAxis.left - chart.plotLeft : 0,
            verticalAxis = chart.inverted ? this.xAxis : this.yAxis,
            verticalAxisShift = verticalAxis ?
                verticalAxis.top - chart.plotTop : 0;
        var _a = options.x,
            x = _a === void 0 ? 0 : _a,
            _b = options.y,
            y = _b === void 0 ? 0 : _b,
            off,
            justified;
        // Off left
        off = (alignAttr.x || 0) + padding + horizontalAxisShift;
        if (off < 0) {
            if (align === 'right' && x >= 0) {
                options.align = 'left';
                options.inside = true;
            }
            else {
                x -= off;
            }
            justified = true;
        }
        // Off right
        off = (alignAttr.x || 0) + bBox.width - padding + horizontalAxisShift;
        if (off > chart.plotWidth) {
            if (align === 'left' && x <= 0) {
                options.align = 'right';
                options.inside = true;
            }
            else {
                x += chart.plotWidth - off;
            }
            justified = true;
        }
        // Off top
        off = alignAttr.y + padding + verticalAxisShift;
        if (off < 0) {
            if (verticalAlign === 'bottom' && y >= 0) {
                options.verticalAlign = 'top';
                options.inside = true;
            }
            else {
                y -= off;
            }
            justified = true;
        }
        // Off bottom
        off = (alignAttr.y || 0) + bBox.height - padding + verticalAxisShift;
        if (off > chart.plotHeight) {
            if (verticalAlign === 'top' && y <= 0) {
                options.verticalAlign = 'bottom';
                options.inside = true;
            }
            else {
                y += chart.plotHeight - off;
            }
            justified = true;
        }
        if (justified) {
            options.x = x;
            options.y = y;
            dataLabel.placed = !isNew;
            dataLabel.align(options, void 0, alignTo);
        }
        return justified;
    }
    /**
     * Merge two objects that can be arrays. If one of them is an array, the
     * other is merged into each element. If both are arrays, each element is
     * merged by index. If neither are arrays, we use normal merge.
     * @private
     */
    function mergeArrays(one, two) {
        var res = [],
            i;
        if (DataLabel_isArray(one) && !DataLabel_isArray(two)) {
            res = one.map(function (el) {
                return DataLabel_merge(el, two);
            });
        }
        else if (DataLabel_isArray(two) && !DataLabel_isArray(one)) {
            res = two.map(function (el) {
                return DataLabel_merge(one, el);
            });
        }
        else if (!DataLabel_isArray(one) && !DataLabel_isArray(two)) {
            res = DataLabel_merge(one, two);
        }
        else if (DataLabel_isArray(one) && DataLabel_isArray(two)) {
            i = Math.max(one.length, two.length);
            while (i--) {
                res[i] = DataLabel_merge(one[i], two[i]);
            }
        }
        return res;
    }
    /**
     * Merge plotOptions and series options for dataLabels.
     * @private
     */
    function mergedDataLabelOptions(series) {
        var _a,
            _b;
        var plotOptions = series.chart.options.plotOptions;
        return DataLabel_splat(mergeArrays(mergeArrays((_a = plotOptions === null || plotOptions === void 0 ? void 0 : plotOptions.series) === null || _a === void 0 ? void 0 : _a.dataLabels, (_b = plotOptions === null || plotOptions === void 0 ? void 0 : plotOptions[series.type]) === null || _b === void 0 ? void 0 : _b.dataLabels), series.options.dataLabels));
    }
    /**
     * Set starting position for data label sorting animation.
     * @private
     */
    function setDataLabelStartPos(point, dataLabel, isNew, isInside, alignOptions) {
        var chart = this.chart, inverted = chart.inverted, xAxis = this.xAxis, reversed = xAxis.reversed, labelCenter = ((inverted ? dataLabel.height : dataLabel.width) || 0) / 2, pointWidth = point.pointWidth, halfWidth = pointWidth ? pointWidth / 2 : 0;
        dataLabel.startXPos = inverted ?
            alignOptions.x :
            (reversed ?
                -labelCenter - halfWidth :
                xAxis.width - labelCenter + halfWidth);
        dataLabel.startYPos = inverted ?
            (reversed ?
                this.yAxis.height - labelCenter + halfWidth :
                -labelCenter - halfWidth) : alignOptions.y;
        // We need to handle visibility in case of sorting point outside plot
        // area
        if (!isInside) {
            dataLabel
                .attr({ opacity: 1 })
                .animate({ opacity: 0 }, void 0, dataLabel.hide);
        }
        else if (dataLabel.visibility === 'hidden') {
            dataLabel.show();
            dataLabel
                .attr({ opacity: 0 })
                .animate({ opacity: 1 });
        }
        // Save start position on first render, but do not change position
        if (!chart.hasRendered) {
            return;
        }
        // Set start position
        if (isNew) {
            dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos });
        }
        dataLabel.placed = true;
    }
})(DataLabel || (DataLabel = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Series_DataLabel = (DataLabel);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Callback JavaScript function to format the data label as a string. Note that
 * if a `format` is defined, the format takes precedence and the formatter is
 * ignored.
 *
 * @callback Highcharts.DataLabelsFormatterCallbackFunction
 *
 * @param {Highcharts.Point} this
 * Data label context to format
 *
 * @param {Highcharts.DataLabelsOptions} options
 * [API options](/highcharts/plotOptions.series.dataLabels) of the data label
 *
 * @return {number|string|null|undefined}
 * Formatted data label text
 */
/**
 * Values for handling data labels that flow outside the plot area.
 *
 * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Series/Column/ColumnDataLabel.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var ColumnDataLabel_composed = Core_Globals.composed;

var ColumnDataLabel_Series = Series_SeriesRegistry.series;

var ColumnDataLabel_merge = Core_Utilities.merge, ColumnDataLabel_pick = Core_Utilities.pick, ColumnDataLabel_pushUnique = Core_Utilities.pushUnique;
/* *
 *
 *  Composition
 *
 * */
var ColumnDataLabel;
(function (ColumnDataLabel) {
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Override the basic data label alignment by adjusting for the position of
     * the column.
     * @private
     */
    function alignDataLabel(point, dataLabel, options, alignTo, isNew) {
        var inverted = this.chart.inverted,
            series = point.series,
            xLen = (series.xAxis ? series.xAxis.len : this.chart.plotSizeX) || 0,
            yLen = (series.yAxis ? series.yAxis.len : this.chart.plotSizeY) || 0, 
            // Data label box for alignment
            dlBox = point.dlBox || point.shapeArgs,
            below = ColumnDataLabel_pick(point.below, // Range series
            point.plotY >
                ColumnDataLabel_pick(this.translatedThreshold,
            yLen)), 
            // Draw it inside the box?
            inside = ColumnDataLabel_pick(options.inside, !!this.options.stacking);
        // Align to the column itself, or the top of it
        if (dlBox) { // Area range uses this method but not alignTo
            alignTo = ColumnDataLabel_merge(dlBox);
            // Check for specific overflow and crop conditions (#13240)
            if (!(options.overflow === 'allow' && options.crop === false)) {
                if (alignTo.y < 0) {
                    alignTo.height += alignTo.y;
                    alignTo.y = 0;
                }
                // If parts of the box overshoots outside the plot area, modify
                // the box to center the label inside
                var overshoot = alignTo.y + alignTo.height - yLen;
                if (overshoot > 0 && overshoot < alignTo.height - 1) {
                    alignTo.height -= overshoot;
                }
            }
            if (inverted) {
                alignTo = {
                    x: yLen - alignTo.y - alignTo.height,
                    y: xLen - alignTo.x - alignTo.width,
                    width: alignTo.height,
                    height: alignTo.width
                };
            }
            // Compute the alignment box
            if (!inside) {
                if (inverted) {
                    alignTo.x += below ? 0 : alignTo.width;
                    alignTo.width = 0;
                }
                else {
                    alignTo.y += below ? alignTo.height : 0;
                    alignTo.height = 0;
                }
            }
        }
        // When alignment is undefined (typically columns and bars), display the
        // individual point below or above the point depending on the threshold
        options.align = ColumnDataLabel_pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left');
        options.verticalAlign = ColumnDataLabel_pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom');
        // Call the parent method
        ColumnDataLabel_Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
        // If label was justified and we have contrast, set it:
        if (options.inside && point.contrastColor) {
            dataLabel.css({
                color: point.contrastColor
            });
        }
    }
    /** @private */
    function compose(ColumnSeriesClass) {
        Series_DataLabel.compose(ColumnDataLabel_Series);
        if (ColumnDataLabel_pushUnique(ColumnDataLabel_composed, 'ColumnDataLabel')) {
            ColumnSeriesClass.prototype.alignDataLabel = alignDataLabel;
        }
    }
    ColumnDataLabel.compose = compose;
})(ColumnDataLabel || (ColumnDataLabel = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Column_ColumnDataLabel = (ColumnDataLabel);

;// ./code/es5/es-modules/Series/Bar/BarSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var BarSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();



var BarSeries_extend = Core_Utilities.extend, BarSeries_merge = Core_Utilities.merge;
/* *
 *
 *  Class
 *
 * */
/**
 * Bar series type.
 *
 * @private
 * @class
 * @name Highcharts.seriesTypes.bar
 *
 * @augments Highcharts.Series
 */
var BarSeries = /** @class */ (function (_super) {
    BarSeries_extends(BarSeries, _super);
    function BarSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Static Properties
     *
     * */
    /**
     * A bar series is a special type of column series where the columns are
     * horizontal.
     *
     * @sample highcharts/demo/bar-chart/
     *         Bar chart
     *
     * @extends      plotOptions.column
     * @product      highcharts
     * @optionparent plotOptions.bar
     */
    BarSeries.defaultOptions = BarSeries_merge(Column_ColumnSeries.defaultOptions, {
    // Nothing here yet
    });
    return BarSeries;
}(Column_ColumnSeries));
BarSeries_extend(BarSeries.prototype, {
    inverted: true
});
Series_SeriesRegistry.registerSeriesType('bar', BarSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Bar_BarSeries = ((/* unused pure expression or super */ null && (BarSeries)));
/* *
 *
 *  API Options
 *
 * */
/**
 * A `bar` series. If the [type](#series.bar.type) option is not specified,
 * it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.bar
 * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit,
 *            linecap, lineWidth, marker, connectEnds, step
 * @product   highcharts
 * @apioption series.bar
 */
/**
 * An array of data points for the series. For the `bar` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 5],
 *        [1, 10],
 *        [2, 3]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.bar.turboThreshold), this option is not
 *    available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 1,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 10,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.column.data
 * @product   highcharts
 * @apioption series.bar.data
 */
/**
 * @excluding halo,lineWidth,lineWidthPlus,marker
 * @product   highcharts highstock
 * @apioption series.bar.states.hover
 */
/**
 * @excluding halo,lineWidth,lineWidthPlus,marker
 * @product   highcharts highstock
 * @apioption series.bar.states.select
 */
''; // Gets doclets above into transpiled

;// ./code/es5/es-modules/Series/Scatter/ScatterSeriesDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * A scatter plot uses cartesian coordinates to display values for two
 * variables for a set of data.
 *
 * @sample {highcharts} highcharts/demo/scatter/
 *         Scatter plot
 *
 * @extends      plotOptions.line
 * @excluding    cropThreshold, legendSymbolColor, pointPlacement, shadow,
 *               useOhlcData
 * @product      highcharts highstock
 * @optionparent plotOptions.scatter
 */
var ScatterSeriesDefaults = {
    /**
     * The width of the line connecting the data points.
     *
     * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/
     *         0 by default
     * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/
     *         1px
     *
     * @product highcharts highstock
     */
    lineWidth: 0,
    findNearestPointBy: 'xy',
    /**
     * Apply a jitter effect for the rendered markers. When plotting
     * discrete values, a little random noise may help telling the points
     * apart. The jitter setting applies a random displacement of up to `n`
     * axis units in either direction. So for example on a horizontal X
     * axis, setting the `jitter.x` to 0.24 will render the point in a
     * random position between 0.24 units to the left and 0.24 units to the
     * right of the true axis position. On a category axis, setting it to
     * 0.5 will fill up the bin and make the data appear continuous.
     *
     * When rendered on top of a box plot or a column series, a jitter value
     * of 0.24 will correspond to the underlying series' default
     * [groupPadding](
     * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding)
     * and [pointPadding](
     * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding)
     * settings.
     *
     * **Note:** With boost mode enabled, the jitter effect is not supported.
     *
     * @sample {highcharts} highcharts/demo/scatter-jitter
     *         Jitter on a scatter plot
     *
     * @sample {highcharts} highcharts/series-scatter/jitter-boxplot
     *         Jittered scatter plot on top of a box plot
     *
     * @product highcharts highstock
     * @since 7.0.2
     */
    jitter: {
        /**
         * The maximal X offset for the random jitter effect.
         */
        x: 0,
        /**
         * The maximal Y offset for the random jitter effect.
         */
        y: 0
    },
    marker: {
        enabled: true // Overrides auto-enabling in line series (#3647)
    },
    /**
     * Sticky tracking of mouse events. When true, the `mouseOut` event
     * on a series isn't triggered until the mouse moves over another
     * series, or out of the plot area. When false, the `mouseOut` event on
     * a series is triggered when the mouse leaves the area around the
     * series' graph or markers. This also implies the tooltip. When
     * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
     * will be hidden when moving the mouse between series.
     *
     * @type      {boolean}
     * @default   false
     * @product   highcharts highstock highmaps
     * @apioption plotOptions.scatter.stickyTracking
     */
    /**
     * A configuration object for the tooltip rendering of each single
     * series. Properties are inherited from [tooltip](#tooltip).
     * Overridable properties are `headerFormat`, `pointFormat`,
     * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other
     * series, in a scatter plot the series.name by default shows in the
     * headerFormat and point.x and point.y in the pointFormat.
     *
     * @product highcharts highstock highmaps
     */
    tooltip: {
        /**
         * @product highcharts highstock
         */
        headerFormat: '<span style="color:{point.color}">\u25CF</span> ' +
            '<span style="font-size: 0.8em"> {series.name}</span><br/>',
        pointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>'
    }
};
/**
 * A `scatter` series. If the [type](#series.scatter.type) option is
 * not specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.scatter
 * @excluding cropThreshold, dataParser, dataURL, useOhlcData
 * @product   highcharts highstock
 * @apioption series.scatter
 */
/**
 * An array of data points for the series. For the `scatter` series
 * type, points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. The `x` values will be automatically
 *    calculated, either starting at 0 and incremented by 1, or from
 *    `pointStart` and `pointInterval` given in the series options. If the axis
 *    has categories, these will be used. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of arrays with 2 values. In this case, the values correspond to
 *    `x,y`. If the first value is a string, it is applied as the name of the
 *    point, and the `x` value is inferred.
 *    ```js
 *    data: [
 *        [0, 0],
 *        [1, 8],
 *        [2, 9]
 *    ]
 *    ```
 *
 * 3. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.scatter.turboThreshold), this option is not
 *    available.
 *    ```js
 *    data: [{
 *        x: 1,
 *        y: 2,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        x: 1,
 *        y: 4,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
 * @extends   series.line.data
 * @product   highcharts highstock
 * @apioption series.scatter.data
 */
''; // Keeps doclets above in JS file
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Scatter_ScatterSeriesDefaults = (ScatterSeriesDefaults);

;// ./code/es5/es-modules/Series/Scatter/ScatterSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var ScatterSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();


var ScatterSeries_a = Series_SeriesRegistry.seriesTypes, ScatterSeries_ColumnSeries = ScatterSeries_a.column, ScatterSeries_LineSeries = ScatterSeries_a.line;

var ScatterSeries_addEvent = Core_Utilities.addEvent, ScatterSeries_extend = Core_Utilities.extend, ScatterSeries_merge = Core_Utilities.merge;
/* *
 *
 *  Class
 *
 * */
/**
 * Scatter series type.
 *
 * @private
 */
var ScatterSeries = /** @class */ (function (_super) {
    ScatterSeries_extends(ScatterSeries, _super);
    function ScatterSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Optionally add the jitter effect.
     * @private
     */
    ScatterSeries.prototype.applyJitter = function () {
        var series = this,
            jitter = this.options.jitter,
            len = this.points.length;
        /**
         * Return a repeatable, pseudo-random number based on an integer
         * seed.
         * @private
         */
        function unrandom(seed) {
            var rand = Math.sin(seed) * 10000;
            return rand - Math.floor(rand);
        }
        if (jitter) {
            this.points.forEach(function (point, i) {
                ['x', 'y'].forEach(function (dim, j) {
                    if (jitter[dim] && !point.isNull) {
                        var plotProp = "plot".concat(dim.toUpperCase()), axis = series["" + dim + "Axis"], translatedJitter = jitter[dim] *
                                axis.transA;
                        if (axis && !axis.logarithmic) {
                            // Identify the outer bounds of the jitter range
                            var min = Math.max(0, (point[plotProp] || 0) - translatedJitter),
                                max = Math.min(axis.len, (point[plotProp] || 0) + translatedJitter);
                            // Find a random position within this range
                            point[plotProp] = min +
                                (max - min) * unrandom(i + j * len);
                            // Update clientX for the tooltip k-d-tree
                            if (dim === 'x') {
                                point.clientX = point.plotX;
                            }
                        }
                    }
                });
            });
        }
    };
    /**
     * @private
     */
    ScatterSeries.prototype.drawGraph = function () {
        if (this.options.lineWidth) {
            _super.prototype.drawGraph.call(this);
        }
        else if (this.graph) {
            this.graph = this.graph.destroy();
        }
    };
    /* *
     *
     *  Static Properties
     *
     * */
    ScatterSeries.defaultOptions = ScatterSeries_merge(ScatterSeries_LineSeries.defaultOptions, Scatter_ScatterSeriesDefaults);
    return ScatterSeries;
}(ScatterSeries_LineSeries));
ScatterSeries_extend(ScatterSeries.prototype, {
    drawTracker: ScatterSeries_ColumnSeries.prototype.drawTracker,
    sorted: false,
    requireSorting: false,
    noSharedTooltip: true,
    trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup']
});
/* *
 *
 *  Events
 *
 * */
/* eslint-disable no-invalid-this */
ScatterSeries_addEvent(ScatterSeries, 'afterTranslate', function () {
    this.applyJitter();
});
Series_SeriesRegistry.registerSeriesType('scatter', ScatterSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Scatter_ScatterSeries = ((/* unused pure expression or super */ null && (ScatterSeries)));

;// ./code/es5/es-modules/Series/CenteredUtilities.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var CenteredUtilities_deg2rad = Core_Globals.deg2rad;


var CenteredUtilities_fireEvent = Core_Utilities.fireEvent, CenteredUtilities_isNumber = Core_Utilities.isNumber, CenteredUtilities_pick = Core_Utilities.pick, CenteredUtilities_relativeLength = Core_Utilities.relativeLength;
/**
 * @private
 */
var CenteredUtilities;
(function (CenteredUtilities) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Get the center of the pie based on the size and center options relative
     * to the plot area. Borrowed by the polar and gauge series types.
     *
     * @private
     * @function Highcharts.CenteredSeriesMixin.getCenter
     */
    function getCenter() {
        var options = this.options,
            chart = this.chart,
            slicingRoom = 2 * (options.slicedOffset || 0),
            plotWidth = chart.plotWidth - 2 * slicingRoom,
            plotHeight = chart.plotHeight - 2 * slicingRoom,
            centerOption = options.center,
            smallestSize = Math.min(plotWidth,
            plotHeight),
            thickness = options.thickness;
        var handleSlicingRoom,
            size = options.size,
            innerSize = options.innerSize || 0,
            i,
            value;
        if (typeof size === 'string') {
            size = parseFloat(size);
        }
        if (typeof innerSize === 'string') {
            innerSize = parseFloat(innerSize);
        }
        var positions = [
                CenteredUtilities_pick(centerOption === null || centerOption === void 0 ? void 0 : centerOption[0], '50%'),
                CenteredUtilities_pick(centerOption === null || centerOption === void 0 ? void 0 : centerOption[1], '50%'),
                // Prevent from negative values
                CenteredUtilities_pick(size && size < 0 ? void 0 : options.size, '100%'),
                CenteredUtilities_pick(innerSize && innerSize < 0 ? void 0 : options.innerSize || 0, '0%')
            ];
        // No need for inner size in angular (gauges) series but still required
        // for pie series
        if (chart.angular && !(this instanceof Series_Series)) {
            positions[3] = 0;
        }
        for (i = 0; i < 4; ++i) {
            value = positions[i];
            handleSlicingRoom = i < 2 || (i === 2 && /%$/.test(value));
            // I == 0: centerX, relative to width
            // i == 1: centerY, relative to height
            // i == 2: size, relative to smallestSize
            // i == 3: innerSize, relative to size
            positions[i] = CenteredUtilities_relativeLength(value, [plotWidth, plotHeight, smallestSize, positions[2]][i]) + (handleSlicingRoom ? slicingRoom : 0);
        }
        // Inner size cannot be larger than size (#3632)
        if (positions[3] > positions[2]) {
            positions[3] = positions[2];
        }
        // Thickness overrides innerSize, need to be less than pie size (#6647)
        if (CenteredUtilities_isNumber(thickness) &&
            thickness * 2 < positions[2] && thickness > 0) {
            positions[3] = positions[2] - thickness * 2;
        }
        CenteredUtilities_fireEvent(this, 'afterGetCenter', { positions: positions });
        return positions;
    }
    CenteredUtilities.getCenter = getCenter;
    /**
     * GetStartAndEndRadians - Calculates start and end angles in radians.
     * Used in series types such as pie and sunburst.
     *
     * @private
     * @function Highcharts.CenteredSeriesMixin.getStartAndEndRadians
     *
     * @param {number} [start]
     *        Start angle in degrees.
     *
     * @param {number} [end]
     *        Start angle in degrees.
     *
     * @return {Highcharts.RadianAngles}
     *         Returns an object containing start and end angles as radians.
     */
    function getStartAndEndRadians(start, end) {
        var startAngle = CenteredUtilities_isNumber(start) ? start : 0, // Must be a number
            endAngle = ((CenteredUtilities_isNumber(end) && // Must be a number
                end > startAngle && // Must be larger than the start angle
                // difference must be less than 360 degrees
                (end - startAngle) < 360) ?
                end :
                startAngle + 360),
            correction = -90;
        return {
            start: CenteredUtilities_deg2rad * (startAngle + correction),
            end: CenteredUtilities_deg2rad * (endAngle + correction)
        };
    }
    CenteredUtilities.getStartAndEndRadians = getStartAndEndRadians;
})(CenteredUtilities || (CenteredUtilities = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Series_CenteredUtilities = (CenteredUtilities);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * @private
 * @interface Highcharts.RadianAngles
 */ /**
* @name Highcharts.RadianAngles#end
* @type {number}
*/ /**
* @name Highcharts.RadianAngles#start
* @type {number}
*/
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Series/Pie/PiePoint.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var PiePoint_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var PiePoint_assign = (undefined && undefined.__assign) || function () {
    PiePoint_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 PiePoint_assign.apply(this, arguments);
};

var PiePoint_setAnimation = AnimationUtilities.setAnimation;


var PiePoint_addEvent = Core_Utilities.addEvent, PiePoint_defined = Core_Utilities.defined, PiePoint_extend = Core_Utilities.extend, PiePoint_isNumber = Core_Utilities.isNumber, PiePoint_pick = Core_Utilities.pick, PiePoint_relativeLength = Core_Utilities.relativeLength;
/* *
 *
 *  Class
 *
 * */
var PiePoint = /** @class */ (function (_super) {
    PiePoint_extends(PiePoint, _super);
    /**
     * Initialize the pie slice.
     * @private
     */
    function PiePoint(series, options, x) {
        var _a;
        var _this = _super.call(this,
            series,
            options,
            x) || this;
        _this.half = 0;
        (_a = _this.name) !== null && _a !== void 0 ? _a : (_this.name = 'Slice');
        // Add event listener for select
        var toggleSlice = function (e) {
                _this.slice(e.type === 'select');
        };
        PiePoint_addEvent(_this, 'select', toggleSlice);
        PiePoint_addEvent(_this, 'unselect', toggleSlice);
        return _this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Extendable method for getting the path of the connector between the
     * data label and the pie slice.
     * @private
     */
    PiePoint.prototype.getConnectorPath = function (dataLabel) {
        var labelPosition = dataLabel.dataLabelPosition,
            options = (dataLabel.options || {}),
            connectorShape = options.connectorShape,
            shapeFunc = (this.connectorShapes[connectorShape] || connectorShape);
        return labelPosition && shapeFunc.call(this, PiePoint_assign(PiePoint_assign({}, labelPosition.computed), { alignment: labelPosition.alignment }), labelPosition.connectorPosition, options) || [];
    };
    /**
     * @private
     */
    PiePoint.prototype.getTranslate = function () {
        return this.sliced && this.slicedTranslation || {
            translateX: 0,
            translateY: 0
        };
    };
    /**
     * @private
     */
    PiePoint.prototype.haloPath = function (size) {
        var shapeArgs = this.shapeArgs;
        return this.sliced || !this.visible ?
            [] :
            this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
                // Substract 1px to ensure the background is not bleeding
                // through between the halo and the slice (#7495).
                innerR: shapeArgs.r - 1,
                start: shapeArgs.start,
                end: shapeArgs.end,
                borderRadius: shapeArgs.borderRadius
            });
    };
    /**
     * Negative points are not valid (#1530, #3623, #5322)
     * @private
     */
    PiePoint.prototype.isValid = function () {
        return PiePoint_isNumber(this.y) && this.y >= 0;
    };
    /**
     * Toggle the visibility of a pie slice or other data point. Note that this
     * method is available only for some series, like pie, treemap and sunburst.
     *
     * @function Highcharts.Point#setVisible
     *
     * @param {boolean} [vis]
     * True to show the pie slice or other data point, false to hide. If
     * undefined, the visibility is toggled.
     *
     * @param {boolean} [redraw] Whether to redraw the chart after the point is
     * altered. If doing more operations on the chart, it is a good idea to set
     * redraw to false and call {@link Chart#redraw|chart.redraw()} after.
     *
     */
    PiePoint.prototype.setVisible = function (vis, redraw) {
        if (redraw === void 0) { redraw = true; }
        if (vis !== this.visible) {
            // If called without an argument, toggle visibility
            this.update({
                visible: vis !== null && vis !== void 0 ? vis : !this.visible
            }, redraw, void 0, false);
        }
    };
    /**
     * Set or toggle whether the slice is cut out from the pie.
     * @private
     *
     * @param {boolean} sliced
     * When undefined, the slice state is toggled.
     *
     * @param {boolean} [redraw]
     * Whether to redraw the chart. True by default.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     * Animation options.
     */
    PiePoint.prototype.slice = function (sliced, redraw, animation) {
        var series = this.series,
            chart = series.chart;
        PiePoint_setAnimation(animation, chart);
        // Redraw is true by default
        redraw = PiePoint_pick(redraw, true);
        /**
         * Pie series only. Whether to display a slice offset from the
         * center.
         * @name Highcharts.Point#sliced
         * @type {boolean|undefined}
         */
        // if called without an argument, toggle
        this.sliced = this.options.sliced = sliced =
            PiePoint_defined(sliced) ? sliced : !this.sliced;
        // Update userOptions.data
        series.options.data[series.data.indexOf(this)] =
            this.options;
        if (this.graphic) {
            this.graphic.animate(this.getTranslate());
        }
    };
    return PiePoint;
}(Series_Point));
PiePoint_extend(PiePoint.prototype, {
    connectorShapes: {
        // Only one available before v7.0.0
        fixedOffset: function (labelPosition, connectorPosition, options) {
            var breakAt = connectorPosition.breakAt,
                touchingSliceAt = connectorPosition.touchingSliceAt,
                lineSegment = options.softConnector ? [
                    'C', // Soft break
                    // 1st control point (of the curve)
                    labelPosition.x +
                        // 5 gives the connector a little horizontal bend
                        (labelPosition.alignment === 'left' ? -5 : 5),
                    labelPosition.y, //
                    2 * breakAt.x - touchingSliceAt.x, // 2nd control point
                    2 * breakAt.y - touchingSliceAt.y, //
                    breakAt.x, // End of the curve
                    breakAt.y //
                ] : [
                    'L', // Pointy break
                    breakAt.x,
                    breakAt.y
                ];
            // Assemble the path
            return ([
                ['M', labelPosition.x, labelPosition.y],
                lineSegment,
                ['L', touchingSliceAt.x, touchingSliceAt.y]
            ]);
        },
        straight: function (labelPosition, connectorPosition) {
            var touchingSliceAt = connectorPosition.touchingSliceAt;
            // Direct line to the slice
            return [
                ['M', labelPosition.x, labelPosition.y],
                ['L', touchingSliceAt.x, touchingSliceAt.y]
            ];
        },
        crookedLine: function (labelPosition, connectorPosition, options) {
            var _a = connectorPosition.angle,
                angle = _a === void 0 ? this.angle || 0 : _a,
                breakAt = connectorPosition.breakAt,
                touchingSliceAt = connectorPosition.touchingSliceAt,
                series = this.series,
                _b = series.center,
                cx = _b[0],
                cy = _b[1],
                diameter = _b[2],
                r = diameter / 2,
                _c = series.chart,
                plotLeft = _c.plotLeft,
                plotWidth = _c.plotWidth,
                leftAligned = labelPosition.alignment === 'left',
                x = labelPosition.x,
                y = labelPosition.y;
            var crookX = breakAt.x;
            if (options.crookDistance) {
                var crookDistance = PiePoint_relativeLength(// % to fraction
                    options.crookDistance, 1);
                crookX = leftAligned ?
                    cx +
                        r +
                        (plotWidth + plotLeft - cx - r) * (1 - crookDistance) :
                    plotLeft + (cx - r) * crookDistance;
                // When the crookDistance option is undefined, make the bend in the
                // intersection between the radial line in the middle of the slice,
                // and the extension of the label position.
            }
            else {
                crookX = cx + (cy - y) * Math.tan(angle - Math.PI / 2);
            }
            var path = [['M',
                x,
                y]];
            // The crookedLine formula doesn't make sense if the path overlaps
            // the label - use straight line instead in that case
            if (leftAligned ?
                (crookX <= x && crookX >= breakAt.x) :
                (crookX >= x && crookX <= breakAt.x)) {
                path.push(['L', crookX, y]);
            }
            path.push(['L', breakAt.x, breakAt.y], ['L', touchingSliceAt.x, touchingSliceAt.y]);
            return path;
        }
    }
});
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Pie_PiePoint = (PiePoint);

;// ./code/es5/es-modules/Series/Pie/PieSeriesDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Options
 *
 * */
/**
 * A pie chart is a circular graphic which is divided into slices to
 * illustrate numerical proportion.
 *
 * @sample highcharts/demo/pie-chart/
 *         Pie chart
 *
 * @extends      plotOptions.line
 * @excluding    animationLimit, boostThreshold, connectEnds, connectNulls,
 *               cropThreshold, dashStyle, dataSorting, dragDrop,
 *               findNearestPointBy, getExtremesFromAll, label, lineWidth,
 *               linkedTo, marker, negativeColor, pointInterval,
 *               pointIntervalUnit, pointPlacement, pointStart,
 *               softThreshold, stacking, step, threshold, turboThreshold,
 *               zoneAxis, zones, dataSorting, boostBlending
 * @product      highcharts highmaps
 * @optionparent plotOptions.pie
 *
 * @private
 */
var PieSeriesDefaults = {
    /**
     * The corner radius of the border surrounding each slice. A number
     * signifies pixels. A percentage string, like for example `50%`, signifies
     * a size relative to the radius and the inner radius.
     *
     * @sample  highcharts/plotoptions/series-border-radius
     *          Column and pie with rounded border
     *
     * @since   11.0.0
     *
     * @type      {number|string|Highcharts.BorderRadiusOptionsObject}
     */
    borderRadius: 3,
    /**
     * @excluding legendItemClick
     * @apioption plotOptions.pie.events
     */
    /**
     * Fires when the checkbox next to the point name in the legend is
     * clicked. One parameter, event, is passed to the function. The state
     * of the checkbox is found by event.checked. The checked item is found
     * by event.item. Return false to prevent the default action which is to
     * toggle the select state of the series.
     *
     * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
     *         Alert checkbox status
     *
     * @type      {Function}
     * @since     1.2.0
     * @product   highcharts highmaps
     * @context   Highcharts.Point
     * @apioption plotOptions.pie.events.checkboxClick
     */
    /**
     * Fires when the legend item belonging to the pie point (slice) is
     * clicked. The `this` keyword refers to the point itself. One
     * parameter, `event`, is passed to the function, containing common
     * event information. The default action is to toggle the visibility of
     * the point. This can be prevented by calling `event.preventDefault()`.
     *
     *  **Note:** This option is deprecated in favor of
     * [legend.events.itemClick](#legend.events.itemClick).
     *
     * @deprecated 11.4.4
     * @type       {Highcharts.PointLegendItemClickCallbackFunction}
     * @since      1.2.0
     * @product    highcharts highmaps
     * @apioption  plotOptions.pie.point.events.legendItemClick
     */
    /**
     * The center of the pie chart relative to the plot area. Can be
     * percentages or pixel values. The default behaviour (as of 3.0) is to
     * center the pie so that all slices and data labels are within the plot
     * area. As a consequence, the pie may actually jump around in a chart
     * with dynamic values, as the data labels move. In that case, the
     * center should be explicitly set, for example to `["50%", "50%"]`.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-center/
     *         Centered at 100, 100
     *
     * @type    {Array<(number|string|null),(number|string|null)>}
     * @default [null, null]
     * @product highcharts highmaps
     *
     * @private
     */
    center: [null, null],
    /**
     * The color of the pie series. A pie series is represented as an empty
     * circle if the total sum of its values is 0. Use this property to
     * define the color of its border.
     *
     * In styled mode, the color can be defined by the
     * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
     * color can be set with the `.highcharts-series`,
     * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
     * `.highcharts-series-{n}` class, or individual classes given by the
     * `className` option.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
     *         Empty pie series
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default   ${palette.neutralColor20}
     * @apioption plotOptions.pie.color
     */
    /**
     * @product highcharts
     *
     * @private
     */
    clip: false,
    /**
     * @ignore-option
     *
     * @private
     */
    colorByPoint: true, // Always true for pies
    /**
     * A series specific or series type specific color set to use instead
     * of the global [colors](#colors).
     *
     * @sample {highcharts} highcharts/demo/pie-monochrome/
     *         Set default colors for all pies
     *
     * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
     * @since     3.0
     * @product   highcharts highmaps
     * @apioption plotOptions.pie.colors
     */
    /**
     * @declare   Highcharts.SeriesPieDataLabelsOptionsObject
     * @extends   plotOptions.series.dataLabels
     * @excluding align, allowOverlap, inside, staggerLines, step
     * @private
     */
    dataLabels: {
        /**
         * Alignment method for data labels. Possible values are:
         *
         * - `plotEdges`: Each label touches the nearest vertical edge of
         *   the plot area.
         *
         * - `connectors`: Connectors have the same x position and the
         *   widest label of each half (left & right) touches the nearest
         *   vertical edge of the plot area.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/
         *         alignTo: connectors
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/
         *         alignTo: plotEdges
         *
         * @type      {string}
         * @since     7.0.0
         * @product   highcharts highmaps
         * @apioption plotOptions.pie.dataLabels.alignTo
         */
        /**
         * The color of the line connecting the data label to the pie slice.
         * The default color is the same as the point's color.
         *
         * In styled mode, the connector stroke is given in the
         * `.highcharts-data-label-connector` class.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/
         *         Blue connectors
         * @sample {highcharts} highcharts/css/pie-point/
         *         Styled connectors
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @since     2.1
         * @product   highcharts highmaps
         * @apioption plotOptions.pie.dataLabels.connectorColor
         */
        /**
         * The distance from the data label to the connector. Note that
         * data labels also have a default `padding`, so in order for the
         * connector to touch the text, the `padding` must also be 0.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/
         *         No padding
         *
         * @since   2.1
         * @product highcharts highmaps
         */
        connectorPadding: 5,
        /**
         * Specifies the method that is used to generate the connector path.
         * Highcharts provides 3 built-in connector shapes: `'crookedLine'`
         * (default since v11), `'fixedOffset'` and `'straight'`.
         *
         * Users can provide their own method by passing a function instead of a
         * string. Three arguments are passed to the callback:
         *
         * - An object that holds the information about the coordinates of the
         *   label (`x` & `y` properties) and how the label is located in
         *   relation to the pie (`alignment` property). `alignment` can by one
         *   of the following: `'left'` (pie on the left side of the data
         *   label), `'right'` (pie on the right side of the data label) or
         *   `'center'` (data label overlaps the pie).
         *
         * - An object that holds the information about the position of the
         *   connector. Its `touchingSliceAt`  porperty tells the position of
         *   the place where the connector touches the slice.
         *
         * - Data label options
         *
         * The function has to return an SVG path definition in array form (see
         * the example).
         *
         * @sample {highcharts}
         *         highcharts/plotoptions/pie-datalabels-connectorshape-string/
         *         connectorShape is a String
         * @sample {highcharts}
         *         highcharts/plotoptions/pie-datalabels-connectorshape-function/
         *         connectorShape is a function
         *
         * @type    {string|Function}
         * @since   7.0.0
         * @product highcharts highmaps
         */
        connectorShape: 'crookedLine',
        /**
         * The width of the line connecting the data label to the pie slice.
         *
         * In styled mode, the connector stroke width is given in the
         * `.highcharts-data-label-connector` class.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/
         *         Disable the connector
         * @sample {highcharts} highcharts/css/pie-point/
         *         Styled connectors
         *
         * @type      {number}
         * @default   1
         * @since     2.1
         * @product   highcharts highmaps
         * @apioption plotOptions.pie.dataLabels.connectorWidth
         */
        /**
         * Works only if `connectorShape` is `'crookedLine'`. It defines how
         * far from the vertical plot edge the coonnector path should be
         * crooked. With the default, `undefined`, the crook is placed so that
         * the horizontal line from the label intersects with the radial line
         * extending through the center of the pie slice.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/
         *         crookDistance set to 90%
         *
         * @since   7.0.0
         * @product highcharts highmaps
         */
        crookDistance: void 0,
        /**
         * The distance of the data label from the pie's edge. Negative
         * numbers put the data label on top of the pie slices. Can also be
         * defined as a percentage of pie's radius. Connectors are only
         * shown for data labels outside the pie.
         *
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/
         *         Data labels on top of the pie
         *
         * @type    {number|string}
         * @since   2.1
         * @product highcharts highmaps
         */
        distance: 30,
        enabled: true,
        /**
         * A
         * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
         * for the data label. Available variables are the same as for
         * `formatter`.
         *
         * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
         *         Add a unit
         *
         * @type      {string}
         * @default   undefined
         * @since     3.0
         * @apioption plotOptions.pie.dataLabels.format
         */
        // eslint-disable-next-line valid-jsdoc
        /**
         * Callback JavaScript function to format the data label. Note that
         * if a `format` is defined, the format takes precedence and the
         * formatter is ignored.
         *
         * @type {Highcharts.DataLabelsFormatterCallbackFunction}
         * @default function () { return this.point.isNull ? void 0 : this.point.name; }
         */
        formatter: function () {
            return this.isNull ? void 0 : this.name;
        },
        /**
         * Whether to render the connector as a soft arc or a line with a sharp
         * break. Works only if `connectorShape` equals to `fixedOffset`.
         *
         * @sample {highcharts}
         *         highcharts/plotoptions/pie-datalabels-softconnector-true/
         *         Soft
         * @sample {highcharts}
         *         highcharts/plotoptions/pie-datalabels-softconnector-false/
         *         Non soft
         *
         * @since   2.1.7
         * @product highcharts highmaps
         */
        softConnector: true,
        /**
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow
         *         Long labels truncated with an ellipsis
         * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap
         *         Long labels are wrapped
         *
         * @type      {Highcharts.CSSObject}
         * @apioption plotOptions.pie.dataLabels.style
         */
        x: 0
    },
    /**
     * If the total sum of the pie's values is 0, the series is represented
     * as an empty circle . The `fillColor` option defines the color of that
     * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set
     * the border thickness.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
     *         Empty pie series
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @private
     */
    fillColor: void 0,
    /**
     * The end angle of the pie in degrees where 0 is top and 90 is right.
     * Defaults to `startAngle` plus 360.
     *
     * @sample {highcharts} highcharts/demo/pie-semi-circle/
     *         Semi-circle donut
     *
     * @type      {number}
     * @since     1.3.6
     * @product   highcharts highmaps
     * @apioption plotOptions.pie.endAngle
     */
    /**
     * Thickness describing the ring size for a donut type chart,
     * overriding [innerSize](#plotOptions.pie.innerSize).
     *
     * @type      {number}
     * @default   undefined
     * @product   highcharts
     * @since 10.1.0
     * @apioption plotOptions.pie.thickness
     * @private
     */
    /**
     * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries),
     * this option tells whether the series shall be redrawn as if the
     * hidden point were `null`.
     *
     * The default value changed from `false` to `true` with Highcharts
     * 3.0.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/
     *         True, the hiddden point is ignored
     *
     * @since   2.3.0
     * @product highcharts highmaps
     *
     * @private
     */
    ignoreHiddenPoint: true,
    /**
     * @default   true
     * @extends   plotOptions.series.inactiveOtherPoints
     * @private
     */
    inactiveOtherPoints: true,
    /**
     * The size of the inner diameter for the pie. A size greater than 0
     * renders a donut chart. Can be a percentage or pixel value.
     * Percentages are relative to the pie size. Pixel values are given as
     * integers. Setting overridden by thickness.
     *
     *
     * Note: in Highcharts < 4.1.2, the percentage was relative to the plot
     * area, not the pie size.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/
     *         80px inner size
     * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/
     *         50% of the plot area
     * @sample {highcharts} highcharts/demo/3d-pie-donut/
     *         3D donut
     *
     * @type      {number|string}
     * @default   0
     * @since     2.0
     * @product   highcharts highmaps
     * @apioption plotOptions.pie.innerSize
     */
    /**
     * @ignore-option
     *
     * @private
     */
    legendType: 'point',
    /**
     * @ignore-option
     *
     * @private
     */
    marker: null, // Point options are specified in the base options
    /**
     * The minimum size for a pie in response to auto margins. The pie will
     * try to shrink to make room for data labels in side the plot area,
     *  but only to this size.
     *
     * @type      {number|string}
     * @default   80
     * @since     3.0
     * @product   highcharts highmaps
     * @apioption plotOptions.pie.minSize
     */
    /**
     * The diameter of the pie relative to the plot area. Can be a
     * percentage or pixel value. Pixel values are given as integers. The
     * default behaviour (as of 3.0) is to scale to the plot area and give
     * room for data labels within the plot area.
     * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the
     * default size calculation. As a consequence, the size of the pie may
     * vary when points are updated and data labels more around. In that
     * case it is best to set a fixed value, for example `"75%"`.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-size/
     *         Smaller pie
     *
     * @type    {number|string|null}
     * @product highcharts highmaps
     *
     * @private
     */
    size: null,
    /**
     * Whether to display this particular series or series type in the
     * legend. Since 2.1, pies are not shown in the legend by default.
     *
     * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
     *         One series in the legend, one hidden
     *
     * @product highcharts highmaps
     *
     * @private
     */
    showInLegend: false,
    /**
     * If a point is sliced, moved out from the center, how many pixels
     * should it be moved?.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/
     *         20px offset
     *
     * @product highcharts highmaps
     *
     * @private
     */
    slicedOffset: 10,
    /**
     * The start angle of the pie slices in degrees where 0 is top and 90
     * right.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/
     *         Start from right
     *
     * @type      {number}
     * @default   0
     * @since     2.3.4
     * @product   highcharts highmaps
     * @apioption plotOptions.pie.startAngle
     */
    /**
     * Sticky tracking of mouse events. When true, the `mouseOut` event
     * on a series isn't triggered until the mouse moves over another
     * series, or out of the plot area. When false, the `mouseOut` event on
     * a series is triggered when the mouse leaves the area around the
     * series'  graph or markers. This also implies the tooltip. When
     * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
     * will be hidden when moving the mouse between series.
     *
     * @product highcharts highmaps
     *
     * @private
     */
    stickyTracking: false,
    tooltip: {
        followPointer: true
    },
    /**
     * The color of the border surrounding each slice. When `null`, the
     * border takes the same color as the slice fill. This can be used
     * together with a `borderWidth` to fill drawing gaps created by
     * antialiazing artefacts in borderless pies.
     *
     * In styled mode, the border stroke is given in the `.highcharts-point`
     * class.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/
     *         Black border
     *
     * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default #ffffff
     * @product highcharts highmaps
     *
     * @private
     */
    borderColor: "#ffffff" /* Palette.backgroundColor */,
    /**
     * The width of the border surrounding each slice.
     *
     * When setting the border width to 0, there may be small gaps between
     * the slices due to SVG antialiasing artefacts. To work around this,
     * keep the border width at 0.5 or 1, but set the `borderColor` to
     * `null` instead.
     *
     * In styled mode, the border stroke width is given in the
     * `.highcharts-point` class.
     *
     * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/
     *         3px border
     *
     * @product highcharts highmaps
     *
     * @private
     */
    borderWidth: 1,
    /**
     * @ignore-option
     * @private
     */
    lineWidth: void 0, // #12222
    states: {
        /**
         * @extends   plotOptions.series.states.hover
         * @excluding marker, lineWidth, lineWidthPlus
         * @product   highcharts highmaps
         */
        hover: {
            /**
             * How much to brighten the point on interaction. Requires the
             * main color to be defined in hex or rgb(a) format.
             *
             * In styled mode, the hover brightness is by default replaced
             * by a fill-opacity given in the `.highcharts-point-hover`
             * class.
             *
             * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/
             *         Brightened by 0.5
             *
             * @product highcharts highmaps
             */
            brightness: 0.1
        }
    }
};
/**
 * A `pie` series. If the [type](#series.pie.type) option is not specified,
 * it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.pie
 * @excluding cropThreshold, dataParser, dataURL, linkedTo, stack, xAxis, yAxis,
 *            dataSorting, step, boostThreshold, boostBlending
 * @product   highcharts highmaps
 * @apioption series.pie
 */
/**
 * An array of data points for the series. For the `pie` series type,
 * points can be given in the following ways:
 *
 * 1. An array of numerical values. In this case, the numerical values will be
 *    interpreted as `y` options. Example:
 *    ```js
 *    data: [0, 5, 3, 5]
 *    ```
 *
 * 2. An array of objects with named values. The following snippet shows only a
 *    few settings, see the complete options set below. If the total number of
 *    data points exceeds the series'
 *    [turboThreshold](#series.pie.turboThreshold),
 *    this option is not available.
 *    ```js
 *    data: [{
 *        y: 1,
 *        name: "Point2",
 *        color: "#00FF00"
 *    }, {
 *        y: 7,
 *        name: "Point1",
 *        color: "#FF00FF"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/chart/reflow-true/
 *         Numerical values
 * @sample {highcharts} highcharts/series/data-array-of-arrays/
 *         Arrays of numeric x and y
 * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
 *         Arrays of datetime x and y
 * @sample {highcharts} highcharts/series/data-array-of-name-value/
 *         Arrays of point.name and y
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @type      {Array<number|Array<string,(number|null)>|null|*>}
 * @extends   series.line.data
 * @excluding marker, x
 * @product   highcharts highmaps
 * @apioption series.pie.data
 */
/**
 * @type      {Highcharts.SeriesPieDataLabelsOptionsObject}
 * @product   highcharts highmaps
 * @apioption series.pie.data.dataLabels
 */
/**
 * The sequential index of the data point in the legend.
 *
 * @type      {number}
 * @product   highcharts highmaps
 * @apioption series.pie.data.legendIndex
 */
/**
 * Whether to display a slice offset from the center.
 *
 * @sample {highcharts} highcharts/point/sliced/
 *         One sliced point
 *
 * @type      {boolean}
 * @product   highcharts highmaps
 * @apioption series.pie.data.sliced
 */
/**
 * @extends plotOptions.pie.dataLabels
 * @excluding align, allowOverlap, inside, staggerLines, step
 * @product   highcharts highmaps
 * @apioption series.pie.dataLabels
 */
/**
 * @excluding legendItemClick
 * @product   highcharts highmaps
 * @apioption series.pie.events
 */
''; // Placeholder for transpiled doclets above
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Pie_PieSeriesDefaults = (PieSeriesDefaults);

;// ./code/es5/es-modules/Series/Pie/PieSeries.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var PieSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var getStartAndEndRadians = Series_CenteredUtilities.getStartAndEndRadians;


var PieSeries_noop = Core_Globals.noop;






var PieSeries_clamp = Core_Utilities.clamp, PieSeries_extend = Core_Utilities.extend, PieSeries_fireEvent = Core_Utilities.fireEvent, PieSeries_merge = Core_Utilities.merge, PieSeries_pick = Core_Utilities.pick;
/* *
 *
 *  Class
 *
 * */
/**
 * Pie series type.
 *
 * @private
 * @class
 * @name Highcharts.seriesTypes.pie
 *
 * @augments Highcharts.Series
 */
var PieSeries = /** @class */ (function (_super) {
    PieSeries_extends(PieSeries, _super);
    function PieSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Animates the pies in.
     * @private
     */
    PieSeries.prototype.animate = function (init) {
        var series = this,
            points = series.points,
            startAngleRad = series.startAngleRad;
        if (!init) {
            points.forEach(function (point) {
                var graphic = point.graphic,
                    args = point.shapeArgs;
                if (graphic && args) {
                    // Start values
                    graphic.attr({
                        // Animate from inner radius (#779)
                        r: PieSeries_pick(point.startR, (series.center && series.center[3] / 2)),
                        start: startAngleRad,
                        end: startAngleRad
                    });
                    // Animate
                    graphic.animate({
                        r: args.r,
                        start: args.start,
                        end: args.end
                    }, series.options.animation);
                }
            });
        }
    };
    /**
     * Called internally to draw auxiliary graph in pie-like series in
     * situtation when the default graph is not sufficient enough to present
     * the data well. Auxiliary graph is saved in the same object as
     * regular graph.
     * @private
     */
    PieSeries.prototype.drawEmpty = function () {
        var start = this.startAngleRad,
            end = this.endAngleRad,
            options = this.options;
        var centerX,
            centerY;
        // Draw auxiliary graph if there're no visible points.
        if (this.total === 0 && this.center) {
            centerX = this.center[0];
            centerY = this.center[1];
            if (!this.graph) {
                this.graph = this.chart.renderer
                    .arc(centerX, centerY, this.center[1] / 2, 0, start, end)
                    .addClass('highcharts-empty-series')
                    .add(this.group);
            }
            this.graph.attr({
                d: SVG_Symbols.arc(centerX, centerY, this.center[2] / 2, 0, {
                    start: start,
                    end: end,
                    innerR: this.center[3] / 2
                })
            });
            if (!this.chart.styledMode) {
                this.graph.attr({
                    'stroke-width': options.borderWidth,
                    fill: options.fillColor || 'none',
                    stroke: options.color || "#cccccc" /* Palette.neutralColor20 */
                });
            }
        }
        else if (this.graph) { // Destroy the graph object.
            this.graph = this.graph.destroy();
        }
    };
    /**
     * Slices in pie chart are initialized in DOM, but it's shapes and
     * animations are normally run in `drawPoints()`.
     * @private
     */
    PieSeries.prototype.drawPoints = function () {
        var renderer = this.chart.renderer;
        this.points.forEach(function (point) {
            // When updating a series between 2d and 3d or cartesian and
            // polar, the shape type changes.
            if (point.graphic && point.hasNewShapeType()) {
                point.graphic = point.graphic.destroy();
            }
            if (!point.graphic) {
                point.graphic = renderer[point.shapeType](point.shapeArgs)
                    .add(point.series.group);
                point.delayedRendering = true;
            }
        });
    };
    /**
     * Extend the generatePoints method by adding total and percentage
     * properties to each point
     * @private
     */
    PieSeries.prototype.generatePoints = function () {
        _super.prototype.generatePoints.call(this);
        this.updateTotals();
    };
    /**
     * Utility for getting the x value from a given y, used for anticollision
     * logic in data labels.
     * @private
     */
    PieSeries.prototype.getX = function (y, left, point, dataLabel) {
        var center = this.center, 
            // Variable pie has individual radius
            radius = this.radii ?
                this.radii[point.index] || 0 :
                center[2] / 2,
            labelPosition = dataLabel.dataLabelPosition,
            distance = (labelPosition === null || labelPosition === void 0 ? void 0 : labelPosition.distance) || 0;
        var angle = Math.asin(PieSeries_clamp((y - center[1]) / (radius + distance), -1, 1));
        var x = center[0] +
                (left ? -1 : 1) *
                    (Math.cos(angle) * (radius + distance)) +
                (distance > 0 ?
                    (left ? -1 : 1) * (dataLabel.padding || 0) :
                    0);
        return x;
    };
    /**
     * Define hasData function for non-cartesian series. Returns true if the
     * series has points at all.
     * @private
     */
    PieSeries.prototype.hasData = function () {
        return !!this.dataTable.rowCount;
    };
    /**
     * Draw the data points
     * @private
     */
    PieSeries.prototype.redrawPoints = function () {
        var series = this,
            chart = series.chart;
        var groupTranslation,
            graphic,
            pointAttr,
            shapeArgs;
        this.drawEmpty();
        // Apply the drop-shadow to the group because otherwise each element
        // would cast a shadow on others
        if (series.group && !chart.styledMode) {
            series.group.shadow(series.options.shadow);
        }
        // Draw the slices
        series.points.forEach(function (point) {
            var animateTo = {};
            graphic = point.graphic;
            if (!point.isNull && graphic) {
                shapeArgs = point.shapeArgs;
                // If the point is sliced, use special translation, else use
                // plot area translation
                groupTranslation = point.getTranslate();
                if (!chart.styledMode) {
                    pointAttr = series.pointAttribs(point, (point.selected && 'select'));
                }
                // Draw the slice
                if (!point.delayedRendering) {
                    graphic
                        .setRadialReference(series.center);
                    if (!chart.styledMode) {
                        PieSeries_merge(true, animateTo, pointAttr);
                    }
                    PieSeries_merge(true, animateTo, shapeArgs, groupTranslation);
                    graphic.animate(animateTo);
                }
                else {
                    graphic
                        .setRadialReference(series.center)
                        .attr(shapeArgs)
                        .attr(groupTranslation);
                    if (!chart.styledMode) {
                        graphic
                            .attr(pointAttr)
                            .attr({ 'stroke-linejoin': 'round' });
                    }
                    point.delayedRendering = false;
                }
                graphic
                    .attr({
                    visibility: point.visible ? 'inherit' : 'hidden'
                });
                graphic.addClass(point.getClassName(), true);
            }
            else if (graphic) {
                point.graphic = graphic.destroy();
            }
        });
    };
    /**
     * Utility for sorting data labels.
     * @private
     */
    PieSeries.prototype.sortByAngle = function (points, sign) {
        points.sort(function (a, b) {
            return ((typeof a.angle !== 'undefined') &&
                (b.angle - a.angle) * sign);
        });
    };
    /**
     * Do translation for pie slices
     * @private
     */
    PieSeries.prototype.translate = function (positions) {
        PieSeries_fireEvent(this, 'translate');
        this.generatePoints();
        var series = this,
            precision = 1000, // Issue #172
            options = series.options,
            slicedOffset = options.slicedOffset,
            radians = getStartAndEndRadians(options.startAngle,
            options.endAngle),
            startAngleRad = series.startAngleRad = radians.start,
            endAngleRad = series.endAngleRad = radians.end,
            circ = endAngleRad - startAngleRad, // 2 * Math.PI,
            points = series.points,
            ignoreHiddenPoint = options.ignoreHiddenPoint,
            len = points.length;
        var start,
            end,
            angle, 
            // The x component of the radius vector for a given point
            radiusX,
            radiusY,
            i,
            point,
            cumulative = 0;
        // Get positions - either an integer or a percentage string must be
        // given. If positions are passed as a parameter, we're in a
        // recursive loop for adjusting space for data labels.
        if (!positions) {
            /**
             * The series center position, read only. This applies only to
             * circular chart types like pie and sunburst. It is an array of
             * `[centerX, centerY, diameter, innerDiameter]`.
             *
             * @name Highcharts.Series#center
             * @type {Array<number>}
             */
            series.center = positions = series.getCenter();
        }
        // Calculate the geometry for each point
        for (i = 0; i < len; i++) {
            point = points[i];
            // Set start and end angle
            start = startAngleRad + (cumulative * circ);
            if (point.isValid() &&
                (!ignoreHiddenPoint || point.visible)) {
                cumulative += point.percentage / 100;
            }
            end = startAngleRad + (cumulative * circ);
            // Set the shape
            var shapeArgs = {
                    x: positions[0],
                    y: positions[1],
                    r: positions[2] / 2,
                    innerR: positions[3] / 2,
                    start: Math.round(start * precision) / precision,
                    end: Math.round(end * precision) / precision
                };
            point.shapeType = 'arc';
            point.shapeArgs = shapeArgs;
            // The angle must stay within -90 and 270 (#2645)
            angle = (end + start) / 2;
            if (angle > 1.5 * Math.PI) {
                angle -= 2 * Math.PI;
            }
            else if (angle < -Math.PI / 2) {
                angle += 2 * Math.PI;
            }
            // Center for the sliced out slice
            point.slicedTranslation = {
                translateX: Math.round(Math.cos(angle) * slicedOffset),
                translateY: Math.round(Math.sin(angle) * slicedOffset)
            };
            // Set the anchor point for tooltips
            radiusX = Math.cos(angle) * positions[2] / 2;
            radiusY = Math.sin(angle) * positions[2] / 2;
            point.tooltipPos = [
                positions[0] + radiusX * 0.7,
                positions[1] + radiusY * 0.7
            ];
            point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ?
                1 :
                0;
            point.angle = angle;
        }
        PieSeries_fireEvent(series, 'afterTranslate');
    };
    /**
     * Recompute total chart sum and update percentages of points.
     * @private
     */
    PieSeries.prototype.updateTotals = function () {
        var points = this.points,
            len = points.length,
            ignoreHiddenPoint = this.options.ignoreHiddenPoint;
        var i,
            point,
            total = 0;
        // Get the total sum
        for (i = 0; i < len; i++) {
            point = points[i];
            if (point.isValid() &&
                (!ignoreHiddenPoint || point.visible)) {
                total += point.y;
            }
        }
        this.total = total;
        // Set each point's properties
        for (i = 0; i < len; i++) {
            point = points[i];
            point.percentage =
                (total > 0 && (point.visible || !ignoreHiddenPoint)) ?
                    point.y / total * 100 :
                    0;
            point.total = total;
        }
    };
    /* *
     *
     *  Static Properties
     *
     * */
    PieSeries.defaultOptions = PieSeries_merge(Series_Series.defaultOptions, Pie_PieSeriesDefaults);
    return PieSeries;
}(Series_Series));
PieSeries_extend(PieSeries.prototype, {
    axisTypes: [],
    directTouch: true,
    drawGraph: void 0,
    drawTracker: Column_ColumnSeries.prototype.drawTracker,
    getCenter: Series_CenteredUtilities.getCenter,
    getSymbol: PieSeries_noop,
    invertible: false,
    isCartesian: false,
    noSharedTooltip: true,
    pointAttribs: Column_ColumnSeries.prototype.pointAttribs,
    pointClass: Pie_PiePoint,
    requireSorting: false,
    searchPoint: PieSeries_noop,
    trackerGroups: ['group', 'dataLabelsGroup']
});
Series_SeriesRegistry.registerSeriesType('pie', PieSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Pie_PieSeries = ((/* unused pure expression or super */ null && (PieSeries)));

;// ./code/es5/es-modules/Series/Pie/PieDataLabel.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var PieDataLabel_composed = Core_Globals.composed, PieDataLabel_noop = Core_Globals.noop;

var PieDataLabel_distribute = Renderer_RendererUtilities.distribute;

var PieDataLabel_Series = Series_SeriesRegistry.series;

var PieDataLabel_arrayMax = Core_Utilities.arrayMax, PieDataLabel_clamp = Core_Utilities.clamp, PieDataLabel_defined = Core_Utilities.defined, PieDataLabel_pick = Core_Utilities.pick, PieDataLabel_pushUnique = Core_Utilities.pushUnique, PieDataLabel_relativeLength = Core_Utilities.relativeLength;
/* *
 *
 *  Composition
 *
 * */
var PieDataLabel_ColumnDataLabel;
(function (ColumnDataLabel) {
    /* *
     *
     *  Constants
     *
     * */
    var dataLabelPositioners = {
            // Based on the value computed in Highcharts' distribute algorithm.
            radialDistributionY: function (point,
        dataLabel) {
                var _a;
            return (((_a = dataLabel.dataLabelPosition) === null || _a === void 0 ? void 0 : _a.top) || 0) +
                point.distributeBox.pos;
        },
        // Get the x - use the natural x position for labels near the top and
        // bottom, to prevent the top and botton slice connectors from touching
        // each other on either side. Based on the value computed in Highcharts'
        // distribute algorithm.
        radialDistributionX: function (series, point, y, naturalY, dataLabel) {
            var pos = dataLabel.dataLabelPosition;
            return series.getX(y < ((pos === null || pos === void 0 ? void 0 : pos.top) || 0) + 2 || y > ((pos === null || pos === void 0 ? void 0 : pos.bottom) || 0) - 2 ?
                naturalY :
                y, point.half, point, dataLabel);
        },
        // The dataLabels.distance determines the x position of the label
        justify: function (point, dataLabel, radius, seriesCenter) {
            var _a;
            return seriesCenter[0] + (point.half ? -1 : 1) *
                (radius + (((_a = dataLabel.dataLabelPosition) === null || _a === void 0 ? void 0 : _a.distance) || 0));
        },
        // Left edges of the left-half labels touch the left edge of the plot
        // area. Right edges of the right-half labels touch the right edge of
        // the plot area.
        alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) {
            var dataLabelWidth = dataLabel.getBBox().width;
            return half ? dataLabelWidth + plotLeft :
                plotWidth - dataLabelWidth - plotLeft;
        },
        // Connectors of each side end in the same x position. Labels are
        // aligned to them. Left edge of the widest left-half label touches the
        // left edge of the plot area. Right edge of the widest right-half label
        // touches the right edge of the plot area.
        alignToConnectors: function (points, half, plotWidth, plotLeft) {
            var maxDataLabelWidth = 0,
                dataLabelWidth;
            // Find widest data label
            points.forEach(function (point) {
                dataLabelWidth = point.dataLabel.getBBox().width;
                if (dataLabelWidth > maxDataLabelWidth) {
                    maxDataLabelWidth = dataLabelWidth;
                }
            });
            return half ? maxDataLabelWidth + plotLeft :
                plotWidth - maxDataLabelWidth - plotLeft;
        }
    };
    /* *
     *
     *  Functions
     *
     * */
    /** @private */
    function compose(PieSeriesClass) {
        Series_DataLabel.compose(PieDataLabel_Series);
        if (PieDataLabel_pushUnique(PieDataLabel_composed, 'PieDataLabel')) {
            var pieProto = PieSeriesClass.prototype;
            pieProto.dataLabelPositioners = dataLabelPositioners;
            pieProto.alignDataLabel = PieDataLabel_noop;
            pieProto.drawDataLabels = drawDataLabels;
            pieProto.getDataLabelPosition = getDataLabelPosition;
            pieProto.placeDataLabels = placeDataLabels;
            pieProto.verifyDataLabelOverflow = verifyDataLabelOverflow;
        }
    }
    ColumnDataLabel.compose = compose;
    /** @private */
    function getDataLabelPosition(point, distance) {
        var halfPI = Math.PI / 2,
            _a = point.shapeArgs || {},
            _b = _a.start,
            start = _b === void 0 ? 0 : _b,
            _c = _a.end,
            end = _c === void 0 ? 0 : _c;
        var angle = point.angle || 0;
        // If a large slice is crossing the lowest point, prefer rendering it 45
        // degrees out at either lower right or lower left. That's where there's
        // most likely to be space available and avoid text being truncated
        // (#22100). Technically this logic should also apply to the top point,
        // but that is more of an edge case since the default start angle is at
        // the top.
        if (distance > 0 &&
            // Crossing the bottom
            start < halfPI && end > halfPI &&
            // Angle within the bottom quadrant
            angle > halfPI / 2 && angle < halfPI * 1.5) {
            angle = angle <= halfPI ?
                Math.max(halfPI / 2, (start + halfPI) / 2) :
                Math.min(halfPI * 1.5, (halfPI + end) / 2);
        }
        var _d = this, center = _d.center, options = _d.options, r = center[2] / 2, cosAngle = Math.cos(angle), sinAngle = Math.sin(angle), x = center[0] + cosAngle * r, y = center[1] + sinAngle * r, finalConnectorOffset = Math.min((options.slicedOffset || 0) + (options.borderWidth || 0), distance / 5); // #1678
            return {
                natural: {
                    // Initial position of the data label - it's utilized for
                    // finding the final position for the label
                    x: x + cosAngle * distance,
                    y: y + sinAngle * distance
                },
                computed: {
                // Used for generating connector path - initialized later in
                // drawDataLabels function x: undefined, y: undefined
                },
                // Left - pie on the left side of the data label
                // Right - pie on the right side of the data label
                // Center - data label overlaps the pie
                alignment: distance < 0 ? 'center' : point.half ? 'right' : 'left',
                connectorPosition: {
                    angle: angle,
                    breakAt: {
                        x: x + cosAngle * finalConnectorOffset,
                        y: y + sinAngle * finalConnectorOffset
                    },
                    touchingSliceAt: {
                        x: x,
                        y: y
                    }
                },
                distance: distance
            };
    }
    /**
     * Override the base drawDataLabels method by pie specific functionality
     * @private
     */
    function drawDataLabels() {
        var _this = this;
        var _a;
        var series = this, points = series.points, chart = series.chart, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotLeft = chart.plotLeft, maxWidth = Math.round(chart.chartWidth / 3), seriesCenter = series.center, radius = seriesCenter[2] / 2, centerY = seriesCenter[1], halves = [
                [], // Right
                [] // Left
            ], overflow = [0, 0, 0, 0], // Top, right, bottom, left
            dataLabelPositioners = series.dataLabelPositioners;
        var connector,
            dataLabelWidth,
            labelHeight,
            maxLabelDistance = 0;
        // Get out if not enabled
        if (!series.visible || !((_a = series.hasDataLabels) === null || _a === void 0 ? void 0 : _a.call(series))) {
            return;
        }
        // Reset all labels that have been shortened
        points.forEach(function (point) {
            (point.dataLabels || []).forEach(function (dataLabel) {
                if (dataLabel.shortened) {
                    dataLabel
                        .attr({
                        width: 'auto'
                    }).css({
                        width: 'auto',
                        textOverflow: 'clip'
                    });
                    dataLabel.shortened = false;
                }
            });
        });
        // Run parent method
        PieDataLabel_Series.prototype.drawDataLabels.apply(series);
        points.forEach(function (point) {
            (point.dataLabels || []).forEach(function (dataLabel, i) {
                var _a;
                var r = seriesCenter[2] / 2,
                    dataLabelOptions = dataLabel.options,
                    distance = PieDataLabel_relativeLength((dataLabelOptions === null || dataLabelOptions === void 0 ? void 0 : dataLabelOptions.distance) || 0,
                    r);
                // Arrange points for collision detection
                if (i === 0) {
                    halves[point.half].push(point);
                }
                // Avoid long labels squeezing the pie size too far down
                if (!PieDataLabel_defined((_a = dataLabelOptions === null || dataLabelOptions === void 0 ? void 0 : dataLabelOptions.style) === null || _a === void 0 ? void 0 : _a.width)) {
                    if (dataLabel.getBBox().width > maxWidth) {
                        dataLabel.css({
                            // Use a fraction of the maxWidth to avoid wrapping
                            // close to the end of the string.
                            width: Math.round(maxWidth * 0.7) + 'px'
                        });
                        dataLabel.shortened = true;
                    }
                }
                dataLabel.dataLabelPosition = _this.getDataLabelPosition(point, distance);
                maxLabelDistance = Math.max(maxLabelDistance, distance);
            });
        });
        /* Loop over the points in each half, starting from the top and bottom
         * of the pie to detect overlapping labels.
         */
        halves.forEach(function (points, halfIdx) {
            var length = points.length,
                positions = [];
            var top,
                bottom,
                size = 0,
                distributionLength;
            if (!length) {
                return;
            }
            // Sort by angle
            series.sortByAngle(points, halfIdx - 0.5);
            // Only do anti-collision when we have dataLabels outside the pie
            // and have connectors. (#856)
            if (maxLabelDistance > 0) {
                top = Math.max(0, centerY - radius - maxLabelDistance);
                bottom = Math.min(centerY + radius + maxLabelDistance, chart.plotHeight);
                points.forEach(function (point) {
                    // Check if specific points' label is outside the pie
                    (point.dataLabels || []).forEach(function (dataLabel) {
                        var _a;
                        var labelPosition = dataLabel.dataLabelPosition;
                        if (labelPosition &&
                            labelPosition.distance > 0) {
                            // The point.top depends on point.labelDistance
                            // value. Used for calculation of y value in getX
                            // method
                            labelPosition.top = Math.max(0, centerY - radius - labelPosition.distance);
                            labelPosition.bottom = Math.min(centerY + radius + labelPosition.distance, chart.plotHeight);
                            size = dataLabel.getBBox().height || 21;
                            dataLabel.lineHeight = chart.renderer.fontMetrics(dataLabel.text || dataLabel).h + 2 * dataLabel.padding;
                            point.distributeBox = {
                                target: ((((_a = dataLabel.dataLabelPosition) === null || _a === void 0 ? void 0 : _a.natural.y) || 0) -
                                    labelPosition.top +
                                    dataLabel.lineHeight / 2),
                                size: size,
                                rank: point.y
                            };
                            positions.push(point.distributeBox);
                        }
                    });
                });
                distributionLength = bottom + size - top;
                PieDataLabel_distribute(positions, distributionLength, distributionLength / 5);
                // Uncomment this to visualize the boxes
                /*
                points.forEach((point): void => {
                    const box = point.distributeBox;
                    point.dlBox?.destroy();
                    if (box?.pos) {
                        point.dlBox = chart.renderer.rect(
                            chart.plotLeft + this.center[0] + (
                                halfIdx ?
                                    -this.center[2] / 2 - 100 :
                                    this.center[2] / 2
                            ),
                            chart.plotTop + box.pos,
                            100,
                            box.size
                        )
                            .attr({
                                stroke: 'silver',
                                'stroke-width': 1
                            })
                            .add();
                    }
                });
                // */
            }
            // Now the used slots are sorted, fill them up sequentially
            points.forEach(function (point) {
                (point.dataLabels || []).forEach(function (dataLabel) {
                    var dataLabelOptions = (dataLabel.options || {}),
                        distributeBox = point.distributeBox,
                        labelPosition = dataLabel.dataLabelPosition,
                        naturalY = (labelPosition === null || labelPosition === void 0 ? void 0 : labelPosition.natural.y) || 0,
                        connectorPadding = dataLabelOptions
                            .connectorPadding || 0,
                        lineHeight = dataLabel.lineHeight || 21,
                        bBox = dataLabel.getBBox(),
                        topOffset = (lineHeight - bBox.height) / 2;
                    var x = 0,
                        y = naturalY,
                        visibility = 'inherit';
                    if (labelPosition) {
                        if (positions &&
                            PieDataLabel_defined(distributeBox) &&
                            labelPosition.distance > 0) {
                            if (typeof distributeBox.pos === 'undefined') {
                                visibility = 'hidden';
                            }
                            else {
                                labelHeight = distributeBox.size;
                                // Find label's y position
                                y = dataLabelPositioners
                                    .radialDistributionY(point, dataLabel);
                            }
                        }
                        // Find label's x position. The justify option is
                        // undocumented in the API - preserve support for it
                        if (dataLabelOptions.justify) {
                            x = dataLabelPositioners.justify(point, dataLabel, radius, seriesCenter);
                        }
                        else {
                            switch (dataLabelOptions.alignTo) {
                                case 'connectors':
                                    x = dataLabelPositioners.alignToConnectors(points, halfIdx, plotWidth, plotLeft);
                                    break;
                                case 'plotEdges':
                                    x = dataLabelPositioners.alignToPlotEdges(dataLabel, halfIdx, plotWidth, plotLeft);
                                    break;
                                default:
                                    x = dataLabelPositioners.radialDistributionX(series, point, y - topOffset, naturalY, dataLabel);
                            }
                        }
                        // Record the placement and visibility
                        labelPosition.attribs = {
                            visibility: visibility,
                            align: labelPosition.alignment
                        };
                        labelPosition.posAttribs = {
                            x: x +
                                (dataLabelOptions.x || 0) + // (#12985)
                                ({
                                    left: connectorPadding,
                                    right: -connectorPadding
                                }[labelPosition.alignment] || 0),
                            y: y +
                                (dataLabelOptions.y || 0) - // (#12985)
                                // Vertically center
                                lineHeight / 2
                        };
                        labelPosition.computed.x = x;
                        labelPosition.computed.y = y - topOffset;
                        // Detect overflowing data labels
                        if (PieDataLabel_pick(dataLabelOptions.crop, true)) {
                            dataLabelWidth = dataLabel.getBBox().width;
                            var sideOverflow = void 0;
                            // Overflow left
                            if (x - dataLabelWidth < connectorPadding &&
                                halfIdx === 1 // Left half
                            ) {
                                sideOverflow = Math.round(dataLabelWidth - x + connectorPadding);
                                overflow[3] = Math.max(sideOverflow, overflow[3]);
                                // Overflow right
                            }
                            else if (x + dataLabelWidth >
                                plotWidth - connectorPadding &&
                                halfIdx === 0 // Right half
                            ) {
                                sideOverflow = Math.round(x +
                                    dataLabelWidth -
                                    plotWidth +
                                    connectorPadding);
                                overflow[1] = Math.max(sideOverflow, overflow[1]);
                            }
                            // Overflow top
                            if (y - labelHeight / 2 < 0) {
                                overflow[0] = Math.max(Math.round(-y + labelHeight / 2), overflow[0]);
                                // Overflow left
                            }
                            else if (y + labelHeight / 2 > plotHeight) {
                                overflow[2] = Math.max(Math.round(y + labelHeight / 2 - plotHeight), overflow[2]);
                            }
                            labelPosition.sideOverflow = sideOverflow;
                        }
                    }
                }); // For each data label of the point
            }); // For each point
        }); // For each half
        // Do not apply the final placement and draw the connectors until we
        // have verified that labels are not spilling over.
        if (PieDataLabel_arrayMax(overflow) === 0 ||
            this.verifyDataLabelOverflow(overflow)) {
            // Place the labels in the final position
            this.placeDataLabels();
            this.points.forEach(function (point) {
                (point.dataLabels || []).forEach(function (dataLabel) {
                    var _a;
                    // #8864: every connector can have individual options
                    var _b = (dataLabel.options || {}),
                        connectorColor = _b.connectorColor,
                        _c = _b.connectorWidth,
                        connectorWidth = _c === void 0 ? 1 : _c,
                        labelPosition = dataLabel.dataLabelPosition;
                    // Draw the connector
                    if (connectorWidth) {
                        var isNew = void 0;
                        connector = dataLabel.connector;
                        if (labelPosition && labelPosition.distance > 0) {
                            isNew = !connector;
                            if (!connector) {
                                dataLabel.connector = connector = chart.renderer
                                    .path()
                                    .addClass('highcharts-data-label-connector ' +
                                    ' highcharts-color-' +
                                    point.colorIndex +
                                    (point.className ?
                                        ' ' + point.className :
                                        ''))
                                    .add(series.dataLabelsGroup);
                            }
                            if (!chart.styledMode) {
                                connector.attr({
                                    'stroke-width': connectorWidth,
                                    'stroke': (connectorColor ||
                                        point.color ||
                                        "#666666" /* Palette.neutralColor60 */)
                                });
                            }
                            connector[isNew ? 'attr' : 'animate']({
                                d: point.getConnectorPath(dataLabel)
                            });
                            connector.attr({
                                visibility: (_a = labelPosition.attribs) === null || _a === void 0 ? void 0 : _a.visibility
                            });
                        }
                        else if (connector) {
                            dataLabel.connector = connector.destroy();
                        }
                    }
                });
            });
        }
    }
    /**
     * Perform the final placement of the data labels after we have verified
     * that they fall within the plot area.
     * @private
     */
    function placeDataLabels() {
        this.points.forEach(function (point) {
            (point.dataLabels || []).forEach(function (dataLabel) {
                var _a;
                var labelPosition = dataLabel.dataLabelPosition;
                if (labelPosition) {
                    // Shorten data labels with ellipsis if they still overflow
                    // after the pie has reached minSize (#223).
                    if (labelPosition.sideOverflow) {
                        dataLabel.css({
                            width: (Math.max(dataLabel.getBBox().width -
                                labelPosition.sideOverflow, 0)) + 'px',
                            textOverflow: ((((_a = dataLabel.options) === null || _a === void 0 ? void 0 : _a.style) || {})
                                .textOverflow ||
                                'ellipsis')
                        });
                        dataLabel.shortened = true;
                    }
                    dataLabel.attr(labelPosition.attribs);
                    dataLabel[dataLabel.moved ? 'animate' : 'attr'](labelPosition.posAttribs);
                    dataLabel.moved = true;
                }
                else if (dataLabel) {
                    dataLabel.attr({ y: -9999 });
                }
            });
            // Clear for update
            delete point.distributeBox;
        }, this);
    }
    /**
     * Verify whether the data labels are allowed to draw, or we should run more
     * translation and data label positioning to keep them inside the plot area.
     * Returns true when data labels are ready to draw.
     * @private
     */
    function verifyDataLabelOverflow(overflow) {
        var center = this.center,
            options = this.options,
            centerOption = options.center,
            minSize = options.minSize || 80;
        var newSize = minSize, 
            // If a size is set, return true and don't try to shrink the pie
            // to fit the labels.
            ret = options.size !== null;
        if (!ret) {
            // Handle horizontal size and center
            if (centerOption[0] !== null) { // Fixed center
                newSize = Math.max(center[2] -
                    Math.max(overflow[1], overflow[3]), minSize);
            }
            else { // Auto center
                newSize = Math.max(
                // Horizontal overflow
                center[2] - overflow[1] - overflow[3], minSize);
                // Horizontal center
                center[0] += (overflow[3] - overflow[1]) / 2;
            }
            // Handle vertical size and center
            if (centerOption[1] !== null) { // Fixed center
                newSize = PieDataLabel_clamp(newSize, minSize, center[2] - Math.max(overflow[0], overflow[2]));
            }
            else { // Auto center
                newSize = PieDataLabel_clamp(newSize, minSize, 
                // Vertical overflow
                center[2] - overflow[0] - overflow[2]);
                // Vertical center
                center[1] += (overflow[0] - overflow[2]) / 2;
            }
            // If the size must be decreased, we need to run translate and
            // drawDataLabels again
            if (newSize < center[2]) {
                center[2] = newSize;
                center[3] = Math.min(// #3632
                options.thickness ?
                    Math.max(0, newSize - options.thickness * 2) :
                    Math.max(0, PieDataLabel_relativeLength(options.innerSize || 0, newSize)), newSize); // #6647
                this.translate(center);
                if (this.drawDataLabels) {
                    this.drawDataLabels();
                }
                // Else, return true to indicate that the pie and its labels is
                // within the plot area
            }
            else {
                ret = true;
            }
        }
        return ret;
    }
})(PieDataLabel_ColumnDataLabel || (PieDataLabel_ColumnDataLabel = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var PieDataLabel = (PieDataLabel_ColumnDataLabel);

;// ./code/es5/es-modules/Core/Geometry/GeometryUtilities.js
/* *
 *
 *  (c) 2010-2024 Highsoft AS
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Namespace
 *
 * */
var GeometryUtilities;
(function (GeometryUtilities) {
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Calculates the center between a list of points.
     *
     * @private
     *
     * @param {Array<Highcharts.PositionObject>} points
     * A list of points to calculate the center of.
     *
     * @return {Highcharts.PositionObject}
     * Calculated center
     */
    function getCenterOfPoints(points) {
        var sum = points.reduce(function (sum,
            point) {
                sum.x += point.x;
            sum.y += point.y;
            return sum;
        }, { x: 0, y: 0 });
        return {
            x: sum.x / points.length,
            y: sum.y / points.length
        };
    }
    GeometryUtilities.getCenterOfPoints = getCenterOfPoints;
    /**
     * Calculates the distance between two points based on their x and y
     * coordinates.
     *
     * @private
     *
     * @param {Highcharts.PositionObject} p1
     * The x and y coordinates of the first point.
     *
     * @param {Highcharts.PositionObject} p2
     * The x and y coordinates of the second point.
     *
     * @return {number}
     * Returns the distance between the points.
     */
    function getDistanceBetweenPoints(p1, p2) {
        return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
    }
    GeometryUtilities.getDistanceBetweenPoints = getDistanceBetweenPoints;
    /**
     * Calculates the angle between two points.
     * @todo add unit tests.
     * @private
     * @param {Highcharts.PositionObject} p1 The first point.
     * @param {Highcharts.PositionObject} p2 The second point.
     * @return {number} Returns the angle in radians.
     */
    function getAngleBetweenPoints(p1, p2) {
        return Math.atan2(p2.x - p1.x, p2.y - p1.y);
    }
    GeometryUtilities.getAngleBetweenPoints = getAngleBetweenPoints;
    /**
     * Test for point in polygon. Polygon defined as array of [x,y] points.
     * @private
     * @param {PositionObject} point The point potentially within a polygon.
     * @param {Array<Array<number>>} polygon The polygon potentially containing the point.
     */
    function pointInPolygon(_a, polygon) {
        var x = _a.x,
            y = _a.y;
        var len = polygon.length;
        var i,
            j,
            inside = false;
        for (i = 0, j = len - 1; i < len; j = i++) {
            var _b = polygon[i],
                x1 = _b[0],
                y1 = _b[1],
                _c = polygon[j],
                x2 = _c[0],
                y2 = _c[1];
            if (y1 > y !== y2 > y &&
                (x < (x2 - x1) *
                    (y - y1) /
                    (y2 - y1) +
                    x1)) {
                inside = !inside;
            }
        }
        return inside;
    }
    GeometryUtilities.pointInPolygon = pointInPolygon;
})(GeometryUtilities || (GeometryUtilities = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Geometry_GeometryUtilities = (GeometryUtilities);

;// ./code/es5/es-modules/Extensions/OverlappingDataLabels.js
/* *
 *
 *  Highcharts module to hide overlapping data labels.
 *  This module is included in Highcharts.
 *
 *  (c) 2009-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var pointInPolygon = Geometry_GeometryUtilities.pointInPolygon;

var OverlappingDataLabels_addEvent = Core_Utilities.addEvent, OverlappingDataLabels_fireEvent = Core_Utilities.fireEvent, OverlappingDataLabels_objectEach = Core_Utilities.objectEach, OverlappingDataLabels_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/**
 * Hide overlapping labels. Labels are moved and faded in and out on zoom to
 * provide a smooth visual impression.
 *
 * @requires modules/overlapping-datalabels
 *
 * @private
 * @function Highcharts.Chart#hideOverlappingLabels
 * @param {Array<Highcharts.SVGElement>} labels
 *        Rendered data labels
 */
function chartHideOverlappingLabels(labels) {
    var chart = this,
        len = labels.length,
        isIntersectRect = function (box1,
        box2) { return !(box2.x >= box1.x + box1.width ||
            box2.x + box2.width <= box1.x ||
            box2.y >= box1.y + box1.height ||
            box2.y + box2.height <= box1.y); },
        isPolygonOverlap = function (box1Poly,
        box2Poly) {
            for (var _i = 0,
        box1Poly_1 = box1Poly; _i < box1Poly_1.length; _i++) {
                var p = box1Poly_1[_i];
            if (pointInPolygon({ x: p[0], y: p[1] }, box2Poly)) {
                return true;
            }
        }
        return false;
    };
    /**
     * Get the box with its position inside the chart, as opposed to getBBox
     * that only reports the position relative to the parent.
     */
    function getAbsoluteBox(label) {
        var _a,
            _b;
        if (label && (!label.alignAttr || label.placed)) {
            var padding = label.box ? 0 : (label.padding || 0),
                pos = label.alignAttr || {
                    x: label.attr('x'),
                    y: label.attr('y')
                },
                bBox = label.getBBox();
            label.width = bBox.width;
            label.height = bBox.height;
            return {
                x: pos.x + (((_a = label.parentGroup) === null || _a === void 0 ? void 0 : _a.translateX) || 0) + padding,
                y: pos.y + (((_b = label.parentGroup) === null || _b === void 0 ? void 0 : _b.translateY) || 0) + padding,
                width: (label.width || 0) - 2 * padding,
                height: (label.height || 0) - 2 * padding,
                polygon: bBox === null || bBox === void 0 ? void 0 : bBox.polygon
            };
        }
    }
    var label,
        label1,
        label2,
        box1,
        box2,
        isLabelAffected = false;
    for (var i = 0; i < len; i++) {
        label = labels[i];
        if (label) {
            // Mark with initial opacity
            label.oldOpacity = label.opacity;
            label.newOpacity = 1;
            label.absoluteBox = getAbsoluteBox(label);
        }
    }
    // Prevent a situation in a gradually rising slope, that each label will
    // hide the previous one because the previous one always has lower rank.
    labels.sort(function (a, b) { return (b.labelrank || 0) - (a.labelrank || 0); });
    // Detect overlapping labels
    for (var i = 0; i < len; ++i) {
        label1 = labels[i];
        box1 = label1 && label1.absoluteBox;
        var box1Poly = box1 === null || box1 === void 0 ? void 0 : box1.polygon;
        for (var j = i + 1; j < len; ++j) {
            label2 = labels[j];
            box2 = label2 && label2.absoluteBox;
            var toHide = false;
            if (box1 &&
                box2 &&
                label1 !== label2 && // #6465, polar chart with connectEnds
                label1.newOpacity !== 0 &&
                label2.newOpacity !== 0 &&
                // #15863 dataLabels are no longer hidden by translation
                label1.visibility !== 'hidden' &&
                label2.visibility !== 'hidden') {
                var box2Poly = box2.polygon;
                // If labels have polygons, only evaluate
                // based on polygons
                if (box1Poly &&
                    box2Poly &&
                    box1Poly !== box2Poly) {
                    if (isPolygonOverlap(box1Poly, box2Poly)) {
                        toHide = true;
                    }
                    // If there are no polygons, evaluate rectangles coliding
                }
                else if (isIntersectRect(box1, box2)) {
                    toHide = true;
                }
                if (toHide) {
                    var overlappingLabel = (label1.labelrank < label2.labelrank ?
                            label1 :
                            label2),
                        labelText = overlappingLabel.text;
                    overlappingLabel.newOpacity = 0;
                    if (labelText === null || labelText === void 0 ? void 0 : labelText.element.querySelector('textPath')) {
                        labelText.hide();
                    }
                }
            }
        }
    }
    // Hide or show
    for (var _i = 0, labels_1 = labels; _i < labels_1.length; _i++) {
        var label_1 = labels_1[_i];
        if (hideOrShow(label_1, chart)) {
            isLabelAffected = true;
        }
    }
    if (isLabelAffected) {
        OverlappingDataLabels_fireEvent(chart, 'afterHideAllOverlappingLabels');
    }
}
/** @private */
function compose(ChartClass) {
    var chartProto = ChartClass.prototype;
    if (!chartProto.hideOverlappingLabels) {
        chartProto.hideOverlappingLabels = chartHideOverlappingLabels;
        OverlappingDataLabels_addEvent(ChartClass, 'render', OverlappingDataLabels_onChartRender);
    }
}
/**
 * Hide or show labels based on opacity.
 *
 * @private
 * @function hideOrShow
 * @param {Highcharts.SVGElement} label
 * The label.
 * @param {Highcharts.Chart} chart
 * The chart that contains the label.
 * @return {boolean}
 * Whether label is affected
 */
function hideOrShow(label, chart) {
    var complete,
        newOpacity,
        isLabelAffected = false;
    if (label) {
        newOpacity = label.newOpacity;
        if (label.oldOpacity !== newOpacity) {
            // Toggle data labels
            if (label.hasClass('highcharts-data-label')) {
                // Make sure the label is completely hidden to avoid catching
                // clicks (#4362)
                label[newOpacity ? 'removeClass' : 'addClass']('highcharts-data-label-hidden');
                complete = function () {
                    if (!chart.styledMode) {
                        label.css({
                            pointerEvents: newOpacity ? 'auto' : 'none'
                        });
                    }
                };
                isLabelAffected = true;
                // Animate or set the opacity
                label[label.isOld ? 'animate' : 'attr']({ opacity: newOpacity }, void 0, complete);
                OverlappingDataLabels_fireEvent(chart, 'afterHideOverlappingLabel');
                // Toggle other labels, tick labels
            }
            else {
                label.attr({
                    opacity: newOpacity
                });
            }
        }
        label.isOld = true;
    }
    return isLabelAffected;
}
/**
 * Collect potential overlapping data labels. Stack labels probably don't need
 * to be considered because they are usually accompanied by data labels that lie
 * inside the columns.
 * @private
 */
function OverlappingDataLabels_onChartRender() {
    var _a;
    var chart = this;
    var labels = [];
    // Consider external label collectors
    for (var _i = 0, _b = (chart.labelCollectors || []); _i < _b.length; _i++) {
        var collector = _b[_i];
        labels = labels.concat(collector());
    }
    for (var _c = 0, _d = (chart.yAxis || []); _c < _d.length; _c++) {
        var yAxis = _d[_c];
        if (yAxis.stacking &&
            yAxis.options.stackLabels &&
            !yAxis.options.stackLabels.allowOverlap) {
            OverlappingDataLabels_objectEach(yAxis.stacking.stacks, function (stack) {
                OverlappingDataLabels_objectEach(stack, function (stackItem) {
                    if (stackItem.label) {
                        labels.push(stackItem.label);
                    }
                });
            });
        }
    }
    for (var _e = 0, _f = (chart.series || []); _e < _f.length; _e++) {
        var series = _f[_e];
        if (series.visible && ((_a = series.hasDataLabels) === null || _a === void 0 ? void 0 : _a.call(series))) { // #3866
            var push = function (points) {
                    var _loop_1 = function (point) {
                        if (point.visible) {
                            (point.dataLabels || []).forEach(function (label) {
                                var _a,
                _b;
                            var options = label.options || {};
                            label.labelrank = OverlappingDataLabels_pick(options.labelrank, point.labelrank, (_a = point.shapeArgs) === null || _a === void 0 ? void 0 : _a.height); // #4118
                            // Allow overlap if the option is explicitly true
                            if (
                            // #13449
                            (_b = options.allowOverlap) !== null && _b !== void 0 ? _b : 
                            // Pie labels outside have a separate placement
                            // logic, skip the overlap logic
                            Number(options.distance) > 0) {
                                label.oldOpacity = label.opacity;
                                label.newOpacity = 1;
                                hideOrShow(label, chart);
                                // Do not allow overlap
                            }
                            else {
                                labels.push(label);
                            }
                        });
                    }
                };
                for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
                    var point = points_1[_i];
                    _loop_1(point);
                }
            };
            push(series.nodes || []);
            push(series.points);
        }
    }
    this.hideOverlappingLabels(labels);
}
/* *
 *
 *  Default Export
 *
 * */
var OverlappingDataLabels = {
    compose: compose
};
/* harmony default export */ var Extensions_OverlappingDataLabels = (OverlappingDataLabels);

;// ./code/es5/es-modules/Extensions/BorderRadius.js
/* *
 *
 *  Highcharts Border Radius module
 *
 *  Author: Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var BorderRadius_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};

var BorderRadius_defaultOptions = Defaults.defaultOptions;

var BorderRadius_noop = Core_Globals.noop;

var BorderRadius_addEvent = Core_Utilities.addEvent, BorderRadius_extend = Core_Utilities.extend, BorderRadius_isObject = Core_Utilities.isObject, BorderRadius_merge = Core_Utilities.merge, BorderRadius_relativeLength = Core_Utilities.relativeLength;
/* *
 *
 *  Constants
 *
 * */
var defaultBorderRadiusOptions = {
    radius: 0,
    scope: 'stack',
    where: void 0
};
/* *
 *
 *  Variables
 *
 * */
var oldArc = BorderRadius_noop;
var oldRoundedRect = BorderRadius_noop;
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function applyBorderRadius(path, i, r) {
    var a = path[i];
    var b = path[i + 1];
    if (b[0] === 'Z') {
        b = path[0];
    }
    var line,
        arc,
        fromLineToArc;
    // From straight line to arc
    if ((a[0] === 'M' || a[0] === 'L') && b[0] === 'A') {
        line = a;
        arc = b;
        fromLineToArc = true;
        // From arc to straight line
    }
    else if (a[0] === 'A' && (b[0] === 'M' || b[0] === 'L')) {
        line = b;
        arc = a;
    }
    if (line && arc && arc.params) {
        var bigR = arc[1], 
            // In our use cases, outer pie slice arcs are clockwise and inner
            // arcs (donut/sunburst etc) are anti-clockwise
            clockwise = arc[5], params = arc.params, start = params.start, end = params.end, cx = params.cx, cy = params.cy;
        // Some geometric constants
        var relativeR = clockwise ? (bigR - r) : (bigR + r), 
            // The angle, on the big arc, that the border radius arc takes up
            angleOfBorderRadius = relativeR ? Math.asin(r / relativeR) : 0,
            angleOffset = clockwise ?
                angleOfBorderRadius :
                -angleOfBorderRadius, 
            // The distance along the radius of the big arc to the starting
            // point of the small border radius arc
            distanceBigCenterToStartArc = (Math.cos(angleOfBorderRadius) *
                relativeR);
        // From line to arc
        if (fromLineToArc) {
            // Update the cache
            params.start = start + angleOffset;
            // First move to the start position at the radial line. We want to
            // start one borderRadius closer to the center.
            line[1] = cx + distanceBigCenterToStartArc * Math.cos(start);
            line[2] = cy + distanceBigCenterToStartArc * Math.sin(start);
            // Now draw an arc towards the point where the small circle touches
            // the great circle.
            path.splice(i + 1, 0, [
                'A',
                r,
                r,
                0, // Slanting,
                0, // Long arc
                1, // Clockwise
                cx + bigR * Math.cos(params.start),
                cy + bigR * Math.sin(params.start)
            ]);
            // From arc to line
        }
        else {
            // Update the cache
            params.end = end - angleOffset;
            // End the big arc a bit earlier
            arc[6] = cx + bigR * Math.cos(params.end);
            arc[7] = cy + bigR * Math.sin(params.end);
            // Draw a small arc towards a point on the end angle, but one
            // borderRadius closer to the center relative to the perimeter.
            path.splice(i + 1, 0, [
                'A',
                r,
                r,
                0,
                0,
                1,
                cx + distanceBigCenterToStartArc * Math.cos(end),
                cy + distanceBigCenterToStartArc * Math.sin(end)
            ]);
        }
        // Long or short arc must be reconsidered because we have modified the
        // start and end points
        arc[4] = Math.abs(params.end - params.start) < Math.PI ? 0 : 1;
    }
}
/**
 * Extend arc with borderRadius.
 * @private
 */
function BorderRadius_arc(x, y, w, h, options) {
    if (options === void 0) { options = {}; }
    var path = oldArc(x,
        y,
        w,
        h,
        options),
        _a = options.innerR,
        innerR = _a === void 0 ? 0 : _a,
        _b = options.r,
        r = _b === void 0 ? w : _b,
        _c = options.start,
        start = _c === void 0 ? 0 : _c,
        _d = options.end,
        end = _d === void 0 ? 0 : _d;
    if (options.open || !options.borderRadius) {
        return path;
    }
    var alpha = end - start,
        sinHalfAlpha = Math.sin(alpha / 2),
        borderRadius = Math.max(Math.min(BorderRadius_relativeLength(options.borderRadius || 0,
        r - innerR), 
        // Cap to half the sector radius
        (r - innerR) / 2, 
        // For smaller pie slices, cap to the largest small circle that
        // can be fitted within the sector
        (r * sinHalfAlpha) / (1 + sinHalfAlpha)), 0), 
        // For the inner radius, we need an extra cap because the inner arc
        // is shorter than the outer arc
        innerBorderRadius = Math.min(borderRadius, 2 * (alpha / Math.PI) * innerR);
    // Apply turn-by-turn border radius. Start at the end since we're
    // splicing in arc segments.
    var i = path.length - 1;
    while (i--) {
        applyBorderRadius(path, i, i > 1 ? innerBorderRadius : borderRadius);
    }
    return path;
}
/** @private */
function seriesOnAfterColumnTranslate() {
    var _a,
        _b;
    if (this.options.borderRadius &&
        !(this.chart.is3d && this.chart.is3d())) {
        var _c = this,
            options = _c.options,
            yAxis = _c.yAxis,
            percent = options.stacking === 'percent',
            seriesDefault = (_b = (_a = BorderRadius_defaultOptions.plotOptions) === null || _a === void 0 ? void 0 : _a[this.type]) === null || _b === void 0 ? void 0 : _b.borderRadius,
            borderRadius = optionsToObject(options.borderRadius,
            BorderRadius_isObject(seriesDefault) ? seriesDefault : {}),
            reversed = yAxis.options.reversed;
        for (var _i = 0, _d = this.points; _i < _d.length; _i++) {
            var point = _d[_i];
            var shapeArgs = point.shapeArgs;
            if (point.shapeType === 'roundedRect' && shapeArgs) {
                var _e = shapeArgs.width,
                    width = _e === void 0 ? 0 : _e,
                    _f = shapeArgs.height,
                    height = _f === void 0 ? 0 : _f,
                    _g = shapeArgs.y,
                    y = _g === void 0 ? 0 : _g;
                var brBoxY = y,
                    brBoxHeight = height;
                // It would be nice to refactor StackItem.getStackBox/
                // setOffset so that we could get a reliable box out of
                // it. Currently it is close if we remove the label
                // offset, but we still need to run crispCol and also
                // flip it if inverted, so atm it is simpler to do it
                // like the below.
                if (borderRadius.scope === 'stack' &&
                    point.stackTotal) {
                    var stackEnd = yAxis.translate(percent ? 100 : point.stackTotal,
                        false,
                        true,
                        false,
                        true),
                        stackThreshold = yAxis.translate(options.threshold || 0,
                        false,
                        true,
                        false,
                        true),
                        box = this.crispCol(0,
                        Math.min(stackEnd,
                        stackThreshold), 0,
                        Math.abs(stackEnd - stackThreshold));
                    brBoxY = box.y;
                    brBoxHeight = box.height;
                }
                var flip = (point.negative ? -1 : 1) *
                        (reversed ? -1 : 1) === -1;
                // Handle the where option
                var where = borderRadius.where;
                // Waterfall, hanging columns should have rounding on
                // all sides
                if (!where &&
                    this.is('waterfall') &&
                    Math.abs((point.yBottom || 0) -
                        (this.translatedThreshold || 0)) > this.borderWidth) {
                    where = 'all';
                }
                if (!where) {
                    where = 'end';
                }
                // Get the radius
                var r = Math.min(BorderRadius_relativeLength(borderRadius.radius,
                    width),
                    width / 2, 
                    // Cap to the height, but not if where is `end`
                    where === 'all' ? height / 2 : Infinity) || 0;
                // If the `where` option is 'end', cut off the
                // rectangles by making the border-radius box one r
                // greater, so that the imaginary radius falls outside
                // the rectangle.
                if (where === 'end') {
                    if (flip) {
                        brBoxY -= r;
                        brBoxHeight += r;
                    }
                    else {
                        brBoxHeight += r;
                    }
                }
                BorderRadius_extend(shapeArgs, { brBoxHeight: brBoxHeight, brBoxY: brBoxY, r: r });
            }
        }
    }
}
/** @private */
function BorderRadius_compose(SeriesClass, SVGElementClass, SVGRendererClass) {
    var PieSeriesClass = SeriesClass.types.pie;
    if (!SVGElementClass.symbolCustomAttribs.includes('borderRadius')) {
        var symbols = SVGRendererClass.prototype.symbols;
        BorderRadius_addEvent(SeriesClass, 'afterColumnTranslate', seriesOnAfterColumnTranslate, {
            // After columnrange and polar column modifications
            order: 9
        });
        BorderRadius_addEvent(PieSeriesClass, 'afterTranslate', pieSeriesOnAfterTranslate);
        SVGElementClass.symbolCustomAttribs.push('borderRadius', 'brBoxHeight', 'brBoxY');
        oldArc = symbols.arc;
        oldRoundedRect = symbols.roundedRect;
        symbols.arc = BorderRadius_arc;
        symbols.roundedRect = BorderRadius_roundedRect;
    }
}
/** @private */
function optionsToObject(options, seriesBROptions) {
    if (!BorderRadius_isObject(options)) {
        options = { radius: options || 0 };
    }
    return BorderRadius_merge(defaultBorderRadiusOptions, seriesBROptions, options);
}
/** @private */
function pieSeriesOnAfterTranslate() {
    var borderRadius = optionsToObject(this.options.borderRadius);
    for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
        var point = _a[_i];
        var shapeArgs = point.shapeArgs;
        if (shapeArgs) {
            shapeArgs.borderRadius = BorderRadius_relativeLength(borderRadius.radius, (shapeArgs.r || 0) - ((shapeArgs.innerR) || 0));
        }
    }
}
/**
 * Extend roundedRect with individual cutting through rOffset.
 * @private
 */
function BorderRadius_roundedRect(x, y, width, height, options) {
    if (options === void 0) { options = {}; }
    var path = oldRoundedRect(x,
        y,
        width,
        height,
        options),
        _a = options.r,
        r = _a === void 0 ? 0 : _a,
        _b = options.brBoxHeight,
        brBoxHeight = _b === void 0 ? height : _b,
        _c = options.brBoxY,
        brBoxY = _c === void 0 ? y : _c,
        brOffsetTop = y - brBoxY,
        brOffsetBtm = (brBoxY + brBoxHeight) - (y + height), 
        // When the distance to the border-radius box is greater than the r
        // itself, it means no border radius. The -0.1 accounts for float
        // rounding errors.
        rTop = (brOffsetTop - r) > -0.1 ? 0 : r,
        rBtm = (brOffsetBtm - r) > -0.1 ? 0 : r,
        cutTop = Math.max(rTop && brOffsetTop, 0),
        cutBtm = Math.max(rBtm && brOffsetBtm, 0);
    /*

    The naming of control points:

      / a -------- b \
     /                \
    h                  c
    |                  |
    |                  |
    |                  |
    g                  d
     \                /
      \ f -------- e /

    */
    var a = [x + rTop,
        y],
        b = [x + width - rTop,
        y],
        c = [x + width,
        y + rTop],
        d = [
            x + width,
        y + height - rBtm
        ],
        e = [
            x + width - rBtm,
            y + height
        ],
        f = [x + rBtm,
        y + height],
        g = [x,
        y + height - rBtm],
        h = [x,
        y + rTop];
    var applyPythagoras = function (r,
        altitude) { return Math.sqrt(Math.pow(r, 2) - Math.pow(altitude, 2)); };
    // Inside stacks, cut off part of the top
    if (cutTop) {
        var base = applyPythagoras(rTop,
            rTop - cutTop);
        a[0] -= base;
        b[0] += base;
        c[1] = h[1] = y + rTop - cutTop;
    }
    // Column is lower than the radius. Cut off bottom inside the top
    // radius.
    if (height < rTop - cutTop) {
        var base = applyPythagoras(rTop,
            rTop - cutTop - height);
        c[0] = d[0] = x + width - rTop + base;
        e[0] = Math.min(c[0], e[0]);
        f[0] = Math.max(d[0], f[0]);
        g[0] = h[0] = x + rTop - base;
        c[1] = h[1] = y + height;
    }
    // Inside stacks, cut off part of the bottom
    if (cutBtm) {
        var base = applyPythagoras(rBtm,
            rBtm - cutBtm);
        e[0] += base;
        f[0] -= base;
        d[1] = g[1] = y + height - rBtm + cutBtm;
    }
    // Cut off top inside the bottom radius
    if (height < rBtm - cutBtm) {
        var base = applyPythagoras(rBtm,
            rBtm - cutBtm - height);
        c[0] = d[0] = x + width - rBtm + base;
        b[0] = Math.min(c[0], b[0]);
        a[0] = Math.max(d[0], a[0]);
        g[0] = h[0] = x + rBtm - base;
        d[1] = g[1] = y;
    }
    // Preserve the box for data labels
    path.length = 0;
    path.push(BorderRadius_spreadArray(['M'], a, true), BorderRadius_spreadArray(['L'], b, true), BorderRadius_spreadArray(['A', rTop, rTop, 0, 0, 1], c, true), BorderRadius_spreadArray(['L'], d, true), BorderRadius_spreadArray(['A', rBtm, rBtm, 0, 0, 1], e, true), BorderRadius_spreadArray(['L'], f, true), BorderRadius_spreadArray(['A', rBtm, rBtm, 0, 0, 1], g, true), BorderRadius_spreadArray(['L'], h, true), BorderRadius_spreadArray(['A', rTop, rTop, 0, 0, 1], a, true), ['Z']);
    return path;
}
/* *
 *
 *  Default Export
 *
 * */
var BorderRadius = {
    compose: BorderRadius_compose,
    optionsToObject: optionsToObject
};
/* harmony default export */ var Extensions_BorderRadius = (BorderRadius);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * Detailed options for border radius.
 *
 * @sample  {highcharts} highcharts/plotoptions/column-borderradius/
 *          Rounded columns
 * @sample  highcharts/plotoptions/series-border-radius
 *          Column and pie with rounded border
 *
 * @interface Highcharts.BorderRadiusOptionsObject
 */ /**
* The border radius. A number signifies pixels. A percentage string, like for
* example `50%`, signifies a relative size. For columns this is relative to the
* column width, for pies it is relative to the radius and the inner radius.
*
* @name Highcharts.BorderRadiusOptionsObject#radius
* @type {string|number}
*/ /**
* The scope of the rounding for column charts. In a stacked column chart, the
* value `point` means each single point will get rounded corners. The value
* `stack` means the rounding will apply to the full stack, so that only points
* close to the top or bottom will receive rounding.
*
* @name Highcharts.BorderRadiusOptionsObject#scope
* @validvalue ["point", "stack"]
* @type {string}
*/ /**
* For column charts, where in the point or stack to apply rounding. The `end`
* value means only those corners at the point value will be rounded, leaving
* the corners at the base or threshold unrounded. This is the most intuitive
* behaviour. The `all` value means also the base will be rounded.
*
* @name Highcharts.BorderRadiusOptionsObject#where
* @validvalue ["all", "end"]
* @type {string}
* @default end
*/
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Core/Responsive.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Responsive_diffObjects = Core_Utilities.diffObjects, Responsive_extend = Core_Utilities.extend, Responsive_find = Core_Utilities.find, Responsive_merge = Core_Utilities.merge, Responsive_pick = Core_Utilities.pick, Responsive_uniqueKey = Core_Utilities.uniqueKey;
/* *
 *
 *  Composition
 *
 * */
var Responsive;
(function (Responsive) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    function compose(ChartClass) {
        var chartProto = ChartClass.prototype;
        if (!chartProto.matchResponsiveRule) {
            Responsive_extend(chartProto, {
                matchResponsiveRule: matchResponsiveRule,
                setResponsive: setResponsive
            });
        }
        return ChartClass;
    }
    Responsive.compose = compose;
    /**
     * Handle a single responsiveness rule.
     *
     * @private
     * @function Highcharts.Chart#matchResponsiveRule
     * @param {Highcharts.ResponsiveRulesOptions} rule
     * @param {Array<string>} matches
     */
    function matchResponsiveRule(rule, matches) {
        var condition = rule.condition,
            fn = condition.callback || function () {
                return (this.chartWidth <= Responsive_pick(condition.maxWidth,
            Number.MAX_VALUE) &&
                    this.chartHeight <= Responsive_pick(condition.maxHeight,
            Number.MAX_VALUE) &&
                    this.chartWidth >= Responsive_pick(condition.minWidth, 0) &&
                    this.chartHeight >= Responsive_pick(condition.minHeight, 0));
        };
        if (fn.call(this)) {
            matches.push(rule._id);
        }
    }
    /**
     * Update the chart based on the current chart/document size and options
     * for responsiveness.
     *
     * @private
     * @function Highcharts.Chart#setResponsive
     * @param  {boolean} [redraw=true]
     * @param  {boolean} [reset=false]
     * Reset by un-applying all rules. Chart.update resets all rules before
     * applying updated options.
     */
    function setResponsive(redraw, reset) {
        var _this = this;
        var options = this.options.responsive,
            currentResponsive = this.currentResponsive;
        var ruleIds = [],
            undoOptions;
        if (!reset && options && options.rules) {
            options.rules.forEach(function (rule) {
                if (typeof rule._id === 'undefined') {
                    rule._id = Responsive_uniqueKey();
                }
                _this.matchResponsiveRule(rule, ruleIds /* , redraw */);
            }, this);
        }
        // Merge matching rules
        var mergedOptions = Responsive_merge.apply(void 0,
            ruleIds
                .map(function (ruleId) { return Responsive_find((options || {}).rules || [],
            function (rule) { return (rule._id === ruleId); }); })
                .map(function (rule) { return (rule && rule.chartOptions); }));
        mergedOptions.isResponsiveOptions = true;
        // Stringified key for the rules that currently apply.
        ruleIds = (ruleIds.toString() || void 0);
        var currentRuleIds = (currentResponsive && currentResponsive.ruleIds);
        // Changes in what rules apply
        if (ruleIds !== currentRuleIds) {
            // Undo previous rules. Before we apply a new set of rules, we
            // need to roll back completely to base options (#6291).
            if (currentResponsive) {
                this.currentResponsive = void 0;
                this.updatingResponsive = true;
                this.update(currentResponsive.undoOptions, redraw, true);
                this.updatingResponsive = false;
            }
            if (ruleIds) {
                // Get undo-options for matching rules. The `undoOptions``
                // hold the current values before they are changed by the
                // `mergedOptions`.
                undoOptions = Responsive_diffObjects(mergedOptions, this.options, true, this.collectionsWithUpdate);
                undoOptions.isResponsiveOptions = true;
                this.currentResponsive = {
                    ruleIds: ruleIds,
                    mergedOptions: mergedOptions,
                    undoOptions: undoOptions
                };
                if (!this.updatingResponsive) {
                    this.update(mergedOptions, redraw, true);
                }
            }
            else {
                this.currentResponsive = void 0;
            }
        }
    }
})(Responsive || (Responsive = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Core_Responsive = (Responsive);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * A callback function to gain complete control on when the responsive rule
 * applies.
 *
 * @callback Highcharts.ResponsiveCallbackFunction
 *
 * @param {Highcharts.Chart} this
 * Chart context.
 *
 * @return {boolean}
 * Return `true` if it applies.
 */
(''); // Keeps doclets above in JS file
/* *
 *
 *  API Options
 *
 * */
/**
 * Allows setting a set of rules to apply for different screen or chart
 * sizes. Each rule specifies additional chart options.
 *
 * @sample {highstock} stock/demo/responsive/
 *         Stock chart
 * @sample highcharts/responsive/axis/
 *         Axis
 * @sample highcharts/responsive/legend/
 *         Legend
 * @sample highcharts/responsive/classname/
 *         Class name
 *
 * @since     5.0.0
 * @apioption responsive
 */
/**
 * A set of rules for responsive settings. The rules are executed from
 * the top down.
 *
 * @sample {highcharts} highcharts/responsive/axis/
 *         Axis changes
 * @sample {highstock} highcharts/responsive/axis/
 *         Axis changes
 * @sample {highmaps} highcharts/responsive/axis/
 *         Axis changes
 *
 * @type      {Array<*>}
 * @since     5.0.0
 * @apioption responsive.rules
 */
/**
 * A full set of chart options to apply as overrides to the general
 * chart options. The chart options are applied when the given rule
 * is active.
 *
 * A special case is configuration objects that take arrays, for example
 * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these
 * collections, an `id` option is used to map the new option set to
 * an existing object. If an existing object of the same id is not found,
 * the item of the same index updated. So for example, setting `chartOptions`
 * with two series items without an `id`, will cause the existing chart's
 * two series to be updated with respective options.
 *
 * @sample {highstock} stock/demo/responsive/
 *         Stock chart
 * @sample highcharts/responsive/axis/
 *         Axis
 * @sample highcharts/responsive/legend/
 *         Legend
 * @sample highcharts/responsive/classname/
 *         Class name
 *
 * @type      {Highcharts.Options}
 * @since     5.0.0
 * @apioption responsive.rules.chartOptions
 */
/**
 * Under which conditions the rule applies.
 *
 * @since     5.0.0
 * @apioption responsive.rules.condition
 */
/**
 * A callback function to gain complete control on when the responsive
 * rule applies. Return `true` if it applies. This opens for checking
 * against other metrics than the chart size, for example the document
 * size or other elements.
 *
 * @type      {Highcharts.ResponsiveCallbackFunction}
 * @since     5.0.0
 * @context   Highcharts.Chart
 * @apioption responsive.rules.condition.callback
 */
/**
 * The responsive rule applies if the chart height is less than this.
 *
 * @type      {number}
 * @since     5.0.0
 * @apioption responsive.rules.condition.maxHeight
 */
/**
 * The responsive rule applies if the chart width is less than this.
 *
 * @sample highcharts/responsive/axis/
 *         Max width is 500
 *
 * @type      {number}
 * @since     5.0.0
 * @apioption responsive.rules.condition.maxWidth
 */
/**
 * The responsive rule applies if the chart height is greater than this.
 *
 * @type      {number}
 * @default   0
 * @since     5.0.0
 * @apioption responsive.rules.condition.minHeight
 */
/**
 * The responsive rule applies if the chart width is greater than this.
 *
 * @type      {number}
 * @default   0
 * @since     5.0.0
 * @apioption responsive.rules.condition.minWidth
 */
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/masters/highcharts.src.js















































var G = Core_Globals;
// Classes
G.AST = HTML_AST;
G.Axis = Axis_Axis;
G.Chart = Chart_Chart;
G.Color = Color_Color;
G.DataLabel = Series_DataLabel;
G.DataTableCore = Data_DataTableCore;
G.Fx = Animation_Fx;
G.HTMLElement = HTML_HTMLElement;
G.Legend = Legend_Legend;
G.LegendSymbol = Legend_LegendSymbol;
G.OverlappingDataLabels = G.OverlappingDataLabels || Extensions_OverlappingDataLabels;
G.PlotLineOrBand = PlotLineOrBand_PlotLineOrBand;
G.Point = Series_Point;
G.Pointer = Core_Pointer;
G.RendererRegistry = Renderer_RendererRegistry;
G.Series = Series_Series;
G.SeriesRegistry = Series_SeriesRegistry;
G.StackItem = Stacking_StackItem;
G.SVGElement = SVG_SVGElement;
G.SVGRenderer = SVG_SVGRenderer;
G.Templating = Core_Templating;
G.Tick = Axis_Tick;
G.Time = Core_Time;
G.Tooltip = Core_Tooltip;
// Utilities
G.animate = AnimationUtilities.animate;
G.animObject = AnimationUtilities.animObject;
G.chart = Chart_Chart.chart;
G.color = Color_Color.parse;
G.dateFormat = Core_Templating.dateFormat;
G.defaultOptions = Defaults.defaultOptions;
G.distribute = Renderer_RendererUtilities.distribute;
G.format = Core_Templating.format;
G.getDeferredAnimation = AnimationUtilities.getDeferredAnimation;
G.getOptions = Defaults.getOptions;
G.numberFormat = Core_Templating.numberFormat;
G.seriesType = Series_SeriesRegistry.seriesType;
G.setAnimation = AnimationUtilities.setAnimation;
G.setOptions = Defaults.setOptions;
G.stop = AnimationUtilities.stop;
G.time = Defaults.defaultTime;
G.timers = Animation_Fx.timers;
// Compositions
Extensions_BorderRadius.compose(G.Series, G.SVGElement, G.SVGRenderer);
Column_ColumnDataLabel.compose(G.Series.types.column);
Series_DataLabel.compose(G.Series);
Axis_DateTimeAxis.compose(G.Axis);
HTML_HTMLElement.compose(G.SVGRenderer);
Legend_Legend.compose(G.Chart);
Axis_LogarithmicAxis.compose(G.Axis);
Extensions_OverlappingDataLabels.compose(G.Chart);
PieDataLabel.compose(G.Series.types.pie);
PlotLineOrBand_PlotLineOrBand.compose(G.Chart, G.Axis);
Core_Pointer.compose(G.Chart);
Core_Responsive.compose(G.Chart);
Extensions_ScrollablePlotArea.compose(G.Axis, G.Chart, G.Series);
Stacking_StackingAxis.compose(G.Axis, G.Chart, G.Series);
Core_Tooltip.compose(G.Pointer);
Core_Utilities.extend(G, Core_Utilities);
// Default Export
/* harmony default export */ var highcharts_src = (G);

;// ./code/es5/es-modules/Extensions/ArrowSymbols.js
/* *
 *
 *  (c) 2017 Highsoft AS
 *  Authors: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Functions
 *
 * */
/**
 * Creates an arrow symbol. Like a triangle, except not filled.
 * ```
 *                   o
 *             o
 *       o
 * o
 *       o
 *             o
 *                   o
 * ```
 *
 * @private
 * @function
 *
 * @param {number} x
 *        x position of the arrow
 *
 * @param {number} y
 *        y position of the arrow
 *
 * @param {number} w
 *        width of the arrow
 *
 * @param {number} h
 *        height of the arrow
 *
 * @return {Highcharts.SVGPathArray}
 *         Path array
 */
function arrow(x, y, w, h) {
    return [
        ['M', x, y + h / 2],
        ['L', x + w, y],
        ['L', x, y + h / 2],
        ['L', x + w, y + h]
    ];
}
/**
 * Creates a half-width arrow symbol. Like a triangle, except not filled.
 * ```
 *       o
 *    o
 * o
 *    o
 *       o
 * ```
 *
 * @private
 * @function
 *
 * @param {number} x
 *        x position of the arrow
 *
 * @param {number} y
 *        y position of the arrow
 *
 * @param {number} w
 *        width of the arrow
 *
 * @param {number} h
 *        height of the arrow
 *
 * @return {Highcharts.SVGPathArray}
 *         Path array
 */
function arrowHalf(x, y, w, h) {
    return arrow(x, y, w / 2, h);
}
/**
 * @private
 */
function ArrowSymbols_compose(SVGRendererClass) {
    var symbols = SVGRendererClass.prototype.symbols;
    symbols.arrow = arrow;
    symbols['arrow-filled'] = triangleLeft;
    symbols['arrow-filled-half'] = triangleLeftHalf;
    symbols['arrow-half'] = arrowHalf;
    symbols['triangle-left'] = triangleLeft;
    symbols['triangle-left-half'] = triangleLeftHalf;
}
/**
 * Creates a left-oriented triangle.
 * ```
 *             o
 *       ooooooo
 * ooooooooooooo
 *       ooooooo
 *             o
 * ```
 *
 * @private
 * @function
 *
 * @param {number} x
 *        x position of the triangle
 *
 * @param {number} y
 *        y position of the triangle
 *
 * @param {number} w
 *        width of the triangle
 *
 * @param {number} h
 *        height of the triangle
 *
 * @return {Highcharts.SVGPathArray}
 *         Path array
 */
function triangleLeft(x, y, w, h) {
    return [
        ['M', x + w, y],
        ['L', x, y + h / 2],
        ['L', x + w, y + h],
        ['Z']
    ];
}
/**
 * Creates a half-width, left-oriented triangle.
 * ```
 *       o
 *    oooo
 * ooooooo
 *    oooo
 *       o
 * ```
 *
 * @private
 * @function
 *
 * @param {number} x
 *        x position of the triangle
 *
 * @param {number} y
 *        y position of the triangle
 *
 * @param {number} w
 *        width of the triangle
 *
 * @param {number} h
 *        height of the triangle
 *
 * @return {Highcharts.SVGPathArray}
 *         Path array
 */
function triangleLeftHalf(x, y, w, h) {
    return triangleLeft(x, y, w / 2, h);
}
/* *
 *
 *  Default Export
 *
 * */
var ArrowSymbols = {
    compose: ArrowSymbols_compose
};
/* harmony default export */ var Extensions_ArrowSymbols = (ArrowSymbols);

;// ./code/es5/es-modules/Gantt/Connection.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Øystein Moseng, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var Connection_defined = Core_Utilities.defined, Connection_error = Core_Utilities.error, Connection_merge = Core_Utilities.merge, Connection_objectEach = Core_Utilities.objectEach;
/* *
 *
 *  Constants
 *
 * */
var Connection_deg2rad = Core_Globals.deg2rad, max = Math.max, min = Math.min;
/* *
 *
 *  Class
 *
 * */
/**
 * The Connection class. Used internally to represent a connection between two
 * points.
 *
 * @private
 * @class
 * @name Highcharts.Connection
 *
 * @param {Highcharts.Point} from
 *        Connection runs from this Point.
 *
 * @param {Highcharts.Point} to
 *        Connection runs to this Point.
 *
 * @param {Highcharts.ConnectorsOptions} [options]
 *        Connection options.
 */
var Connection = /** @class */ (function () {
    function Connection(from, to, options) {
        this.init(from, to, options);
    }
    /**
     * Initialize the Connection object. Used as constructor only.
     *
     * @function Highcharts.Connection#init
     *
     * @param {Highcharts.Point} from
     *        Connection runs from this Point.
     *
     * @param {Highcharts.Point} to
     *        Connection runs to this Point.
     *
     * @param {Highcharts.ConnectorsOptions} [options]
     *        Connection options.
     */
    Connection.prototype.init = function (from, to, options) {
        this.fromPoint = from;
        this.toPoint = to;
        this.options = options;
        this.chart = from.series.chart;
        this.pathfinder = this.chart.pathfinder;
    };
    /**
     * Add (or update) this connection's path on chart. Stores reference to the
     * created element on this.graphics.path.
     *
     * @function Highcharts.Connection#renderPath
     *
     * @param {Highcharts.SVGPathArray} path
     *        Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10]
     *
     * @param {Highcharts.SVGAttributes} [attribs]
     *        SVG attributes for the path.
     *
     * @param {Partial<Highcharts.AnimationOptionsObject>} [animation]
     *        Animation options for the rendering.
     */
    Connection.prototype.renderPath = function (path, attribs) {
        var connection = this,
            chart = this.chart,
            styledMode = chart.styledMode,
            pathfinder = this.pathfinder,
            anim = {};
        var pathGraphic = connection.graphics && connection.graphics.path;
        // Add the SVG element of the pathfinder group if it doesn't exist
        if (!pathfinder.group) {
            pathfinder.group = chart.renderer.g()
                .addClass('highcharts-pathfinder-group')
                .attr({ zIndex: -1 })
                .add(chart.seriesGroup);
        }
        // Shift the group to compensate for plot area.
        // Note: Do this always (even when redrawing a path) to avoid issues
        // when updating chart in a way that changes plot metrics.
        pathfinder.group.translate(chart.plotLeft, chart.plotTop);
        // Create path if does not exist
        if (!(pathGraphic && pathGraphic.renderer)) {
            pathGraphic = chart.renderer.path()
                .add(pathfinder.group);
            if (!styledMode) {
                pathGraphic.attr({
                    opacity: 0
                });
            }
        }
        // Set path attribs and animate to the new path
        pathGraphic.attr(attribs);
        anim.d = path;
        if (!styledMode) {
            anim.opacity = 1;
        }
        pathGraphic.animate(anim);
        // Store reference on connection
        this.graphics = this.graphics || {};
        this.graphics.path = pathGraphic;
    };
    /**
     * Calculate and add marker graphics for connection to the chart. The
     * created/updated elements are stored on this.graphics.start and
     * this.graphics.end.
     *
     * @function Highcharts.Connection#addMarker
     *
     * @param {string} type
     *        Marker type, either 'start' or 'end'.
     *
     * @param {Highcharts.ConnectorsMarkerOptions} options
     *        All options for this marker. Not calculated or merged with other
     *        options.
     *
     * @param {Highcharts.SVGPathArray} path
     *        Connection path in array format. This is used to calculate the
     *        rotation angle of the markers.
     */
    Connection.prototype.addMarker = function (type, options, path) {
        var connection = this,
            chart = connection.fromPoint.series.chart,
            pathfinder = chart.pathfinder,
            renderer = chart.renderer,
            point = (type === 'start' ?
                connection.fromPoint :
                connection.toPoint),
            anchor = point.getPathfinderAnchorPoint(options);
        var markerVector,
            radians,
            rotation,
            box,
            width,
            height,
            pathVector,
            segment;
        if (!options.enabled) {
            return;
        }
        // Last vector before start/end of path, used to get angle
        if (type === 'start') {
            segment = path[1];
        }
        else { // 'end'
            segment = path[path.length - 2];
        }
        if (segment && segment[0] === 'M' || segment[0] === 'L') {
            pathVector = {
                x: segment[1],
                y: segment[2]
            };
            // Get angle between pathVector and anchor point and use it to
            // create marker position.
            radians = point.getRadiansToVector(pathVector, anchor);
            markerVector = point.getMarkerVector(radians, options.radius, anchor);
            // Rotation of marker is calculated from angle between pathVector
            // and markerVector.
            // (Note:
            //  Used to recalculate radians between markerVector and pathVector,
            //  but this should be the same as between pathVector and anchor.)
            rotation = -radians / Connection_deg2rad;
            if (options.width && options.height) {
                width = options.width;
                height = options.height;
            }
            else {
                width = height = options.radius * 2;
            }
            // Add graphics object if it does not exist
            connection.graphics = connection.graphics || {};
            box = {
                x: markerVector.x - (width / 2),
                y: markerVector.y - (height / 2),
                width: width,
                height: height,
                rotation: rotation,
                rotationOriginX: markerVector.x,
                rotationOriginY: markerVector.y
            };
            if (!connection.graphics[type]) {
                // Create new marker element
                connection.graphics[type] = renderer
                    .symbol(options.symbol)
                    .addClass('highcharts-point-connecting-path-' + type + '-marker' +
                    ' highcharts-color-' + this.fromPoint.colorIndex)
                    .attr(box)
                    .add(pathfinder.group);
                if (!renderer.styledMode) {
                    connection.graphics[type].attr({
                        fill: options.color || connection.fromPoint.color,
                        stroke: options.lineColor,
                        'stroke-width': options.lineWidth,
                        opacity: 0
                    })
                        .animate({
                        opacity: 1
                    }, point.series.options.animation);
                }
            }
            else {
                connection.graphics[type].animate(box);
            }
        }
    };
    /**
     * Calculate and return connection path.
     * Note: Recalculates chart obstacles on demand if they aren't calculated.
     *
     * @function Highcharts.Connection#getPath
     *
     * @param {Highcharts.ConnectorsOptions} options
     *        Connector options. Not calculated or merged with other options.
     *
     * @return {object|undefined}
     *         Calculated SVG path data in array format.
     */
    Connection.prototype.getPath = function (options) {
        var pathfinder = this.pathfinder,
            chart = this.chart,
            algorithm = pathfinder.algorithms[options.type];
        var chartObstacles = pathfinder.chartObstacles;
        if (typeof algorithm !== 'function') {
            Connection_error('"' + options.type + '" is not a Pathfinder algorithm.');
            return {
                path: [],
                obstacles: []
            };
        }
        // This function calculates obstacles on demand if they don't exist
        if (algorithm.requiresObstacles && !chartObstacles) {
            chartObstacles =
                pathfinder.chartObstacles =
                    pathfinder.getChartObstacles(options);
            // If the algorithmMargin was computed, store the result in default
            // options.
            chart.options.connectors.algorithmMargin =
                options.algorithmMargin;
            // Cache some metrics too
            pathfinder.chartObstacleMetrics =
                pathfinder.getObstacleMetrics(chartObstacles);
        }
        // Get the SVG path
        return algorithm(
        // From
        this.fromPoint.getPathfinderAnchorPoint(options.startMarker), 
        // To
        this.toPoint.getPathfinderAnchorPoint(options.endMarker), Connection_merge({
            chartObstacles: chartObstacles,
            lineObstacles: pathfinder.lineObstacles || [],
            obstacleMetrics: pathfinder.chartObstacleMetrics,
            hardBounds: {
                xMin: 0,
                xMax: chart.plotWidth,
                yMin: 0,
                yMax: chart.plotHeight
            },
            obstacleOptions: {
                margin: options.algorithmMargin
            },
            startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker)
        }, options));
    };
    /**
     * (re)Calculate and (re)draw the connection.
     *
     * @function Highcharts.Connection#render
     */
    Connection.prototype.render = function () {
        var connection = this,
            fromPoint = connection.fromPoint,
            series = fromPoint.series,
            chart = series.chart,
            pathfinder = chart.pathfinder,
            attribs = {};
        var options = Connection_merge(chart.options.connectors,
            series.options.connectors,
            fromPoint.options.connectors,
            connection.options);
        // Set path attribs
        if (!chart.styledMode) {
            attribs.stroke = options.lineColor || fromPoint.color;
            attribs['stroke-width'] = options.lineWidth;
            if (options.dashStyle) {
                attribs.dashstyle = options.dashStyle;
            }
        }
        attribs['class'] = // eslint-disable-line dot-notation
            'highcharts-point-connecting-path ' +
                'highcharts-color-' + fromPoint.colorIndex;
        options = Connection_merge(attribs, options);
        // Set common marker options
        if (!Connection_defined(options.marker.radius)) {
            options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5);
        }
        // Get the path
        var pathResult = connection.getPath(options),
            path = pathResult.path;
        // Always update obstacle storage with obstacles from this path.
        // We don't know if future calls will need this for their algorithm.
        if (pathResult.obstacles) {
            pathfinder.lineObstacles =
                pathfinder.lineObstacles || [];
            pathfinder.lineObstacles =
                pathfinder.lineObstacles.concat(pathResult.obstacles);
        }
        // Add the calculated path to the pathfinder group
        connection.renderPath(path, attribs);
        // Render the markers
        connection.addMarker('start', Connection_merge(options.marker, options.startMarker), path);
        connection.addMarker('end', Connection_merge(options.marker, options.endMarker), path);
    };
    /**
     * Destroy connection by destroying the added graphics elements.
     *
     * @function Highcharts.Connection#destroy
     */
    Connection.prototype.destroy = function () {
        if (this.graphics) {
            Connection_objectEach(this.graphics, function (val) {
                val.destroy();
            });
            delete this.graphics;
        }
    };
    return Connection;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Gantt_Connection = (Connection);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * The default pathfinder algorithm to use for a chart. It is possible to define
 * your own algorithms by adding them to the
 * `Highcharts.Pathfinder.prototype.algorithms`
 * object before the chart has been created.
 *
 * The default algorithms are as follows:
 *
 * `straight`:      Draws a straight line between the connecting
 *                  points. Does not avoid other points when drawing.
 *
 * `simpleConnect`: Finds a path between the points using right angles
 *                  only. Takes only starting/ending points into
 *                  account, and will not avoid other points.
 *
 * `fastAvoid`:     Finds a path between the points using right angles
 *                  only. Will attempt to avoid other points, but its
 *                  focus is performance over accuracy. Works well with
 *                  less dense datasets.
 *
 * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Extensions/CurrentDateIndication.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Author: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var CurrentDateIndication_composed = Core_Globals.composed;

var CurrentDateIndication_addEvent = Core_Utilities.addEvent, CurrentDateIndication_merge = Core_Utilities.merge, CurrentDateIndication_pushUnique = Core_Utilities.pushUnique, CurrentDateIndication_wrap = Core_Utilities.wrap;
/* *
 *
 *  Constants
 *
 * */
/**
 * Show an indicator on the axis for the current date and time. Can be a
 * boolean or a configuration object similar to
 * [xAxis.plotLines](#xAxis.plotLines).
 *
 * @sample gantt/current-date-indicator/demo
 *         Current date indicator enabled
 * @sample gantt/current-date-indicator/object-config
 *         Current date indicator with custom options
 *
 * @declare   Highcharts.CurrentDateIndicatorOptions
 * @type      {boolean|CurrentDateIndicatorOptions}
 * @default   true
 * @extends   xAxis.plotLines
 * @excluding value
 * @product   gantt
 * @apioption xAxis.currentDateIndicator
 */
var CurrentDateIndication_defaultOptions = {
    color: "#ccd3ff" /* Palette.highlightColor20 */,
    width: 2,
    /**
     * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions
     */
    label: {
        /**
         * Format of the label. This options is passed as the first argument to
         * [dateFormat](/class-reference/Highcharts.Time#dateFormat) function.
         *
         * @type      {string|Intl.DateTimeFormatOptions}
         * @product   gantt
         * @apioption xAxis.currentDateIndicator.label.format
         */
        format: '%[abdYHM]',
        formatter: function (value, format) {
            return this.axis.chart.time.dateFormat(format || '', value, true);
        },
        rotation: 0,
        /**
         * @type {Highcharts.CSSObject}
         */
        style: {
            /** @internal */
            fontSize: '0.7em'
        }
    }
};
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function CurrentDateIndication_compose(AxisClass, PlotLineOrBandClass) {
    if (CurrentDateIndication_pushUnique(CurrentDateIndication_composed, 'CurrentDateIndication')) {
        CurrentDateIndication_addEvent(AxisClass, 'afterSetOptions', onAxisAfterSetOptions);
        CurrentDateIndication_addEvent(PlotLineOrBandClass, 'render', onPlotLineOrBandRender);
        CurrentDateIndication_wrap(PlotLineOrBandClass.prototype, 'getLabelText', wrapPlotLineOrBandGetLabelText);
    }
}
/**
 * @private
 */
function onAxisAfterSetOptions() {
    var options = this.options,
        cdiOptions = options.currentDateIndicator;
    if (cdiOptions) {
        var plotLineOptions = typeof cdiOptions === 'object' ?
                CurrentDateIndication_merge(CurrentDateIndication_defaultOptions,
            cdiOptions) :
                CurrentDateIndication_merge(CurrentDateIndication_defaultOptions);
        plotLineOptions.value = Date.now();
        plotLineOptions.className = 'highcharts-current-date-indicator';
        if (!options.plotLines) {
            options.plotLines = [];
        }
        options.plotLines.push(plotLineOptions);
    }
}
/**
 * @private
 */
function onPlotLineOrBandRender() {
    // If the label already exists, update its text
    if (this.label) {
        this.label.attr({
            text: this.getLabelText(this.options.label)
        });
    }
}
/**
 * @private
 */
function wrapPlotLineOrBandGetLabelText(defaultMethod, defaultLabelOptions) {
    var options = this.options;
    if (options &&
        options.className &&
        options.className.indexOf('highcharts-current-date-indicator') !== -1 &&
        options.label &&
        typeof options.label.formatter === 'function') {
        options.value = Date.now();
        return options.label.formatter
            .call(this, options.value, options.label.format);
    }
    return defaultMethod.call(this, defaultLabelOptions);
}
/* *
 *
 *  Default Export
 *
 * */
var CurrentDateIndication = {
    compose: CurrentDateIndication_compose
};
/* harmony default export */ var Extensions_CurrentDateIndication = (CurrentDateIndication);

;// ./code/es5/es-modules/Core/Chart/GanttChart.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Author: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var GanttChart_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();


var GanttChart_defaultOptions = Defaults.defaultOptions;

var GanttChart_isArray = Core_Utilities.isArray, GanttChart_merge = Core_Utilities.merge, GanttChart_splat = Core_Utilities.splat;
/* *
 *
 *  Class
 *
 * */
/**
 * Gantt-optimized chart. Use {@link Highcharts.Chart|Chart} for common charts.
 *
 * @requires modules/gantt
 *
 * @class
 * @name Highcharts.GanttChart
 * @extends Highcharts.Chart
 */
var GanttChart = /** @class */ (function (_super) {
    GanttChart_extends(GanttChart, _super);
    function GanttChart() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Initializes the chart. The constructor's arguments are passed on
     * directly.
     *
     * @function Highcharts.GanttChart#init
     *
     * @param {Highcharts.Options} userOptions
     *        Custom options.
     *
     * @param {Function} [callback]
     *        Function to run when the chart has loaded and all external
     *        images are loaded.
     *
     *
     * @emits Highcharts.GanttChart#event:init
     * @emits Highcharts.GanttChart#event:afterInit
     */
    GanttChart.prototype.init = function (userOptions, callback) {
        var xAxisOptions = userOptions.xAxis,
            yAxisOptions = userOptions.yAxis;
        var defaultLinkedTo;
        // Avoid doing these twice
        userOptions.xAxis = userOptions.yAxis = void 0;
        var options = GanttChart_merge(true, {
                chart: {
                    type: 'gantt'
                },
                title: {
                    text: ''
                },
                legend: {
                    enabled: false
                },
                navigator: {
                    series: { type: 'gantt' },
                    // Bars were clipped, #14060.
                    yAxis: {
                        type: 'category'
                    }
                }
            },
            userOptions, // User's options
            // forced options
            {
                isGantt: true
            });
        userOptions.xAxis = xAxisOptions;
        userOptions.yAxis = yAxisOptions;
        // Apply X axis options to both single and multi x axes If user hasn't
        // defined axes as array, make it into an array and add a second axis by
        // default.
        options.xAxis = (!GanttChart_isArray(userOptions.xAxis) ?
            [userOptions.xAxis || {}, {}] :
            userOptions.xAxis).map(function (xAxisOptions, i) {
            var _a,
                _b,
                _c;
            if (i === 1) { // Second xAxis
                defaultLinkedTo = 0;
            }
            return GanttChart_merge(
            // Defaults
            {
                grid: {
                    borderColor: "#cccccc" /* Palette.neutralColor20 */,
                    enabled: true
                },
                opposite: (_c = (_b = (_a = GanttChart_defaultOptions.xAxis) === null || _a === void 0 ? void 0 : _a.opposite) !== null && _b !== void 0 ? _b : xAxisOptions.opposite) !== null && _c !== void 0 ? _c : true,
                linkedTo: defaultLinkedTo
            }, 
            // User options
            xAxisOptions, 
            // Forced options
            {
                type: 'datetime'
            });
        });
        // Apply Y axis options to both single and multi y axes
        options.yAxis = (GanttChart_splat(userOptions.yAxis || {})).map(function (yAxisOptions) { return GanttChart_merge(
        // Defaults
        {
            grid: {
                borderColor: "#cccccc" /* Palette.neutralColor20 */,
                enabled: true
            },
            staticScale: 50,
            reversed: true,
            // Set default type treegrid, but only if 'categories' is
            // undefined
            type: yAxisOptions.categories ? yAxisOptions.type : 'treegrid'
        }, 
        // User options
        yAxisOptions); });
        _super.prototype.init.call(this, options, callback);
    };
    return GanttChart;
}(Chart_Chart));
/* *
 *
 *  Class Namespace
 *
 * */
(function (GanttChart) {
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable jsdoc/check-param-names */
    /**
     * The factory function for creating new gantt charts. Creates a new {@link
     * Highcharts.GanttChart|GanttChart} object with different default options
     * than the basic Chart.
     *
     * @example
     * // Render a chart in to div#container
     * let chart = Highcharts.ganttChart('container', {
     *     title: {
     *         text: 'My chart'
     *     },
     *     series: [{
     *         data: ...
     *     }]
     * });
     *
     * @function Highcharts.ganttChart
     *
     * @param {string|Highcharts.HTMLDOMElement} renderTo
     *        The DOM element to render to, or its id.
     *
     * @param {Highcharts.Options} options
     *        The chart options structure.
     *
     * @param {Highcharts.ChartCallbackFunction} [callback]
     *        Function to run when the chart has loaded and all external
     *        images are loaded. Defining a
     *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
     *        handler is equivalent.
     *
     * @return {Highcharts.GanttChart}
     *         Returns the Chart object.
     */
    function ganttChart(a, b, c) {
        return new GanttChart(a, b, c);
    }
    GanttChart.ganttChart = ganttChart;
    /* eslint-enable jsdoc/check-param-names */
})(GanttChart || (GanttChart = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Chart_GanttChart = (GanttChart);

;// ./code/es5/es-modules/Stock/Navigator/ChartNavigatorComposition.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var ChartNavigatorComposition_isTouchDevice = Core_Globals.isTouchDevice;

var ChartNavigatorComposition_addEvent = Core_Utilities.addEvent, ChartNavigatorComposition_merge = Core_Utilities.merge, ChartNavigatorComposition_pick = Core_Utilities.pick;
/* *
 *
 *  Constants
 *
 * */
var composedMembers = [];
/* *
 *
 *  Variables
 *
 * */
var NavigatorConstructor;
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function ChartNavigatorComposition_compose(ChartClass, NavigatorClass) {
    if (Core_Utilities.pushUnique(composedMembers, ChartClass)) {
        var chartProto = ChartClass.prototype;
        NavigatorConstructor = NavigatorClass;
        chartProto.callbacks.push(onChartCallback);
        ChartNavigatorComposition_addEvent(ChartClass, 'afterAddSeries', onChartAfterAddSeries);
        ChartNavigatorComposition_addEvent(ChartClass, 'afterSetChartSize', onChartAfterSetChartSize);
        ChartNavigatorComposition_addEvent(ChartClass, 'afterUpdate', onChartAfterUpdate);
        ChartNavigatorComposition_addEvent(ChartClass, 'beforeRender', onChartBeforeRender);
        ChartNavigatorComposition_addEvent(ChartClass, 'beforeShowResetZoom', onChartBeforeShowResetZoom);
        ChartNavigatorComposition_addEvent(ChartClass, 'update', onChartUpdate);
    }
}
/**
 * Handle adding new series.
 * @private
 */
function onChartAfterAddSeries() {
    if (this.navigator) {
        // Recompute which series should be shown in navigator, and add them
        this.navigator.setBaseSeries(null, false);
    }
}
/**
 * For stock charts, extend the Chart.setChartSize method so that we can set the
 * final top position of the navigator once the height of the chart, including
 * the legend, is determined. #367. We can't use Chart.getMargins, because
 * labels offsets are not calculated yet.
 * @private
 */
function onChartAfterSetChartSize() {
    var _a;
    var legend = this.legend,
        navigator = this.navigator;
    var legendOptions,
        xAxis,
        yAxis;
    if (navigator) {
        legendOptions = legend && legend.options;
        xAxis = navigator.xAxis;
        yAxis = navigator.yAxis;
        var scrollbarHeight = navigator.scrollbarHeight,
            scrollButtonSize = navigator.scrollButtonSize;
        // Compute the top position
        if (this.inverted) {
            navigator.left = navigator.opposite ?
                this.chartWidth - scrollbarHeight -
                    navigator.height :
                this.spacing[3] + scrollbarHeight;
            navigator.top = this.plotTop + scrollButtonSize;
        }
        else {
            navigator.left = ChartNavigatorComposition_pick(xAxis.left, this.plotLeft + scrollButtonSize);
            navigator.top = navigator.navigatorOptions.top ||
                this.chartHeight -
                    navigator.height -
                    scrollbarHeight -
                    (((_a = this.scrollbar) === null || _a === void 0 ? void 0 : _a.options.margin) || 0) -
                    this.spacing[2] -
                    (this.rangeSelector && this.extraBottomMargin ?
                        this.rangeSelector.getHeight() :
                        0) -
                    ((legendOptions &&
                        legendOptions.verticalAlign === 'bottom' &&
                        legendOptions.layout !== 'proximate' && // #13392
                        legendOptions.enabled &&
                        !legendOptions.floating) ?
                        legend.legendHeight +
                            ChartNavigatorComposition_pick(legendOptions.margin, 10) :
                        0) -
                    (this.titleOffset ? this.titleOffset[2] : 0);
        }
        if (xAxis && yAxis) { // False if navigator is disabled (#904)
            if (this.inverted) {
                xAxis.options.left = yAxis.options.left = navigator.left;
            }
            else {
                xAxis.options.top = yAxis.options.top = navigator.top;
            }
            xAxis.setAxisSize();
            yAxis.setAxisSize();
        }
    }
}
/**
 * Initialize navigator, if no scrolling exists yet.
 * @private
 */
function onChartAfterUpdate(event) {
    if (!this.navigator && !this.scroller &&
        (this.options.navigator.enabled ||
            this.options.scrollbar.enabled)) {
        this.scroller = this.navigator = new NavigatorConstructor(this);
        if (ChartNavigatorComposition_pick(event.redraw, true)) {
            this.redraw(event.animation); // #7067
        }
    }
}
/**
 * Initialize navigator for stock charts
 * @private
 */
function onChartBeforeRender() {
    var options = this.options;
    if (options.navigator.enabled ||
        options.scrollbar.enabled) {
        this.scroller = this.navigator = new NavigatorConstructor(this);
    }
}
/**
 * For Stock charts. For x only zooming, do not to create the zoom button
 * because X axis zooming is already allowed by the Navigator and Range
 * selector. (#9285)
 * @private
 */
function onChartBeforeShowResetZoom() {
    var chartOptions = this.options,
        navigator = chartOptions.navigator,
        rangeSelector = chartOptions.rangeSelector;
    if (((navigator && navigator.enabled) ||
        (rangeSelector && rangeSelector.enabled)) &&
        ((!ChartNavigatorComposition_isTouchDevice &&
            this.zooming.type === 'x') ||
            (ChartNavigatorComposition_isTouchDevice && this.zooming.pinchType === 'x'))) {
        return false;
    }
}
/**
 * @private
 */
function onChartCallback(chart) {
    var navigator = chart.navigator;
    // Initialize the navigator
    if (navigator && chart.xAxis[0]) {
        var extremes = chart.xAxis[0].getExtremes();
        navigator.render(extremes.min, extremes.max);
    }
}
/**
 * Merge options, if no scrolling exists yet
 * @private
 */
function onChartUpdate(e) {
    var navigatorOptions = (e.options.navigator || {}),
        scrollbarOptions = (e.options.scrollbar || {});
    if (!this.navigator && !this.scroller &&
        (navigatorOptions.enabled || scrollbarOptions.enabled)) {
        ChartNavigatorComposition_merge(true, this.options.navigator, navigatorOptions);
        ChartNavigatorComposition_merge(true, this.options.scrollbar, scrollbarOptions);
        delete e.options.navigator;
        delete e.options.scrollbar;
    }
}
/* *
 *
 *  Default Export
 *
 * */
var ChartNavigatorComposition = {
    compose: ChartNavigatorComposition_compose
};
/* harmony default export */ var Navigator_ChartNavigatorComposition = (ChartNavigatorComposition);

;// ./code/es5/es-modules/Core/Axis/NavigatorAxisComposition.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var NavigatorAxisComposition_isTouchDevice = Core_Globals.isTouchDevice;

var NavigatorAxisComposition_addEvent = Core_Utilities.addEvent, NavigatorAxisComposition_correctFloat = Core_Utilities.correctFloat, NavigatorAxisComposition_defined = Core_Utilities.defined, NavigatorAxisComposition_isNumber = Core_Utilities.isNumber, NavigatorAxisComposition_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function NavigatorAxisComposition_onAxisInit() {
    var axis = this;
    if (!axis.navigatorAxis) {
        axis.navigatorAxis = new NavigatorAxisAdditions(axis);
    }
}
/**
 * For Stock charts, override selection zooming with some special features
 * because X axis zooming is already allowed by the Navigator and Range
 * selector.
 * @private
 */
function onAxisSetExtremes(e) {
    var axis = this,
        chart = axis.chart,
        chartOptions = chart.options,
        navigator = chartOptions.navigator,
        navigatorAxis = axis.navigatorAxis,
        pinchType = chart.zooming.pinchType,
        rangeSelector = chartOptions.rangeSelector,
        zoomType = chart.zooming.type;
    var zoomed;
    if (axis.isXAxis &&
        ((navigator === null || navigator === void 0 ? void 0 : navigator.enabled) || (rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.enabled))) {
        // For y only zooming, ignore the X axis completely
        if (zoomType === 'y' && e.trigger === 'zoom') {
            zoomed = false;
            // For xy zooming, record the state of the zoom before zoom selection,
            // then when the reset button is pressed, revert to this state. This
            // should apply only if the chart is initialized with a range (#6612),
            // otherwise zoom all the way out.
        }
        else if (((e.trigger === 'zoom' && zoomType === 'xy') ||
            (NavigatorAxisComposition_isTouchDevice && pinchType === 'xy')) &&
            axis.options.range) {
            var previousZoom = navigatorAxis.previousZoom;
            // Minimum defined, zooming in
            if (NavigatorAxisComposition_defined(e.min)) {
                navigatorAxis.previousZoom = [axis.min, axis.max];
                // Minimum undefined, resetting zoom
            }
            else if (previousZoom) {
                e.min = previousZoom[0];
                e.max = previousZoom[1];
                navigatorAxis.previousZoom = void 0;
            }
        }
    }
    if (typeof zoomed !== 'undefined') {
        e.preventDefault();
    }
}
/* *
 *
 *  Class
 *
 * */
/**
 * @private
 * @class
 */
var NavigatorAxisAdditions = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function NavigatorAxisAdditions(axis) {
        this.axis = axis;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * @private
     */
    NavigatorAxisAdditions.compose = function (AxisClass) {
        if (!AxisClass.keepProps.includes('navigatorAxis')) {
            AxisClass.keepProps.push('navigatorAxis');
            NavigatorAxisComposition_addEvent(AxisClass, 'init', NavigatorAxisComposition_onAxisInit);
            NavigatorAxisComposition_addEvent(AxisClass, 'setExtremes', onAxisSetExtremes);
        }
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    NavigatorAxisAdditions.prototype.destroy = function () {
        this.axis = void 0;
    };
    /**
     * Add logic to normalize the zoomed range in order to preserve the pressed
     * state of range selector buttons
     *
     * @private
     * @function Highcharts.Axis#toFixedRange
     */
    NavigatorAxisAdditions.prototype.toFixedRange = function (pxMin, pxMax, fixedMin, fixedMax) {
        var axis = this.axis,
            halfPointRange = (axis.pointRange || 0) / 2;
        var newMin = NavigatorAxisComposition_pick(fixedMin,
            axis.translate(pxMin,
            true, !axis.horiz)),
            newMax = NavigatorAxisComposition_pick(fixedMax,
            axis.translate(pxMax,
            true, !axis.horiz));
        // Add/remove half point range to/from the extremes (#1172)
        if (!NavigatorAxisComposition_defined(fixedMin)) {
            newMin = NavigatorAxisComposition_correctFloat(newMin + halfPointRange);
        }
        if (!NavigatorAxisComposition_defined(fixedMax)) {
            newMax = NavigatorAxisComposition_correctFloat(newMax - halfPointRange);
        }
        if (!NavigatorAxisComposition_isNumber(newMin) || !NavigatorAxisComposition_isNumber(newMax)) { // #1195, #7411
            newMin = newMax = void 0;
        }
        return {
            min: newMin,
            max: newMax
        };
    };
    return NavigatorAxisAdditions;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var NavigatorAxisComposition = (NavigatorAxisAdditions);

;// ./code/es5/es-modules/Stock/Navigator/NavigatorDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var NavigatorDefaults_color = Color_Color.parse;

var NavigatorDefaults_seriesTypes = Series_SeriesRegistry.seriesTypes;
/* *
 *
 *  Constants
 *
 * */
/**
 * The navigator is a small series below the main series, displaying
 * a view of the entire data set. It provides tools to zoom in and
 * out on parts of the data as well as panning across the dataset.
 *
 * @product      highstock gantt
 * @optionparent navigator
 */
var NavigatorDefaults = {
    /**
     * Whether the navigator and scrollbar should adapt to updated data
     * in the base X axis. When loading data async, as in the demo below,
     * this should be `false`. Otherwise new data will trigger navigator
     * redraw, which will cause unwanted looping. In the demo below, the
     * data in the navigator is set only once. On navigating, only the main
     * chart content is updated.
     *
     * @sample {highstock} stock/demo/lazy-loading/
     *         Set to false with async data loading
     *
     * @type      {boolean}
     * @default   true
     * @apioption navigator.adaptToUpdatedData
     */
    /**
     * An integer identifying the index to use for the base series, or a
     * string representing the id of the series.
     *
     * **Note**: As of Highcharts 5.0, this is now a deprecated option.
     * Prefer [series.showInNavigator](#plotOptions.series.showInNavigator).
     *
     * @see [series.showInNavigator](#plotOptions.series.showInNavigator)
     *
     * @deprecated
     * @type      {number|string}
     * @default   0
     * @apioption navigator.baseSeries
     */
    /**
     * Enable or disable the navigator.
     *
     * @sample {highstock} stock/navigator/enabled/
     *         Disable the navigator
     *
     * @type      {boolean}
     * @default   true
     * @apioption navigator.enabled
     */
    /**
     * When the chart is inverted, whether to draw the navigator on the
     * opposite side.
     *
     * @type      {boolean}
     * @default   false
     * @since     5.0.8
     * @apioption navigator.opposite
     */
    /**
     * The height of the navigator.
     *
     * @sample {highstock} stock/navigator/height/
     *         A higher navigator
     */
    height: 40,
    /**
     * The distance from the nearest element, the X axis or X axis labels.
     *
     * @sample {highstock} stock/navigator/margin/
     *         A margin of 2 draws the navigator closer to the X axis labels
     */
    margin: 25,
    /**
     * Whether the mask should be inside the range marking the zoomed
     * range, or outside. In Highcharts Stock 1.x it was always `false`.
     *
     * @sample {highstock} stock/demo/maskinside-false/
     *         False, mask outside
     *
     * @since   2.0
     */
    maskInside: true,
    /**
     * Options for the handles for dragging the zoomed area.
     *
     * @sample {highstock} stock/navigator/handles/
     *         Colored handles
     */
    handles: {
        /**
         * Width for handles.
         *
         * @sample {highstock} stock/navigator/styled-handles/
         *         Styled handles
         *
         * @since   6.0.0
         */
        width: 7,
        /**
         * Border radius of the handles.
         *
         * @sample {highstock} stock/navigator/handles-border-radius/
         *      Border radius on the navigator handles.
         *
         * @since 11.4.2
         */
        borderRadius: 0,
        /**
         * Height for handles.
         *
         * @sample {highstock} stock/navigator/styled-handles/
         *         Styled handles
         *
         * @since   6.0.0
         */
        height: 15,
        /**
         * Array to define shapes of handles. 0-index for left, 1-index for
         * right.
         *
         * Additionally, the URL to a graphic can be given on this form:
         * `url(graphic.png)`. Note that for the image to be applied to
         * exported charts, its URL needs to be accessible by the export
         * server.
         *
         * Custom callbacks for symbol path generation can also be added to
         * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
         * used by its method name, as shown in the demo.
         *
         * @sample {highstock} stock/navigator/styled-handles/
         *         Styled handles
         *
         * @type    {Array<string>}
         * @default ["navigator-handle", "navigator-handle"]
         * @since   6.0.0
         */
        symbols: ['navigator-handle', 'navigator-handle'],
        /**
         * Allows to enable/disable handles.
         *
         * @since   6.0.0
         */
        enabled: true,
        /**
         * The width for the handle border and the stripes inside.
         *
         * @sample {highstock} stock/navigator/styled-handles/
         *         Styled handles
         *
         * @since     6.0.0
         * @apioption navigator.handles.lineWidth
         */
        lineWidth: 1,
        /**
         * The fill for the handle.
         *
         * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         */
        backgroundColor: "#f2f2f2" /* Palette.neutralColor5 */,
        /**
         * The stroke for the handle border and the stripes inside.
         *
         * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         */
        borderColor: "#999999" /* Palette.neutralColor40 */
    },
    /**
     * The color of the mask covering the areas of the navigator series
     * that are currently not visible in the main series. The default
     * color is bluish with an opacity of 0.3 to see the series below.
     *
     * @see In styled mode, the mask is styled with the
     *      `.highcharts-navigator-mask` and
     *      `.highcharts-navigator-mask-inside` classes.
     *
     * @sample {highstock} stock/navigator/maskfill/
     *         Blue, semi transparent mask
     *
     * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default rgba(102,133,194,0.3)
     */
    maskFill: NavigatorDefaults_color("#667aff" /* Palette.highlightColor60 */).setOpacity(0.3).get(),
    /**
     * The color of the line marking the currently zoomed area in the
     * navigator.
     *
     * @sample {highstock} stock/navigator/outline/
     *         2px blue outline
     *
     * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @default #cccccc
     */
    outlineColor: "#999999" /* Palette.neutralColor40 */,
    /**
     * The width of the line marking the currently zoomed area in the
     * navigator.
     *
     * @see In styled mode, the outline stroke width is set with the
     *      `.highcharts-navigator-outline` class.
     *
     * @sample {highstock} stock/navigator/outline/
     *         2px blue outline
     *
     * @type    {number}
     */
    outlineWidth: 1,
    /**
     * Options for the navigator series. Available options are the same
     * as any series, documented at [plotOptions](#plotOptions.series)
     * and [series](#series).
     *
     * Unless data is explicitly defined on navigator.series, the data
     * is borrowed from the first series in the chart.
     *
     * Default series options for the navigator series are:
     * ```js
     * series: {
     *     type: 'areaspline',
     *     fillOpacity: 0.05,
     *     dataGrouping: {
     *         smoothed: true
     *     },
     *     lineWidth: 1,
     *     marker: {
     *         enabled: false
     *     }
     * }
     * ```
     *
     * @see In styled mode, the navigator series is styled with the
     *      `.highcharts-navigator-series` class.
     *
     * @sample {highstock} stock/navigator/series-data/
     *         Using a separate data set for the navigator
     * @sample {highstock} stock/navigator/series/
     *         A green navigator series
     *
     * @type {*|Array<*>|Highcharts.SeriesOptionsType|Array<Highcharts.SeriesOptionsType>}
     */
    series: {
        /**
         * The type of the navigator series.
         *
         * Heads up:
         * In column-type navigator, zooming is limited to at least one
         * point with its `pointRange`.
         *
         * @sample {highstock} stock/navigator/column/
         *         Column type navigator
         *
         * @type    {string}
         * @default {highstock} `areaspline` if defined, otherwise `line`
         * @default {gantt} gantt
         */
        type: (typeof NavigatorDefaults_seriesTypes.areaspline === 'undefined' ?
            'line' :
            'areaspline'),
        /**
         * The fill opacity of the navigator series.
         */
        fillOpacity: 0.05,
        /**
         * The pixel line width of the navigator series.
         */
        lineWidth: 1,
        /**
         * @ignore-option
         */
        compare: null,
        /**
         * @ignore-option
         */
        sonification: {
            enabled: false
        },
        /**
         * Unless data is explicitly defined, the data is borrowed from the
         * first series in the chart.
         *
         * @type      {Array<number|Array<number|string|null>|object|null>}
         * @product   highstock
         * @apioption navigator.series.data
         */
        /**
         * Data grouping options for the navigator series.
         *
         * @extends plotOptions.series.dataGrouping
         */
        dataGrouping: {
            approximation: 'average',
            enabled: true,
            groupPixelWidth: 2,
            // Replace smoothed property by anchors, #12455.
            firstAnchor: 'firstPoint',
            anchor: 'middle',
            lastAnchor: 'lastPoint',
            // Day and week differs from plotOptions.series.dataGrouping
            units: [
                ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]],
                ['second', [1, 2, 5, 10, 15, 30]],
                ['minute', [1, 2, 5, 10, 15, 30]],
                ['hour', [1, 2, 3, 4, 6, 8, 12]],
                ['day', [1, 2, 3, 4]],
                ['week', [1, 2, 3]],
                ['month', [1, 3, 6]],
                ['year', null]
            ]
        },
        /**
         * Data label options for the navigator series. Data labels are
         * disabled by default on the navigator series.
         *
         * @extends plotOptions.series.dataLabels
         */
        dataLabels: {
            enabled: false,
            zIndex: 2 // #1839
        },
        id: 'highcharts-navigator-series',
        className: 'highcharts-navigator-series',
        /**
         * Sets the fill color of the navigator series.
         *
         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
         * @apioption navigator.series.color
         */
        /**
         * Line color for the navigator series. Allows setting the color
         * while disallowing the default candlestick setting.
         *
         * @type {Highcharts.ColorString|null}
         */
        lineColor: null, // #4602
        marker: {
            enabled: false
        },
        /**
         * Since Highcharts Stock v8, default value is the same as default
         * `pointRange` defined for a specific type (e.g. `null` for
         * column type).
         *
         * In Highcharts Stock version < 8, defaults to 0.
         *
         * @extends plotOptions.series.pointRange
         * @type {number|null}
         * @apioption navigator.series.pointRange
         */
        /**
         * The threshold option. Setting it to 0 will make the default
         * navigator area series draw its area from the 0 value and up.
         *
         * @type {number|null}
         */
        threshold: null
    },
    /**
     * Enable or disable navigator sticking to right, while adding new
     * points. If `undefined`, the navigator sticks to the axis maximum only
     * if it was already at the maximum prior to adding points.
     *
     * @type      {boolean}
     * @default   undefined
     * @since 10.2.1
     * @sample {highstock} stock/navigator/sticktomax-false/
     * stickToMax set to false
     * @apioption navigator.stickToMax
     */
    /**
     * Options for the navigator X axis. Default series options for the
     * navigator xAxis are:
     * ```js
     * xAxis: {
     *     tickWidth: 0,
     *     lineWidth: 0,
     *     gridLineWidth: 1,
     *     tickPixelInterval: 200,
     *     labels: {
     *            align: 'left',
     *         style: {
     *             color: '#888'
     *         },
     *         x: 3,
     *         y: -4
     *     }
     * }
     * ```
     *
     * @extends   xAxis
     * @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar,
     *            showEmpty, maxRange
     */
    xAxis: {
        /**
         * Additional range on the right side of the xAxis. Works similar to
         * `xAxis.maxPadding`, but the value is set in terms of axis values,
         * percentage or pixels.
         *
         * If it's a number, it is interpreted as axis values, which in a
         * datetime axis equals milliseconds.
         *
         * If it's a percentage string, is interpreted as percentages of the
         * axis length. An overscroll of 50% will make a 100px axis 50px longer.
         *
         * If it's a pixel string, it is interpreted as a fixed pixel value, but
         * limited to 90% of the axis length.
         *
         * If it's undefined, the value is inherited from `xAxis.overscroll`.
         *
         * Can be set for both, main xAxis and navigator's xAxis.
         *
         * @type    {number | string | undefined}
         * @since   6.0.0
         * @apioption navigator.xAxis.overscroll
         */
        className: 'highcharts-navigator-xaxis',
        tickLength: 0,
        lineWidth: 0,
        gridLineColor: "#e6e6e6" /* Palette.neutralColor10 */,
        id: 'navigator-x-axis',
        gridLineWidth: 1,
        tickPixelInterval: 200,
        labels: {
            align: 'left',
            /**
             * @type {Highcharts.CSSObject}
             */
            style: {
                /** @ignore */
                color: "#000000" /* Palette.neutralColor100 */,
                /** @ignore */
                fontSize: '0.7em',
                /** @ignore */
                opacity: 0.6,
                /** @ignore */
                textOutline: '2px contrast'
            },
            x: 3,
            y: -4
        },
        crosshair: false
    },
    /**
     * Options for the navigator Y axis. Default series options for the
     * navigator yAxis are:
     * ```js
     * yAxis: {
     *     gridLineWidth: 0,
     *     startOnTick: false,
     *     endOnTick: false,
     *     minPadding: 0.1,
     *     maxPadding: 0.1,
     *     labels: {
     *         enabled: false
     *     },
     *     title: {
     *         text: null
     *     },
     *     tickWidth: 0
     * }
     * ```
     *
     * @extends   yAxis
     * @excluding height, linkedTo, maxZoom, minRange, ordinal, range,
     *            showEmpty, scrollbar, top, units, maxRange, minLength,
     *            maxLength, resize
     */
    yAxis: {
        className: 'highcharts-navigator-yaxis',
        gridLineWidth: 0,
        startOnTick: false,
        endOnTick: false,
        minPadding: 0.1,
        id: 'navigator-y-axis',
        maxPadding: 0.1,
        labels: {
            enabled: false
        },
        crosshair: false,
        title: {
            text: null
        },
        tickLength: 0,
        tickWidth: 0
    }
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Navigator_NavigatorDefaults = (NavigatorDefaults);
/* *
 *
 *  API Options
 *
 * */
/**
 * Maximum range which can be set using the navigator's handles.
 * Opposite of [xAxis.minRange](#xAxis.minRange).
 *
 * @sample {highstock} stock/navigator/maxrange/
 *         Defined max and min range
 *
 * @type      {number}
 * @since     6.0.0
 * @product   highstock gantt
 * @apioption xAxis.maxRange
 */
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Stock/Navigator/NavigatorSymbols.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var NavigatorSymbols_spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};


var NavigatorSymbols_relativeLength = Core_Utilities.relativeLength;
/* *
 *
 *  Constants
 *
 * */
/**
 * Draw one of the handles on the side of the zoomed range in the navigator.
 * @private
 */
function navigatorHandle(_x, _y, width, height, options) {
    if (options === void 0) { options = {}; }
    var halfWidth = options.width ? options.width / 2 : width,
        markerPosition = 1.5,
        r = NavigatorSymbols_relativeLength(options.borderRadius || 0,
        Math.min(halfWidth * 2,
        height));
    height = options.height || height;
    return NavigatorSymbols_spreadArray([
        ['M', -markerPosition, height / 2 - 3.5],
        ['L', -markerPosition, height / 2 + 4.5],
        ['M', markerPosition - 1, height / 2 - 3.5],
        ['L', markerPosition - 1, height / 2 + 4.5]
    ], SVG_Symbols.rect(-halfWidth - 1, 0.5, halfWidth * 2 + 1, height, { r: r }), true);
}
/* *
 *
 *  Default Export
 *
 * */
var NavigatorSymbols = {
    'navigator-handle': navigatorHandle
};
/* harmony default export */ var Navigator_NavigatorSymbols = (NavigatorSymbols);

;// ./code/es5/es-modules/Stock/Utilities/StockUtilities.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var StockUtilities_defined = Core_Utilities.defined;
/* *
 *
 *  Functions
 *
 * */
/**
 * Sets the chart.fixedRange to the specified value. If the value is larger
 * than actual range, sets it to the maximum possible range. (#20327)
 *
 * @private
 * @function Highcharts.StockChart#setFixedRange
 * @param {number|undefined} range
 *        Range to set in axis units.
 */
function setFixedRange(range) {
    var xAxis = this.xAxis[0];
    if (StockUtilities_defined(xAxis.dataMax) &&
        StockUtilities_defined(xAxis.dataMin) &&
        range) {
        this.fixedRange = Math.min(range, xAxis.dataMax - xAxis.dataMin);
    }
    else {
        this.fixedRange = range;
    }
}
var StockUtilities = {
    setFixedRange: setFixedRange
};
/* harmony default export */ var Utilities_StockUtilities = (StockUtilities);

;// ./code/es5/es-modules/Stock/Navigator/NavigatorComposition.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var NavigatorComposition_setOptions = Defaults.setOptions;

var NavigatorComposition_composed = Core_Globals.composed;




var getRendererType = Renderer_RendererRegistry.getRendererType;

var NavigatorComposition_setFixedRange = Utilities_StockUtilities.setFixedRange;

var NavigatorComposition_addEvent = Core_Utilities.addEvent, NavigatorComposition_extend = Core_Utilities.extend, NavigatorComposition_pushUnique = Core_Utilities.pushUnique;
/* *
 *
 *  Variables
 *
 * */
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function NavigatorComposition_compose(ChartClass, AxisClass, SeriesClass) {
    NavigatorAxisComposition.compose(AxisClass);
    if (NavigatorComposition_pushUnique(NavigatorComposition_composed, 'Navigator')) {
        ChartClass.prototype.setFixedRange = NavigatorComposition_setFixedRange;
        NavigatorComposition_extend(getRendererType().prototype.symbols, Navigator_NavigatorSymbols);
        NavigatorComposition_addEvent(SeriesClass, 'afterUpdate', onSeriesAfterUpdate);
        NavigatorComposition_setOptions({ navigator: Navigator_NavigatorDefaults });
    }
}
/**
 * Handle updating series
 * @private
 */
function onSeriesAfterUpdate() {
    if (this.chart.navigator && !this.options.isInternal) {
        this.chart.navigator.setBaseSeries(null, false);
    }
}
/* *
 *
 *  Default Export
 *
 * */
var NavigatorComposition = {
    compose: NavigatorComposition_compose
};
/* harmony default export */ var Navigator_NavigatorComposition = (NavigatorComposition);

;// ./code/es5/es-modules/Core/Axis/ScrollbarAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var ScrollbarAxis_composed = Core_Globals.composed;

var ScrollbarAxis_addEvent = Core_Utilities.addEvent, ScrollbarAxis_defined = Core_Utilities.defined, ScrollbarAxis_pick = Core_Utilities.pick, ScrollbarAxis_pushUnique = Core_Utilities.pushUnique;
/* *
 *
 *  Composition
 *
 * */
var ScrollbarAxis;
(function (ScrollbarAxis) {
    /* *
     *
     *  Variables
     *
     * */
    var Scrollbar;
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Attaches to axis events to create scrollbars if enabled.
     *
     * @private
     *
     * @param {Highcharts.Axis} AxisClass
     * Axis class to extend.
     *
     * @param {Highcharts.Scrollbar} ScrollbarClass
     * Scrollbar class to use.
     */
    function compose(AxisClass, ScrollbarClass) {
        if (ScrollbarAxis_pushUnique(ScrollbarAxis_composed, 'Axis.Scrollbar')) {
            Scrollbar = ScrollbarClass;
            ScrollbarAxis_addEvent(AxisClass, 'afterGetOffset', onAxisAfterGetOffset);
            ScrollbarAxis_addEvent(AxisClass, 'afterInit', onAxisAfterInit);
            ScrollbarAxis_addEvent(AxisClass, 'afterRender', onAxisAfterRender);
        }
    }
    ScrollbarAxis.compose = compose;
    /** @private */
    function getExtremes(axis) {
        var axisMin = ScrollbarAxis_pick(axis.options && axis.options.min,
            axis.min);
        var axisMax = ScrollbarAxis_pick(axis.options && axis.options.max,
            axis.max);
        return {
            axisMin: axisMin,
            axisMax: axisMax,
            scrollMin: ScrollbarAxis_defined(axis.dataMin) ?
                Math.min(axisMin, axis.min, axis.dataMin, ScrollbarAxis_pick(axis.threshold, Infinity)) : axisMin,
            scrollMax: ScrollbarAxis_defined(axis.dataMax) ?
                Math.max(axisMax, axis.max, axis.dataMax, ScrollbarAxis_pick(axis.threshold, -Infinity)) : axisMax
        };
    }
    /**
     * Make space for a scrollbar.
     * @private
     */
    function onAxisAfterGetOffset() {
        var axis = this,
            scrollbar = axis.scrollbar,
            opposite = scrollbar && !scrollbar.options.opposite,
            index = axis.horiz ? 2 : opposite ? 3 : 1;
        if (scrollbar) {
            // Reset scrollbars offsets
            axis.chart.scrollbarsOffsets = [0, 0];
            axis.chart.axisOffset[index] +=
                scrollbar.size + (scrollbar.options.margin || 0);
        }
    }
    /**
     * Wrap axis initialization and create scrollbar if enabled.
     * @private
     */
    function onAxisAfterInit() {
        var axis = this;
        if (axis.options &&
            axis.options.scrollbar &&
            axis.options.scrollbar.enabled) {
            // Predefined options:
            axis.options.scrollbar.vertical = !axis.horiz;
            axis.options.startOnTick = axis.options.endOnTick = false;
            axis.scrollbar = new Scrollbar(axis.chart.renderer, axis.options.scrollbar, axis.chart);
            ScrollbarAxis_addEvent(axis.scrollbar, 'changed', function (e) {
                var _a = getExtremes(axis),
                    axisMin = _a.axisMin,
                    axisMax = _a.axisMax,
                    unitedMin = _a.scrollMin,
                    unitedMax = _a.scrollMax,
                    range = unitedMax - unitedMin;
                var to,
                    from;
                // #12834, scroll when show/hide series, wrong extremes
                if (!ScrollbarAxis_defined(axisMin) || !ScrollbarAxis_defined(axisMax)) {
                    return;
                }
                if ((axis.horiz && !axis.reversed) ||
                    (!axis.horiz && axis.reversed)) {
                    to = unitedMin + range * this.to;
                    from = unitedMin + range * this.from;
                }
                else {
                    // Y-values in browser are reversed, but this also
                    // applies for reversed horizontal axis:
                    to = unitedMin + range * (1 - this.from);
                    from = unitedMin + range * (1 - this.to);
                }
                if (this.shouldUpdateExtremes(e.DOMType)) {
                    // #17977, set animation to undefined instead of true
                    var animate = e.DOMType === 'mousemove' ||
                            e.DOMType === 'touchmove' ? false : void 0;
                    axis.setExtremes(from, to, true, animate, e);
                }
                else {
                    // When live redraw is disabled, don't change extremes
                    // Only change the position of the scrollbar thumb
                    this.setRange(this.from, this.to);
                }
            });
        }
    }
    /**
     * Wrap rendering axis, and update scrollbar if one is created.
     * @private
     */
    function onAxisAfterRender() {
        var axis = this,
            _a = getExtremes(axis),
            scrollMin = _a.scrollMin,
            scrollMax = _a.scrollMax,
            scrollbar = axis.scrollbar,
            offset = (axis.axisTitleMargin + (axis.titleOffset || 0)),
            scrollbarsOffsets = axis.chart.scrollbarsOffsets,
            axisMargin = axis.options.margin || 0;
        var offsetsIndex,
            from,
            to;
        if (scrollbar && scrollbarsOffsets) {
            if (axis.horiz) {
                // Reserve space for labels/title
                if (!axis.opposite) {
                    scrollbarsOffsets[1] += offset;
                }
                scrollbar.position(axis.left, (axis.top +
                    axis.height +
                    2 +
                    scrollbarsOffsets[1] -
                    (axis.opposite ? axisMargin : 0)), axis.width, axis.height);
                // Next scrollbar should reserve space for margin (if set)
                if (!axis.opposite) {
                    scrollbarsOffsets[1] += axisMargin;
                }
                offsetsIndex = 1;
            }
            else {
                // Reserve space for labels/title
                if (axis.opposite) {
                    scrollbarsOffsets[0] += offset;
                }
                var xPosition = void 0;
                if (!scrollbar.options.opposite) {
                    xPosition = axis.opposite ? 0 : axisMargin;
                }
                else {
                    xPosition = axis.left +
                        axis.width +
                        2 +
                        scrollbarsOffsets[0] -
                        (axis.opposite ? 0 : axisMargin);
                }
                scrollbar.position(xPosition, axis.top, axis.width, axis.height);
                // Next scrollbar should reserve space for margin (if set)
                if (axis.opposite) {
                    scrollbarsOffsets[0] += axisMargin;
                }
                offsetsIndex = 0;
            }
            scrollbarsOffsets[offsetsIndex] += scrollbar.size +
                (scrollbar.options.margin || 0);
            if (isNaN(scrollMin) ||
                isNaN(scrollMax) ||
                !ScrollbarAxis_defined(axis.min) ||
                !ScrollbarAxis_defined(axis.max) ||
                axis.dataMin === axis.dataMax // #10733
            ) {
                // Default action: when data extremes are the same or there is
                // not extremes on the axis, but scrollbar exists, make it
                // full size
                scrollbar.setRange(0, 1);
            }
            else if (axis.min === axis.max) { // #20359
                // When the extremes are the same, set the scrollbar to a point
                // within the extremes range. Utilize pointRange to perform the
                // calculations. (#20359)
                var interval = axis.pointRange / (axis.dataMax +
                        1);
                from = interval * axis.min;
                to = interval * (axis.max + 1);
                scrollbar.setRange(from, to);
            }
            else {
                from = ((axis.min - scrollMin) /
                    (scrollMax - scrollMin));
                to = ((axis.max - scrollMin) /
                    (scrollMax - scrollMin));
                if ((axis.horiz && !axis.reversed) ||
                    (!axis.horiz && axis.reversed)) {
                    scrollbar.setRange(from, to);
                }
                else {
                    // Inverse vertical axis
                    scrollbar.setRange(1 - to, 1 - from);
                }
            }
        }
    }
})(ScrollbarAxis || (ScrollbarAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_ScrollbarAxis = (ScrollbarAxis);

;// ./code/es5/es-modules/Stock/Scrollbar/ScrollbarDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Constant
 *
 * */
/**
 *
 * The scrollbar is a means of panning over the X axis of a stock chart.
 * Scrollbars can also be applied to other types of axes.
 *
 * Another approach to scrollable charts is the [chart.scrollablePlotArea](
 * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that
 * is especially suitable for simpler cartesian charts on mobile.
 *
 * In styled mode, all the presentational options for the
 * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`,
 * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
 * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
 *
 * @sample stock/yaxis/inverted-bar-scrollbar/
 *         A scrollbar on a simple bar chart
 *
 * @product highstock gantt
 * @optionparent scrollbar
 *
 * @private
 */
var ScrollbarDefaults = {
    /**
     * The height of the scrollbar. If `buttonsEnabled` is true , the height
     * also applies to the width of the scroll arrows so that they are always
     * squares.
     *
     * @sample stock/scrollbar/style/
     *         Non-default height
     *
     * @type    {number}
     */
    height: 10,
    /**
     * The border rounding radius of the bar.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    barBorderRadius: 5,
    /**
     * The corner radius of the scrollbar buttons.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    buttonBorderRadius: 0,
    /**
     * Enable or disable the buttons at the end of the scrollbar.
     *
     * @since 11.0.0
     */
    buttonsEnabled: false,
    /**
     * Enable or disable the scrollbar.
     *
     * @sample stock/scrollbar/enabled/
     *         Disable the scrollbar, only use navigator
     *
     * @type      {boolean}
     * @default   true
     * @apioption scrollbar.enabled
     */
    /**
     * Whether to redraw the main chart as the scrollbar or the navigator
     * zoomed window is moved. Defaults to `true` for modern browsers and
     * `false` for legacy IE browsers as well as mobile devices.
     *
     * @sample stock/scrollbar/liveredraw
     *         Setting live redraw to false
     *
     * @type  {boolean}
     * @since 1.3
     */
    liveRedraw: void 0,
    /**
     * The margin between the scrollbar and its axis when the scrollbar is
     * applied directly to an axis, or the navigator in case that is enabled.
     * Defaults to 10 for axis, 0 for navigator.
     *
     * @type {number|undefined}
     */
    margin: void 0,
    /**
     * The minimum width of the scrollbar.
     *
     * @since 1.2.5
     */
    minWidth: 6,
    /** @ignore-option */
    opposite: true,
    /**
     * Whether to show or hide the scrollbar when the scrolled content is
     * zoomed out to it full extent.
     *
     * @type      {boolean}
     * @default   true
     * @apioption scrollbar.showFull
     */
    step: 0.2,
    /**
     * The z index of the scrollbar group.
     */
    zIndex: 3,
    /**
     * The background color of the scrollbar itself.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    barBackgroundColor: "#cccccc" /* Palette.neutralColor20 */,
    /**
     * The width of the bar's border.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    barBorderWidth: 0,
    /**
     * The color of the scrollbar's border.
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    barBorderColor: "#cccccc" /* Palette.neutralColor20 */,
    /**
     * The color of the small arrow inside the scrollbar buttons.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    buttonArrowColor: "#333333" /* Palette.neutralColor80 */,
    /**
     * The color of scrollbar buttons.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    buttonBackgroundColor: "#e6e6e6" /* Palette.neutralColor10 */,
    /**
     * The color of the border of the scrollbar buttons.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    buttonBorderColor: "#cccccc" /* Palette.neutralColor20 */,
    /**
     * The border width of the scrollbar buttons.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    buttonBorderWidth: 1,
    /**
     * The color of the small rifles in the middle of the scrollbar.
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    rifleColor: 'none',
    /**
     * The color of the track background.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    trackBackgroundColor: 'rgba(255, 255, 255, 0.001)', // #18922
    /**
     * The color of the border of the scrollbar track.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     *
     * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     */
    trackBorderColor: "#cccccc" /* Palette.neutralColor20 */,
    /**
     * The corner radius of the border of the scrollbar track.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    trackBorderRadius: 5,
    /**
     * The width of the border of the scrollbar track.
     *
     * @sample stock/scrollbar/style/
     *         Scrollbar styling
     */
    trackBorderWidth: 1
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Scrollbar_ScrollbarDefaults = (ScrollbarDefaults);

;// ./code/es5/es-modules/Stock/Scrollbar/Scrollbar.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var Scrollbar_defaultOptions = Defaults.defaultOptions;




var Scrollbar_addEvent = Core_Utilities.addEvent, Scrollbar_correctFloat = Core_Utilities.correctFloat, Scrollbar_crisp = Core_Utilities.crisp, Scrollbar_defined = Core_Utilities.defined, Scrollbar_destroyObjectProperties = Core_Utilities.destroyObjectProperties, Scrollbar_fireEvent = Core_Utilities.fireEvent, Scrollbar_merge = Core_Utilities.merge, Scrollbar_pick = Core_Utilities.pick, Scrollbar_removeEvent = Core_Utilities.removeEvent;
/* *
 *
 *  Constants
 *
 * */
/* eslint-disable no-invalid-this, valid-jsdoc */
/**
 * A reusable scrollbar, internally used in Highcharts Stock's
 * navigator and optionally on individual axes.
 *
 * @private
 * @class
 * @name Highcharts.Scrollbar
 * @param {Highcharts.SVGRenderer} renderer
 * @param {Highcharts.ScrollbarOptions} options
 * @param {Highcharts.Chart} chart
 */
var Scrollbar = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    function Scrollbar(renderer, options, chart) {
        /* *
         *
         *  Properties
         *
         * */
        this._events = [];
        this.chartX = 0;
        this.chartY = 0;
        this.from = 0;
        this.scrollbarButtons = [];
        this.scrollbarLeft = 0;
        this.scrollbarStrokeWidth = 1;
        this.scrollbarTop = 0;
        this.size = 0;
        this.to = 0;
        this.trackBorderWidth = 1;
        this.x = 0;
        this.y = 0;
        this.init(renderer, options, chart);
    }
    /* *
     *
     *  Static Functions
     *
     * */
    Scrollbar.compose = function (AxisClass) {
        Axis_ScrollbarAxis.compose(AxisClass, Scrollbar);
    };
    /**
     * When we have vertical scrollbar, rifles and arrow in buttons should be
     * rotated. The same method is used in Navigator's handles, to rotate them.
     *
     * @function Highcharts.swapXY
     *
     * @param {Highcharts.SVGPathArray} path
     * Path to be rotated.
     *
     * @param {boolean} [vertical]
     * If vertical scrollbar, swap x-y values.
     *
     * @return {Highcharts.SVGPathArray}
     * Rotated path.
     *
     * @requires modules/stock
     */
    Scrollbar.swapXY = function (path, vertical) {
        if (vertical) {
            path.forEach(function (seg) {
                var len = seg.length;
                var temp;
                for (var i = 0; i < len; i += 2) {
                    temp = seg[i + 1];
                    if (typeof temp === 'number') {
                        seg[i + 1] = seg[i + 2];
                        seg[i + 2] = temp;
                    }
                }
            });
        }
        return path;
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Set up the mouse and touch events for the Scrollbar
     *
     * @private
     * @function Highcharts.Scrollbar#addEvents
     */
    Scrollbar.prototype.addEvents = function () {
        var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1],
            buttons = this.scrollbarButtons,
            bar = this.scrollbarGroup.element,
            track = this.track.element,
            mouseDownHandler = this.mouseDownHandler.bind(this),
            mouseMoveHandler = this.mouseMoveHandler.bind(this),
            mouseUpHandler = this.mouseUpHandler.bind(this);
        var _events = [
                // Mouse events
                [
                    buttons[buttonsOrder[0]].element,
                    'click',
                    this.buttonToMinClick.bind(this)
                ],
                [
                    buttons[buttonsOrder[1]].element,
                    'click',
                    this.buttonToMaxClick.bind(this)
                ],
                [track, 'click',
            this.trackClick.bind(this)],
                [bar, 'mousedown',
            mouseDownHandler],
                [bar.ownerDocument, 'mousemove',
            mouseMoveHandler],
                [bar.ownerDocument, 'mouseup',
            mouseUpHandler],
                // Touch events
                [bar, 'touchstart',
            mouseDownHandler],
                [bar.ownerDocument, 'touchmove',
            mouseMoveHandler],
                [bar.ownerDocument, 'touchend',
            mouseUpHandler]
            ];
        // Add them all
        _events.forEach(function (args) {
            Scrollbar_addEvent.apply(null, args);
        });
        this._events = _events;
    };
    Scrollbar.prototype.buttonToMaxClick = function (e) {
        var scroller = this;
        var range = ((scroller.to - scroller.from) *
                Scrollbar_pick(scroller.options.step, 0.2));
        scroller.updatePosition(scroller.from + range, scroller.to + range);
        Scrollbar_fireEvent(scroller, 'changed', {
            from: scroller.from,
            to: scroller.to,
            trigger: 'scrollbar',
            DOMEvent: e
        });
    };
    Scrollbar.prototype.buttonToMinClick = function (e) {
        var scroller = this;
        var range = Scrollbar_correctFloat(scroller.to - scroller.from) *
                Scrollbar_pick(scroller.options.step, 0.2);
        scroller.updatePosition(Scrollbar_correctFloat(scroller.from - range), Scrollbar_correctFloat(scroller.to - range));
        Scrollbar_fireEvent(scroller, 'changed', {
            from: scroller.from,
            to: scroller.to,
            trigger: 'scrollbar',
            DOMEvent: e
        });
    };
    /**
     * Get normalized (0-1) cursor position over the scrollbar
     *
     * @private
     * @function Highcharts.Scrollbar#cursorToScrollbarPosition
     *
     * @param  {*} normalizedEvent
     *         normalized event, with chartX and chartY values
     *
     * @return {Highcharts.Dictionary<number>}
     *         Local position {chartX, chartY}
     */
    Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) {
        var scroller = this,
            options = scroller.options,
            minWidthDifference = options.minWidth > scroller.calculatedWidth ?
                options.minWidth :
                0; // `minWidth` distorts translation
            return {
                chartX: (normalizedEvent.chartX - scroller.x -
                    scroller.xOffset) /
                    (scroller.barWidth - minWidthDifference),
                chartY: (normalizedEvent.chartY - scroller.y -
                    scroller.yOffset) /
                    (scroller.barWidth - minWidthDifference)
            };
    };
    /**
     * Destroys allocated elements.
     *
     * @private
     * @function Highcharts.Scrollbar#destroy
     */
    Scrollbar.prototype.destroy = function () {
        var scroller = this,
            navigator = scroller.chart.scroller;
        // Disconnect events added in addEvents
        scroller.removeEvents();
        // Destroy properties
        [
            'track',
            'scrollbarRifles',
            'scrollbar',
            'scrollbarGroup',
            'group'
        ].forEach(function (prop) {
            if (scroller[prop] && scroller[prop].destroy) {
                scroller[prop] = scroller[prop].destroy();
            }
        });
        // #6421, chart may have more scrollbars
        if (navigator && scroller === navigator.scrollbar) {
            navigator.scrollbar = null;
            // Destroy elements in collection
            Scrollbar_destroyObjectProperties(navigator.scrollbarButtons);
        }
    };
    /**
     * Draw the scrollbar buttons with arrows
     *
     * @private
     * @function Highcharts.Scrollbar#drawScrollbarButton
     * @param {number} index
     *        0 is left, 1 is right
     */
    Scrollbar.prototype.drawScrollbarButton = function (index) {
        var scroller = this,
            renderer = scroller.renderer,
            scrollbarButtons = scroller.scrollbarButtons,
            options = scroller.options,
            size = scroller.size,
            group = renderer.g().add(scroller.group);
        scrollbarButtons.push(group);
        if (options.buttonsEnabled) {
            // Create a rectangle for the scrollbar button
            var rect = renderer.rect()
                    .addClass('highcharts-scrollbar-button')
                    .add(group);
            // Presentational attributes
            if (!scroller.chart.styledMode) {
                rect.attr({
                    stroke: options.buttonBorderColor,
                    'stroke-width': options.buttonBorderWidth,
                    fill: options.buttonBackgroundColor
                });
            }
            // Place the rectangle based on the rendered stroke width
            rect.attr(rect.crisp({
                x: -0.5,
                y: -0.5,
                width: size,
                height: size,
                r: options.buttonBorderRadius
            }, rect.strokeWidth()));
            // Button arrow
            var arrow = renderer
                    .path(Scrollbar.swapXY([[
                        'M',
                        size / 2 + (index ? -1 : 1),
                        size / 2 - 3
                    ],
                [
                        'L',
                        size / 2 + (index ? -1 : 1),
                        size / 2 + 3
                    ],
                [
                        'L',
                        size / 2 + (index ? 2 : -2),
                        size / 2
                    ]],
                options.vertical))
                    .addClass('highcharts-scrollbar-arrow')
                    .add(scrollbarButtons[index]);
            if (!scroller.chart.styledMode) {
                arrow.attr({
                    fill: options.buttonArrowColor
                });
            }
        }
    };
    /**
     * @private
     * @function Highcharts.Scrollbar#init
     * @param {Highcharts.SVGRenderer} renderer
     * @param {Highcharts.ScrollbarOptions} options
     * @param {Highcharts.Chart} chart
     */
    Scrollbar.prototype.init = function (renderer, options, chart) {
        var scroller = this;
        scroller.scrollbarButtons = [];
        scroller.renderer = renderer;
        scroller.userOptions = options;
        scroller.options = Scrollbar_merge(Scrollbar_ScrollbarDefaults, Scrollbar_defaultOptions.scrollbar, options);
        scroller.options.margin = Scrollbar_pick(scroller.options.margin, 10);
        scroller.chart = chart;
        // Backward compatibility
        scroller.size = Scrollbar_pick(scroller.options.size, scroller.options.height);
        // Init
        if (options.enabled) {
            scroller.render();
            scroller.addEvents();
        }
    };
    Scrollbar.prototype.mouseDownHandler = function (e) {
        var _a;
        var scroller = this,
            normalizedEvent = ((_a = scroller.chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e,
            mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent);
        scroller.chartX = mousePosition.chartX;
        scroller.chartY = mousePosition.chartY;
        scroller.initPositions = [scroller.from, scroller.to];
        scroller.grabbedCenter = true;
    };
    /**
     * Event handler for the mouse move event.
     * @private
     */
    Scrollbar.prototype.mouseMoveHandler = function (e) {
        var _a;
        var scroller = this,
            normalizedEvent = ((_a = scroller.chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e,
            options = scroller.options,
            direction = options.vertical ?
                'chartY' : 'chartX',
            initPositions = scroller.initPositions || [];
        var scrollPosition,
            chartPosition,
            change;
        // In iOS, a mousemove event with e.pageX === 0 is fired when
        // holding the finger down in the center of the scrollbar. This
        // should be ignored.
        if (scroller.grabbedCenter &&
            // #4696, scrollbar failed on Android
            (!e.touches || e.touches[0][direction] !== 0)) {
            chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction];
            scrollPosition = scroller[direction];
            change = chartPosition - scrollPosition;
            scroller.hasDragged = true;
            scroller.updatePosition(initPositions[0] + change, initPositions[1] + change);
            if (scroller.hasDragged) {
                Scrollbar_fireEvent(scroller, 'changed', {
                    from: scroller.from,
                    to: scroller.to,
                    trigger: 'scrollbar',
                    DOMType: e.type,
                    DOMEvent: e
                });
            }
        }
    };
    /**
     * Event handler for the mouse up event.
     * @private
     */
    Scrollbar.prototype.mouseUpHandler = function (e) {
        var scroller = this;
        if (scroller.hasDragged) {
            Scrollbar_fireEvent(scroller, 'changed', {
                from: scroller.from,
                to: scroller.to,
                trigger: 'scrollbar',
                DOMType: e.type,
                DOMEvent: e
            });
        }
        scroller.grabbedCenter =
            scroller.hasDragged =
                scroller.chartX =
                    scroller.chartY = null;
    };
    /**
     * Position the scrollbar, method called from a parent with defined
     * dimensions.
     *
     * @private
     * @function Highcharts.Scrollbar#position
     * @param {number} x
     *        x-position on the chart
     * @param {number} y
     *        y-position on the chart
     * @param {number} width
     *        width of the scrollbar
     * @param {number} height
     *        height of the scrollbar
     */
    Scrollbar.prototype.position = function (x, y, width, height) {
        var scroller = this,
            options = scroller.options,
            buttonsEnabled = options.buttonsEnabled,
            _a = options.margin,
            margin = _a === void 0 ? 0 : _a,
            vertical = options.vertical,
            method = scroller.rendered ? 'animate' : 'attr';
        var xOffset = height,
            yOffset = 0;
        // Make the scrollbar visible when it is repositioned, #15763.
        scroller.group.show();
        scroller.x = x;
        scroller.y = y + this.trackBorderWidth;
        scroller.width = width; // Width with buttons
        scroller.height = height;
        scroller.xOffset = xOffset;
        scroller.yOffset = yOffset;
        // If Scrollbar is a vertical type, swap options:
        if (vertical) {
            scroller.width = scroller.yOffset = width = yOffset = scroller.size;
            scroller.xOffset = xOffset = 0;
            scroller.yOffset = yOffset = buttonsEnabled ? scroller.size : 0;
            // Width without buttons
            scroller.barWidth = height - (buttonsEnabled ? width * 2 : 0);
            scroller.x = x = x + margin;
        }
        else {
            scroller.height = height = scroller.size;
            scroller.xOffset = xOffset = buttonsEnabled ? scroller.size : 0;
            // Width without buttons
            scroller.barWidth = width - (buttonsEnabled ? height * 2 : 0);
            scroller.y = scroller.y + margin;
        }
        // Set general position for a group:
        scroller.group[method]({
            translateX: x,
            translateY: scroller.y
        });
        // Resize background/track:
        scroller.track[method]({
            width: width,
            height: height
        });
        // Move right/bottom button to its place:
        scroller.scrollbarButtons[1][method]({
            translateX: vertical ? 0 : width - xOffset,
            translateY: vertical ? height - yOffset : 0
        });
    };
    /**
     * Removes the event handlers attached previously with addEvents.
     *
     * @private
     * @function Highcharts.Scrollbar#removeEvents
     */
    Scrollbar.prototype.removeEvents = function () {
        this._events.forEach(function (args) {
            Scrollbar_removeEvent.apply(null, args);
        });
        this._events.length = 0;
    };
    /**
     * Render scrollbar with all required items.
     *
     * @private
     * @function Highcharts.Scrollbar#render
     */
    Scrollbar.prototype.render = function () {
        var scroller = this,
            renderer = scroller.renderer,
            options = scroller.options,
            size = scroller.size,
            styledMode = scroller.chart.styledMode,
            group = renderer.g('scrollbar')
                .attr({
                zIndex: options.zIndex
            })
                .hide() // Initially hide the scrollbar #15863
                .add();
        // Draw the scrollbar group
        scroller.group = group;
        // Draw the scrollbar track:
        scroller.track = renderer.rect()
            .addClass('highcharts-scrollbar-track')
            .attr({
            r: options.trackBorderRadius || 0,
            height: size,
            width: size
        }).add(group);
        if (!styledMode) {
            scroller.track.attr({
                fill: options.trackBackgroundColor,
                stroke: options.trackBorderColor,
                'stroke-width': options.trackBorderWidth
            });
        }
        var trackBorderWidth = scroller.trackBorderWidth =
                scroller.track.strokeWidth();
        scroller.track.attr({
            x: -Scrollbar_crisp(0, trackBorderWidth),
            y: -Scrollbar_crisp(0, trackBorderWidth)
        });
        // Draw the scrollbar itself
        scroller.scrollbarGroup = renderer.g().add(group);
        scroller.scrollbar = renderer.rect()
            .addClass('highcharts-scrollbar-thumb')
            .attr({
            height: size - trackBorderWidth,
            width: size - trackBorderWidth,
            r: options.barBorderRadius || 0
        }).add(scroller.scrollbarGroup);
        scroller.scrollbarRifles = renderer
            .path(Scrollbar.swapXY([
            ['M', -3, size / 4],
            ['L', -3, 2 * size / 3],
            ['M', 0, size / 4],
            ['L', 0, 2 * size / 3],
            ['M', 3, size / 4],
            ['L', 3, 2 * size / 3]
        ], options.vertical))
            .addClass('highcharts-scrollbar-rifles')
            .add(scroller.scrollbarGroup);
        if (!styledMode) {
            scroller.scrollbar.attr({
                fill: options.barBackgroundColor,
                stroke: options.barBorderColor,
                'stroke-width': options.barBorderWidth
            });
            scroller.scrollbarRifles.attr({
                stroke: options.rifleColor,
                'stroke-width': 1
            });
        }
        scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth();
        scroller.scrollbarGroup.translate(-Scrollbar_crisp(0, scroller.scrollbarStrokeWidth), -Scrollbar_crisp(0, scroller.scrollbarStrokeWidth));
        // Draw the buttons:
        scroller.drawScrollbarButton(0);
        scroller.drawScrollbarButton(1);
    };
    /**
     * Set scrollbar size, with a given scale.
     *
     * @private
     * @function Highcharts.Scrollbar#setRange
     * @param {number} from
     *        scale (0-1) where bar should start
     * @param {number} to
     *        scale (0-1) where bar should end
     */
    Scrollbar.prototype.setRange = function (from, to) {
        var scroller = this,
            options = scroller.options,
            vertical = options.vertical,
            minWidth = options.minWidth,
            fullWidth = scroller.barWidth,
            method = (this.rendered &&
                !this.hasDragged &&
                !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr';
        if (!Scrollbar_defined(fullWidth)) {
            return;
        }
        var toPX = fullWidth * Math.min(to, 1);
        var fromPX,
            newSize;
        from = Math.max(from, 0);
        fromPX = Math.ceil(fullWidth * from);
        scroller.calculatedWidth = newSize = Scrollbar_correctFloat(toPX - fromPX);
        // We need to recalculate position, if minWidth is used
        if (newSize < minWidth) {
            fromPX = (fullWidth - minWidth + newSize) * from;
            newSize = minWidth;
        }
        var newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset);
        var newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2
            // Store current position:
            scroller.from = from;
        scroller.to = to;
        if (!vertical) {
            scroller.scrollbarGroup[method]({
                translateX: newPos
            });
            scroller.scrollbar[method]({
                width: newSize
            });
            scroller.scrollbarRifles[method]({
                translateX: newRiflesPos
            });
            scroller.scrollbarLeft = newPos;
            scroller.scrollbarTop = 0;
        }
        else {
            scroller.scrollbarGroup[method]({
                translateY: newPos
            });
            scroller.scrollbar[method]({
                height: newSize
            });
            scroller.scrollbarRifles[method]({
                translateY: newRiflesPos
            });
            scroller.scrollbarTop = newPos;
            scroller.scrollbarLeft = 0;
        }
        if (newSize <= 12) {
            scroller.scrollbarRifles.hide();
        }
        else {
            scroller.scrollbarRifles.show();
        }
        // Show or hide the scrollbar based on the showFull setting
        if (options.showFull === false) {
            if (from <= 0 && to >= 1) {
                scroller.group.hide();
            }
            else {
                scroller.group.show();
            }
        }
        scroller.rendered = true;
    };
    /**
     * Checks if the extremes should be updated in response to a scrollbar
     * change event.
     *
     * @private
     * @function Highcharts.Scrollbar#shouldUpdateExtremes
     */
    Scrollbar.prototype.shouldUpdateExtremes = function (eventType) {
        return (Scrollbar_pick(this.options.liveRedraw, Core_Globals.svg &&
            !Core_Globals.isTouchDevice &&
            !this.chart.boosted) ||
            // Mouseup always should change extremes
            eventType === 'mouseup' ||
            eventType === 'touchend' ||
            // Internal events
            !Scrollbar_defined(eventType));
    };
    Scrollbar.prototype.trackClick = function (e) {
        var _a;
        var scroller = this;
        var normalizedEvent = ((_a = scroller.chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e,
            range = scroller.to - scroller.from,
            top = scroller.y + scroller.scrollbarTop,
            left = scroller.x + scroller.scrollbarLeft;
        if ((scroller.options.vertical && normalizedEvent.chartY > top) ||
            (!scroller.options.vertical && normalizedEvent.chartX > left)) {
            // On the top or on the left side of the track:
            scroller.updatePosition(scroller.from + range, scroller.to + range);
        }
        else {
            // On the bottom or the right side of the track:
            scroller.updatePosition(scroller.from - range, scroller.to - range);
        }
        Scrollbar_fireEvent(scroller, 'changed', {
            from: scroller.from,
            to: scroller.to,
            trigger: 'scrollbar',
            DOMEvent: e
        });
    };
    /**
     * Update the scrollbar with new options
     *
     * @private
     * @function Highcharts.Scrollbar#update
     * @param  {Highcharts.ScrollbarOptions} options
     */
    Scrollbar.prototype.update = function (options) {
        this.destroy();
        this.init(this.chart.renderer, Scrollbar_merge(true, this.options, options), this.chart);
    };
    /**
     * Update position option in the Scrollbar, with normalized 0-1 scale
     *
     * @private
     * @function Highcharts.Scrollbar#updatePosition
     * @param  {number} from
     * @param  {number} to
     */
    Scrollbar.prototype.updatePosition = function (from, to) {
        if (to > 1) {
            from = Scrollbar_correctFloat(1 - Scrollbar_correctFloat(to - from));
            to = 1;
        }
        if (from < 0) {
            to = Scrollbar_correctFloat(to - from);
            from = 0;
        }
        this.from = from;
        this.to = to;
    };
    /* *
     *
     *  Static Properties
     *
     * */
    Scrollbar.defaultOptions = Scrollbar_ScrollbarDefaults;
    return Scrollbar;
}());
/* *
 *
 *  Registry
 *
 * */
Scrollbar_defaultOptions.scrollbar = Scrollbar_merge(true, Scrollbar.defaultOptions, Scrollbar_defaultOptions.scrollbar);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Scrollbar_Scrollbar = (Scrollbar);

;// ./code/es5/es-modules/Stock/Navigator/Navigator.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var Navigator_assign = (undefined && undefined.__assign) || function () {
    Navigator_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 Navigator_assign.apply(this, arguments);
};



var Navigator_defaultOptions = Defaults.defaultOptions;

var Navigator_isTouchDevice = Core_Globals.isTouchDevice;




var symbols = SVG_SVGRenderer.prototype.symbols;

var Navigator_addEvent = Core_Utilities.addEvent, Navigator_clamp = Core_Utilities.clamp, Navigator_correctFloat = Core_Utilities.correctFloat, Navigator_defined = Core_Utilities.defined, Navigator_destroyObjectProperties = Core_Utilities.destroyObjectProperties, Navigator_erase = Core_Utilities.erase, Navigator_extend = Core_Utilities.extend, Navigator_find = Core_Utilities.find, Navigator_fireEvent = Core_Utilities.fireEvent, Navigator_isArray = Core_Utilities.isArray, Navigator_isNumber = Core_Utilities.isNumber, Navigator_merge = Core_Utilities.merge, Navigator_pick = Core_Utilities.pick, Navigator_removeEvent = Core_Utilities.removeEvent, Navigator_splat = Core_Utilities.splat;
/* *
 *
 *  Functions
 *
 * */
/**
 * Finding the min or max of a set of variables where we don't know if they are
 * defined, is a pattern that is repeated several places in Highcharts. Consider
 * making this a global utility method.
 * @private
 */
function numExt(extreme) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    var numbers = [].filter.call(args,
        Navigator_isNumber);
    if (numbers.length) {
        return Math[extreme].apply(0, numbers);
    }
}
/* *
 *
 *  Class
 *
 * */
/**
 * The Navigator class
 *
 * @private
 * @class
 * @name Highcharts.Navigator
 *
 * @param {Highcharts.Chart} chart
 *        Chart object
 */
var Navigator = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function Navigator(chart) {
        this.isDirty = false;
        this.scrollbarHeight = 0;
        this.init(chart);
    }
    /* *
     *
     *  Static Properties
     *
     * */
    Navigator.compose = function (ChartClass, AxisClass, SeriesClass) {
        Navigator_ChartNavigatorComposition.compose(ChartClass, Navigator);
        Navigator_NavigatorComposition.compose(ChartClass, AxisClass, SeriesClass);
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Draw one of the handles on the side of the zoomed range in the navigator.
     *
     * @private
     * @function Highcharts.Navigator#drawHandle
     *
     * @param {number} x
     *        The x center for the handle
     *
     * @param {number} index
     *        0 for left and 1 for right
     *
     * @param {boolean|undefined} inverted
     *        Flag for chart.inverted
     *
     * @param {string} verb
     *        Use 'animate' or 'attr'
     */
    Navigator.prototype.drawHandle = function (x, index, inverted, verb) {
        var navigator = this,
            height = navigator.navigatorOptions.handles.height;
        // Place it
        navigator.handles[index][verb](inverted ? {
            translateX: Math.round(navigator.left + navigator.height / 2),
            translateY: Math.round(navigator.top + parseInt(x, 10) + 0.5 - height)
        } : {
            translateX: Math.round(navigator.left + parseInt(x, 10)),
            translateY: Math.round(navigator.top + navigator.height / 2 - height / 2 - 1)
        });
    };
    /**
     * Render outline around the zoomed range
     *
     * @private
     * @function Highcharts.Navigator#drawOutline
     *
     * @param {number} zoomedMin
     *        in pixels position where zoomed range starts
     *
     * @param {number} zoomedMax
     *        in pixels position where zoomed range ends
     *
     * @param {boolean|undefined} inverted
     *        flag if chart is inverted
     *
     * @param {string} verb
     *        use 'animate' or 'attr'
     */
    Navigator.prototype.drawOutline = function (zoomedMin, zoomedMax, inverted, verb) {
        var navigator = this, maskInside = navigator.navigatorOptions.maskInside, outlineWidth = navigator.outline.strokeWidth(), halfOutline = outlineWidth / 2, outlineCorrection = (outlineWidth % 2) / 2, // #5800
            scrollButtonSize = navigator.scrollButtonSize, navigatorSize = navigator.size, navigatorTop = navigator.top, height = navigator.height, lineTop = navigatorTop - halfOutline, lineBtm = navigatorTop + height;
        var left = navigator.left,
            verticalMin,
            path;
        if (inverted) {
            verticalMin = navigatorTop + zoomedMax + outlineCorrection;
            zoomedMax = navigatorTop + zoomedMin + outlineCorrection;
            path = [
                [
                    'M',
                    left + height,
                    navigatorTop - scrollButtonSize - outlineCorrection
                ],
                // Top right of zoomed range
                ['L', left + height, verticalMin],
                ['L', left, verticalMin], // Top left of z.r.
                ['M', left, zoomedMax], // Bottom left of z.r.
                ['L', left + height, zoomedMax], // Bottom right of z.r.
                [
                    'L',
                    left + height,
                    navigatorTop + navigatorSize + scrollButtonSize
                ]
            ];
            if (maskInside) {
                path.push(
                // Upper left of zoomed range
                ['M', left + height, verticalMin - halfOutline], 
                // Upper right of z.r.
                [
                    'L',
                    left + height,
                    zoomedMax + halfOutline
                ]);
            }
        }
        else {
            left -= scrollButtonSize;
            zoomedMin += left + scrollButtonSize - outlineCorrection;
            zoomedMax += left + scrollButtonSize - outlineCorrection;
            path = [
                // Left
                ['M', left, lineTop],
                // Upper left of zoomed range
                ['L', zoomedMin, lineTop],
                // Lower left of z.r.
                ['L', zoomedMin, lineBtm],
                // Lower right of z.r.
                ['M', zoomedMax, lineBtm],
                // Upper right of z.r.
                ['L', zoomedMax, lineTop],
                // Right
                [
                    'L',
                    left + navigatorSize + scrollButtonSize * 2,
                    lineTop
                ]
            ];
            if (maskInside) {
                path.push(
                // Upper left of zoomed range
                ['M', zoomedMin - halfOutline, lineTop], 
                // Upper right of z.r.
                ['L', zoomedMax + halfOutline, lineTop]);
            }
        }
        navigator.outline[verb]({
            d: path
        });
    };
    /**
     * Render outline around the zoomed range
     *
     * @private
     * @function Highcharts.Navigator#drawMasks
     *
     * @param {number} zoomedMin
     *        in pixels position where zoomed range starts
     *
     * @param {number} zoomedMax
     *        in pixels position where zoomed range ends
     *
     * @param {boolean|undefined} inverted
     *        flag if chart is inverted
     *
     * @param {string} verb
     *        use 'animate' or 'attr'
     */
    Navigator.prototype.drawMasks = function (zoomedMin, zoomedMax, inverted, verb) {
        var navigator = this,
            left = navigator.left,
            top = navigator.top,
            navigatorHeight = navigator.height;
        var height,
            width,
            x,
            y;
        // Determine rectangle position & size
        // According to (non)inverted position:
        if (inverted) {
            x = [left, left, left];
            y = [top, top + zoomedMin, top + zoomedMax];
            width = [navigatorHeight, navigatorHeight, navigatorHeight];
            height = [
                zoomedMin,
                zoomedMax - zoomedMin,
                navigator.size - zoomedMax
            ];
        }
        else {
            x = [left, left + zoomedMin, left + zoomedMax];
            y = [top, top, top];
            width = [
                zoomedMin,
                zoomedMax - zoomedMin,
                navigator.size - zoomedMax
            ];
            height = [navigatorHeight, navigatorHeight, navigatorHeight];
        }
        navigator.shades.forEach(function (shade, i) {
            shade[verb]({
                x: x[i],
                y: y[i],
                width: width[i],
                height: height[i]
            });
        });
    };
    /**
     * Generate and update DOM elements for a navigator:
     *
     * - main navigator group
     *
     * - all shades
     *
     * - outline
     *
     * - handles
     *
     * @private
     * @function Highcharts.Navigator#renderElements
     */
    Navigator.prototype.renderElements = function () {
        var _a,
            _b;
        var navigator = this,
            navigatorOptions = navigator.navigatorOptions,
            maskInside = navigatorOptions.maskInside,
            chart = navigator.chart,
            inverted = chart.inverted,
            renderer = chart.renderer,
            mouseCursor = {
                cursor: inverted ? 'ns-resize' : 'ew-resize'
            }, 
            // Create the main navigator group
            navigatorGroup = (_a = navigator.navigatorGroup) !== null && _a !== void 0 ? _a : (navigator.navigatorGroup = renderer
                .g('navigator')
                .attr({
                zIndex: 8,
                visibility: 'hidden'
            })
                .add());
        // Create masks, each mask will get events and fill:
        [
            !maskInside,
            maskInside,
            !maskInside
        ].forEach(function (hasMask, index) {
            var _a;
            var shade = (_a = navigator.shades[index]) !== null && _a !== void 0 ? _a : (navigator.shades[index] = renderer.rect()
                    .addClass('highcharts-navigator-mask' +
                    (index === 1 ? '-inside' : '-outside'))
                    .add(navigatorGroup));
            if (!chart.styledMode) {
                shade.attr({
                    fill: hasMask ? navigatorOptions.maskFill : 'rgba(0,0,0,0)'
                });
                if (index === 1) {
                    shade.css(mouseCursor);
                }
            }
        });
        // Create the outline:
        if (!navigator.outline) {
            navigator.outline = renderer.path()
                .addClass('highcharts-navigator-outline')
                .add(navigatorGroup);
        }
        if (!chart.styledMode) {
            navigator.outline.attr({
                'stroke-width': navigatorOptions.outlineWidth,
                stroke: navigatorOptions.outlineColor
            });
        }
        // Create the handlers:
        if ((_b = navigatorOptions.handles) === null || _b === void 0 ? void 0 : _b.enabled) {
            var handlesOptions_1 = navigatorOptions.handles,
                height_1 = handlesOptions_1.height,
                width_1 = handlesOptions_1.width;
            [0, 1].forEach(function (index) {
                var _a;
                var symbolName = handlesOptions_1.symbols[index];
                if (!navigator.handles[index] ||
                    navigator.handles[index].symbolUrl !== symbolName) {
                    // Generate symbol from scratch if we're dealing with an URL
                    (_a = navigator.handles[index]) === null || _a === void 0 ? void 0 : _a.destroy();
                    navigator.handles[index] = renderer.symbol(symbolName, -width_1 / 2 - 1, 0, width_1, height_1, handlesOptions_1);
                    // Z index is 6 for right handle, 7 for left. Can't be 10,
                    // because of the tooltip in inverted chart (#2908).
                    navigator.handles[index].attr({ zIndex: 7 - index })
                        .addClass('highcharts-navigator-handle ' +
                        'highcharts-navigator-handle-' +
                        ['left', 'right'][index]).add(navigatorGroup);
                    navigator.addMouseEvents();
                    // If the navigator symbol changed, update its path and name
                }
                else if (!navigator.handles[index].isImg &&
                    navigator.handles[index].symbolName !== symbolName) {
                    var symbolFn = symbols[symbolName],
                        path = symbolFn.call(symbols, -width_1 / 2 - 1, 0,
                        width_1,
                        height_1);
                    navigator.handles[index].attr({
                        d: path
                    });
                    navigator.handles[index].symbolName = symbolName;
                }
                if (chart.inverted) {
                    navigator.handles[index].attr({
                        rotation: 90,
                        rotationOriginX: Math.floor(-width_1 / 2),
                        rotationOriginY: (height_1 + width_1) / 2
                    });
                }
                if (!chart.styledMode) {
                    navigator.handles[index]
                        .attr({
                        fill: handlesOptions_1.backgroundColor,
                        stroke: handlesOptions_1.borderColor,
                        'stroke-width': handlesOptions_1.lineWidth,
                        width: handlesOptions_1.width,
                        height: handlesOptions_1.height,
                        x: -width_1 / 2 - 1,
                        y: 0
                    })
                        .css(mouseCursor);
                }
            });
        }
    };
    /**
     * Update navigator
     *
     * @private
     * @function Highcharts.Navigator#update
     *
     * @param {Highcharts.NavigatorOptions} options
     *        Options to merge in when updating navigator
     */
    Navigator.prototype.update = function (options, redraw) {
        var _a,
            _b;
        var _this = this;
        var _c,
            _d;
        if (redraw === void 0) { redraw = false; }
        var chart = this.chart,
            invertedUpdate = chart.options.chart.inverted !==
                ((_c = chart.scrollbar) === null || _c === void 0 ? void 0 : _c.options.vertical);
        Navigator_merge(true, chart.options.navigator, options);
        this.navigatorOptions = chart.options.navigator || {};
        this.setOpposite();
        // Revert to destroy/init for navigator/scrollbar enabled toggle
        if (Navigator_defined(options.enabled) || invertedUpdate) {
            this.destroy();
            this.navigatorEnabled = options.enabled || this.navigatorEnabled;
            return this.init(chart);
        }
        if (this.navigatorEnabled) {
            this.isDirty = true;
            if (options.adaptToUpdatedData === false) {
                this.baseSeries.forEach(function (series) {
                    Navigator_removeEvent(series, 'updatedData', _this.updatedDataHandler);
                }, this);
            }
            if (options.adaptToUpdatedData) {
                this.baseSeries.forEach(function (series) {
                    series.eventsToUnbind.push(Navigator_addEvent(series, 'updatedData', _this.updatedDataHandler));
                }, this);
            }
            // Update navigator series
            if (options.series || options.baseSeries) {
                this.setBaseSeries(void 0, false);
            }
            // Update navigator axis
            if (options.height || options.xAxis || options.yAxis) {
                this.height = (_d = options.height) !== null && _d !== void 0 ? _d : this.height;
                var offsets = this.getXAxisOffsets();
                this.xAxis.update(Navigator_assign(Navigator_assign({}, options.xAxis), (_a = { offsets: offsets }, _a[chart.inverted ? 'width' : 'height'] = this.height, _a[chart.inverted ? 'height' : 'width'] = void 0, _a)), false);
                this.yAxis.update(Navigator_assign(Navigator_assign({}, options.yAxis), (_b = {}, _b[chart.inverted ? 'width' : 'height'] = this.height, _b)), false);
            }
        }
        if (redraw) {
            chart.redraw();
        }
    };
    /**
     * Render the navigator
     *
     * @private
     * @function Highcharts.Navigator#render
     * @param {number} min
     *        X axis value minimum
     * @param {number} max
     *        X axis value maximum
     * @param {number} [pxMin]
     *        Pixel value minimum
     * @param {number} [pxMax]
     *        Pixel value maximum
     */
    Navigator.prototype.render = function (min, max, pxMin, pxMax) {
        var navigator = this,
            chart = navigator.chart,
            xAxis = navigator.xAxis,
            pointRange = xAxis.pointRange || 0,
            scrollbarXAxis = xAxis.navigatorAxis.fake ? chart.xAxis[0] : xAxis,
            navigatorEnabled = navigator.navigatorEnabled,
            rendered = navigator.rendered,
            inverted = chart.inverted,
            minRange = chart.xAxis[0].minRange,
            maxRange = chart.xAxis[0].options.maxRange,
            scrollButtonSize = navigator.scrollButtonSize;
        var navigatorWidth,
            scrollbarLeft,
            scrollbarTop,
            scrollbarHeight = navigator.scrollbarHeight,
            navigatorSize,
            verb;
        // Don't redraw while moving the handles (#4703).
        if (this.hasDragged && !Navigator_defined(pxMin)) {
            return;
        }
        if (this.isDirty) {
            // Update DOM navigator elements
            this.renderElements();
        }
        min = Navigator_correctFloat(min - pointRange / 2);
        max = Navigator_correctFloat(max + pointRange / 2);
        // Don't render the navigator until we have data (#486, #4202, #5172).
        if (!Navigator_isNumber(min) || !Navigator_isNumber(max)) {
            // However, if navigator was already rendered, we may need to resize
            // it. For example hidden series, but visible navigator (#6022).
            if (rendered) {
                pxMin = 0;
                pxMax = Navigator_pick(xAxis.width, scrollbarXAxis.width);
            }
            else {
                return;
            }
        }
        navigator.left = Navigator_pick(xAxis.left, 
        // In case of scrollbar only, without navigator
        chart.plotLeft + scrollButtonSize +
            (inverted ? chart.plotWidth : 0));
        var zoomedMax = navigator.size = navigatorSize = Navigator_pick(xAxis.len, (inverted ? chart.plotHeight : chart.plotWidth) -
                2 * scrollButtonSize);
        if (inverted) {
            navigatorWidth = scrollbarHeight;
        }
        else {
            navigatorWidth = navigatorSize + 2 * scrollButtonSize;
        }
        // Get the pixel position of the handles
        pxMin = Navigator_pick(pxMin, xAxis.toPixels(min, true));
        pxMax = Navigator_pick(pxMax, xAxis.toPixels(max, true));
        // Verify (#1851, #2238)
        if (!Navigator_isNumber(pxMin) || Math.abs(pxMin) === Infinity) {
            pxMin = 0;
            pxMax = navigatorWidth;
        }
        // Are we below the minRange? (#2618, #6191)
        var newMin = xAxis.toValue(pxMin,
            true),
            newMax = xAxis.toValue(pxMax,
            true),
            currentRange = Math.abs(Navigator_correctFloat(newMax - newMin));
        if (currentRange < minRange) {
            if (this.grabbedLeft) {
                pxMin = xAxis.toPixels(newMax - minRange - pointRange, true);
            }
            else if (this.grabbedRight) {
                pxMax = xAxis.toPixels(newMin + minRange + pointRange, true);
            }
        }
        else if (Navigator_defined(maxRange) &&
            Navigator_correctFloat(currentRange - pointRange) > maxRange) {
            if (this.grabbedLeft) {
                pxMin = xAxis.toPixels(newMax - maxRange - pointRange, true);
            }
            else if (this.grabbedRight) {
                pxMax = xAxis.toPixels(newMin + maxRange + pointRange, true);
            }
        }
        // Handles are allowed to cross, but never exceed the plot area
        navigator.zoomedMax = Navigator_clamp(Math.max(pxMin, pxMax), 0, zoomedMax);
        navigator.zoomedMin = Navigator_clamp(navigator.fixedWidth ?
            navigator.zoomedMax - navigator.fixedWidth :
            Math.min(pxMin, pxMax), 0, zoomedMax);
        navigator.range = navigator.zoomedMax - navigator.zoomedMin;
        zoomedMax = Math.round(navigator.zoomedMax);
        var zoomedMin = Math.round(navigator.zoomedMin);
        if (navigatorEnabled) {
            navigator.navigatorGroup.attr({
                visibility: 'inherit'
            });
            // Place elements
            verb = rendered && !navigator.hasDragged ? 'animate' : 'attr';
            navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb);
            navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb);
            if (navigator.navigatorOptions.handles.enabled) {
                navigator.drawHandle(zoomedMin, 0, inverted, verb);
                navigator.drawHandle(zoomedMax, 1, inverted, verb);
            }
        }
        if (navigator.scrollbar) {
            if (inverted) {
                scrollbarTop = navigator.top - scrollButtonSize;
                scrollbarLeft = navigator.left - scrollbarHeight +
                    (navigatorEnabled || !scrollbarXAxis.opposite ? 0 :
                        // Multiple axes has offsets:
                        (scrollbarXAxis.titleOffset || 0) +
                            // Self margin from the axis.title
                            scrollbarXAxis.axisTitleMargin);
                scrollbarHeight = navigatorSize + 2 * scrollButtonSize;
            }
            else {
                scrollbarTop = navigator.top + (navigatorEnabled ?
                    navigator.height :
                    -scrollbarHeight);
                scrollbarLeft = navigator.left - scrollButtonSize;
            }
            // Reposition scrollbar
            navigator.scrollbar.position(scrollbarLeft, scrollbarTop, navigatorWidth, scrollbarHeight);
            // Keep scale 0-1
            navigator.scrollbar.setRange(
            // Use real value, not rounded because range can be very small
            // (#1716)
            navigator.zoomedMin / (navigatorSize || 1), navigator.zoomedMax / (navigatorSize || 1));
        }
        navigator.rendered = true;
        this.isDirty = false;
        Navigator_fireEvent(this, 'afterRender');
    };
    /**
     * Set up the mouse and touch events for the navigator
     *
     * @private
     * @function Highcharts.Navigator#addMouseEvents
     */
    Navigator.prototype.addMouseEvents = function () {
        var navigator = this,
            chart = navigator.chart,
            container = chart.container;
        var eventsToUnbind = [],
            mouseMoveHandler,
            mouseUpHandler;
        /**
         * Create mouse events' handlers.
         * Make them as separate functions to enable wrapping them:
         */
        navigator.mouseMoveHandler = mouseMoveHandler = function (e) {
            navigator.onMouseMove(e);
        };
        navigator.mouseUpHandler = mouseUpHandler = function (e) {
            navigator.onMouseUp(e);
        };
        // Add shades and handles mousedown events
        eventsToUnbind = navigator.getPartsEvents('mousedown');
        eventsToUnbind.push(
        // Add mouse move and mouseup events. These are bind to doc/div,
        // because Navigator.grabbedSomething flags are stored in mousedown
        // events
        Navigator_addEvent(chart.renderTo, 'mousemove', mouseMoveHandler), Navigator_addEvent(container.ownerDocument, 'mouseup', mouseUpHandler), 
        // Touch events
        Navigator_addEvent(chart.renderTo, 'touchmove', mouseMoveHandler), Navigator_addEvent(container.ownerDocument, 'touchend', mouseUpHandler));
        eventsToUnbind.concat(navigator.getPartsEvents('touchstart'));
        navigator.eventsToUnbind = eventsToUnbind;
        // Data events
        if (navigator.series && navigator.series[0]) {
            eventsToUnbind.push(Navigator_addEvent(navigator.series[0].xAxis, 'foundExtremes', function () {
                chart.navigator.modifyNavigatorAxisExtremes();
            }));
        }
    };
    /**
     * Generate events for handles and masks
     *
     * @private
     * @function Highcharts.Navigator#getPartsEvents
     *
     * @param {string} eventName
     *        Event name handler, 'mousedown' or 'touchstart'
     *
     * @return {Array<Function>}
     *         An array of functions to remove navigator functions from the
     *         events again.
     */
    Navigator.prototype.getPartsEvents = function (eventName) {
        var navigator = this,
            events = [];
        ['shades', 'handles'].forEach(function (name) {
            navigator[name].forEach(function (navigatorItem, index) {
                events.push(Navigator_addEvent(navigatorItem.element, eventName, function (e) {
                    navigator[name + 'Mousedown'](e, index);
                }));
            });
        });
        return events;
    };
    /**
     * Mousedown on a shaded mask, either:
     *
     * - will be stored for future drag&drop
     *
     * - will directly shift to a new range
     *
     * @private
     * @function Highcharts.Navigator#shadesMousedown
     *
     * @param {Highcharts.PointerEventObject} e
     *        Mouse event
     *
     * @param {number} index
     *        Index of a mask in Navigator.shades array
     */
    Navigator.prototype.shadesMousedown = function (e, index) {
        var _a;
        e = ((_a = this.chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e;
        var navigator = this,
            chart = navigator.chart,
            xAxis = navigator.xAxis,
            zoomedMin = navigator.zoomedMin,
            navigatorSize = navigator.size,
            range = navigator.range;
        var navigatorPosition = navigator.left,
            chartX = e.chartX,
            fixedMax,
            fixedMin,
            ext,
            left;
        // For inverted chart, swap some options:
        if (chart.inverted) {
            chartX = e.chartY;
            navigatorPosition = navigator.top;
        }
        if (index === 1) {
            // Store information for drag&drop
            navigator.grabbedCenter = chartX;
            navigator.fixedWidth = range;
            navigator.dragOffset = chartX - zoomedMin;
        }
        else {
            // Shift the range by clicking on shaded areas
            left = chartX - navigatorPosition - range / 2;
            if (index === 0) {
                left = Math.max(0, left);
            }
            else if (index === 2 && left + range >= navigatorSize) {
                left = navigatorSize - range;
                if (navigator.reversedExtremes) {
                    // #7713
                    left -= range;
                    fixedMin = navigator.getUnionExtremes().dataMin;
                }
                else {
                    // #2293, #3543
                    fixedMax = navigator.getUnionExtremes().dataMax;
                }
            }
            if (left !== zoomedMin) { // It has actually moved
                navigator.fixedWidth = range; // #1370
                ext = xAxis.navigatorAxis.toFixedRange(left, left + range, fixedMin, fixedMax);
                if (Navigator_defined(ext.min)) { // #7411
                    Navigator_fireEvent(this, 'setRange', {
                        min: Math.min(ext.min, ext.max),
                        max: Math.max(ext.min, ext.max),
                        redraw: true,
                        eventArguments: {
                            trigger: 'navigator'
                        }
                    });
                }
            }
        }
    };
    /**
     * Mousedown on a handle mask.
     * Will store necessary information for drag&drop.
     *
     * @private
     * @function Highcharts.Navigator#handlesMousedown
     * @param {Highcharts.PointerEventObject} e
     *        Mouse event
     * @param {number} index
     *        Index of a handle in Navigator.handles array
     */
    Navigator.prototype.handlesMousedown = function (e, index) {
        var _a;
        e = ((_a = this.chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e;
        var navigator = this,
            chart = navigator.chart,
            baseXAxis = chart.xAxis[0], 
            // For reversed axes, min and max are changed,
            // so the other extreme should be stored
            reverse = navigator.reversedExtremes;
        if (index === 0) {
            // Grab the left handle
            navigator.grabbedLeft = true;
            navigator.otherHandlePos = navigator.zoomedMax;
            navigator.fixedExtreme = reverse ? baseXAxis.min : baseXAxis.max;
        }
        else {
            // Grab the right handle
            navigator.grabbedRight = true;
            navigator.otherHandlePos = navigator.zoomedMin;
            navigator.fixedExtreme = reverse ? baseXAxis.max : baseXAxis.min;
        }
        chart.setFixedRange(void 0);
    };
    /**
     * Mouse move event based on x/y mouse position.
     *
     * @private
     * @function Highcharts.Navigator#onMouseMove
     *
     * @param {Highcharts.PointerEventObject} e
     *        Mouse event
     */
    Navigator.prototype.onMouseMove = function (e) {
        var _a;
        var navigator = this,
            chart = navigator.chart,
            navigatorSize = navigator.navigatorSize,
            range = navigator.range,
            dragOffset = navigator.dragOffset,
            inverted = chart.inverted;
        var left = navigator.left,
            chartX;
        // In iOS, a mousemove event with e.pageX === 0 is fired when holding
        // the finger down in the center of the scrollbar. This should be
        // ignored.
        if (!e.touches || e.touches[0].pageX !== 0) { // #4696
            e = ((_a = chart.pointer) === null || _a === void 0 ? void 0 : _a.normalize(e)) || e;
            chartX = e.chartX;
            // Swap some options for inverted chart
            if (inverted) {
                left = navigator.top;
                chartX = e.chartY;
            }
            // Drag left handle or top handle
            if (navigator.grabbedLeft) {
                navigator.hasDragged = true;
                navigator.render(0, 0, chartX - left, navigator.otherHandlePos);
                // Drag right handle or bottom handle
            }
            else if (navigator.grabbedRight) {
                navigator.hasDragged = true;
                navigator.render(0, 0, navigator.otherHandlePos, chartX - left);
                // Drag scrollbar or open area in navigator
            }
            else if (navigator.grabbedCenter) {
                navigator.hasDragged = true;
                if (chartX < dragOffset) { // Outside left
                    chartX = dragOffset;
                    // Outside right
                }
                else if (chartX >
                    navigatorSize + dragOffset - range) {
                    chartX = navigatorSize + dragOffset - range;
                }
                navigator.render(0, 0, chartX - dragOffset, chartX - dragOffset + range);
            }
            if (navigator.hasDragged &&
                navigator.scrollbar &&
                Navigator_pick(navigator.scrollbar.options.liveRedraw, 
                // By default, don't run live redraw on touch
                // devices or if the chart is in boost.
                !Navigator_isTouchDevice &&
                    !this.chart.boosted)) {
                e.DOMType = e.type;
                setTimeout(function () {
                    navigator.onMouseUp(e);
                }, 0);
            }
        }
    };
    /**
     * Mouse up event based on x/y mouse position.
     *
     * @private
     * @function Highcharts.Navigator#onMouseUp
     * @param {Highcharts.PointerEventObject} e
     *        Mouse event
     */
    Navigator.prototype.onMouseUp = function (e) {
        var navigator = this,
            chart = navigator.chart,
            xAxis = navigator.xAxis,
            scrollbar = navigator.scrollbar,
            DOMEvent = e.DOMEvent || e,
            inverted = chart.inverted,
            verb = navigator.rendered && !navigator.hasDragged ?
                'animate' : 'attr';
        var zoomedMax,
            zoomedMin,
            unionExtremes,
            fixedMin,
            fixedMax,
            ext;
        if (
        // MouseUp is called for both, navigator and scrollbar (that order),
        // which causes calling afterSetExtremes twice. Prevent first call
        // by checking if scrollbar is going to set new extremes (#6334)
        (navigator.hasDragged && (!scrollbar || !scrollbar.hasDragged)) ||
            e.trigger === 'scrollbar') {
            unionExtremes = navigator.getUnionExtremes();
            // When dragging one handle, make sure the other one doesn't change
            if (navigator.zoomedMin === navigator.otherHandlePos) {
                fixedMin = navigator.fixedExtreme;
            }
            else if (navigator.zoomedMax === navigator.otherHandlePos) {
                fixedMax = navigator.fixedExtreme;
            }
            // Snap to right edge (#4076)
            if (navigator.zoomedMax === navigator.size) {
                fixedMax = navigator.reversedExtremes ?
                    unionExtremes.dataMin :
                    unionExtremes.dataMax;
            }
            // Snap to left edge (#7576)
            if (navigator.zoomedMin === 0) {
                fixedMin = navigator.reversedExtremes ?
                    unionExtremes.dataMax :
                    unionExtremes.dataMin;
            }
            ext = xAxis.navigatorAxis.toFixedRange(navigator.zoomedMin, navigator.zoomedMax, fixedMin, fixedMax);
            if (Navigator_defined(ext.min)) {
                Navigator_fireEvent(this, 'setRange', {
                    min: Math.min(ext.min, ext.max),
                    max: Math.max(ext.min, ext.max),
                    redraw: true,
                    animation: navigator.hasDragged ? false : null,
                    eventArguments: {
                        trigger: 'navigator',
                        triggerOp: 'navigator-drag',
                        DOMEvent: DOMEvent // #1838
                    }
                });
            }
        }
        if (e.DOMType !== 'mousemove' &&
            e.DOMType !== 'touchmove') {
            navigator.grabbedLeft = navigator.grabbedRight =
                navigator.grabbedCenter = navigator.fixedWidth =
                    navigator.fixedExtreme = navigator.otherHandlePos =
                        navigator.hasDragged = navigator.dragOffset = null;
        }
        // Update position of navigator shades, outline and handles (#12573)
        if (navigator.navigatorEnabled &&
            Navigator_isNumber(navigator.zoomedMin) &&
            Navigator_isNumber(navigator.zoomedMax)) {
            zoomedMin = Math.round(navigator.zoomedMin);
            zoomedMax = Math.round(navigator.zoomedMax);
            if (navigator.shades) {
                navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb);
            }
            if (navigator.outline) {
                navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb);
            }
            if (navigator.navigatorOptions.handles.enabled &&
                Object.keys(navigator.handles).length ===
                    navigator.handles.length) {
                navigator.drawHandle(zoomedMin, 0, inverted, verb);
                navigator.drawHandle(zoomedMax, 1, inverted, verb);
            }
        }
    };
    /**
     * Removes the event handlers attached previously with addEvents.
     *
     * @private
     * @function Highcharts.Navigator#removeEvents
     */
    Navigator.prototype.removeEvents = function () {
        if (this.eventsToUnbind) {
            this.eventsToUnbind.forEach(function (unbind) {
                unbind();
            });
            this.eventsToUnbind = void 0;
        }
        this.removeBaseSeriesEvents();
    };
    /**
     * Remove data events.
     *
     * @private
     * @function Highcharts.Navigator#removeBaseSeriesEvents
     */
    Navigator.prototype.removeBaseSeriesEvents = function () {
        var baseSeries = this.baseSeries || [];
        if (this.navigatorEnabled && baseSeries[0]) {
            if (this.navigatorOptions.adaptToUpdatedData !== false) {
                baseSeries.forEach(function (series) {
                    Navigator_removeEvent(series, 'updatedData', this.updatedDataHandler);
                }, this);
            }
            // We only listen for extremes-events on the first baseSeries
            if (baseSeries[0].xAxis) {
                Navigator_removeEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes);
            }
        }
    };
    /**
     * Calculate the navigator xAxis offsets
     *
     * @private
     */
    Navigator.prototype.getXAxisOffsets = function () {
        return (this.chart.inverted ?
            [this.scrollButtonSize, 0, -this.scrollButtonSize, 0] :
            [0, -this.scrollButtonSize, 0, this.scrollButtonSize]);
    };
    /**
     * Initialize the Navigator object
     *
     * @private
     * @function Highcharts.Navigator#init
     */
    Navigator.prototype.init = function (chart) {
        var _a;
        var chartOptions = chart.options,
            navigatorOptions = chartOptions.navigator || {},
            navigatorEnabled = navigatorOptions.enabled,
            scrollbarOptions = chartOptions.scrollbar || {},
            scrollbarEnabled = scrollbarOptions.enabled,
            height = navigatorEnabled && navigatorOptions.height || 0,
            scrollbarHeight = scrollbarEnabled && scrollbarOptions.height || 0,
            scrollButtonSize = scrollbarOptions.buttonsEnabled && scrollbarHeight || 0;
        this.handles = [];
        this.shades = [];
        this.chart = chart;
        this.setBaseSeries();
        this.height = height;
        this.scrollbarHeight = scrollbarHeight;
        this.scrollButtonSize = scrollButtonSize;
        this.scrollbarEnabled = scrollbarEnabled;
        this.navigatorEnabled = navigatorEnabled;
        this.navigatorOptions = navigatorOptions;
        this.scrollbarOptions = scrollbarOptions;
        this.setOpposite();
        var navigator = this,
            baseSeries = navigator.baseSeries,
            xAxisIndex = chart.xAxis.length,
            yAxisIndex = chart.yAxis.length,
            baseXaxis = baseSeries && baseSeries[0] && baseSeries[0].xAxis ||
                chart.xAxis[0] || { options: {} };
        chart.isDirtyBox = true;
        if (navigator.navigatorEnabled) {
            var offsets = this.getXAxisOffsets();
            // An x axis is required for scrollbar also
            navigator.xAxis = new Axis_Axis(chart, Navigator_merge({
                // Inherit base xAxis' break, ordinal options and overscroll
                breaks: baseXaxis.options.breaks,
                ordinal: baseXaxis.options.ordinal,
                overscroll: baseXaxis.options.overscroll
            }, navigatorOptions.xAxis, {
                type: 'datetime',
                yAxis: (_a = navigatorOptions.yAxis) === null || _a === void 0 ? void 0 : _a.id,
                index: xAxisIndex,
                isInternal: true,
                offset: 0,
                keepOrdinalPadding: true, // #2436
                startOnTick: false,
                endOnTick: false,
                // Inherit base xAxis' padding when ordinal is false (#16915).
                minPadding: baseXaxis.options.ordinal ? 0 :
                    baseXaxis.options.minPadding,
                maxPadding: baseXaxis.options.ordinal ? 0 :
                    baseXaxis.options.maxPadding,
                zoomEnabled: false
            }, chart.inverted ? {
                offsets: offsets,
                width: height
            } : {
                offsets: offsets,
                height: height
            }), 'xAxis');
            navigator.yAxis = new Axis_Axis(chart, Navigator_merge(navigatorOptions.yAxis, {
                alignTicks: false,
                offset: 0,
                index: yAxisIndex,
                isInternal: true,
                reversed: Navigator_pick((navigatorOptions.yAxis &&
                    navigatorOptions.yAxis.reversed), (chart.yAxis[0] && chart.yAxis[0].reversed), false), // #14060
                zoomEnabled: false
            }, chart.inverted ? {
                width: height
            } : {
                height: height
            }), 'yAxis');
            // If we have a base series, initialize the navigator series
            if (baseSeries || navigatorOptions.series.data) {
                navigator.updateNavigatorSeries(false);
                // If not, set up an event to listen for added series
            }
            else if (chart.series.length === 0) {
                navigator.unbindRedraw = Navigator_addEvent(chart, 'beforeRedraw', function () {
                    // We've got one, now add it as base
                    if (chart.series.length > 0 && !navigator.series) {
                        navigator.setBaseSeries();
                        navigator.unbindRedraw(); // Reset
                    }
                });
            }
            navigator.reversedExtremes = (chart.inverted && !navigator.xAxis.reversed) || (!chart.inverted && navigator.xAxis.reversed);
            // Render items, so we can bind events to them:
            navigator.renderElements();
            // Add mouse events
            navigator.addMouseEvents();
            // In case of scrollbar only, fake an x axis to get translation
        }
        else {
            navigator.xAxis = {
                chart: chart,
                navigatorAxis: {
                    fake: true
                },
                translate: function (value, reverse) {
                    var axis = chart.xAxis[0], ext = axis.getExtremes(), scrollTrackWidth = axis.len - 2 * scrollButtonSize, min = numExt('min', axis.options.min, ext.dataMin), valueRange = numExt('max', axis.options.max, ext.dataMax) - min;
                    return reverse ?
                        // From pixel to value
                        (value * valueRange / scrollTrackWidth) + min :
                        // From value to pixel
                        scrollTrackWidth * (value - min) / valueRange;
                },
                toPixels: function (value) {
                    return this.translate(value);
                },
                toValue: function (value) {
                    return this.translate(value, true);
                }
            };
            navigator.xAxis.navigatorAxis.axis = navigator.xAxis;
            navigator.xAxis.navigatorAxis.toFixedRange = (NavigatorAxisComposition.prototype.toFixedRange.bind(navigator.xAxis.navigatorAxis));
        }
        // Initialize the scrollbar
        if (chart.options.scrollbar.enabled) {
            var options = Navigator_merge(chart.options.scrollbar, { vertical: chart.inverted });
            if (!Navigator_isNumber(options.margin) && navigator.navigatorEnabled) {
                options.margin = chart.inverted ? -3 : 3;
            }
            chart.scrollbar = navigator.scrollbar = new Scrollbar_Scrollbar(chart.renderer, options, chart);
            Navigator_addEvent(navigator.scrollbar, 'changed', function (e) {
                var range = navigator.size,
                    to = range * this.to,
                    from = range * this.from;
                navigator.hasDragged = navigator.scrollbar.hasDragged;
                navigator.render(0, 0, from, to);
                if (this.shouldUpdateExtremes(e.DOMType)) {
                    setTimeout(function () {
                        navigator.onMouseUp(e);
                    });
                }
            });
        }
        // Add data events
        navigator.addBaseSeriesEvents();
        // Add redraw events
        navigator.addChartEvents();
    };
    /**
     * Set the opposite property on navigator
     *
     * @private
     */
    Navigator.prototype.setOpposite = function () {
        var navigatorOptions = this.navigatorOptions,
            navigatorEnabled = this.navigatorEnabled,
            chart = this.chart;
        this.opposite = Navigator_pick(navigatorOptions.opposite, Boolean(!navigatorEnabled && chart.inverted)); // #6262
    };
    /**
     * Get the union data extremes of the chart - the outer data extremes of the
     * base X axis and the navigator axis.
     *
     * @private
     * @function Highcharts.Navigator#getUnionExtremes
     */
    Navigator.prototype.getUnionExtremes = function (returnFalseOnNoBaseSeries) {
        var baseAxis = this.chart.xAxis[0],
            time = this.chart.time,
            navAxis = this.xAxis,
            navAxisOptions = navAxis.options,
            baseAxisOptions = baseAxis.options;
        var ret;
        if (!returnFalseOnNoBaseSeries || baseAxis.dataMin !== null) {
            ret = {
                dataMin: Navigator_pick(// #4053
                time.parse(navAxisOptions === null || navAxisOptions === void 0 ? void 0 : navAxisOptions.min), numExt('min', time.parse(baseAxisOptions.min), baseAxis.dataMin, navAxis.dataMin, navAxis.min)),
                dataMax: Navigator_pick(time.parse(navAxisOptions === null || navAxisOptions === void 0 ? void 0 : navAxisOptions.max), numExt('max', time.parse(baseAxisOptions.max), baseAxis.dataMax, navAxis.dataMax, navAxis.max))
            };
        }
        return ret;
    };
    /**
     * Set the base series and update the navigator series from this. With a bit
     * of modification we should be able to make this an API method to be called
     * from the outside
     *
     * @private
     * @function Highcharts.Navigator#setBaseSeries
     * @param {Highcharts.SeriesOptionsType} [baseSeriesOptions]
     *        Additional series options for a navigator
     * @param {boolean} [redraw]
     *        Whether to redraw after update.
     */
    Navigator.prototype.setBaseSeries = function (baseSeriesOptions, redraw) {
        var chart = this.chart,
            baseSeries = this.baseSeries = [];
        baseSeriesOptions = (baseSeriesOptions ||
            chart.options && chart.options.navigator.baseSeries ||
            (chart.series.length ?
                // Find the first non-navigator series (#8430)
                Navigator_find(chart.series, function (s) { return (!s.options.isInternal); }).index :
                0));
        // Iterate through series and add the ones that should be shown in
        // navigator.
        (chart.series || []).forEach(function (series, i) {
            if (
            // Don't include existing nav series
            !series.options.isInternal &&
                (series.options.showInNavigator ||
                    (i === baseSeriesOptions ||
                        series.options.id === baseSeriesOptions) &&
                        series.options.showInNavigator !== false)) {
                baseSeries.push(series);
            }
        });
        // When run after render, this.xAxis already exists
        if (this.xAxis && !this.xAxis.navigatorAxis.fake) {
            this.updateNavigatorSeries(true, redraw);
        }
    };
    /**
     * Update series in the navigator from baseSeries, adding new if does not
     * exist.
     *
     * @private
     * @function Highcharts.Navigator.updateNavigatorSeries
     */
    Navigator.prototype.updateNavigatorSeries = function (addEvents, redraw) {
        var _a,
            _b;
        var navigator = this,
            chart = navigator.chart,
            baseSeries = navigator.baseSeries,
            navSeriesMixin = {
                enableMouseTracking: false,
                index: null, // #6162
                linkedTo: null, // #6734
                group: 'nav', // For columns
                padXAxis: false,
                xAxis: (_a = this.navigatorOptions.xAxis) === null || _a === void 0 ? void 0 : _a.id,
                yAxis: (_b = this.navigatorOptions.yAxis) === null || _b === void 0 ? void 0 : _b.id,
                showInLegend: false,
                stacking: void 0, // #4823
                isInternal: true,
                states: {
                    inactive: {
                        opacity: 1
                    }
                }
            }, 
            // Remove navigator series that are no longer in the baseSeries
            navigatorSeries = navigator.series =
                (navigator.series || []).filter(function (navSeries) {
                    var base = navSeries.baseSeries;
                if (baseSeries.indexOf(base) < 0) { // Not in array
                    // If there is still a base series connected to this
                    // series, remove event handler and reference.
                    if (base) {
                        Navigator_removeEvent(base, 'updatedData', navigator.updatedDataHandler);
                        delete base.navigatorSeries;
                    }
                    // Kill the nav series. It may already have been
                    // destroyed (#8715).
                    if (navSeries.chart) {
                        navSeries.destroy();
                    }
                    return false;
                }
                return true;
            });
        var baseOptions,
            mergedNavSeriesOptions,
            chartNavigatorSeriesOptions = navigator.navigatorOptions.series,
            baseNavigatorOptions;
        // Go through each base series and merge the options to create new
        // series
        if (baseSeries && baseSeries.length) {
            baseSeries.forEach(function (base) {
                var _a;
                var linkedNavSeries = base.navigatorSeries,
                    userNavOptions = Navigator_extend(
                    // Grab color and visibility from base as default
                    {
                        color: base.color,
                        visible: base.visible
                    }, !Navigator_isArray(chartNavigatorSeriesOptions) ?
                        chartNavigatorSeriesOptions :
                        Navigator_defaultOptions.navigator.series);
                // Don't update if the series exists in nav and we have disabled
                // adaptToUpdatedData.
                if (linkedNavSeries &&
                    navigator.navigatorOptions.adaptToUpdatedData === false) {
                    return;
                }
                navSeriesMixin.name = 'Navigator ' + baseSeries.length;
                baseOptions = base.options || {};
                baseNavigatorOptions = baseOptions.navigatorOptions || {};
                // The dataLabels options are not merged correctly
                // if the settings are an array, #13847.
                userNavOptions.dataLabels = Navigator_splat(userNavOptions.dataLabels);
                mergedNavSeriesOptions = Navigator_merge(baseOptions, navSeriesMixin, userNavOptions, baseNavigatorOptions);
                // Once nav series type is resolved, pick correct pointRange
                mergedNavSeriesOptions.pointRange = Navigator_pick(
                // Stricte set pointRange in options
                userNavOptions.pointRange, baseNavigatorOptions.pointRange, 
                // Fallback to default values, e.g. `null` for column
                Navigator_defaultOptions.plotOptions[mergedNavSeriesOptions.type || 'line'].pointRange);
                // Merge data separately. Do a slice to avoid mutating the
                // navigator options from base series (#4923).
                var navigatorSeriesData = baseNavigatorOptions.data || userNavOptions.data;
                navigator.hasNavigatorData =
                    navigator.hasNavigatorData || !!navigatorSeriesData;
                mergedNavSeriesOptions.data = (navigatorSeriesData ||
                    ((_a = baseOptions.data) === null || _a === void 0 ? void 0 : _a.slice(0)));
                // Update or add the series
                if (linkedNavSeries && linkedNavSeries.options) {
                    linkedNavSeries.update(mergedNavSeriesOptions, redraw);
                }
                else {
                    base.navigatorSeries = chart.initSeries(mergedNavSeriesOptions);
                    // Set data on initial run with dataSorting enabled (#20318)
                    chart.setSortedData();
                    base.navigatorSeries.baseSeries = base; // Store ref
                    navigatorSeries.push(base.navigatorSeries);
                }
            });
        }
        // If user has defined data (and no base series) or explicitly defined
        // navigator.series as an array, we create these series on top of any
        // base series.
        if (chartNavigatorSeriesOptions.data &&
            !(baseSeries && baseSeries.length) ||
            Navigator_isArray(chartNavigatorSeriesOptions)) {
            navigator.hasNavigatorData = false;
            // Allow navigator.series to be an array
            chartNavigatorSeriesOptions =
                Navigator_splat(chartNavigatorSeriesOptions);
            chartNavigatorSeriesOptions.forEach(function (userSeriesOptions, i) {
                navSeriesMixin.name =
                    'Navigator ' + (navigatorSeries.length + 1);
                mergedNavSeriesOptions = Navigator_merge(Navigator_defaultOptions.navigator.series, {
                    // Since we don't have a base series to pull color from,
                    // try to fake it by using color from series with same
                    // index. Otherwise pull from the colors array. We need
                    // an explicit color as otherwise updates will increment
                    // color counter and we'll get a new color for each
                    // update of the nav series.
                    color: chart.series[i] &&
                        !chart.series[i].options.isInternal &&
                        chart.series[i].color ||
                        chart.options.colors[i] ||
                        chart.options.colors[0]
                }, navSeriesMixin, userSeriesOptions);
                mergedNavSeriesOptions.data = userSeriesOptions.data;
                if (mergedNavSeriesOptions.data) {
                    navigator.hasNavigatorData = true;
                    navigatorSeries.push(chart.initSeries(mergedNavSeriesOptions));
                }
            });
        }
        if (addEvents) {
            this.addBaseSeriesEvents();
        }
    };
    /**
     * Add data events.
     * For example when main series is updated we need to recalculate extremes
     *
     * @private
     * @function Highcharts.Navigator#addBaseSeriesEvent
     */
    Navigator.prototype.addBaseSeriesEvents = function () {
        var _this = this;
        var navigator = this,
            baseSeries = navigator.baseSeries || [];
        // Bind modified extremes event to first base's xAxis only.
        // In event of > 1 base-xAxes, the navigator will ignore those.
        // Adding this multiple times to the same axis is no problem, as
        // duplicates should be discarded by the browser.
        if (baseSeries[0] && baseSeries[0].xAxis) {
            baseSeries[0].eventsToUnbind.push(Navigator_addEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes));
        }
        baseSeries.forEach(function (base) {
            // Link base series show/hide to navigator series visibility
            base.eventsToUnbind.push(Navigator_addEvent(base, 'show', function () {
                if (this.navigatorSeries) {
                    this.navigatorSeries.setVisible(true, false);
                }
            }));
            base.eventsToUnbind.push(Navigator_addEvent(base, 'hide', function () {
                if (this.navigatorSeries) {
                    this.navigatorSeries.setVisible(false, false);
                }
            }));
            // Respond to updated data in the base series, unless explicitly
            // not adapting to data changes.
            if (_this.navigatorOptions.adaptToUpdatedData !== false) {
                if (base.xAxis) {
                    base.eventsToUnbind.push(Navigator_addEvent(base, 'updatedData', _this.updatedDataHandler));
                }
            }
            // Handle series removal
            base.eventsToUnbind.push(Navigator_addEvent(base, 'remove', function () {
                if (baseSeries) {
                    Navigator_erase(baseSeries, base); // #21043
                }
                if (this.navigatorSeries && navigator.series) {
                    Navigator_erase(navigator.series, this.navigatorSeries);
                    if (Navigator_defined(this.navigatorSeries.options)) {
                        this.navigatorSeries.remove(false);
                    }
                    delete this.navigatorSeries;
                }
            }));
        });
    };
    /**
     * Get minimum from all base series connected to the navigator
     * @private
     * @param {number} currentSeriesMin
     *        Minium from the current series
     * @return {number}
     *         Minimum from all series
     */
    Navigator.prototype.getBaseSeriesMin = function (currentSeriesMin) {
        return this.baseSeries.reduce(function (min, series) {
            var _a;
            // #10193
            return Math.min(min, (_a = series.getColumn('x')[0]) !== null && _a !== void 0 ? _a : min);
        }, currentSeriesMin);
    };
    /**
     * Set the navigator x axis extremes to reflect the total. The navigator
     * extremes should always be the extremes of the union of all series in the
     * chart as well as the navigator series.
     *
     * @private
     * @function Highcharts.Navigator#modifyNavigatorAxisExtremes
     */
    Navigator.prototype.modifyNavigatorAxisExtremes = function () {
        var xAxis = this.xAxis;
        if (typeof xAxis.getExtremes !== 'undefined') {
            var unionExtremes = this.getUnionExtremes(true);
            if (unionExtremes &&
                (unionExtremes.dataMin !== xAxis.min ||
                    unionExtremes.dataMax !== xAxis.max)) {
                xAxis.min = unionExtremes.dataMin;
                xAxis.max = unionExtremes.dataMax;
            }
        }
    };
    /**
     * Hook to modify the base axis extremes with information from the Navigator
     *
     * @private
     * @function Highcharts.Navigator#modifyBaseAxisExtremes
     */
    Navigator.prototype.modifyBaseAxisExtremes = function () {
        var _a;
        var baseXAxis = this,
            navigator = baseXAxis.chart.navigator,
            baseExtremes = baseXAxis.getExtremes(),
            baseMin = baseExtremes.min,
            baseMax = baseExtremes.max,
            baseDataMin = baseExtremes.dataMin,
            baseDataMax = baseExtremes.dataMax,
            range = baseMax - baseMin,
            stickToMin = navigator.stickToMin,
            stickToMax = navigator.stickToMax,
            overscroll = Navigator_pick((_a = baseXAxis.ordinal) === null || _a === void 0 ? void 0 : _a.convertOverscroll(baseXAxis.options.overscroll), 0),
            navigatorSeries = navigator.series && navigator.series[0],
            hasSetExtremes = !!baseXAxis.setExtremes, 
            // When the extremes have been set by range selector button, don't
            // stick to min or max. The range selector buttons will handle the
            // extremes. (#5489)
            unmutable = baseXAxis.eventArgs &&
                baseXAxis.eventArgs.trigger === 'rangeSelectorButton';
        var newMax,
            newMin;
        if (!unmutable) {
            // If the zoomed range is already at the min, move it to the right
            // as new data comes in
            if (stickToMin) {
                newMin = baseDataMin;
                newMax = newMin + range;
            }
            // If the zoomed range is already at the max, move it to the right
            // as new data comes in
            if (stickToMax) {
                newMax = baseDataMax + overscroll;
                // If stickToMin is true, the new min value is set above
                if (!stickToMin) {
                    newMin = Math.max(baseDataMin, // Don't go below data extremes (#13184)
                    newMax - range, navigator.getBaseSeriesMin(navigatorSeries && navigatorSeries.xData ?
                        navigatorSeries.xData[0] :
                        -Number.MAX_VALUE));
                }
            }
            // Update the extremes
            if (hasSetExtremes && (stickToMin || stickToMax)) {
                if (Navigator_isNumber(newMin)) {
                    baseXAxis.min = baseXAxis.userMin = newMin;
                    baseXAxis.max = baseXAxis.userMax = newMax;
                }
            }
        }
        // Reset
        navigator.stickToMin =
            navigator.stickToMax = null;
    };
    /**
     * Handler for updated data on the base series. When data is modified, the
     * navigator series must reflect it. This is called from the Chart.redraw
     * function before axis and series extremes are computed.
     *
     * @private
     * @function Highcharts.Navigator#updateDataHandler
     */
    Navigator.prototype.updatedDataHandler = function () {
        var navigator = this.chart.navigator,
            baseSeries = this,
            navigatorSeries = this.navigatorSeries,
            shouldStickToMax = navigator.reversedExtremes ?
                Math.round(navigator.zoomedMin) === 0 :
                Math.round(navigator.zoomedMax) >= Math.round(navigator.size);
        // If the scrollbar is scrolled all the way to the right, keep right as
        // new data comes in, unless user set navigator.stickToMax to false.
        navigator.stickToMax = Navigator_pick(this.chart.options.navigator &&
            this.chart.options.navigator.stickToMax, shouldStickToMax);
        navigator.stickToMin = navigator.shouldStickToMin(baseSeries, navigator);
        // Set the navigator series data to the new data of the base series
        if (navigatorSeries && !navigator.hasNavigatorData) {
            navigatorSeries.options.pointStart = baseSeries.getColumn('x')[0];
            navigatorSeries.setData(baseSeries.options.data, false, null, false); // #5414
        }
    };
    /**
     * Detect if the zoomed area should stick to the minimum, #14742.
     *
     * @private
     * @function Highcharts.Navigator#shouldStickToMin
     */
    Navigator.prototype.shouldStickToMin = function (baseSeries, navigator) {
        var xDataMin = navigator.getBaseSeriesMin(baseSeries.getColumn('x')[0]),
            xAxis = baseSeries.xAxis,
            max = xAxis.max,
            min = xAxis.min,
            range = xAxis.options.range;
        var stickToMin = true;
        if (Navigator_isNumber(max) && Navigator_isNumber(min)) {
            // If range declared, stick to the minimum only if the range
            // is smaller than the data set range.
            if (range && max - xDataMin > 0) {
                stickToMin = max - xDataMin < range;
            }
            else {
                // If the current axis minimum falls outside the new
                // updated dataset, we must adjust.
                stickToMin = min <= xDataMin;
            }
        }
        else {
            stickToMin = false; // #15864
        }
        return stickToMin;
    };
    /**
     * Add chart events, like redrawing navigator, when chart requires that.
     *
     * @private
     * @function Highcharts.Navigator#addChartEvents
     */
    Navigator.prototype.addChartEvents = function () {
        if (!this.eventsToUnbind) {
            this.eventsToUnbind = [];
        }
        this.eventsToUnbind.push(
        // Move the scrollbar after redraw, like after data updata even if
        // axes don't redraw
        Navigator_addEvent(this.chart, 'redraw', function () {
            var navigator = this.navigator,
                xAxis = navigator && (navigator.baseSeries &&
                    navigator.baseSeries[0] &&
                    navigator.baseSeries[0].xAxis ||
                    this.xAxis[0]); // #5709, #13114
                if (xAxis) {
                    navigator.render(xAxis.min,
                xAxis.max);
            }
        }), 
        // Make room for the navigator, can be placed around the chart:
        Navigator_addEvent(this.chart, 'getMargins', function () {
            var chart = this,
                navigator = chart.navigator;
            var marginName = navigator.opposite ?
                    'plotTop' : 'marginBottom';
            if (chart.inverted) {
                marginName = navigator.opposite ?
                    'marginRight' : 'plotLeft';
            }
            chart[marginName] =
                (chart[marginName] || 0) + (navigator.navigatorEnabled || !chart.inverted ?
                    navigator.height + navigator.scrollbarHeight :
                    0) + navigator.navigatorOptions.margin;
        }), Navigator_addEvent(Navigator, 'setRange', function (e) {
            this.chart.xAxis[0].setExtremes(e.min, e.max, e.redraw, e.animation, e.eventArguments);
        }));
    };
    /**
     * Destroys allocated elements.
     *
     * @private
     * @function Highcharts.Navigator#destroy
     */
    Navigator.prototype.destroy = function () {
        var _this = this;
        // Disconnect events added in addEvents
        this.removeEvents();
        if (this.xAxis) {
            Navigator_erase(this.chart.xAxis, this.xAxis);
            Navigator_erase(this.chart.axes, this.xAxis);
        }
        if (this.yAxis) {
            Navigator_erase(this.chart.yAxis, this.yAxis);
            Navigator_erase(this.chart.axes, this.yAxis);
        }
        // Destroy series
        (this.series || []).forEach(function (s) {
            if (s.destroy) {
                s.destroy();
            }
        });
        // Destroy properties
        [
            'series', 'xAxis', 'yAxis', 'shades', 'outline', 'scrollbarTrack',
            'scrollbarRifles', 'scrollbarGroup', 'scrollbar', 'navigatorGroup',
            'rendered'
        ].forEach(function (prop) {
            if (_this[prop] && _this[prop].destroy) {
                _this[prop].destroy();
            }
            _this[prop] = null;
        });
        // Destroy elements in collection
        [this.handles].forEach(function (coll) {
            Navigator_destroyObjectProperties(coll);
        });
        this.navigatorEnabled = false;
    };
    return Navigator;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Navigator_Navigator = (Navigator);

;// ./code/es5/es-modules/Stock/RangeSelector/RangeSelectorDefaults.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  Declarations
 *
 * */
/**
 * An object containing language-related strings and settings. A typical setup
 * uses `Highcharts.setOptions` to make the options apply to all charts in the
 * same page.
 *
 * ```js
 * Highcharts.setOptions({
 *     lang: {
 *         locale: 'fr'
 *     }
 * });
 * ```
 *
 * @optionparent lang
 */
var lang = {
    /**
     * The text for the label for the range selector buttons.
     *
     * @product highstock gantt
     */
    rangeSelectorZoom: 'Zoom',
    /**
     * The text for the label for the "from" input box in the range
     * selector. Since v9.0, this string is empty as the label is not
     * rendered by default.
     *
     * @product highstock gantt
     */
    rangeSelectorFrom: '',
    /**
     * The text for the label for the "to" input box in the range selector.
     *
     * @product highstock gantt
     */
    rangeSelectorTo: '→'
};
/**
 * The range selector is a tool for selecting ranges to display within
 * the chart. It provides buttons to select preconfigured ranges in
 * the chart, like 1 day, 1 week, 1 month etc. It also provides input
 * boxes where min and max dates can be manually input.
 *
 * @product      highstock gantt
 * @optionparent rangeSelector
 */
var rangeSelector = {
    /**
     * Whether to enable all buttons from the start. By default buttons are
     * only enabled if the corresponding time range exists on the X axis,
     * but enabling all buttons allows for dynamically loading different
     * time ranges.
     *
     * @sample {highstock} stock/rangeselector/allbuttonsenabled-true/
     *         All buttons enabled
     *
     * @since     2.0.3
     */
    allButtonsEnabled: false,
    /**
     * An array of configuration objects for the buttons.
     *
     * Defaults to:
     * ```js
     * buttons: [{
     *     type: 'month',
     *     count: 1,
     *     text: '1m',
     *     title: 'View 1 month'
     * }, {
     *     type: 'month',
     *     count: 3,
     *     text: '3m',
     *     title: 'View 3 months'
     * }, {
     *     type: 'month',
     *     count: 6,
     *     text: '6m',
     *     title: 'View 6 months'
     * }, {
     *     type: 'ytd',
     *     text: 'YTD',
     *     title: 'View year to date'
     * }, {
     *     type: 'year',
     *     count: 1,
     *     text: '1y',
     *     title: 'View 1 year'
     * }, {
     *     type: 'all',
     *     text: 'All',
     *     title: 'View all'
     * }]
     * ```
     *
     * @sample {highstock} stock/demo/rangeselector-datagrouping/
     *         Data grouping by buttons
     *
     * @type      {Array<*>}
     */
    buttons: [{
            type: 'month',
            count: 1,
            text: '1m',
            title: 'View 1 month'
        }, {
            type: 'month',
            count: 3,
            text: '3m',
            title: 'View 3 months'
        }, {
            type: 'month',
            count: 6,
            text: '6m',
            title: 'View 6 months'
        }, {
            type: 'ytd',
            text: 'YTD',
            title: 'View year to date'
        }, {
            type: 'year',
            count: 1,
            text: '1y',
            title: 'View 1 year'
        }, {
            type: 'all',
            text: 'All',
            title: 'View all'
        }],
    /**
     * How many units of the defined type the button should span. If `type`
     * is "month" and `count` is 3, the button spans three months.
     *
     * @type      {number}
     * @default   1
     * @apioption rangeSelector.buttons.count
     */
    /**
     * Fires when clicking on the rangeSelector button. One parameter,
     * event, is passed to the function, containing common event
     * information.
     *
     * ```js
     * click: function(e) {
     *   console.log(this);
     * }
     * ```
     *
     * Return false to stop default button's click action.
     *
     * @sample {highstock} stock/rangeselector/button-click/
     *         Click event on the button
     *
     * @type      {Highcharts.RangeSelectorClickCallbackFunction}
     * @apioption rangeSelector.buttons.events.click
     */
    /**
     * Additional range (in milliseconds) added to the end of the calculated
     * time span.
     *
     * @sample {highstock} stock/rangeselector/min-max-offsets/
     *         Button offsets
     *
     * @type      {number}
     * @default   0
     * @since     6.0.0
     * @apioption rangeSelector.buttons.offsetMax
     */
    /**
     * Additional range (in milliseconds) added to the start of the
     * calculated time span.
     *
     * @sample {highstock} stock/rangeselector/min-max-offsets/
     *         Button offsets
     *
     * @type      {number}
     * @default   0
     * @since     6.0.0
     * @apioption rangeSelector.buttons.offsetMin
     */
    /**
     * When buttons apply dataGrouping on a series, by default zooming
     * in/out will deselect buttons and unset dataGrouping. Enable this
     * option to keep buttons selected when extremes change.
     *
     * @sample {highstock} stock/rangeselector/preserve-datagrouping/
     *         Different preserveDataGrouping settings
     *
     * @type      {boolean}
     * @default   false
     * @since     6.1.2
     * @apioption rangeSelector.buttons.preserveDataGrouping
     */
    /**
     * A custom data grouping object for each button.
     *
     * @see [series.dataGrouping](#plotOptions.series.dataGrouping)
     *
     * @sample {highstock} stock/demo/rangeselector-datagrouping/
     *         Data grouping by range selector buttons
     *
     * @type      {*}
     * @extends   plotOptions.series.dataGrouping
     * @apioption rangeSelector.buttons.dataGrouping
     */
    /**
     * The text for the button itself.
     *
     * @type      {string}
     * @apioption rangeSelector.buttons.text
     */
    /**
     * Explanation for the button, shown as a tooltip on hover, and used by
     * assistive technology.
     *
     * @type      {string}
     * @apioption rangeSelector.buttons.title
     */
    /**
     * Defined the time span for the button. Can be one of `millisecond`,
     * `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `ytd`,
     * and `all`.
     *
     * @type       {Highcharts.RangeSelectorButtonTypeValue}
     * @apioption  rangeSelector.buttons.type
     */
    /**
     * The space in pixels between the buttons in the range selector.
     */
    buttonSpacing: 5,
    /**
     * Whether to collapse the range selector buttons into a dropdown when
     * there is not enough room to show everything in a single row, instead
     * of dividing the range selector into multiple rows.
     * Can be one of the following:
     *  - `always`: Always collapse
     *  - `responsive`: Only collapse when there is not enough room
     *  - `never`: Never collapse
     *
     * @sample {highstock} stock/rangeselector/dropdown/
     *         Dropdown option
     *
     * @validvalue ["always", "responsive", "never"]
     * @since 9.0.0
     */
    dropdown: 'responsive',
    /**
     * Enable or disable the range selector. Default to `true` for stock
     * charts, using the `stockChart` factory.
     *
     * @sample {highstock} stock/rangeselector/enabled/
     *         Disable the range selector
     *
     * @type {boolean|undefined}
     * @default {highstock} true
     */
    enabled: void 0,
    /**
     * The vertical alignment of the rangeselector box. Allowed properties
     * are `top`, `middle`, `bottom`.
     *
     * @sample {highstock} stock/rangeselector/vertical-align-middle/
     *         Middle
     * @sample {highstock} stock/rangeselector/vertical-align-bottom/
     *         Bottom
     *
     * @type  {Highcharts.VerticalAlignValue}
     * @since 6.0.0
     */
    verticalAlign: 'top',
    /**
     * A collection of attributes for the buttons. The object takes SVG
     * attributes like `fill`, `stroke`, `stroke-width`, as well as `style`,
     * a collection of CSS properties for the text.
     *
     * The object can also be extended with states, so you can set
     * presentational options for `hover`, `select` or `disabled` button
     * states.
     *
     * CSS styles for the text label.
     *
     * In styled mode, the buttons are styled by the
     * `.highcharts-range-selector-buttons .highcharts-button` rule with its
     * different states.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @type {Highcharts.SVGAttributes}
     */
    buttonTheme: {
        /** @ignore */
        width: 28,
        /** @ignore */
        height: 18,
        /** @ignore */
        padding: 2,
        /** @ignore */
        zIndex: 7 // #484, #852
    },
    /**
     * When the rangeselector is floating, the plot area does not reserve
     * space for it. This opens for positioning anywhere on the chart.
     *
     * @sample {highstock} stock/rangeselector/floating/
     *         Placing the range selector between the plot area and the
     *         navigator
     *
     * @since 6.0.0
     */
    floating: false,
    /**
     * The x offset of the range selector relative to its horizontal
     * alignment within `chart.spacingLeft` and `chart.spacingRight`.
     *
     * @since 6.0.0
     */
    x: 0,
    /**
     * The y offset of the range selector relative to its horizontal
     * alignment within `chart.spacingLeft` and `chart.spacingRight`.
     *
     * @since 6.0.0
     */
    y: 0,
    /**
     * Deprecated. The height of the range selector. Currently it is
     * calculated dynamically.
     *
     * @deprecated
     * @type  {number|undefined}
     * @since 2.1.9
     */
    height: void 0, // Reserved space for buttons and input
    /**
     * The border color of the date input boxes.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @type      {Highcharts.ColorString}
     * @since     1.3.7
     */
    inputBoxBorderColor: 'none',
    /**
     * The pixel height of the date input boxes.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @since     1.3.7
     */
    inputBoxHeight: 17,
    /**
     * The pixel width of the date input boxes. When `undefined`, the width
     * is fitted to the rendered content.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @type   {number|undefined}
     * @since  1.3.7
     */
    inputBoxWidth: void 0,
    /**
     * The date format in the input boxes when not selected for editing.
     * Defaults to `%e %b %Y`.
     *
     * This is used to determine which type of input to show,
     * `datetime-local`, `date` or `time` and falling back to `text` when
     * the browser does not support the input type or the format contains
     * milliseconds.
     *
     * @sample {highstock} stock/rangeselector/input-type/
     *         Input types
     * @sample {highstock} stock/rangeselector/input-format/
     *         Milliseconds in the range selector
     *
     */
    inputDateFormat: '%[ebY]',
    /**
     * A custom callback function to parse values entered in the input boxes and
     * return a valid JavaScript time as milliseconds since 1970. The first
     * argument passed is the value to parse, second is a boolean indicating use
     * of UTC time. The third is a reference to the `time` object. Time zone can
     * be read from `time.timezone`.
     *
     * This will only get called for inputs of type `text`. Since v8.2.3, the
     * input type is dynamically determined based on the granularity of the
     * `inputDateFormat` and the browser support.
     *
     * @sample {highstock} stock/rangeselector/input-format/
     *         Milliseconds in the range selector
     *
     * @type      {Highcharts.RangeSelectorParseCallbackFunction}
     * @since     1.3.3
     */
    inputDateParser: void 0,
    /**
     * The date format in the input boxes when they are selected for
     * editing. This must be a format that is recognized by JavaScript
     * Date.parse.
     *
     * This will only be used for inputs of type `text`. Since v8.2.3,
     * the input type is dynamically determined based on the granularity
     * of the `inputDateFormat` and the browser support.
     *
     * @sample {highstock} stock/rangeselector/input-format/
     *         Milliseconds in the range selector
     *
     */
    inputEditDateFormat: '%Y-%m-%d',
    /**
     * Enable or disable the date input boxes.
     */
    inputEnabled: true,
    /**
     * Positioning for the input boxes. Allowed properties are `align`,
     *  `x` and `y`.
     *
     * @since 1.2.4
     */
    inputPosition: {
        /**
         * The alignment of the input box. Allowed properties are `left`,
         * `center`, `right`.
         *
         * @sample {highstock} stock/rangeselector/input-button-opposite-alignment/
         *         Opposite alignment
         *
         * @sample {highstock} stock/rangeselector/input-button-same-alignment/
         *         Same alignment for buttons and input
         *
         * @type  {Highcharts.AlignValue}
         * @since 6.0.0
         */
        align: 'right',
        /**
         * X offset of the input row.
         */
        x: 0,
        /**
         * Y offset of the input row.
         */
        y: 0
    },
    /**
     * The space in pixels between the labels and the date input boxes in
     * the range selector.
     *
     * @since 9.0.0
     */
    inputSpacing: 5,
    /**
     * The index of the button to appear pre-selected. If the selected range
     * exceeds the total data range and the 'all' option is available,
     * the 'all' option, showing the full range, is automatically selected.
     *
     * @type      {number}
     */
    selected: void 0,
    /**
     * Positioning for the button row.
     *
     * @since 1.2.4
     */
    buttonPosition: {
        /**
         * The alignment of the input box. Allowed properties are `left`,
         * `center`, `right`.
         *
         * @sample {highstock} stock/rangeselector/input-button-opposite-alignment/
         *         Opposite alignment
         *
         * @sample {highstock} stock/rangeselector/input-button-same-alignment/
         *         Same alignment for buttons and input
         *
         * @type  {Highcharts.AlignValue}
         * @since 6.0.0
         */
        align: 'left',
        /**
         * X offset of the button row.
         */
        x: 0,
        /**
         * Y offset of the button row.
         */
        y: 0
    },
    /**
     * CSS for the HTML inputs in the range selector.
     *
     * In styled mode, the inputs are styled by the
     * `.highcharts-range-input text` rule in SVG mode, and
     * `input.highcharts-range-selector` when active.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @type      {Highcharts.CSSObject}
     * @apioption rangeSelector.inputStyle
     */
    inputStyle: {
        /** @ignore */
        color: "#334eff" /* Palette.highlightColor80 */,
        /** @ignore */
        cursor: 'pointer',
        /** @ignore */
        fontSize: '0.8em'
    },
    /**
     * CSS styles for the labels - the Zoom, From and To texts.
     *
     * In styled mode, the labels are styled by the
     * `.highcharts-range-label` class.
     *
     * @sample {highstock} stock/rangeselector/styling/
     *         Styling the buttons and inputs
     *
     * @type {Highcharts.CSSObject}
     */
    labelStyle: {
        /** @ignore */
        color: "#666666" /* Palette.neutralColor60 */,
        /** @ignore */
        fontSize: '0.8em'
    }
};
/* *
 *
 *  Default Export
 *
 * */
var RangeSelectorDefaults = {
    lang: lang,
    rangeSelector: rangeSelector
};
/* harmony default export */ var RangeSelector_RangeSelectorDefaults = (RangeSelectorDefaults);

;// ./code/es5/es-modules/Stock/RangeSelector/RangeSelectorComposition.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var RangeSelectorComposition_defaultOptions = Defaults.defaultOptions;

var RangeSelectorComposition_composed = Core_Globals.composed;


var RangeSelectorComposition_addEvent = Core_Utilities.addEvent, RangeSelectorComposition_defined = Core_Utilities.defined, RangeSelectorComposition_extend = Core_Utilities.extend, RangeSelectorComposition_isNumber = Core_Utilities.isNumber, RangeSelectorComposition_merge = Core_Utilities.merge, RangeSelectorComposition_pick = Core_Utilities.pick, RangeSelectorComposition_pushUnique = Core_Utilities.pushUnique;
/* *
 *
 *  Constants
 *
 * */
var chartDestroyEvents = [];
/* *
 *
 *  Variables
 *
 * */
var RangeSelectorConstructor;
/* *
 *
 *  Functions
 *
 * */
/**
 * Get the axis min value based on the range option and the current max. For
 * stock charts this is extended via the {@link RangeSelector} so that if the
 * selected range is a multiple of months or years, it is compensated for
 * various month lengths.
 *
 * @private
 * @function Highcharts.Axis#minFromRange
 * @return {number|undefined}
 *         The new minimum value.
 */
function axisMinFromRange() {
    var rangeOptions = this.range,
        type = rangeOptions.type,
        max = this.max,
        time = this.chart.time, 
        // Get the true range from a start date
        getTrueRange = function (base,
        count) {
            var original = time.toParts(base),
        modified = original.slice();
        if (type === 'year') {
            modified[0] += count;
        }
        else {
            modified[1] += count;
        }
        var d = time.makeTime.apply(time,
            modified);
        var numbers = time.toParts(d);
        // When subtracting a month still places us in the same month, like
        // subtracting one month from March 31 places us on February 31,
        // which translates to March 3 (#6537)
        if (type === 'month' &&
            original[1] === numbers[1] &&
            Math.abs(count) === 1) {
            modified[0] = original[0];
            modified[1] = original[1];
            // 0 is the last day of the previous month
            modified[2] = 0;
        }
        d = time.makeTime.apply(time, modified);
        return d - base;
    };
    var min,
        range;
    if (RangeSelectorComposition_isNumber(rangeOptions)) {
        min = max - rangeOptions;
        range = rangeOptions;
    }
    else if (rangeOptions) {
        min = max + getTrueRange(max, -(rangeOptions.count || 1));
        // Let the fixedRange reflect initial settings (#5930)
        if (this.chart) {
            this.chart.setFixedRange(max - min);
        }
    }
    var dataMin = RangeSelectorComposition_pick(this.dataMin,
        Number.MIN_VALUE);
    if (!RangeSelectorComposition_isNumber(min)) {
        min = dataMin;
    }
    if (min <= dataMin) {
        min = dataMin;
        if (typeof range === 'undefined') { // #4501
            range = getTrueRange(min, rangeOptions.count);
        }
        this.newMax = Math.min(min + range, RangeSelectorComposition_pick(this.dataMax, Number.MAX_VALUE));
    }
    if (!RangeSelectorComposition_isNumber(max)) {
        min = void 0;
    }
    else if (!RangeSelectorComposition_isNumber(rangeOptions) &&
        rangeOptions &&
        rangeOptions._offsetMin) {
        min += rangeOptions._offsetMin;
    }
    return min;
}
/**
 * @private
 */
function updateRangeSelectorButtons() {
    var _a;
    (_a = this.rangeSelector) === null || _a === void 0 ? void 0 : _a.redrawElements();
}
/**
 * @private
 */
function RangeSelectorComposition_compose(AxisClass, ChartClass, RangeSelectorClass) {
    RangeSelectorConstructor = RangeSelectorClass;
    if (RangeSelectorComposition_pushUnique(RangeSelectorComposition_composed, 'RangeSelector')) {
        var chartProto = ChartClass.prototype;
        AxisClass.prototype.minFromRange = axisMinFromRange;
        RangeSelectorComposition_addEvent(ChartClass, 'afterGetContainer', createRangeSelector);
        RangeSelectorComposition_addEvent(ChartClass, 'beforeRender', RangeSelectorComposition_onChartBeforeRender);
        RangeSelectorComposition_addEvent(ChartClass, 'destroy', onChartDestroy);
        RangeSelectorComposition_addEvent(ChartClass, 'getMargins', onChartGetMargins);
        RangeSelectorComposition_addEvent(ChartClass, 'redraw', redrawRangeSelector);
        RangeSelectorComposition_addEvent(ChartClass, 'update', RangeSelectorComposition_onChartUpdate);
        RangeSelectorComposition_addEvent(ChartClass, 'beforeRedraw', updateRangeSelectorButtons);
        chartProto.callbacks.push(redrawRangeSelector);
        RangeSelectorComposition_extend(RangeSelectorComposition_defaultOptions, { rangeSelector: RangeSelector_RangeSelectorDefaults.rangeSelector });
        RangeSelectorComposition_extend(RangeSelectorComposition_defaultOptions.lang, RangeSelector_RangeSelectorDefaults.lang);
    }
}
/**
 * Initialize rangeselector for stock charts
 * @private
 */
function createRangeSelector() {
    if (this.options.rangeSelector &&
        this.options.rangeSelector.enabled) {
        this.rangeSelector = new RangeSelectorConstructor(this);
    }
}
/**
 * @private
 */
function RangeSelectorComposition_onChartBeforeRender() {
    var chart = this,
        rangeSelector = chart.rangeSelector;
    if (rangeSelector) {
        if (RangeSelectorComposition_isNumber(rangeSelector.deferredYTDClick)) {
            rangeSelector.clickButton(rangeSelector.deferredYTDClick);
            delete rangeSelector.deferredYTDClick;
        }
        var verticalAlign = rangeSelector.options.verticalAlign;
        if (!rangeSelector.options.floating) {
            if (verticalAlign === 'bottom') {
                this.extraBottomMargin = true;
            }
            else if (verticalAlign === 'top') {
                this.extraTopMargin = true;
            }
        }
    }
}
function redrawRangeSelector() {
    var chart = this;
    var rangeSelector = this.rangeSelector;
    if (!rangeSelector) {
        return;
    }
    var alignTo;
    var extremes = chart.xAxis[0].getExtremes();
    var legend = chart.legend;
    var verticalAlign = (rangeSelector &&
            rangeSelector.options.verticalAlign);
    if (RangeSelectorComposition_isNumber(extremes.min)) {
        rangeSelector.render(extremes.min, extremes.max);
    }
    // Re-align the legend so that it's below the rangeselector
    if (legend.display &&
        verticalAlign === 'top' &&
        verticalAlign === legend.options.verticalAlign) {
        // Create a new alignment box for the legend.
        alignTo = RangeSelectorComposition_merge(chart.spacingBox);
        if (legend.options.layout === 'vertical') {
            alignTo.y = chart.plotTop;
        }
        else {
            alignTo.y += rangeSelector.getHeight();
        }
        legend.group.placed = false; // Don't animate the alignment.
        legend.align(alignTo);
    }
}
/**
 * Remove resize/afterSetExtremes at chart destroy.
 * @private
 */
function onChartDestroy() {
    for (var i = 0, iEnd = chartDestroyEvents.length; i < iEnd; ++i) {
        var events = chartDestroyEvents[i];
        if (events[0] === this) {
            events[1].forEach(function (unbind) { return unbind(); });
            chartDestroyEvents.splice(i, 1);
            return;
        }
    }
}
/**
 *
 */
function onChartGetMargins() {
    var _a;
    var rangeSelector = this.rangeSelector;
    if ((_a = rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.options) === null || _a === void 0 ? void 0 : _a.enabled) {
        var rangeSelectorHeight = rangeSelector.getHeight();
        var verticalAlign = rangeSelector.options.verticalAlign;
        if (!rangeSelector.options.floating) {
            if (verticalAlign === 'bottom') {
                this.marginBottom += rangeSelectorHeight;
            }
            else if (verticalAlign !== 'middle') {
                this.plotTop += rangeSelectorHeight;
            }
        }
    }
}
/**
 * @private
 */
function RangeSelectorComposition_onChartUpdate(e) {
    var chart = this,
        options = e.options,
        optionsRangeSelector = options.rangeSelector,
        extraBottomMarginWas = this.extraBottomMargin,
        extraTopMarginWas = this.extraTopMargin;
    var rangeSelector = chart.rangeSelector;
    if (optionsRangeSelector &&
        optionsRangeSelector.enabled &&
        !RangeSelectorComposition_defined(rangeSelector) &&
        this.options.rangeSelector) {
        this.options.rangeSelector.enabled = true;
        this.rangeSelector = rangeSelector = new RangeSelectorConstructor(this);
    }
    this.extraBottomMargin = false;
    this.extraTopMargin = false;
    if (rangeSelector) {
        var verticalAlign = (optionsRangeSelector &&
                optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign);
        if (!rangeSelector.options.floating) {
            if (verticalAlign === 'bottom') {
                this.extraBottomMargin = true;
            }
            else if (verticalAlign !== 'middle') {
                this.extraTopMargin = true;
            }
        }
        if (this.extraBottomMargin !== extraBottomMarginWas ||
            this.extraTopMargin !== extraTopMarginWas) {
            this.isDirtyBox = true;
        }
    }
}
/* *
 *
 *  Default Export
 *
 * */
var RangeSelectorComposition = {
    compose: RangeSelectorComposition_compose
};
/* harmony default export */ var RangeSelector_RangeSelectorComposition = (RangeSelectorComposition);

;// ./code/es5/es-modules/Core/Axis/OrdinalAxis.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var OrdinalAxis_assign = (undefined && undefined.__assign) || function () {
    OrdinalAxis_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 OrdinalAxis_assign.apply(this, arguments);
};




var OrdinalAxis_addEvent = Core_Utilities.addEvent, OrdinalAxis_correctFloat = Core_Utilities.correctFloat, OrdinalAxis_css = Core_Utilities.css, OrdinalAxis_defined = Core_Utilities.defined, OrdinalAxis_error = Core_Utilities.error, OrdinalAxis_isNumber = Core_Utilities.isNumber, OrdinalAxis_pick = Core_Utilities.pick, OrdinalAxis_timeUnits = Core_Utilities.timeUnits, OrdinalAxis_isString = Core_Utilities.isString;
/* *
 *
 *  Composition
 *
 * */
/**
 * Extends the axis with ordinal support.
 * @private
 */
var OrdinalAxis;
(function (OrdinalAxis) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Extends the axis with ordinal support.
     *
     * @private
     *
     * @param AxisClass
     * Axis class to extend.
     *
     * @param ChartClass
     * Chart class to use.
     *
     * @param SeriesClass
     * Series class to use.
     */
    function compose(AxisClass, SeriesClass, ChartClass) {
        var axisProto = AxisClass.prototype;
        if (!axisProto.ordinal2lin) {
            axisProto.getTimeTicks = getTimeTicks;
            axisProto.index2val = index2val;
            axisProto.lin2val = lin2val;
            axisProto.val2lin = val2lin;
            // Record this to prevent overwriting by broken-axis module (#5979)
            axisProto.ordinal2lin = axisProto.val2lin;
            OrdinalAxis_addEvent(AxisClass, 'afterInit', onAxisAfterInit);
            OrdinalAxis_addEvent(AxisClass, 'foundExtremes', onAxisFoundExtremes);
            OrdinalAxis_addEvent(AxisClass, 'afterSetScale', onAxisAfterSetScale);
            OrdinalAxis_addEvent(AxisClass, 'initialAxisTranslation', onAxisInitialAxisTranslation);
            OrdinalAxis_addEvent(ChartClass, 'pan', onChartPan);
            OrdinalAxis_addEvent(ChartClass, 'touchpan', onChartPan);
            OrdinalAxis_addEvent(SeriesClass, 'updatedData', onSeriesUpdatedData);
        }
        return AxisClass;
    }
    OrdinalAxis.compose = compose;
    /**
     * In an ordinal axis, there might be areas with dense concentrations of
     * points, then large gaps between some. Creating equally distributed
     * ticks over this entire range may lead to a huge number of ticks that
     * will later be removed. So instead, break the positions up in
     * segments, find the tick positions for each segment then concatenize
     * them. This method is used from both data grouping logic and X axis
     * tick position logic.
     * @private
     */
    function getTimeTicks(normalizedInterval, min, max, startOfWeek, positions, closestDistance, findHigherRanks) {
        if (positions === void 0) { positions = []; }
        if (closestDistance === void 0) { closestDistance = 0; }
        var higherRanks = {},
            tickPixelIntervalOption = this.options.tickPixelInterval,
            time = this.chart.time, 
            // Record all the start positions of a segment, to use when
            // deciding what's a gap in the data.
            segmentStarts = [];
        var end,
            segmentPositions,
            hasCrossedHigherRank,
            info,
            outsideMax,
            start = 0,
            groupPositions = [],
            lastGroupPosition = -Number.MAX_VALUE;
        // The positions are not always defined, for example for ordinal
        // positions when data has regular interval (#1557, #2090)
        if ((!this.options.ordinal && !this.options.breaks) ||
            !positions ||
            positions.length < 3 ||
            typeof min === 'undefined') {
            return time.getTimeTicks.apply(time, arguments);
        }
        // Analyze the positions array to split it into segments on gaps
        // larger than 5 times the closest distance. The closest distance is
        // already found at this point, so we reuse that instead of
        // computing it again.
        var posLength = positions.length;
        for (end = 0; end < posLength; end++) {
            outsideMax = end && positions[end - 1] > max;
            if (positions[end] < min) { // Set the last position before min
                start = end;
            }
            if (end === posLength - 1 ||
                positions[end + 1] - positions[end] > closestDistance * 5 ||
                outsideMax) {
                // For each segment, calculate the tick positions from the
                // getTimeTicks utility function. The interval will be the
                // same regardless of how long the segment is.
                if (positions[end] > lastGroupPosition) { // #1475
                    segmentPositions = time.getTimeTicks(normalizedInterval, positions[start], positions[end], startOfWeek);
                    // Prevent duplicate groups, for example for multiple
                    // segments within one larger time frame (#1475)
                    while (segmentPositions.length &&
                        segmentPositions[0] <= lastGroupPosition) {
                        segmentPositions.shift();
                    }
                    if (segmentPositions.length) {
                        lastGroupPosition =
                            segmentPositions[segmentPositions.length - 1];
                    }
                    segmentStarts.push(groupPositions.length);
                    groupPositions = groupPositions.concat(segmentPositions);
                }
                // Set start of next segment
                start = end + 1;
            }
            if (outsideMax) {
                break;
            }
        }
        // Get the grouping info from the last of the segments. The info is
        // the same for all segments.
        if (segmentPositions) {
            info = segmentPositions.info;
            // Optionally identify ticks with higher rank, for example
            // when the ticks have crossed midnight.
            if (findHigherRanks && info.unitRange <= OrdinalAxis_timeUnits.hour) {
                end = groupPositions.length - 1;
                // Compare points two by two
                for (start = 1; start < end; start++) {
                    if (time.dateFormat('%d', groupPositions[start]) !==
                        time.dateFormat('%d', groupPositions[start - 1])) {
                        higherRanks[groupPositions[start]] = 'day';
                        hasCrossedHigherRank = true;
                    }
                }
                // If the complete array has crossed midnight, we want
                // to mark the first positions also as higher rank
                if (hasCrossedHigherRank) {
                    higherRanks[groupPositions[0]] = 'day';
                }
                info.higherRanks = higherRanks;
            }
            // Save the info
            info.segmentStarts = segmentStarts;
            groupPositions.info = info;
        }
        else {
            OrdinalAxis_error(12, false, this.chart);
        }
        // Don't show ticks within a gap in the ordinal axis, where the
        // space between two points is greater than a portion of the tick
        // pixel interval
        if (findHigherRanks && OrdinalAxis_defined(tickPixelIntervalOption)) {
            var length_1 = groupPositions.length,
                translatedArr = [],
                distances = [];
            var itemToRemove = void 0,
                translated = void 0,
                lastTranslated = void 0,
                medianDistance = void 0,
                distance = void 0,
                i = length_1;
            // Find median pixel distance in order to keep a reasonably even
            // distance between ticks (#748)
            while (i--) {
                translated = this.translate(groupPositions[i]);
                if (lastTranslated) {
                    distances[i] = lastTranslated - translated;
                }
                translatedArr[i] = lastTranslated = translated;
            }
            distances.sort(function (a, b) { return a - b; });
            medianDistance = distances[Math.floor(distances.length / 2)];
            if (medianDistance < tickPixelIntervalOption * 0.6) {
                medianDistance = null;
            }
            // Now loop over again and remove ticks where needed
            i = groupPositions[length_1 - 1] > max ? length_1 - 1 : length_1; // #817
            lastTranslated = void 0;
            while (i--) {
                translated = translatedArr[i];
                distance = Math.abs(lastTranslated - translated);
                // #4175 - when axis is reversed, the distance, is negative but
                // tickPixelIntervalOption positive, so we need to compare the
                // same values
                // Remove ticks that are closer than 0.6 times the pixel
                // interval from the one to the right, but not if it is close to
                // the median distance (#748).
                if (lastTranslated &&
                    distance < tickPixelIntervalOption * 0.8 &&
                    (medianDistance === null || distance < medianDistance * 0.8)) {
                    // Is this a higher ranked position with a normal
                    // position to the right?
                    if (higherRanks[groupPositions[i]] &&
                        !higherRanks[groupPositions[i + 1]]) {
                        // Yes: remove the lower ranked neighbour to the
                        // right
                        itemToRemove = i + 1;
                        lastTranslated = translated; // #709
                    }
                    else {
                        // No: remove this one
                        itemToRemove = i;
                    }
                    groupPositions.splice(itemToRemove, 1);
                }
                else {
                    lastTranslated = translated;
                }
            }
        }
        return groupPositions;
    }
    /**
     * Get axis position of given index of the extended ordinal positions.
     * Used only when panning an ordinal axis.
     *
     * @private
     * @function Highcharts.Axis#index2val
     * @param {number} index
     * The index value of searched point
     */
    function index2val(index) {
        var axis = this,
            ordinal = axis.ordinal, 
            // Context could be changed to extendedOrdinalPositions.
            ordinalPositions = ordinal.positions;
        // The visible range contains only equally spaced values.
        if (!ordinalPositions) {
            return index;
        }
        var i = ordinalPositions.length - 1,
            distance;
        if (index < 0) { // Out of range, in effect panning to the left
            index = ordinalPositions[0];
        }
        else if (index > i) { // Out of range, panning to the right
            index = ordinalPositions[i];
        }
        else { // Split it up
            i = Math.floor(index);
            distance = index - i; // The decimal
        }
        if (typeof distance !== 'undefined' &&
            typeof ordinalPositions[i] !== 'undefined') {
            return ordinalPositions[i] + (distance ?
                distance *
                    (ordinalPositions[i + 1] - ordinalPositions[i]) :
                0);
        }
        return index;
    }
    /**
     * Translate from linear (internal) to axis value.
     *
     * @private
     * @function Highcharts.Axis#lin2val
     * @param {number} val
     * The linear abstracted value.
     */
    function lin2val(val) {
        var axis = this,
            ordinal = axis.ordinal,
            localMin = axis.old ? axis.old.min : axis.min,
            localA = axis.old ? axis.old.transA : axis.transA;
        // Always use extendedPositions (#19816)
        var positions = ordinal.getExtendedPositions();
        // In some cases (especially in early stages of the chart creation) the
        // getExtendedPositions might return undefined.
        if (positions === null || positions === void 0 ? void 0 : positions.length) {
            // Convert back from modivied value to pixels. // #15970
            var pixelVal = OrdinalAxis_correctFloat((val - localMin) * localA +
                    axis.minPixelPadding),
                index = OrdinalAxis_correctFloat(ordinal.getIndexOfPoint(pixelVal,
                positions)),
                mantissa = OrdinalAxis_correctFloat(index % 1);
            // Check if the index is inside position array. If true,
            // read/approximate value for that exact index.
            if (index >= 0 && index <= positions.length - 1) {
                var leftNeighbour = positions[Math.floor(index)],
                    rightNeighbour = positions[Math.ceil(index)],
                    distance = rightNeighbour - leftNeighbour;
                return positions[Math.floor(index)] + mantissa * distance;
            }
        }
        // If the value is outside positions array, return initial value
        return val; // #16784
    }
    /**
     * Internal function to calculate the precise index in ordinalPositions
     * array.
     * @private
     */
    function getIndexInArray(ordinalPositions, val) {
        var index = OrdinalAxis.Additions.findIndexOf(ordinalPositions,
            val,
            true);
        if (ordinalPositions[index] === val) {
            return index;
        }
        var percent = (val - ordinalPositions[index]) /
                (ordinalPositions[index + 1] - ordinalPositions[index]);
        return index + percent;
    }
    /**
    * @private
    */
    function onAxisAfterInit() {
        var axis = this;
        if (!axis.ordinal) {
            axis.ordinal = new OrdinalAxis.Additions(axis);
        }
    }
    /**
     * @private
     */
    function onAxisFoundExtremes() {
        var axis = this,
            eventArgs = axis.eventArgs,
            options = axis.options;
        if (axis.isXAxis &&
            OrdinalAxis_defined(options.overscroll) &&
            options.overscroll !== 0 &&
            OrdinalAxis_isNumber(axis.max) &&
            OrdinalAxis_isNumber(axis.min)) {
            if (axis.options.ordinal && !axis.ordinal.originalOrdinalRange) {
                // Calculate the original ordinal range
                axis.ordinal.getExtendedPositions(false);
            }
            if (axis.max === axis.dataMax &&
                (
                // Panning is an exception. We don't want to apply
                // overscroll when panning over the dataMax
                (eventArgs === null || eventArgs === void 0 ? void 0 : eventArgs.trigger) !== 'pan' ||
                    axis.isInternal) &&
                // Scrollbar buttons are the other execption
                (eventArgs === null || eventArgs === void 0 ? void 0 : eventArgs.trigger) !== 'navigator') {
                var overscroll = axis.ordinal.convertOverscroll(options.overscroll);
                axis.max += overscroll;
                // Live data and buttons require translation for the min:
                if (!axis.isInternal &&
                    OrdinalAxis_defined(axis.userMin) &&
                    (eventArgs === null || eventArgs === void 0 ? void 0 : eventArgs.trigger) !== 'mousewheel') {
                    axis.min += overscroll;
                }
            }
        }
    }
    /**
     * For ordinal axis, that loads data async, redraw axis after data is
     * loaded. If we don't do that, axis will have the same extremes as
     * previously, but ordinal positions won't be calculated. See #10290
     * @private
     */
    function onAxisAfterSetScale() {
        var axis = this;
        if (axis.horiz && !axis.isDirty) {
            axis.isDirty = axis.isOrdinal &&
                axis.chart.navigator &&
                !axis.chart.navigator.adaptToUpdatedData;
        }
    }
    /**
     * @private
     */
    function onAxisInitialAxisTranslation() {
        var axis = this;
        if (axis.ordinal) {
            axis.ordinal.beforeSetTickPositions();
            axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval);
        }
    }
    /**
     * Extending the Chart.pan method for ordinal axes
     * @private
     */
    function onChartPan(e) {
        var chart = this,
            xAxis = chart.xAxis[0],
            overscroll = xAxis.ordinal.convertOverscroll(xAxis.options.overscroll),
            chartX = e.originalEvent.chartX,
            panning = chart.options.chart.panning;
        var runBase = false;
        if (panning &&
            panning.type !== 'y' &&
            xAxis.options.ordinal &&
            xAxis.series.length &&
            // On touch devices, let default function handle the pinching
            (!e.touches || e.touches.length <= 1)) {
            var mouseDownX = chart.mouseDownX,
                extremes = xAxis.getExtremes(),
                dataMin = extremes.dataMin,
                dataMax = extremes.dataMax,
                min = extremes.min,
                max = extremes.max,
                hoverPoints = chart.hoverPoints,
                closestPointRange = (xAxis.closestPointRange ||
                    (xAxis.ordinal && xAxis.ordinal.overscrollPointsRange)),
                pointPixelWidth = (xAxis.translationSlope *
                    (xAxis.ordinal.slope || closestPointRange)), 
                // How many ordinal units did we move?
                movedUnits = Math.round((mouseDownX - chartX) / pointPixelWidth), 
                // Get index of all the chart's points
                extendedOrdinalPositions = xAxis.ordinal.getExtendedPositions(),
                extendedAxis = {
                    ordinal: {
                        positions: extendedOrdinalPositions,
                        extendedOrdinalPositions: extendedOrdinalPositions
                    }
                },
                index2val_1 = xAxis.index2val,
                val2lin_1 = xAxis.val2lin;
            var trimmedRange = void 0,
                ordinalPositions = void 0;
            // Make sure panning to the edges does not decrease the zoomed range
            if ((min <= dataMin && movedUnits < 0) ||
                (max + overscroll >= dataMax && movedUnits > 0)) {
                return;
            }
            // We have an ordinal axis, but the data is equally spaced
            if (!extendedAxis.ordinal.positions) {
                runBase = true;
            }
            else if (Math.abs(movedUnits) > 1) {
                // Remove active points for shared tooltip
                if (hoverPoints) {
                    hoverPoints.forEach(function (point) {
                        point.setState();
                    });
                }
                // In grouped data series, the last ordinal position represents
                // the grouped data, which is to the left of the real data max.
                // If we don't compensate for this, we will be allowed to pan
                // grouped data series passed the right of the plot area.
                ordinalPositions = extendedAxis.ordinal.positions;
                if (dataMax >
                    ordinalPositions[ordinalPositions.length - 1]) {
                    ordinalPositions.push(dataMax);
                }
                // Get the new min and max values by getting the ordinal index
                // for the current extreme, then add the moved units and
                // translate back to values. This happens on the extended
                // ordinal positions if the new position is out of range, else
                // it happens on the current x axis which is smaller and faster.
                chart.setFixedRange(max - min);
                trimmedRange = xAxis.navigatorAxis
                    .toFixedRange(void 0, void 0, index2val_1.apply(extendedAxis, [
                    val2lin_1.apply(extendedAxis, [min, true]) +
                        movedUnits
                ]), index2val_1.apply(extendedAxis, [
                    val2lin_1.apply(extendedAxis, [max, true]) +
                        movedUnits
                ]));
                // Apply it if it is within the available data range
                if (trimmedRange.min >= Math.min(ordinalPositions[0], min) &&
                    trimmedRange.max <= Math.max(ordinalPositions[ordinalPositions.length - 1], max) + overscroll) {
                    xAxis.setExtremes(trimmedRange.min, trimmedRange.max, true, false, { trigger: 'pan' });
                }
                chart.mouseDownX = chartX; // Set new reference for next run
                OrdinalAxis_css(chart.container, { cursor: 'move' });
            }
        }
        else {
            runBase = true;
        }
        // Revert to the linear chart.pan version
        if (runBase || (panning && /y/.test(panning.type))) {
            if (overscroll) {
                xAxis.max = xAxis.dataMax + overscroll;
            }
        }
        else {
            e.preventDefault();
        }
    }
    /**
     * @private
     */
    function onSeriesUpdatedData() {
        var xAxis = this.xAxis;
        // Destroy the extended ordinal index on updated data
        // and destroy extendedOrdinalPositions, #16055.
        if (xAxis && xAxis.options.ordinal) {
            delete xAxis.ordinal.index;
            delete xAxis.ordinal.originalOrdinalRange;
        }
    }
    /**
     * Translate from a linear axis value to the corresponding ordinal axis
     * position. If there are no gaps in the ordinal axis this will be the
     * same. The translated value is the value that the point would have if
     * the axis was linear, using the same min and max.
     *
     * @private
     * @function Highcharts.Axis#val2lin
     * @param {number} val
     * The axis value.
     * @param {boolean} [toIndex]
     * Whether to return the index in the ordinalPositions or the new value.
     */
    function val2lin(val, toIndex) {
        var axis = this,
            ordinal = axis.ordinal,
            ordinalPositions = ordinal.positions;
        var slope = ordinal.slope,
            extendedOrdinalPositions;
        if (!ordinalPositions) {
            return val;
        }
        var ordinalLength = ordinalPositions.length;
        var ordinalIndex;
        // If the searched value is inside visible plotArea, ivastigate the
        // value basing on ordinalPositions.
        if (ordinalPositions[0] <= val &&
            ordinalPositions[ordinalLength - 1] >= val) {
            ordinalIndex = getIndexInArray(ordinalPositions, val);
            // Final return value is based on ordinalIndex
        }
        else {
            extendedOrdinalPositions =
                ordinal.getExtendedPositions &&
                    ordinal.getExtendedPositions();
            if (!(extendedOrdinalPositions && extendedOrdinalPositions.length)) {
                return val;
            }
            var length_2 = extendedOrdinalPositions.length;
            if (!slope) {
                slope =
                    (extendedOrdinalPositions[length_2 - 1] -
                        extendedOrdinalPositions[0]) /
                        length_2;
            }
            // `originalPointReference` is equal to the index of first point of
            // ordinalPositions in extendedOrdinalPositions.
            var originalPositionsReference = getIndexInArray(extendedOrdinalPositions,
                ordinalPositions[0]);
            // If the searched value is outside the visiblePlotArea,
            // check if it is inside extendedOrdinalPositions.
            if (val >= extendedOrdinalPositions[0] &&
                val <=
                    extendedOrdinalPositions[length_2 - 1]) {
                // Return Value
                ordinalIndex = getIndexInArray(extendedOrdinalPositions, val) -
                    originalPositionsReference;
            }
            else {
                if (!toIndex) {
                    // If the value is outside positions array,
                    // return initial value, #16784
                    return val;
                }
                // Since ordinal.slope is the average distance between 2
                // points on visible plotArea, this can be used to calculate
                // the approximate position of the point, which is outside
                // the extendedOrdinalPositions.
                if (val < extendedOrdinalPositions[0]) {
                    var diff = extendedOrdinalPositions[0] - val,
                        approximateIndexOffset = diff / slope;
                    ordinalIndex =
                        -originalPositionsReference -
                            approximateIndexOffset;
                }
                else {
                    var diff = val -
                            extendedOrdinalPositions[length_2 - 1],
                        approximateIndexOffset = diff / slope;
                    ordinalIndex =
                        approximateIndexOffset +
                            length_2 -
                            originalPositionsReference;
                }
            }
        }
        return toIndex ? ordinalIndex : slope * (ordinalIndex || 0) +
            ordinal.offset;
    }
    /* *
     *
     *  Classes
     *
     * */
    /**
     * @private
     */
    var Additions = /** @class */ (function () {
            /* *
             *
             *  Constructors
             *
             * */
            /**
             * @private
             */
            function Additions(axis) {
                this.index = {};
            this.axis = axis;
        }
        /* *
        *
        *  Functions
        *
        * */
        /**
         * Calculate the ordinal positions before tick positions are calculated.
         * @private
         */
        Additions.prototype.beforeSetTickPositions = function () {
            var _a;
            var axis = this.axis,
                ordinal = axis.ordinal,
                extremes = axis.getExtremes(),
                min = extremes.min,
                max = extremes.max,
                hasBreaks = (_a = axis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks,
                isOrdinal = axis.options.ordinal;
            var len,
                uniqueOrdinalPositions,
                dist,
                minIndex,
                maxIndex,
                slope,
                i,
                ordinalPositions = [],
                overscrollPointsRange = Number.MAX_VALUE,
                useOrdinal = false,
                adjustOrdinalExtremesPoints = false,
                isBoosted = false;
            // Apply the ordinal logic
            if (isOrdinal || hasBreaks) { // #4167 YAxis is never ordinal ?
                var distanceBetweenPoint_1 = 0;
                axis.series.forEach(function (series, i) {
                    var xData = series.getColumn('x',
                        true);
                    uniqueOrdinalPositions = [];
                    // For an axis with multiple series, check if the distance
                    // between points is identical throughout all series.
                    if (i > 0 &&
                        series.options.id !== 'highcharts-navigator-series' &&
                        xData.length > 1) {
                        adjustOrdinalExtremesPoints = (distanceBetweenPoint_1 !== xData[1] - xData[0]);
                    }
                    distanceBetweenPoint_1 = xData[1] - xData[0];
                    if (series.boosted) {
                        isBoosted = series.boosted;
                    }
                    if (series.reserveSpace() &&
                        (series
                            .takeOrdinalPosition !== false || hasBreaks)) {
                        // Concatenate the processed X data into the existing
                        // positions, or the empty array
                        ordinalPositions = ordinalPositions.concat(xData);
                        len = ordinalPositions.length;
                        // Remove duplicates (#1588)
                        ordinalPositions.sort(function (a, b) {
                            // Without a custom function it is sorted as strings
                            return a - b;
                        });
                        overscrollPointsRange = Math.min(overscrollPointsRange, OrdinalAxis_pick(
                        // Check for a single-point series:
                        series.closestPointRange, overscrollPointsRange));
                        if (len) {
                            i = 0;
                            while (i < len - 1) {
                                if (ordinalPositions[i] !==
                                    ordinalPositions[i + 1]) {
                                    uniqueOrdinalPositions.push(ordinalPositions[i + 1]);
                                }
                                i++;
                            }
                            // Check first item:
                            if (uniqueOrdinalPositions[0] !==
                                ordinalPositions[0]) {
                                uniqueOrdinalPositions.unshift(ordinalPositions[0]);
                            }
                            ordinalPositions = uniqueOrdinalPositions;
                        }
                    }
                });
                if (!axis.ordinal.originalOrdinalRange) {
                    // Calculate current originalOrdinalRange
                    axis.ordinal.originalOrdinalRange =
                        (ordinalPositions.length - 1) * overscrollPointsRange;
                }
                // If the distance between points is not identical throughout
                // all series, remove the first and last ordinal position to
                // avoid enabling ordinal logic when it is not needed, #17405.
                // Only for boosted series because changes are negligible.
                if (adjustOrdinalExtremesPoints && isBoosted) {
                    ordinalPositions.pop();
                    ordinalPositions.shift();
                }
                // Cache the length
                len = ordinalPositions.length;
                // Check if we really need the overhead of mapping axis data
                // against the ordinal positions. If the series consist of
                // evenly spaced data any way, we don't need any ordinal logic.
                if (len > 2) { // Two points have equal distance by default
                    dist = ordinalPositions[1] - ordinalPositions[0];
                    i = len - 1;
                    while (i-- && !useOrdinal) {
                        if (ordinalPositions[i + 1] - ordinalPositions[i] !==
                            dist) {
                            useOrdinal = true;
                        }
                    }
                    // When zooming in on a week, prevent axis padding for
                    // weekends even though the data within the week is evenly
                    // spaced.
                    if (!axis.options.keepOrdinalPadding &&
                        (ordinalPositions[0] - min > dist ||
                            (max -
                                ordinalPositions[ordinalPositions.length - 1]) > dist)) {
                        useOrdinal = true;
                    }
                }
                else if (axis.options.overscroll) {
                    if (len === 2) {
                        // Exactly two points, distance for overscroll is fixed:
                        overscrollPointsRange =
                            ordinalPositions[1] - ordinalPositions[0];
                    }
                    else if (len === 1) {
                        // We have just one point, closest distance is unknown.
                        // Assume then it is last point and overscrolled range:
                        overscrollPointsRange = axis.ordinal.convertOverscroll(axis.options.overscroll);
                        ordinalPositions = [
                            ordinalPositions[0],
                            ordinalPositions[0] + overscrollPointsRange
                        ];
                    }
                    else {
                        // In case of zooming in on overscrolled range, stick to
                        // the old range:
                        overscrollPointsRange = ordinal.overscrollPointsRange;
                    }
                }
                // Record the slope and offset to compute the linear values from
                // the array index. Since the ordinal positions may exceed the
                // current range, get the start and end positions within it
                // (#719, #665b)
                if (useOrdinal || axis.forceOrdinal) {
                    if (axis.options.overscroll) {
                        ordinal.overscrollPointsRange = overscrollPointsRange;
                        ordinalPositions = ordinalPositions.concat(ordinal.getOverscrollPositions());
                    }
                    // Register
                    ordinal.positions = ordinalPositions;
                    // This relies on the ordinalPositions being set. Use
                    // Math.max and Math.min to prevent padding on either sides
                    // of the data.
                    minIndex = axis.ordinal2lin(// #5979
                    Math.max(min, ordinalPositions[0]), true);
                    maxIndex = Math.max(axis.ordinal2lin(Math.min(max, ordinalPositions[ordinalPositions.length - 1]), true), 1); // #3339
                    // Set the slope and offset of the values compared to the
                    // indices in the ordinal positions.
                    ordinal.slope = slope =
                        (max - min) / (maxIndex - minIndex);
                    ordinal.offset = min - (minIndex * slope);
                }
                else {
                    ordinal.overscrollPointsRange = OrdinalAxis_pick(axis.closestPointRange, ordinal.overscrollPointsRange);
                    ordinal.positions = axis.ordinal.slope = ordinal.offset =
                        void 0;
                }
            }
            axis.isOrdinal = isOrdinal && useOrdinal; // #3818, #4196, #4926
            ordinal.groupIntervalFactor = null; // Reset for next run
        };
        /**
         * Faster way of using the Array.indexOf method.
         * Works for sorted arrays only with unique values.
         *
         * @param {Array} sortedArray
         *        The sorted array inside which we are looking for.
         * @param {number} key
         *        The key to being found.
         * @param {boolean} indirectSearch
         *        In case of lack of the point in the array, should return
         *        value be equal to -1 or the closest smaller index.
         *  @private
         */
        Additions.findIndexOf = function (sortedArray, key, indirectSearch) {
            var start = 0,
                end = sortedArray.length - 1,
                middle;
            while (start < end) {
                middle = Math.ceil((start + end) / 2);
                // Key found as the middle element.
                if (sortedArray[middle] <= key) {
                    // Continue searching to the right.
                    start = middle;
                }
                else {
                    // Continue searching to the left.
                    end = middle - 1;
                }
            }
            if (sortedArray[start] === key) {
                return start;
            }
            // Key could not be found.
            return !indirectSearch ? -1 : start;
        };
        /**
         * Get the ordinal positions for the entire data set. This is necessary
         * in chart panning because we need to find out what points or data
         * groups are available outside the visible range. When a panning
         * operation starts, if an index for the given grouping does not exists,
         * it is created and cached. This index is deleted on updated data, so
         * it will be regenerated the next time a panning operation starts.
         * @private
         */
        Additions.prototype.getExtendedPositions = function (withOverscroll) {
            if (withOverscroll === void 0) { withOverscroll = true; }
            var ordinal = this,
                axis = ordinal.axis,
                axisProto = axis.constructor.prototype,
                chart = axis.chart,
                key = axis.series.reduce(function (k,
                series) {
                    var grouping = series.currentDataGrouping;
                return (k +
                    (grouping ? grouping.count + grouping.unitName : 'raw'));
            }, ''), overscroll = withOverscroll ?
                axis.ordinal.convertOverscroll(axis.options.overscroll) : 0, extremes = axis.getExtremes();
            var fakeAxis,
                fakeSeries = void 0,
                ordinalIndex = ordinal.index;
            // If this is the first time, or the ordinal index is deleted by
            // updatedData,
            // create it.
            if (!ordinalIndex) {
                ordinalIndex = ordinal.index = {};
            }
            if (!ordinalIndex[key]) {
                // Create a fake axis object where the extended ordinal
                // positions are emulated
                fakeAxis = {
                    series: [],
                    chart: chart,
                    forceOrdinal: false,
                    getExtremes: function () {
                        return {
                            min: extremes.dataMin,
                            max: extremes.dataMax + overscroll
                        };
                    },
                    applyGrouping: axisProto.applyGrouping,
                    getGroupPixelWidth: axisProto.getGroupPixelWidth,
                    getTimeTicks: axisProto.getTimeTicks,
                    options: {
                        ordinal: true
                    },
                    ordinal: {
                        getGroupIntervalFactor: this.getGroupIntervalFactor
                    },
                    ordinal2lin: axisProto.ordinal2lin, // #6276
                    getIndexOfPoint: axisProto.getIndexOfPoint,
                    val2lin: axisProto.val2lin // #2590
                };
                fakeAxis.ordinal.axis = fakeAxis;
                // Add the fake series to hold the full data, then apply
                // processData to it
                axis.series.forEach(function (series) {
                    var _a,
                        _b,
                        _c;
                    fakeSeries = {
                        xAxis: fakeAxis,
                        chart: chart,
                        groupPixelWidth: series.groupPixelWidth,
                        destroyGroupedData: Core_Globals.noop,
                        getColumn: series.getColumn,
                        applyGrouping: series.applyGrouping,
                        getProcessedData: series.getProcessedData,
                        reserveSpace: series.reserveSpace,
                        visible: series.visible
                    };
                    var xData = series.getColumn('x').concat(withOverscroll ?
                            ordinal.getOverscrollPositions() :
                            []);
                    fakeSeries.dataTable = new Data_DataTableCore({
                        columns: {
                            x: xData
                        }
                    });
                    fakeSeries.options = OrdinalAxis_assign(OrdinalAxis_assign({}, series.options), { dataGrouping: series.currentDataGrouping ? {
                            firstAnchor: (_a = series.options.dataGrouping) === null || _a === void 0 ? void 0 : _a.firstAnchor,
                            anchor: (_b = series.options.dataGrouping) === null || _b === void 0 ? void 0 : _b.anchor,
                            lastAnchor: (_c = series.options.dataGrouping) === null || _c === void 0 ? void 0 : _c.firstAnchor,
                            enabled: true,
                            forced: true,
                            approximation: 'open',
                            units: [[
                                    series.currentDataGrouping.unitName,
                                    [series.currentDataGrouping.count]
                                ]]
                        } : {
                            enabled: false
                        } });
                    fakeAxis.series.push(fakeSeries);
                    series.processData.apply(fakeSeries);
                });
                fakeAxis.applyGrouping({ hasExtremesChanged: true });
                // Force to use the ordinal when points are evenly spaced (e.g.
                // weeks), #3825.
                if (((fakeSeries === null || fakeSeries === void 0 ? void 0 : fakeSeries.closestPointRange) !==
                    (fakeSeries === null || fakeSeries === void 0 ? void 0 : fakeSeries.basePointRange)) &&
                    fakeSeries.currentDataGrouping) {
                    fakeAxis.forceOrdinal = true;
                }
                // Run beforeSetTickPositions to compute the ordinalPositions
                axis.ordinal.beforeSetTickPositions.apply({ axis: fakeAxis });
                if (!axis.ordinal.originalOrdinalRange &&
                    fakeAxis.ordinal.originalOrdinalRange) {
                    axis.ordinal.originalOrdinalRange =
                        fakeAxis.ordinal.originalOrdinalRange;
                }
                // Cache it
                if (fakeAxis.ordinal.positions) {
                    ordinalIndex[key] = fakeAxis.ordinal.positions;
                }
            }
            return ordinalIndex[key];
        };
        /**
         * Find the factor to estimate how wide the plot area would have been if
         * ordinal gaps were included. This value is used to compute an imagined
         * plot width in order to establish the data grouping interval.
         *
         * A real world case is the intraday-candlestick example. Without this
         * logic, it would show the correct data grouping when viewing a range
         * within each day, but once moving the range to include the gap between
         * two days, the interval would include the cut-away night hours and the
         * data grouping would be wrong. So the below method tries to compensate
         * by identifying the most common point interval, in this case days.
         *
         * An opposite case is presented in issue #718. We have a long array of
         * daily data, then one point is appended one hour after the last point.
         * We expect the data grouping not to change.
         *
         * In the future, if we find cases where this estimation doesn't work
         * optimally, we might need to add a second pass to the data grouping
         * logic, where we do another run with a greater interval if the number
         * of data groups is more than a certain fraction of the desired group
         * count.
         * @private
         */
        Additions.prototype.getGroupIntervalFactor = function (xMin, xMax, series) {
            var ordinal = this,
                processedXData = series.getColumn('x',
                true),
                len = processedXData.length,
                distances = [];
            var median,
                i,
                groupIntervalFactor = ordinal.groupIntervalFactor;
            // Only do this computation for the first series, let the other
            // inherit it (#2416)
            if (!groupIntervalFactor) {
                // Register all the distances in an array
                for (i = 0; i < len - 1; i++) {
                    distances[i] = (processedXData[i + 1] -
                        processedXData[i]);
                }
                // Sort them and find the median
                distances.sort(function (a, b) {
                    return a - b;
                });
                median = distances[Math.floor(len / 2)];
                // Compensate for series that don't extend through the entire
                // axis extent. #1675.
                xMin = Math.max(xMin, processedXData[0]);
                xMax = Math.min(xMax, processedXData[len - 1]);
                ordinal.groupIntervalFactor = groupIntervalFactor =
                    (len * median) / (xMax - xMin);
            }
            // Return the factor needed for data grouping
            return groupIntervalFactor;
        };
        /**
         * Get index of point inside the ordinal positions array.
         *
         * @private
         * @param {number} pixelVal
         * The pixel value of a point.
         *
         * @param {Array<number>} [ordinalArray]
         * An array of all points available on the axis for the given data set.
         * Either ordinalPositions if the value is inside the plotArea or
         * extendedOrdinalPositions if not.
         */
        Additions.prototype.getIndexOfPoint = function (pixelVal, ordinalArray) {
            var ordinal = this,
                axis = ordinal.axis,
                min = axis.min,
                minX = axis.minPixelPadding,
                indexOfMin = getIndexInArray(ordinalArray,
                min);
            var ordinalPointPixelInterval = axis.translationSlope *
                    (ordinal.slope ||
                        axis.closestPointRange ||
                        ordinal.overscrollPointsRange);
            var shiftIndex = OrdinalAxis_correctFloat((pixelVal - minX) / ordinalPointPixelInterval);
            return indexOfMin + shiftIndex;
        };
        /**
         * Get ticks for an ordinal axis within a range where points don't
         * exist. It is required when overscroll is enabled. We can't base on
         * points, because we may not have any, so we use approximated
         * pointRange and generate these ticks between Axis.dataMax,
         * Axis.dataMax + Axis.overscroll evenly spaced. Used in panning and
         * navigator scrolling.
         * @private
         */
        Additions.prototype.getOverscrollPositions = function () {
            var ordinal = this,
                axis = ordinal.axis,
                extraRange = ordinal.convertOverscroll(axis.options.overscroll),
                distance = ordinal.overscrollPointsRange,
                positions = [];
            var max = axis.dataMax;
            if (OrdinalAxis_defined(distance)) {
                // Max + pointRange because we need to scroll to the last
                while (max < axis.dataMax + extraRange) {
                    max += distance;
                    positions.push(max);
                }
            }
            return positions;
        };
        /**
         * Make the tick intervals closer because the ordinal gaps make the
         * ticks spread out or cluster.
         * @private
         */
        Additions.prototype.postProcessTickInterval = function (tickInterval) {
            // Problem: https://jsfiddle.net/highcharts/FQm4E/1/. This is a case
            // where this algorithm doesn't work optimally. In this case, the
            // tick labels are spread out per week, but all the gaps reside
            // within weeks. So we have a situation where the labels are courser
            // than the ordinal gaps, and thus the tick interval should not be
            // altered.
            var ordinal = this,
                axis = ordinal.axis,
                ordinalSlope = ordinal.slope,
                closestPointRange = axis.closestPointRange;
            var ret;
            if (ordinalSlope && closestPointRange) {
                if (!axis.options.breaks) {
                    ret = (tickInterval /
                        (ordinalSlope / closestPointRange));
                }
                else {
                    ret = closestPointRange || tickInterval; // #7275
                }
            }
            else {
                ret = tickInterval;
            }
            return ret;
        };
        /**
         * If overscroll is pixel or pecentage value, convert it to axis range.
         *
         * @private
         * @param {number | string} overscroll
         * Overscroll value in axis range, pixels or percentage value.
         * @return {number}
         * Overscroll value in axis range.
         */
        Additions.prototype.convertOverscroll = function (overscroll) {
            if (overscroll === void 0) { overscroll = 0; }
            var ordinal = this,
                axis = ordinal.axis,
                calculateOverscroll = function (overscrollPercentage) {
                    return OrdinalAxis_pick(ordinal.originalOrdinalRange,
                OrdinalAxis_defined(axis.dataMax) && OrdinalAxis_defined(axis.dataMin) ?
                        axis.dataMax - axis.dataMin : 0) * overscrollPercentage;
            };
            if (OrdinalAxis_isString(overscroll)) {
                var overscrollValue = parseInt(overscroll, 10);
                if (/%$/.test(overscroll)) {
                    // If overscroll is percentage
                    return calculateOverscroll(overscrollValue / 100);
                }
                if (/px/.test(overscroll)) {
                    // If overscroll is pixels, it is limited to 90% of the axis
                    // length to prevent division by zero
                    var limitedOverscrollValue = Math.min(overscrollValue,
                        axis.len * 0.9),
                        pixelToPercent = limitedOverscrollValue / axis.len;
                    return calculateOverscroll(pixelToPercent / (1 - pixelToPercent));
                }
                // If overscroll is a string but not pixels or percentage,
                // return 0 as no overscroll
                return 0;
            }
            return overscroll;
        };
        return Additions;
    }());
    OrdinalAxis.Additions = Additions;
})(OrdinalAxis || (OrdinalAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_OrdinalAxis = (OrdinalAxis);

;// ./code/es5/es-modules/Stock/RangeSelector/RangeSelector.js
/* *
 *
 *  (c) 2010-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var RangeSelector_defaultOptions = Defaults.defaultOptions;





var RangeSelector_addEvent = Core_Utilities.addEvent, RangeSelector_createElement = Core_Utilities.createElement, RangeSelector_css = Core_Utilities.css, RangeSelector_defined = Core_Utilities.defined, RangeSelector_destroyObjectProperties = Core_Utilities.destroyObjectProperties, RangeSelector_diffObjects = Core_Utilities.diffObjects, RangeSelector_discardElement = Core_Utilities.discardElement, RangeSelector_extend = Core_Utilities.extend, RangeSelector_fireEvent = Core_Utilities.fireEvent, RangeSelector_isNumber = Core_Utilities.isNumber, RangeSelector_isString = Core_Utilities.isString, RangeSelector_merge = Core_Utilities.merge, RangeSelector_objectEach = Core_Utilities.objectEach, RangeSelector_pick = Core_Utilities.pick, RangeSelector_splat = Core_Utilities.splat;
/* *
 *
 *  Functions
 *
 * */
/**
 * Get the preferred input type based on a date format string.
 *
 * @private
 * @function preferredInputType
 */
function preferredInputType(format) {
    var hasTimeKey = function (char) {
            return new RegExp("%[[a-zA-Z]*".concat(char)).test(format);
    };
    var ms = RangeSelector_isString(format) ?
            format.indexOf('%L') !== -1 :
            // Implemented but not typed as of 2024
            format.fractionalSecondDigits;
    if (ms) {
        return 'text';
    }
    var date = RangeSelector_isString(format) ?
            ['a', 'A', 'd', 'e', 'w', 'b', 'B', 'm', 'o', 'y', 'Y']
                .some(hasTimeKey) :
            format.dateStyle || format.day || format.month || format.year;
    var time = RangeSelector_isString(format) ?
            ['H', 'k', 'I', 'l', 'M', 'S'].some(hasTimeKey) :
            format.timeStyle || format.hour || format.minute || format.second;
    if (date && time) {
        return 'datetime-local';
    }
    if (date) {
        return 'date';
    }
    if (time) {
        return 'time';
    }
    return 'text';
}
/* *
 *
 *  Class
 *
 * */
/**
 * The range selector.
 *
 * @private
 * @class
 * @name Highcharts.RangeSelector
 * @param {Highcharts.Chart} chart
 */
var RangeSelector = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function RangeSelector(chart) {
        var _this = this;
        this.isDirty = false;
        this.buttonOptions = RangeSelector.prototype.defaultButtons;
        this.initialButtonGroupWidth = 0;
        this.maxButtonWidth = function () {
            var buttonWidth = 0;
            _this.buttons.forEach(function (button) {
                var bBox = button.getBBox();
                if (bBox.width > buttonWidth) {
                    buttonWidth = bBox.width;
                }
            });
            return buttonWidth;
        };
        this.init(chart);
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * @private
     */
    RangeSelector.compose = function (AxisClass, ChartClass) {
        RangeSelector_RangeSelectorComposition.compose(AxisClass, ChartClass, RangeSelector);
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * The method to run when one of the buttons in the range selectors is
     * clicked
     *
     * @private
     * @function Highcharts.RangeSelector#clickButton
     * @param {number} i
     *        The index of the button
     * @param {boolean} [redraw]
     */
    RangeSelector.prototype.clickButton = function (i, redraw) {
        var rangeSelector = this,
            chart = rangeSelector.chart,
            rangeOptions = rangeSelector.buttonOptions[i],
            baseAxis = chart.xAxis[0],
            unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {},
            type = rangeOptions.type,
            dataGrouping = rangeOptions.dataGrouping;
        var dataMin = unionExtremes.dataMin,
            dataMax = unionExtremes.dataMax,
            newMin,
            newMax = RangeSelector_isNumber(baseAxis === null || baseAxis === void 0 ? void 0 : baseAxis.max) ? Math.round(Math.min(baseAxis.max,
            dataMax !== null && dataMax !== void 0 ? dataMax : baseAxis.max)) : void 0, // #1568
            baseXAxisOptions,
            range = rangeOptions._range,
            rangeMin,
            ctx,
            ytdExtremes,
            addOffsetMin = true;
        // Chart has no data, base series is removed
        if (dataMin === null || dataMax === null) {
            return;
        }
        rangeSelector.setSelected(i);
        // Apply dataGrouping associated to button
        if (dataGrouping) {
            this.forcedDataGrouping = true;
            Axis_Axis.prototype.setDataGrouping.call(baseAxis || { chart: this.chart }, dataGrouping, false);
            this.frozenStates = rangeOptions.preserveDataGrouping;
        }
        // Apply range
        if (type === 'month' || type === 'year') {
            if (!baseAxis) {
                // This is set to the user options and picked up later when the
                // axis is instantiated so that we know the min and max.
                range = rangeOptions;
            }
            else {
                ctx = {
                    range: rangeOptions,
                    max: newMax,
                    chart: chart,
                    dataMin: dataMin,
                    dataMax: dataMax
                };
                newMin = baseAxis.minFromRange.call(ctx);
                if (RangeSelector_isNumber(ctx.newMax)) {
                    newMax = ctx.newMax;
                }
                // #15799: offsetMin is added in minFromRange so that it works
                // with pre-selected buttons as well
                addOffsetMin = false;
            }
            // Fixed times like minutes, hours, days
        }
        else if (range) {
            if (RangeSelector_isNumber(newMax)) {
                newMin = Math.max(newMax - range, dataMin);
                newMax = Math.min(newMin + range, dataMax);
                addOffsetMin = false;
            }
        }
        else if (type === 'ytd') {
            // On user clicks on the buttons, or a delayed action running from
            // the beforeRender event (below), the baseAxis is defined.
            if (baseAxis) {
                // When "ytd" is the pre-selected button for the initial view,
                // its calculation is delayed and rerun in the beforeRender
                // event (below). When the series are initialized, but before
                // the chart is rendered, we have access to the xData array
                // (#942).
                if (baseAxis.hasData() && (!RangeSelector_isNumber(dataMax) ||
                    !RangeSelector_isNumber(dataMin))) {
                    dataMin = Number.MAX_VALUE;
                    dataMax = -Number.MAX_VALUE;
                    chart.series.forEach(function (series) {
                        // Reassign it to the last item
                        var xData = series.getColumn('x');
                        if (xData.length) {
                            dataMin = Math.min(xData[0], dataMin);
                            dataMax = Math.max(xData[xData.length - 1], dataMax);
                        }
                    });
                    redraw = false;
                }
                if (RangeSelector_isNumber(dataMax) && RangeSelector_isNumber(dataMin)) {
                    ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin);
                    newMin = rangeMin = ytdExtremes.min;
                    newMax = ytdExtremes.max;
                }
                // "ytd" is pre-selected. We don't yet have access to processed
                // point and extremes data (things like pointStart and pointInterval
                // are missing), so we delay the process (#942)
            }
            else {
                rangeSelector.deferredYTDClick = i;
                return;
            }
        }
        else if (type === 'all' && baseAxis) {
            // If the navigator exist and the axis range is declared reset that
            // range and from now on only use the range set by a user, #14742.
            if (chart.navigator && chart.navigator.baseSeries[0]) {
                chart.navigator.baseSeries[0].xAxis.options.range = void 0;
            }
            newMin = dataMin;
            newMax = dataMax;
        }
        if (addOffsetMin && rangeOptions._offsetMin && RangeSelector_defined(newMin)) {
            newMin += rangeOptions._offsetMin;
        }
        if (rangeOptions._offsetMax && RangeSelector_defined(newMax)) {
            newMax += rangeOptions._offsetMax;
        }
        if (this.dropdown) {
            this.dropdown.selectedIndex = i + 1;
        }
        // Update the chart
        if (!baseAxis) {
            // Axis not yet instantiated. Temporarily set min and range
            // options and axes once defined and remove them on
            // chart load (#4317 & #20529).
            baseXAxisOptions = RangeSelector_splat(chart.options.xAxis || {})[0];
            var axisRangeUpdateEvent_1 = RangeSelector_addEvent(chart, 'afterCreateAxes',
                function () {
                    var xAxis = chart.xAxis[0];
                xAxis.range = xAxis.options.range = range;
                xAxis.min = xAxis.options.min = rangeMin;
            });
            RangeSelector_addEvent(chart, 'load', function resetMinAndRange() {
                var xAxis = chart.xAxis[0];
                chart.setFixedRange(rangeOptions._range);
                xAxis.options.range = baseXAxisOptions.range;
                xAxis.options.min = baseXAxisOptions.min;
                axisRangeUpdateEvent_1(); // Remove event
            });
        }
        else if (RangeSelector_isNumber(newMin) && RangeSelector_isNumber(newMax)) {
            // Existing axis object. Set extremes after render time.
            baseAxis.setExtremes(newMin, newMax, RangeSelector_pick(redraw, true), void 0, // Auto animation
            {
                trigger: 'rangeSelectorButton',
                rangeSelectorButton: rangeOptions
            });
            chart.setFixedRange(rangeOptions._range);
        }
        RangeSelector_fireEvent(this, 'afterBtnClick');
    };
    /**
     * Set the selected option. This method only sets the internal flag, it
     * doesn't update the buttons or the actual zoomed range.
     *
     * @private
     * @function Highcharts.RangeSelector#setSelected
     * @param {number} [selected]
     */
    RangeSelector.prototype.setSelected = function (selected) {
        this.selected = this.options.selected = selected;
    };
    /**
     * Initialize the range selector
     *
     * @private
     * @function Highcharts.RangeSelector#init
     * @param {Highcharts.Chart} chart
     */
    RangeSelector.prototype.init = function (chart) {
        var rangeSelector = this,
            options = chart.options.rangeSelector,
            buttonOptions = options.buttons,
            selectedOption = options.selected,
            blurInputs = function () {
                var minInput = rangeSelector.minInput,
            maxInput = rangeSelector.maxInput;
            // #3274 in some case blur is not defined
            if (minInput && !!minInput.blur) {
                RangeSelector_fireEvent(minInput, 'blur');
            }
            if (maxInput && !!maxInput.blur) {
                RangeSelector_fireEvent(maxInput, 'blur');
            }
        };
        rangeSelector.chart = chart;
        rangeSelector.options = options;
        rangeSelector.buttons = [];
        rangeSelector.buttonOptions = buttonOptions;
        this.eventsToUnbind = [];
        this.eventsToUnbind.push(RangeSelector_addEvent(chart.container, 'mousedown', blurInputs));
        this.eventsToUnbind.push(RangeSelector_addEvent(chart, 'resize', blurInputs));
        // Extend the buttonOptions with actual range
        buttonOptions.forEach(rangeSelector.computeButtonRange);
        // Zoomed range based on a pre-selected button index
        if (typeof selectedOption !== 'undefined' &&
            buttonOptions[selectedOption]) {
            this.clickButton(selectedOption, false);
        }
        this.eventsToUnbind.push(RangeSelector_addEvent(chart, 'load', function () {
            // If a data grouping is applied to the current button, release it
            // when extremes change
            if (chart.xAxis && chart.xAxis[0]) {
                RangeSelector_addEvent(chart.xAxis[0], 'setExtremes', function (e) {
                    if (RangeSelector_isNumber(this.max) &&
                        RangeSelector_isNumber(this.min) &&
                        this.max - this.min !== chart.fixedRange &&
                        e.trigger !== 'rangeSelectorButton' &&
                        e.trigger !== 'updatedData' &&
                        rangeSelector.forcedDataGrouping &&
                        !rangeSelector.frozenStates) {
                        this.setDataGrouping(false, false);
                    }
                });
            }
        }));
        this.createElements();
    };
    /**
     * Dynamically update the range selector buttons after a new range has been
     * set
     *
     * @private
     * @function Highcharts.RangeSelector#updateButtonStates
     */
    RangeSelector.prototype.updateButtonStates = function () {
        var rangeSelector = this,
            chart = this.chart,
            dropdown = this.dropdown,
            dropdownLabel = this.dropdownLabel,
            baseAxis = chart.xAxis[0],
            actualRange = Math.round(baseAxis.max - baseAxis.min),
            hasNoData = !baseAxis.hasVisibleSeries,
            day = 24 * 36e5, // A single day in milliseconds
            unionExtremes = (chart.scroller &&
                chart.scroller.getUnionExtremes()) || baseAxis,
            dataMin = unionExtremes.dataMin,
            dataMax = unionExtremes.dataMax,
            ytdExtremes = rangeSelector.getYTDExtremes(dataMax,
            dataMin),
            ytdMin = ytdExtremes.min,
            ytdMax = ytdExtremes.max,
            selected = rangeSelector.selected,
            allButtonsEnabled = rangeSelector.options.allButtonsEnabled,
            buttonStates = new Array(rangeSelector.buttonOptions.length)
                .fill(0),
            selectedExists = RangeSelector_isNumber(selected),
            buttons = rangeSelector.buttons;
        var isSelectedTooGreat = false,
            selectedIndex = null;
        rangeSelector.buttonOptions.forEach(function (rangeOptions, i) {
            var _a;
            var range = rangeOptions._range,
                type = rangeOptions.type,
                count = rangeOptions.count || 1,
                offsetRange = rangeOptions._offsetMax -
                    rangeOptions._offsetMin,
                isSelected = i === selected, 
                // Disable buttons where the range exceeds what is allowed i;
            // the current view
            isTooGreatRange = range >
                dataMax - dataMin, 
            // Disable buttons where the range is smaller than the minimum
            // range
            isTooSmallRange = range < baseAxis.minRange;
            // Do not select the YTD button if not explicitly told so
            var isYTDButNotSelected = false, 
                // Disable the All button if we're already showing all
                isSameRange = range === actualRange;
            if (isSelected && isTooGreatRange) {
                isSelectedTooGreat = true;
            }
            if (baseAxis.isOrdinal &&
                ((_a = baseAxis.ordinal) === null || _a === void 0 ? void 0 : _a.positions) &&
                range &&
                actualRange < range) {
                // Handle ordinal ranges
                var positions = baseAxis.ordinal.positions,
                    prevOrdinalPosition = Axis_OrdinalAxis.Additions.findIndexOf(positions,
                    baseAxis.min,
                    true),
                    nextOrdinalPosition = Math.min(Axis_OrdinalAxis.Additions.findIndexOf(positions,
                    baseAxis.max,
                    true) + 1,
                    positions.length - 1);
                if (positions[nextOrdinalPosition] -
                    positions[prevOrdinalPosition] > range) {
                    isSameRange = true;
                }
            }
            else if (
            // Months and years have variable range so we check the extremes
            (type === 'month' || type === 'year') &&
                (actualRange + 36e5 >=
                    { month: 28, year: 365 }[type] * day * count - offsetRange) &&
                (actualRange - 36e5 <=
                    { month: 31, year: 366 }[type] * day * count + offsetRange)) {
                isSameRange = true;
            }
            else if (type === 'ytd') {
                isSameRange = (ytdMax - ytdMin + offsetRange) === actualRange;
                isYTDButNotSelected = !isSelected;
            }
            else if (type === 'all') {
                isSameRange = (baseAxis.max - baseAxis.min >=
                    dataMax - dataMin);
            }
            // The new zoom area happens to match the range for a button - mark
            // it selected. This happens when scrolling across an ordinal gap.
            // It can be seen in the intraday demos when selecting 1h and scroll
            // across the night gap.
            var disable = (!allButtonsEnabled &&
                    !(isSelectedTooGreat && type === 'all') &&
                    (isTooGreatRange ||
                        isTooSmallRange ||
                        hasNoData));
            var select = ((isSelectedTooGreat && type === 'all') ||
                    (isYTDButNotSelected ? false : isSameRange) ||
                    (isSelected && rangeSelector.frozenStates));
            if (disable) {
                buttonStates[i] = 3;
            }
            else if (select) {
                if (!selectedExists || i === selected) {
                    selectedIndex = i;
                }
            }
        });
        if (selectedIndex !== null) {
            buttonStates[selectedIndex] = 2;
            rangeSelector.setSelected(selectedIndex);
            if (this.dropdown) {
                this.dropdown.selectedIndex = selectedIndex + 1;
            }
        }
        else {
            rangeSelector.setSelected();
            if (this.dropdown) {
                this.dropdown.selectedIndex = -1;
            }
            if (dropdownLabel) {
                dropdownLabel.setState(0);
                dropdownLabel.attr({
                    text: (RangeSelector_defaultOptions.lang.rangeSelectorZoom || '') + ' â–¾'
                });
            }
        }
        for (var i = 0; i < buttonStates.length; i++) {
            var state = buttonStates[i];
            var button = buttons[i];
            if (button.state !== state) {
                button.setState(state);
                if (dropdown) {
                    dropdown.options[i + 1].disabled = (state === 3);
                    if (state === 2) {
                        if (dropdownLabel) {
                            dropdownLabel.setState(2);
                            dropdownLabel.attr({
                                text: rangeSelector.buttonOptions[i].text + ' â–¾'
                            });
                        }
                        dropdown.selectedIndex = i + 1;
                    }
                    var bbox = dropdownLabel.getBBox();
                    RangeSelector_css(dropdown, {
                        width: "" + bbox.width + "px",
                        height: "" + bbox.height + "px"
                    });
                }
            }
        }
    };
    /**
     * Compute and cache the range for an individual button
     *
     * @private
     * @function Highcharts.RangeSelector#computeButtonRange
     * @param {Highcharts.RangeSelectorButtonsOptions} rangeOptions
     */
    RangeSelector.prototype.computeButtonRange = function (rangeOptions) {
        var type = rangeOptions.type,
            count = rangeOptions.count || 1, 
            // These time intervals have a fixed number of milliseconds, as
            // opposed to month, ytd and year
            fixedTimes = {
                millisecond: 1,
                second: 1000,
                minute: 60 * 1000,
                hour: 3600 * 1000,
                day: 24 * 3600 * 1000,
                week: 7 * 24 * 3600 * 1000
            };
        // Store the range on the button object
        if (fixedTimes[type]) {
            rangeOptions._range = fixedTimes[type] * count;
        }
        else if (type === 'month' || type === 'year') {
            rangeOptions._range = {
                month: 30,
                year: 365
            }[type] * 24 * 36e5 * count;
        }
        rangeOptions._offsetMin = RangeSelector_pick(rangeOptions.offsetMin, 0);
        rangeOptions._offsetMax = RangeSelector_pick(rangeOptions.offsetMax, 0);
        rangeOptions._range +=
            rangeOptions._offsetMax - rangeOptions._offsetMin;
    };
    /**
     * Get the unix timestamp of a HTML input for the dates
     *
     * @private
     * @function Highcharts.RangeSelector#getInputValue
     */
    RangeSelector.prototype.getInputValue = function (name) {
        var input = name === 'min' ? this.minInput : this.maxInput;
        var options = this.chart.options
                .rangeSelector;
        var time = this.chart.time;
        if (input) {
            return ((input.type === 'text' && options.inputDateParser) ||
                this.defaultInputDateParser)(input.value, time.timezone === 'UTC', time);
        }
        return 0;
    };
    /**
     * Set the internal and displayed value of a HTML input for the dates
     *
     * @private
     * @function Highcharts.RangeSelector#setInputValue
     */
    RangeSelector.prototype.setInputValue = function (name, inputTime) {
        var options = this.options, time = this.chart.time, input = name === 'min' ? this.minInput : this.maxInput, dateBox = name === 'min' ? this.minDateBox : this.maxDateBox;
        if (input) {
            input.setAttribute('type', preferredInputType(options.inputDateFormat || '%e %b %Y'));
            var hcTimeAttr = input.getAttribute('data-hc-time');
            var updatedTime = RangeSelector_defined(hcTimeAttr) ? Number(hcTimeAttr) : void 0;
            if (RangeSelector_defined(inputTime)) {
                var previousTime = updatedTime;
                if (RangeSelector_defined(previousTime)) {
                    input.setAttribute('data-hc-time-previous', previousTime);
                }
                input.setAttribute('data-hc-time', inputTime);
                updatedTime = inputTime;
            }
            input.value = time.dateFormat((this.inputTypeFormats[input.type] ||
                options.inputEditDateFormat), updatedTime);
            if (dateBox) {
                dateBox.attr({
                    text: time.dateFormat(options.inputDateFormat, updatedTime)
                });
            }
        }
    };
    /**
     * Set the min and max value of a HTML input for the dates
     *
     * @private
     * @function Highcharts.RangeSelector#setInputExtremes
     */
    RangeSelector.prototype.setInputExtremes = function (name, min, max) {
        var input = name === 'min' ? this.minInput : this.maxInput;
        if (input) {
            var format = this.inputTypeFormats[input.type];
            var time = this.chart.time;
            if (format) {
                var newMin = time.dateFormat(format,
                    min);
                if (input.min !== newMin) {
                    input.min = newMin;
                }
                var newMax = time.dateFormat(format,
                    max);
                if (input.max !== newMax) {
                    input.max = newMax;
                }
            }
        }
    };
    /**
     * @private
     * @function Highcharts.RangeSelector#showInput
     * @param {string} name
     */
    RangeSelector.prototype.showInput = function (name) {
        var dateBox = name === 'min' ? this.minDateBox : this.maxDateBox, input = name === 'min' ? this.minInput : this.maxInput;
        if (input && dateBox && this.inputGroup) {
            var isTextInput = input.type === 'text',
                _a = this.inputGroup,
                _b = _a.translateX,
                translateX = _b === void 0 ? 0 : _b,
                _c = _a.translateY,
                translateY = _c === void 0 ? 0 : _c,
                _d = dateBox.x,
                x = _d === void 0 ? 0 : _d,
                _e = dateBox.width,
                width = _e === void 0 ? 0 : _e,
                _f = dateBox.height,
                height = _f === void 0 ? 0 : _f,
                inputBoxWidth = this.options.inputBoxWidth;
            RangeSelector_css(input, {
                width: isTextInput ?
                    ((width + (inputBoxWidth ? -2 : 20)) + 'px') :
                    'auto',
                height: (height - 2) + 'px',
                border: '2px solid silver'
            });
            if (isTextInput && inputBoxWidth) {
                RangeSelector_css(input, {
                    left: (translateX + x) + 'px',
                    top: translateY + 'px'
                });
                // Inputs of types date, time or datetime-local should be centered
                // on top of the dateBox
            }
            else {
                RangeSelector_css(input, {
                    left: Math.min(Math.round(x +
                        translateX -
                        (input.offsetWidth - width) / 2), this.chart.chartWidth - input.offsetWidth) + 'px',
                    top: (translateY - (input.offsetHeight - height) / 2) + 'px'
                });
            }
        }
    };
    /**
     * @private
     * @function Highcharts.RangeSelector#hideInput
     * @param {string} name
     */
    RangeSelector.prototype.hideInput = function (name) {
        var input = name === 'min' ? this.minInput : this.maxInput;
        if (input) {
            RangeSelector_css(input, {
                top: '-9999em',
                border: 0,
                width: '1px',
                height: '1px'
            });
        }
    };
    /**
     * @private
     * @function Highcharts.RangeSelector#defaultInputDateParser
     */
    RangeSelector.prototype.defaultInputDateParser = function (inputDate, useUTC, time) {
        return (time === null || time === void 0 ? void 0 : time.parse(inputDate)) || 0;
    };
    /**
     * Draw either the 'from' or the 'to' HTML input box of the range selector
     *
     * @private
     * @function Highcharts.RangeSelector#drawInput
     */
    RangeSelector.prototype.drawInput = function (name) {
        var _a = this,
            chart = _a.chart,
            div = _a.div,
            inputGroup = _a.inputGroup;
        var rangeSelector = this,
            chartStyle = chart.renderer.style || {},
            renderer = chart.renderer,
            options = chart.options.rangeSelector,
            lang = RangeSelector_defaultOptions.lang,
            isMin = name === 'min';
        /**
         * @private
         */
        function updateExtremes(name) {
            var _a;
            var maxInput = rangeSelector.maxInput,
                minInput = rangeSelector.minInput,
                chartAxis = chart.xAxis[0],
                unionExtremes = ((_a = chart.scroller) === null || _a === void 0 ? void 0 : _a.getUnionExtremes()) || chartAxis,
                dataMin = unionExtremes.dataMin,
                dataMax = unionExtremes.dataMax,
                currentExtreme = chart.xAxis[0].getExtremes()[name];
            var value = rangeSelector.getInputValue(name);
            if (RangeSelector_isNumber(value) && value !== currentExtreme) {
                // Validate the extremes. If it goes beyond the data min or
                // max, use the actual data extreme (#2438).
                if (isMin && maxInput && RangeSelector_isNumber(dataMin)) {
                    if (value > Number(maxInput.getAttribute('data-hc-time'))) {
                        value = void 0;
                    }
                    else if (value < dataMin) {
                        value = dataMin;
                    }
                }
                else if (minInput && RangeSelector_isNumber(dataMax)) {
                    if (value < Number(minInput.getAttribute('data-hc-time'))) {
                        value = void 0;
                    }
                    else if (value > dataMax) {
                        value = dataMax;
                    }
                }
                // Set the extremes
                if (typeof value !== 'undefined') { // @todo typeof undefined
                    chartAxis.setExtremes(isMin ? value : chartAxis.min, isMin ? chartAxis.max : value, void 0, void 0, { trigger: 'rangeSelectorInput' });
                }
            }
        }
        // Create the text label
        var text = lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'] || '';
        var label = renderer
                .label(text, 0)
                .addClass('highcharts-range-label')
                .attr({
                padding: text ? 2 : 0,
                height: text ? options.inputBoxHeight : 0
            })
                .add(inputGroup);
        // Create an SVG label that shows updated date ranges and records click
        // events that bring in the HTML input.
        var dateBox = renderer
                .label('', 0)
                .addClass('highcharts-range-input')
                .attr({
                padding: 2,
                width: options.inputBoxWidth,
                height: options.inputBoxHeight,
                'text-align': 'center'
            })
                .on('click',
            function () {
                // If it is already focused, the onfocus event doesn't fire
                // (#3713)
                rangeSelector.showInput(name);
            rangeSelector[name + 'Input'].focus();
        });
        if (!chart.styledMode) {
            dateBox.attr({
                stroke: options.inputBoxBorderColor,
                'stroke-width': 1
            });
        }
        dateBox.add(inputGroup);
        // Create the HTML input element. This is rendered as 1x1 pixel then set
        // to the right size when focused.
        var input = RangeSelector_createElement('input', {
                name: name,
                className: 'highcharts-range-selector'
            },
            void 0,
            div);
        // #14788: Setting input.type to an unsupported type throws in IE, so
        // we need to use setAttribute instead
        input.setAttribute('type', preferredInputType(options.inputDateFormat || '%e %b %Y'));
        if (!chart.styledMode) {
            // Styles
            label.css(RangeSelector_merge(chartStyle, options.labelStyle));
            dateBox.css(RangeSelector_merge({
                color: "#333333" /* Palette.neutralColor80 */
            }, chartStyle, options.inputStyle));
            RangeSelector_css(input, RangeSelector_extend({
                position: 'absolute',
                border: 0,
                boxShadow: '0 0 15px rgba(0,0,0,0.3)',
                width: '1px', // Chrome needs a pixel to see it
                height: '1px',
                padding: 0,
                textAlign: 'center',
                fontSize: chartStyle.fontSize,
                fontFamily: chartStyle.fontFamily,
                top: '-9999em' // #4798
            }, options.inputStyle));
        }
        // Blow up the input box
        input.onfocus = function () {
            rangeSelector.showInput(name);
        };
        // Hide away the input box
        input.onblur = function () {
            // Update extremes only when inputs are active
            if (input === Core_Globals.doc.activeElement) { // Only when focused
                // Update also when no `change` event is triggered, like when
                // clicking inside the SVG (#4710)
                updateExtremes(name);
            }
            // #10404 - move hide and blur outside focus
            rangeSelector.hideInput(name);
            rangeSelector.setInputValue(name);
            input.blur(); // #4606
        };
        var keyDown = false;
        // Handle changes in the input boxes
        input.onchange = function () {
            // Update extremes and blur input when clicking date input calendar
            if (!keyDown) {
                updateExtremes(name);
                rangeSelector.hideInput(name);
                input.blur();
            }
        };
        input.onkeypress = function (event) {
            // IE does not fire onchange on enter
            if (event.keyCode === 13) {
                updateExtremes(name);
            }
        };
        input.onkeydown = function (event) {
            keyDown = true;
            // Arrow keys
            if (event.key === 'ArrowUp' ||
                event.key === 'ArrowDown' ||
                event.key === 'Tab') {
                updateExtremes(name);
            }
        };
        input.onkeyup = function () {
            keyDown = false;
        };
        return { dateBox: dateBox, input: input, label: label };
    };
    /**
     * Get the position of the range selector buttons and inputs. This can be
     * overridden from outside for custom positioning.
     *
     * @private
     * @function Highcharts.RangeSelector#getPosition
     */
    RangeSelector.prototype.getPosition = function () {
        var chart = this.chart,
            options = chart.options.rangeSelector,
            top = options.verticalAlign === 'top' ?
                chart.plotTop - chart.axisOffset[0] :
                0; // Set offset only for verticalAlign top
            return {
                buttonTop: top + options.buttonPosition.y,
                inputTop: top + options.inputPosition.y - 10
            };
    };
    /**
     * Get the extremes of YTD. Will choose dataMax if its value is lower than
     * the current timestamp. Will choose dataMin if its value is higher than
     * the timestamp for the start of current year.
     *
     * @private
     * @function Highcharts.RangeSelector#getYTDExtremes
     * @return {*}
     * Returns min and max for the YTD
     */
    RangeSelector.prototype.getYTDExtremes = function (dataMax, dataMin) {
        var time = this.chart.time,
            year = time.toParts(dataMax)[0],
            startOfYear = time.makeTime(year, 0);
        return {
            max: dataMax,
            min: Math.max(dataMin, startOfYear)
        };
    };
    RangeSelector.prototype.createElements = function () {
        var _a;
        var chart = this.chart,
            renderer = chart.renderer,
            container = chart.container,
            chartOptions = chart.options,
            options = chartOptions.rangeSelector,
            inputEnabled = options.inputEnabled,
            inputsZIndex = RangeSelector_pick((_a = chartOptions.chart.style) === null || _a === void 0 ? void 0 : _a.zIndex, 0) + 1;
        if (options.enabled === false) {
            return;
        }
        this.group = renderer.g('range-selector-group')
            .attr({
            zIndex: 7
        })
            .add();
        this.div = RangeSelector_createElement('div', void 0, {
            position: 'relative',
            height: 0,
            zIndex: inputsZIndex
        });
        if (this.buttonOptions.length) {
            this.renderButtons();
        }
        // First create a wrapper outside the container in order to make
        // the inputs work and make export correct
        if (container.parentNode) {
            container.parentNode.insertBefore(this.div, container);
        }
        if (inputEnabled) {
            this.createInputs();
        }
    };
    /**
     * Create the input elements and its group.
     *
     */
    RangeSelector.prototype.createInputs = function () {
        this.inputGroup = this.chart.renderer.g('input-group').add(this.group);
        var minElems = this.drawInput('min');
        this.minDateBox = minElems.dateBox;
        this.minLabel = minElems.label;
        this.minInput = minElems.input;
        var maxElems = this.drawInput('max');
        this.maxDateBox = maxElems.dateBox;
        this.maxLabel = maxElems.label;
        this.maxInput = maxElems.input;
    };
    /**
     * Render the range selector including the buttons and the inputs. The first
     * time render is called, the elements are created and positioned. On
     * subsequent calls, they are moved and updated.
     *
     * @private
     * @function Highcharts.RangeSelector#render
     * @param {number} [min]
     *        X axis minimum
     * @param {number} [max]
     *        X axis maximum
     */
    RangeSelector.prototype.render = function (min, max) {
        var _a,
            _b;
        if (this.options.enabled === false) {
            return;
        }
        var chart = this.chart,
            chartOptions = chart.options,
            options = chartOptions.rangeSelector, 
            // Place inputs above the container
            inputEnabled = options.inputEnabled;
        if (inputEnabled) {
            if (!this.inputGroup) {
                this.createInputs();
            }
            // Set or reset the input values
            this.setInputValue('min', min);
            this.setInputValue('max', max);
            if (!this.chart.styledMode) {
                (_a = this.maxLabel) === null || _a === void 0 ? void 0 : _a.css(options.labelStyle);
                (_b = this.minLabel) === null || _b === void 0 ? void 0 : _b.css(options.labelStyle);
            }
            var unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || chart.xAxis[0] || {};
            if (RangeSelector_defined(unionExtremes.dataMin) &&
                RangeSelector_defined(unionExtremes.dataMax)) {
                var minRange = chart.xAxis[0].minRange || 0;
                this.setInputExtremes('min', unionExtremes.dataMin, Math.min(unionExtremes.dataMax, this.getInputValue('max')) - minRange);
                this.setInputExtremes('max', Math.max(unionExtremes.dataMin, this.getInputValue('min')) + minRange, unionExtremes.dataMax);
            }
            // Reflow
            if (this.inputGroup) {
                var x_1 = 0;
                [
                    this.minLabel,
                    this.minDateBox,
                    this.maxLabel,
                    this.maxDateBox
                ].forEach(function (label) {
                    if (label) {
                        var width = label.getBBox().width;
                        if (width) {
                            label.attr({ x: x_1 });
                            x_1 += width + options.inputSpacing;
                        }
                    }
                });
            }
        }
        else {
            if (this.inputGroup) {
                this.inputGroup.destroy();
                delete this.inputGroup;
            }
        }
        if (!this.chart.styledMode) {
            if (this.zoomText) {
                this.zoomText.css(options.labelStyle);
            }
        }
        this.alignElements();
        this.updateButtonStates();
    };
    /**
     * Render the range buttons. This only runs the first time, later the
     * positioning is laid out in alignElements.
     *
     * @private
     * @function Highcharts.RangeSelector#renderButtons
     */
    RangeSelector.prototype.renderButtons = function () {
        var _this = this;
        var _a,
            _b;
        var _c;
        var _d = this,
            chart = _d.chart,
            options = _d.options;
        var lang = RangeSelector_defaultOptions.lang;
        var renderer = chart.renderer;
        var buttonTheme = RangeSelector_merge(options.buttonTheme);
        var states = buttonTheme && buttonTheme.states;
        // Prevent the button from resetting the width when the button state
        // changes since we need more control over the width when collapsing
        // the buttons
        delete buttonTheme.width;
        delete buttonTheme.states;
        this.buttonGroup = renderer.g('range-selector-buttons').add(this.group);
        var dropdown = this.dropdown = RangeSelector_createElement('select',
            void 0, {
                position: 'absolute',
                padding: 0,
                border: 0,
                cursor: 'pointer',
                opacity: 0.0001
            },
            this.div);
        // Create a label for dropdown select element
        var userButtonTheme = (_a = chart.userOptions.rangeSelector) === null || _a === void 0 ? void 0 : _a.buttonTheme;
        this.dropdownLabel = renderer.button('', 0, 0, function () { }, RangeSelector_merge(buttonTheme, {
            'stroke-width': RangeSelector_pick(buttonTheme['stroke-width'], 0),
            width: 'auto',
            paddingLeft: RangeSelector_pick(options.buttonTheme.paddingLeft, userButtonTheme === null || userButtonTheme === void 0 ? void 0 : userButtonTheme.padding, 8),
            paddingRight: RangeSelector_pick(options.buttonTheme.paddingRight, userButtonTheme === null || userButtonTheme === void 0 ? void 0 : userButtonTheme.padding, 8)
        }), states && states.hover, states && states.select, states && states.disabled)
            .hide()
            .add(this.group);
        // Prevent page zoom on iPhone
        RangeSelector_addEvent(dropdown, 'touchstart', function () {
            dropdown.style.fontSize = '16px';
        });
        // Forward events from select to button
        var mouseOver = Core_Globals.isMS ? 'mouseover' : 'mouseenter', mouseOut = Core_Globals.isMS ? 'mouseout' : 'mouseleave';
        RangeSelector_addEvent(dropdown, mouseOver, function () {
            RangeSelector_fireEvent(_this.dropdownLabel.element, mouseOver);
        });
        RangeSelector_addEvent(dropdown, mouseOut, function () {
            RangeSelector_fireEvent(_this.dropdownLabel.element, mouseOut);
        });
        RangeSelector_addEvent(dropdown, 'change', function () {
            var button = _this.buttons[dropdown.selectedIndex - 1];
            RangeSelector_fireEvent(button.element, 'click');
        });
        this.zoomText = renderer
            .label(lang.rangeSelectorZoom || '', 0)
            .attr({
            padding: options.buttonTheme.padding,
            height: options.buttonTheme.height,
            paddingLeft: 0,
            paddingRight: 0
        })
            .add(this.buttonGroup);
        if (!this.chart.styledMode) {
            this.zoomText.css(options.labelStyle);
            (_b = (_c = options.buttonTheme)['stroke-width']) !== null && _b !== void 0 ? _b : (_c['stroke-width'] = 0);
        }
        RangeSelector_createElement('option', {
            textContent: this.zoomText.textStr,
            disabled: true
        }, void 0, dropdown);
        this.createButtons();
    };
    RangeSelector.prototype.createButtons = function () {
        var _this = this;
        var options = this.options;
        var buttonTheme = RangeSelector_merge(options.buttonTheme);
        var states = buttonTheme && buttonTheme.states;
        // Prevent the button from resetting the width when the button state
        // changes since we need more control over the width when collapsing
        // the buttons
        var width = buttonTheme.width || 28;
        delete buttonTheme.width;
        delete buttonTheme.states;
        this.buttonOptions.forEach(function (rangeOptions, i) {
            _this.createButton(rangeOptions, i, width, states);
        });
    };
    RangeSelector.prototype.createButton = function (rangeOptions, i, width, states) {
        var _this = this;
        var _a = this,
            dropdown = _a.dropdown,
            buttons = _a.buttons,
            chart = _a.chart,
            options = _a.options;
        var renderer = chart.renderer;
        var buttonTheme = RangeSelector_merge(options.buttonTheme);
        dropdown === null || dropdown === void 0 ? void 0 : dropdown.add(RangeSelector_createElement('option', {
            textContent: rangeOptions.title || rangeOptions.text
        }), i + 2);
        buttons[i] = renderer
            .button(rangeOptions.text, 0, 0, function (e) {
            // Extract events from button object and call
            var buttonEvents = (rangeOptions.events && rangeOptions.events.click);
            var callDefaultEvent;
            if (buttonEvents) {
                callDefaultEvent =
                    buttonEvents.call(rangeOptions, e);
            }
            if (callDefaultEvent !== false) {
                _this.clickButton(i);
            }
            _this.isActive = true;
        }, buttonTheme, states && states.hover, states && states.select, states && states.disabled)
            .attr({
            'text-align': 'center',
            width: width
        })
            .add(this.buttonGroup);
        if (rangeOptions.title) {
            buttons[i].attr('title', rangeOptions.title);
        }
    };
    /**
     * Align the elements horizontally and vertically.
     *
     * @private
     * @function Highcharts.RangeSelector#alignElements
     */
    RangeSelector.prototype.alignElements = function () {
        var _this = this;
        var _a;
        var _b = this,
            buttonGroup = _b.buttonGroup,
            buttons = _b.buttons,
            chart = _b.chart,
            group = _b.group,
            inputGroup = _b.inputGroup,
            options = _b.options,
            zoomText = _b.zoomText;
        var chartOptions = chart.options;
        var navButtonOptions = (chartOptions.exporting &&
                chartOptions.exporting.enabled !== false &&
                chartOptions.navigation &&
                chartOptions.navigation.buttonOptions);
        var buttonPosition = options.buttonPosition,
            inputPosition = options.inputPosition,
            verticalAlign = options.verticalAlign;
        // Get the X offset required to avoid overlapping with the exporting
        // button. This is used both by the buttonGroup and the inputGroup.
        var getXOffsetForExportButton = function (group,
            position,
            rightAligned) {
                if (navButtonOptions &&
                    _this.titleCollision(chart) &&
                    verticalAlign === 'top' &&
                    rightAligned && ((position.y -
                    group.getBBox().height - 12) <
                    ((navButtonOptions.y || 0) +
                        (navButtonOptions.height || 0) +
                        chart.spacing[0]))) {
                    return -40;
            }
            return 0;
        };
        var plotLeft = chart.plotLeft;
        if (group && buttonPosition && inputPosition) {
            var translateX = buttonPosition.x - chart.spacing[3];
            if (buttonGroup) {
                this.positionButtons();
                if (!this.initialButtonGroupWidth) {
                    var width_1 = 0;
                    if (zoomText) {
                        width_1 += zoomText.getBBox().width + 5;
                    }
                    buttons.forEach(function (button, i) {
                        width_1 += button.width || 0;
                        if (i !== buttons.length - 1) {
                            width_1 += options.buttonSpacing;
                        }
                    });
                    this.initialButtonGroupWidth = width_1;
                }
                plotLeft -= chart.spacing[3];
                // Detect collision between button group and exporting
                var xOffsetForExportButton_1 = getXOffsetForExportButton(buttonGroup,
                    buttonPosition,
                    buttonPosition.align === 'right' ||
                        inputPosition.align === 'right');
                this.alignButtonGroup(xOffsetForExportButton_1);
                if ((_a = this.buttonGroup) === null || _a === void 0 ? void 0 : _a.translateY) {
                    this.dropdownLabel
                        .attr({ y: this.buttonGroup.translateY });
                }
                // Skip animation
                group.placed = buttonGroup.placed = chart.hasLoaded;
            }
            var xOffsetForExportButton = 0;
            if (options.inputEnabled && inputGroup) {
                // Detect collision between the input group and exporting button
                xOffsetForExportButton = getXOffsetForExportButton(inputGroup, inputPosition, buttonPosition.align === 'right' ||
                    inputPosition.align === 'right');
                if (inputPosition.align === 'left') {
                    translateX = plotLeft;
                }
                else if (inputPosition.align === 'right') {
                    translateX = -Math.max(chart.axisOffset[1], -xOffsetForExportButton);
                }
                // Update the alignment to the updated spacing box
                inputGroup.align({
                    y: inputPosition.y,
                    width: inputGroup.getBBox().width,
                    align: inputPosition.align,
                    // Fix wrong getBBox() value on right align
                    x: inputPosition.x + translateX - 2
                }, true, chart.spacingBox);
                // Skip animation
                inputGroup.placed = chart.hasLoaded;
            }
            this.handleCollision(xOffsetForExportButton);
            // Vertical align
            group.align({
                verticalAlign: verticalAlign
            }, true, chart.spacingBox);
            var alignTranslateY = group.alignAttr.translateY;
            // Set position
            var groupHeight = group.getBBox().height + 20; // # 20 padding
                var translateY = 0;
            // Calculate bottom position
            if (verticalAlign === 'bottom') {
                var legendOptions = chart.legend && chart.legend.options;
                var legendHeight = (legendOptions &&
                        legendOptions.verticalAlign === 'bottom' &&
                        legendOptions.enabled &&
                        !legendOptions.floating ?
                        (chart.legend.legendHeight +
                            RangeSelector_pick(legendOptions.margin, 10)) :
                        0);
                groupHeight = groupHeight + legendHeight - 20;
                translateY = (alignTranslateY -
                    groupHeight -
                    (options.floating ? 0 : options.y) -
                    (chart.titleOffset ? chart.titleOffset[2] : 0) -
                    10 // 10 spacing
                );
            }
            if (verticalAlign === 'top') {
                if (options.floating) {
                    translateY = 0;
                }
                if (chart.titleOffset && chart.titleOffset[0]) {
                    translateY = chart.titleOffset[0];
                }
                translateY += ((chart.margin[0] - chart.spacing[0]) || 0);
            }
            else if (verticalAlign === 'middle') {
                if (inputPosition.y === buttonPosition.y) {
                    translateY = alignTranslateY;
                }
                else if (inputPosition.y || buttonPosition.y) {
                    if (inputPosition.y < 0 ||
                        buttonPosition.y < 0) {
                        translateY -= Math.min(inputPosition.y, buttonPosition.y);
                    }
                    else {
                        translateY = alignTranslateY - groupHeight;
                    }
                }
            }
            group.translate(options.x, options.y + Math.floor(translateY));
            // Translate HTML inputs
            var _c = this,
                minInput = _c.minInput,
                maxInput = _c.maxInput,
                dropdown = _c.dropdown;
            if (options.inputEnabled && minInput && maxInput) {
                minInput.style.marginTop = group.translateY + 'px';
                maxInput.style.marginTop = group.translateY + 'px';
            }
            if (dropdown) {
                dropdown.style.marginTop = group.translateY + 'px';
            }
        }
    };
    /**
     * @private
     */
    RangeSelector.prototype.redrawElements = function () {
        var _a,
            _b,
            _c,
            _d,
            _e,
            _f,
            _g;
        var chart = this.chart,
            _h = this.options,
            inputBoxHeight = _h.inputBoxHeight,
            inputBoxBorderColor = _h.inputBoxBorderColor;
        (_a = this.maxDateBox) === null || _a === void 0 ? void 0 : _a.attr({
            height: inputBoxHeight
        });
        (_b = this.minDateBox) === null || _b === void 0 ? void 0 : _b.attr({
            height: inputBoxHeight
        });
        if (!chart.styledMode) {
            (_c = this.maxDateBox) === null || _c === void 0 ? void 0 : _c.attr({
                stroke: inputBoxBorderColor
            });
            (_d = this.minDateBox) === null || _d === void 0 ? void 0 : _d.attr({
                stroke: inputBoxBorderColor
            });
        }
        if (this.isDirty) {
            this.isDirty = false;
            // Reset this prop to force redrawing collapse of buttons
            this.isCollapsed = void 0;
            var newButtonsOptions = (_e = this.options.buttons) !== null && _e !== void 0 ? _e : [];
            var btnLength = Math.min(newButtonsOptions.length,
                this.buttonOptions.length);
            var _j = this,
                dropdown = _j.dropdown,
                options = _j.options;
            var buttonTheme = RangeSelector_merge(options.buttonTheme);
            var states = buttonTheme && buttonTheme.states;
            // Prevent the button from resetting the width when the button state
            // changes since we need more control over the width when collapsing
            // the buttons
            var width = buttonTheme.width || 28;
            // Destroy additional buttons
            if (newButtonsOptions.length < this.buttonOptions.length) {
                for (var i = this.buttonOptions.length - 1; i >= newButtonsOptions.length; i--) {
                    var btn = this.buttons.pop();
                    btn === null || btn === void 0 ? void 0 : btn.destroy();
                    (_f = this.dropdown) === null || _f === void 0 ? void 0 : _f.options.remove(i + 1);
                }
            }
            // Update current buttons
            for (var i = btnLength - 1; i >= 0; i--) {
                var diff = RangeSelector_diffObjects(newButtonsOptions[i],
                    this.buttonOptions[i]);
                if (Object.keys(diff).length !== 0) {
                    var rangeOptions = newButtonsOptions[i];
                    this.buttons[i].destroy();
                    dropdown === null || dropdown === void 0 ? void 0 : dropdown.options.remove(i + 1);
                    this.createButton(rangeOptions, i, width, states);
                    this.computeButtonRange(rangeOptions);
                }
            }
            // Create missing buttons
            if (newButtonsOptions.length > this.buttonOptions.length) {
                for (var i = this.buttonOptions.length; i < newButtonsOptions.length; i++) {
                    this.createButton(newButtonsOptions[i], i, width, states);
                    this.computeButtonRange(newButtonsOptions[i]);
                }
            }
            this.buttonOptions = (_g = this.options.buttons) !== null && _g !== void 0 ? _g : [];
            if (RangeSelector_defined(this.options.selected) && this.buttons.length) {
                this.clickButton(this.options.selected, false);
            }
        }
    };
    /**
     * Align the button group horizontally and vertically.
     *
     * @private
     * @function Highcharts.RangeSelector#alignButtonGroup
     * @param {number} xOffsetForExportButton
     * @param {number} [width]
     */
    RangeSelector.prototype.alignButtonGroup = function (xOffsetForExportButton, width) {
        var _a = this,
            chart = _a.chart,
            options = _a.options,
            buttonGroup = _a.buttonGroup,
            dropdown = _a.dropdown,
            dropdownLabel = _a.dropdownLabel;
        var buttonPosition = options.buttonPosition;
        var plotLeft = chart.plotLeft - chart.spacing[3];
        var translateX = buttonPosition.x - chart.spacing[3];
        var dropdownTranslateX = chart.plotLeft;
        if (buttonPosition.align === 'right') {
            translateX += xOffsetForExportButton - plotLeft; // #13014
            if (this.hasVisibleDropdown) {
                dropdownTranslateX = chart.chartWidth +
                    xOffsetForExportButton -
                    this.maxButtonWidth() - 20;
            }
        }
        else if (buttonPosition.align === 'center') {
            translateX -= plotLeft / 2;
            if (this.hasVisibleDropdown) {
                dropdownTranslateX = chart.chartWidth / 2 -
                    this.maxButtonWidth();
            }
        }
        if (dropdown) {
            RangeSelector_css(dropdown, {
                left: dropdownTranslateX + 'px',
                top: (buttonGroup === null || buttonGroup === void 0 ? void 0 : buttonGroup.translateY) + 'px'
            });
        }
        dropdownLabel === null || dropdownLabel === void 0 ? void 0 : dropdownLabel.attr({
            x: dropdownTranslateX
        });
        if (buttonGroup) {
            // Align button group
            buttonGroup.align({
                y: buttonPosition.y,
                width: RangeSelector_pick(width, this.initialButtonGroupWidth),
                align: buttonPosition.align,
                x: translateX
            }, true, chart.spacingBox);
        }
    };
    /**
     * @private
     * @function Highcharts.RangeSelector#positionButtons
     */
    RangeSelector.prototype.positionButtons = function () {
        var _a = this,
            buttons = _a.buttons,
            chart = _a.chart,
            options = _a.options,
            zoomText = _a.zoomText;
        var verb = chart.hasLoaded ? 'animate' : 'attr';
        var buttonPosition = options.buttonPosition;
        var plotLeft = chart.plotLeft;
        var buttonLeft = plotLeft;
        if (zoomText && zoomText.visibility !== 'hidden') {
            // #8769, allow dynamically updating margins
            zoomText[verb]({
                x: RangeSelector_pick(plotLeft + buttonPosition.x, plotLeft)
            });
            // Button start position
            buttonLeft += buttonPosition.x +
                zoomText.getBBox().width + 5;
        }
        for (var i = 0, iEnd = this.buttonOptions.length; i < iEnd; ++i) {
            if (buttons[i].visibility !== 'hidden') {
                buttons[i][verb]({ x: buttonLeft });
                // Increase the button position for the next button
                buttonLeft += (buttons[i].width || 0) + options.buttonSpacing;
            }
            else {
                buttons[i][verb]({ x: plotLeft });
            }
        }
    };
    /**
     * Handle collision between the button group and the input group
     *
     * @private
     * @function Highcharts.RangeSelector#handleCollision
     *
     * @param  {number} xOffsetForExportButton
     *                  The X offset of the group required to make room for the
     *                  exporting button
     */
    RangeSelector.prototype.handleCollision = function (xOffsetForExportButton) {
        var _a = this,
            chart = _a.chart,
            buttonGroup = _a.buttonGroup,
            inputGroup = _a.inputGroup,
            initialButtonGroupWidth = _a.initialButtonGroupWidth;
        var _b = this.options,
            buttonPosition = _b.buttonPosition,
            dropdown = _b.dropdown,
            inputPosition = _b.inputPosition;
        var moveInputsDown = function () {
                if (inputGroup && buttonGroup) {
                    inputGroup.attr({
                        translateX: inputGroup.alignAttr.translateX + (chart.axisOffset[1] >= -xOffsetForExportButton ?
                            0 :
                            -xOffsetForExportButton),
                        translateY: inputGroup.alignAttr.translateY +
                            buttonGroup.getBBox().height + 10
                    });
            }
        };
        // Detect collision
        if (inputGroup && buttonGroup) {
            if (inputPosition.align === buttonPosition.align) {
                moveInputsDown();
                if (initialButtonGroupWidth >
                    chart.plotWidth + xOffsetForExportButton - 20) {
                    this.collapseButtons();
                }
                else {
                    this.expandButtons();
                }
            }
            else if (initialButtonGroupWidth -
                xOffsetForExportButton +
                inputGroup.getBBox().width >
                chart.plotWidth) {
                if (dropdown === 'responsive') {
                    this.collapseButtons();
                }
                else {
                    moveInputsDown();
                }
            }
            else {
                this.expandButtons();
            }
        }
        else if (buttonGroup && dropdown === 'responsive') {
            if (initialButtonGroupWidth > chart.plotWidth) {
                this.collapseButtons();
            }
            else {
                this.expandButtons();
            }
        }
        // Forced states
        if (buttonGroup) {
            if (dropdown === 'always') {
                this.collapseButtons();
            }
            if (dropdown === 'never') {
                this.expandButtons();
            }
        }
        this.alignButtonGroup(xOffsetForExportButton);
    };
    /**
     * Collapse the buttons and show the select element.
     *
     * @private
     * @function Highcharts.RangeSelector#collapseButtons
     * @param {number} xOffsetForExportButton
     */
    RangeSelector.prototype.collapseButtons = function () {
        var _a = this,
            buttons = _a.buttons,
            zoomText = _a.zoomText;
        if (this.isCollapsed === true) {
            return;
        }
        this.isCollapsed = true;
        zoomText.hide();
        buttons.forEach(function (button) { return void button.hide(); });
        this.showDropdown();
    };
    /**
     * Show all the buttons and hide the select element.
     *
     * @private
     * @function Highcharts.RangeSelector#expandButtons
     */
    RangeSelector.prototype.expandButtons = function () {
        var _a = this,
            buttons = _a.buttons,
            zoomText = _a.zoomText;
        if (this.isCollapsed === false) {
            return;
        }
        this.isCollapsed = false;
        this.hideDropdown();
        zoomText.show();
        buttons.forEach(function (button) { return void button.show(); });
        this.positionButtons();
    };
    /**
     * Position the select element on top of the button.
     *
     * @private
     * @function Highcharts.RangeSelector#showDropdown
     */
    RangeSelector.prototype.showDropdown = function () {
        var _a = this,
            buttonGroup = _a.buttonGroup,
            dropdownLabel = _a.dropdownLabel,
            dropdown = _a.dropdown;
        if (buttonGroup && dropdown) {
            dropdownLabel.show();
            RangeSelector_css(dropdown, { visibility: 'inherit' });
            this.hasVisibleDropdown = true;
        }
    };
    /**
     * @private
     * @function Highcharts.RangeSelector#hideDropdown
     */
    RangeSelector.prototype.hideDropdown = function () {
        var dropdown = this.dropdown;
        if (dropdown) {
            this.dropdownLabel.hide();
            RangeSelector_css(dropdown, {
                visibility: 'hidden',
                width: '1px',
                height: '1px'
            });
            this.hasVisibleDropdown = false;
        }
    };
    /**
     * Extracts height of range selector
     *
     * @private
     * @function Highcharts.RangeSelector#getHeight
     * @return {number}
     * Returns rangeSelector height
     */
    RangeSelector.prototype.getHeight = function () {
        var rangeSelector = this,
            options = rangeSelector.options,
            rangeSelectorGroup = rangeSelector.group,
            inputPosition = options.inputPosition,
            buttonPosition = options.buttonPosition,
            yPosition = options.y,
            buttonPositionY = buttonPosition.y,
            inputPositionY = inputPosition.y;
        var rangeSelectorHeight = 0;
        if (options.height) {
            return options.height;
        }
        // Align the elements before we read the height in case we're switching
        // between wrapped and non-wrapped layout
        this.alignElements();
        rangeSelectorHeight = rangeSelectorGroup ?
            // 13px to keep back compatibility
            (rangeSelectorGroup.getBBox(true).height) + 13 +
                yPosition :
            0;
        var minPosition = Math.min(inputPositionY,
            buttonPositionY);
        if ((inputPositionY < 0 && buttonPositionY < 0) ||
            (inputPositionY > 0 && buttonPositionY > 0)) {
            rangeSelectorHeight += Math.abs(minPosition);
        }
        return rangeSelectorHeight;
    };
    /**
     * Detect collision with title or subtitle
     *
     * @private
     * @function Highcharts.RangeSelector#titleCollision
     * @return {boolean}
     * Returns collision status
     */
    RangeSelector.prototype.titleCollision = function (chart) {
        return !(chart.options.title.text ||
            chart.options.subtitle.text);
    };
    /**
     * Update the range selector with new options
     *
     * @private
     * @function Highcharts.RangeSelector#update
     * @param {Highcharts.RangeSelectorOptions} options
     */
    RangeSelector.prototype.update = function (options, redraw) {
        if (redraw === void 0) { redraw = true; }
        var chart = this.chart;
        RangeSelector_merge(true, this.options, options);
        if (this.options.selected &&
            this.options.selected >= this.options.buttons.length) {
            this.options.selected = void 0;
            chart.options.rangeSelector.selected = void 0;
        }
        if (RangeSelector_defined(options.enabled)) {
            this.destroy();
            return this.init(chart);
        }
        this.isDirty = !!options.buttons;
        if (redraw) {
            this.render();
        }
    };
    /**
     * Destroys allocated elements.
     *
     * @private
     * @function Highcharts.RangeSelector#destroy
     */
    RangeSelector.prototype.destroy = function () {
        var rSelector = this,
            minInput = rSelector.minInput,
            maxInput = rSelector.maxInput;
        if (rSelector.eventsToUnbind) {
            rSelector.eventsToUnbind.forEach(function (unbind) { return unbind(); });
            rSelector.eventsToUnbind = void 0;
        }
        // Destroy elements in collections
        RangeSelector_destroyObjectProperties(rSelector.buttons);
        // Clear input element events
        if (minInput) {
            minInput.onfocus = minInput.onblur = minInput.onchange = null;
        }
        if (maxInput) {
            maxInput.onfocus = maxInput.onblur = maxInput.onchange = null;
        }
        // Destroy HTML and SVG elements
        RangeSelector_objectEach(rSelector, function (val, key) {
            if (val && key !== 'chart') {
                if (val instanceof SVG_SVGElement) {
                    // SVGElement
                    val.destroy();
                }
                else if (val instanceof window.HTMLElement) {
                    // HTML element
                    RangeSelector_discardElement(val);
                }
                delete rSelector[key];
            }
            if (val !== RangeSelector.prototype[key]) {
                rSelector[key] = null;
            }
        }, this);
        this.buttons = [];
    };
    return RangeSelector;
}());
RangeSelector_extend(RangeSelector.prototype, {
    /**
     * The date formats to use when setting min, max and value on date inputs.
     * @private
     */
    inputTypeFormats: {
        'datetime-local': '%Y-%m-%dT%H:%M:%S',
        'date': '%Y-%m-%d',
        'time': '%H:%M:%S'
    }
});
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var RangeSelector_RangeSelector = (RangeSelector);
/* *
 *
 *  API Options
 *
 * */
/**
 * Define the time span for the button
 *
 * @typedef {"all"|"day"|"hour"|"millisecond"|"minute"|"month"|"second"|"week"|"year"|"ytd"} Highcharts.RangeSelectorButtonTypeValue
 */
/**
 * Callback function to react on button clicks.
 *
 * @callback Highcharts.RangeSelectorClickCallbackFunction
 *
 * @param {global.Event} e
 *        Event arguments.
 *
 * @param {boolean|undefined}
 *        Return false to cancel the default button event.
 */
/**
 * Callback function to parse values entered in the input boxes and return a
 * valid JavaScript time as milliseconds since 1970.
 *
 * @callback Highcharts.RangeSelectorParseCallbackFunction
 *
 * @param {string} value
 *        Input value to parse.
 *
 * @return {number}
 *         Parsed JavaScript time value.
 */
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Series/PathUtilities.js
/* *
 *
 *  (c) 2010-2024 Pawel Lysy
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var getLinkPath = {
    'default': getDefaultPath,
    straight: getStraightPath,
    curved: getCurvedPath
};
/**
 *
 */
function getDefaultPath(pathParams) {
    var x1 = pathParams.x1,
        y1 = pathParams.y1,
        x2 = pathParams.x2,
        y2 = pathParams.y2,
        _a = pathParams.width,
        width = _a === void 0 ? 0 : _a,
        _b = pathParams.inverted,
        inverted = _b === void 0 ? false : _b,
        radius = pathParams.radius,
        parentVisible = pathParams.parentVisible;
    var path = [
            ['M',
        x1,
        y1],
            ['L',
        x1,
        y1],
            ['C',
        x1,
        y1,
        x1,
        y2,
        x1,
        y2],
            ['L',
        x1,
        y2],
            ['C',
        x1,
        y1,
        x1,
        y2,
        x1,
        y2],
            ['L',
        x1,
        y2]
        ];
    return parentVisible ?
        applyRadius([
            ['M', x1, y1],
            ['L', x1 + width * (inverted ? -0.5 : 0.5), y1],
            ['L', x1 + width * (inverted ? -0.5 : 0.5), y2],
            ['L', x2, y2]
        ], radius) :
        path;
}
/**
 *
 */
function getStraightPath(pathParams) {
    var x1 = pathParams.x1,
        y1 = pathParams.y1,
        x2 = pathParams.x2,
        y2 = pathParams.y2,
        _a = pathParams.width,
        width = _a === void 0 ? 0 : _a,
        _b = pathParams.inverted,
        inverted = _b === void 0 ? false : _b,
        parentVisible = pathParams.parentVisible;
    return parentVisible ? [
        ['M', x1, y1],
        ['L', x1 + width * (inverted ? -1 : 1), y2],
        ['L', x2, y2]
    ] : [
        ['M', x1, y1],
        ['L', x1, y2],
        ['L', x1, y2]
    ];
}
/**
 *
 */
function getCurvedPath(pathParams) {
    var x1 = pathParams.x1,
        y1 = pathParams.y1,
        x2 = pathParams.x2,
        y2 = pathParams.y2,
        _a = pathParams.offset,
        offset = _a === void 0 ? 0 : _a,
        _b = pathParams.width,
        width = _b === void 0 ? 0 : _b,
        _c = pathParams.inverted,
        inverted = _c === void 0 ? false : _c,
        parentVisible = pathParams.parentVisible;
    return parentVisible ?
        [
            ['M', x1, y1],
            [
                'C',
                x1 + offset,
                y1,
                x1 - offset + width * (inverted ? -1 : 1),
                y2,
                x1 + width * (inverted ? -1 : 1),
                y2
            ],
            ['L', x2, y2]
        ] :
        [
            ['M', x1, y1],
            ['C', x1, y1, x1, y2, x1, y2],
            ['L', x2, y2]
        ];
}
/**
 * General function to apply corner radius to a path
 * @private
 */
function applyRadius(path, r) {
    var d = [];
    for (var i = 0; i < path.length; i++) {
        var x = path[i][1];
        var y = path[i][2];
        if (typeof x === 'number' && typeof y === 'number') {
            // MoveTo
            if (i === 0) {
                d.push(['M', x, y]);
            }
            else if (i === path.length - 1) {
                d.push(['L', x, y]);
                // CurveTo
            }
            else if (r) {
                var prevSeg = path[i - 1];
                var nextSeg = path[i + 1];
                if (prevSeg && nextSeg) {
                    var x1 = prevSeg[1],
                        y1 = prevSeg[2],
                        x2 = nextSeg[1],
                        y2 = nextSeg[2];
                    // Only apply to breaks
                    if (typeof x1 === 'number' &&
                        typeof x2 === 'number' &&
                        typeof y1 === 'number' &&
                        typeof y2 === 'number' &&
                        x1 !== x2 &&
                        y1 !== y2) {
                        var directionX = x1 < x2 ? 1 : -1,
                            directionY = y1 < y2 ? 1 : -1;
                        d.push([
                            'L',
                            x - directionX * Math.min(Math.abs(x - x1), r),
                            y - directionY * Math.min(Math.abs(y - y1), r)
                        ], [
                            'C',
                            x,
                            y,
                            x,
                            y,
                            x + directionX * Math.min(Math.abs(x - x2), r),
                            y + directionY * Math.min(Math.abs(y - y2), r)
                        ]);
                    }
                }
                // LineTo
            }
            else {
                d.push(['L', x, y]);
            }
        }
    }
    return d;
}
var PathUtilities = {
    applyRadius: applyRadius,
    getLinkPath: getLinkPath
};
/* harmony default export */ var Series_PathUtilities = (PathUtilities);

;// ./code/es5/es-modules/Gantt/PathfinderAlgorithms.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Author: Øystein Moseng
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var PathfinderAlgorithms_pick = Core_Utilities.pick;
/* *
 *
 *  Constants
 *
 * */
var PathfinderAlgorithms_min = Math.min, PathfinderAlgorithms_max = Math.max, abs = Math.abs;
/* *
 *
 *  Functions
 *
 * */
/**
 * Get index of last obstacle before xMin. Employs a type of binary search, and
 * thus requires that obstacles are sorted by xMin value.
 *
 * @private
 * @function findLastObstacleBefore
 *
 * @param {Array<object>} obstacles
 *        Array of obstacles to search in.
 *
 * @param {number} xMin
 *        The xMin threshold.
 *
 * @param {number} [startIx]
 *        Starting index to search from. Must be within array range.
 *
 * @return {number}
 *         The index of the last obstacle element before xMin.
 */
function findLastObstacleBefore(obstacles, xMin, startIx) {
    var min = xMin - 0.0000001; // Make sure we include all obstacles at xMin
        var left = startIx || 0, // Left limit
        right = obstacles.length - 1, // Right limit
        cursor,
        cmp;
    while (left <= right) {
        cursor = (right + left) >> 1;
        cmp = min - obstacles[cursor].xMin;
        if (cmp > 0) {
            left = cursor + 1;
        }
        else if (cmp < 0) {
            right = cursor - 1;
        }
        else {
            return cursor;
        }
    }
    return left > 0 ? left - 1 : 0;
}
/**
 * Test if a point lays within an obstacle.
 *
 * @private
 * @function pointWithinObstacle
 *
 * @param {Object} obstacle
 *        Obstacle to test.
 *
 * @param {Highcharts.Point} point
 *        Point with x/y props.
 *
 * @return {boolean}
 *         Whether point is within the obstacle or not.
 */
function pointWithinObstacle(obstacle, point) {
    return (point.x <= obstacle.xMax &&
        point.x >= obstacle.xMin &&
        point.y <= obstacle.yMax &&
        point.y >= obstacle.yMin);
}
/**
 * Find the index of an obstacle that wraps around a point.
 * Returns -1 if not found.
 *
 * @private
 * @function findObstacleFromPoint
 *
 * @param {Array<object>} obstacles
 *        Obstacles to test.
 *
 * @param {Highcharts.Point} point
 *        Point with x/y props.
 *
 * @return {number}
 *         Ix of the obstacle in the array, or -1 if not found.
 */
function findObstacleFromPoint(obstacles, point) {
    var i = findLastObstacleBefore(obstacles,
        point.x + 1) + 1;
    while (i--) {
        if (obstacles[i].xMax >= point.x &&
            // Optimization using lazy evaluation
            pointWithinObstacle(obstacles[i], point)) {
            return i;
        }
    }
    return -1;
}
/**
 * Get SVG path array from array of line segments.
 *
 * @private
 * @function pathFromSegments
 *
 * @param {Array<object>} segments
 *        The segments to build the path from.
 *
 * @return {Highcharts.SVGPathArray}
 *         SVG path array as accepted by the SVG Renderer.
 */
function pathFromSegments(segments) {
    var path = [];
    if (segments.length) {
        path.push(['M', segments[0].start.x, segments[0].start.y]);
        for (var i = 0; i < segments.length; ++i) {
            path.push(['L', segments[i].end.x, segments[i].end.y]);
        }
    }
    return path;
}
/**
 * Limits obstacle max/mins in all directions to bounds. Modifies input
 * obstacle.
 *
 * @private
 * @function limitObstacleToBounds
 *
 * @param {Object} obstacle
 *        Obstacle to limit.
 *
 * @param {Object} bounds
 *        Bounds to use as limit.
 *
 * @return {void}
 */
function limitObstacleToBounds(obstacle, bounds) {
    obstacle.yMin = PathfinderAlgorithms_max(obstacle.yMin, bounds.yMin);
    obstacle.yMax = PathfinderAlgorithms_min(obstacle.yMax, bounds.yMax);
    obstacle.xMin = PathfinderAlgorithms_max(obstacle.xMin, bounds.xMin);
    obstacle.xMax = PathfinderAlgorithms_min(obstacle.xMax, bounds.xMax);
}
/**
 * Get an SVG path from a starting coordinate to an ending coordinate.
 * Draws a straight line.
 *
 * @function Highcharts.Pathfinder.algorithms.straight
 *
 * @param {Highcharts.PositionObject} start
 *        Starting coordinate, object with x/y props.
 *
 * @param {Highcharts.PositionObject} end
 *        Ending coordinate, object with x/y props.
 *
 * @return {Object}
 *         An object with the SVG path in Array form as accepted by the SVG
 *         renderer, as well as an array of new obstacles making up this
 *         path.
 */
function straight(start, end) {
    return {
        path: [
            ['M', start.x, start.y],
            ['L', end.x, end.y]
        ],
        obstacles: [{ start: start, end: end }]
    };
}
/**
 * Find a path from a starting coordinate to an ending coordinate, using
 * right angles only, and taking only starting/ending obstacle into
 * consideration.
 *
 * @function Highcharts.Pathfinder.algorithms.simpleConnect
 *
 * @param {Highcharts.PositionObject} start
 *        Starting coordinate, object with x/y props.
 *
 * @param {Highcharts.PositionObject} end
 *        Ending coordinate, object with x/y props.
 *
 * @param {Object} options
 *        Options for the algorithm:
 *        - chartObstacles: Array of chart obstacles to avoid
 *        - startDirectionX: Optional. True if starting in the X direction.
 *          If not provided, the algorithm starts in the direction that is
 *          the furthest between start/end.
 *
 * @return {Object}
 *         An object with the SVG path in Array form as accepted by the SVG
 *         renderer, as well as an array of new obstacles making up this
 *         path.
 */
var simpleConnect = function (start, end, options) {
    var segments = [],
        chartObstacles = options.chartObstacles,
        startObstacleIx = findObstacleFromPoint(chartObstacles,
        start),
        endObstacleIx = findObstacleFromPoint(chartObstacles,
        end);
    var endSegment,
        dir = PathfinderAlgorithms_pick(options.startDirectionX,
        abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y',
        startObstacle,
        endObstacle,
        waypoint,
        useMax,
        endPoint;
    // eslint-disable-next-line valid-jsdoc
    /**
     * Return a clone of a point with a property set from a target object,
     * optionally with an offset
     * @private
     */
    function copyFromPoint(from, fromKey, to, toKey, offset) {
        var point = {
                x: from.x,
                y: from.y
            };
        point[fromKey] = to[toKey || fromKey] + (offset || 0);
        return point;
    }
    // eslint-disable-next-line valid-jsdoc
    /**
     * Return waypoint outside obstacle.
     * @private
     */
    function getMeOut(obstacle, point, direction) {
        var useMax = abs(point[direction] - obstacle[direction + 'Min']) >
                abs(point[direction] - obstacle[direction + 'Max']);
        return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1);
    }
    // Pull out end point
    if (endObstacleIx > -1) {
        endObstacle = chartObstacles[endObstacleIx];
        waypoint = getMeOut(endObstacle, end, dir);
        endSegment = {
            start: waypoint,
            end: end
        };
        endPoint = waypoint;
    }
    else {
        endPoint = end;
    }
    // If an obstacle envelops the start point, add a segment to get out,
    // and around it.
    if (startObstacleIx > -1) {
        startObstacle = chartObstacles[startObstacleIx];
        waypoint = getMeOut(startObstacle, start, dir);
        segments.push({
            start: start,
            end: waypoint
        });
        // If we are going back again, switch direction to get around start
        // obstacle.
        if (
        // Going towards max from start:
        waypoint[dir] >= start[dir] ===
            // Going towards min to end:
            waypoint[dir] >= endPoint[dir]) {
            dir = dir === 'y' ? 'x' : 'y';
            useMax = start[dir] < end[dir];
            segments.push({
                start: waypoint,
                end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1)
            });
            // Switch direction again
            dir = dir === 'y' ? 'x' : 'y';
        }
    }
    // We are around the start obstacle. Go towards the end in one
    // direction.
    var prevWaypoint = segments.length ?
            segments[segments.length - 1].end :
            start;
    waypoint = copyFromPoint(prevWaypoint, dir, endPoint);
    segments.push({
        start: prevWaypoint,
        end: waypoint
    });
    // Final run to end point in the other direction
    dir = dir === 'y' ? 'x' : 'y';
    var waypoint2 = copyFromPoint(waypoint,
        dir,
        endPoint);
    segments.push({
        start: waypoint,
        end: waypoint2
    });
    // Finally add the endSegment
    segments.push(endSegment);
    var path = Series_PathUtilities.applyRadius(pathFromSegments(segments),
        options.radius);
    return {
        path: path,
        obstacles: segments
    };
};
simpleConnect.requiresObstacles = true;
/**
 * Find a path from a starting coordinate to an ending coordinate, taking
 * obstacles into consideration. Might not always find the optimal path,
 * but is fast, and usually good enough.
 *
 * @function Highcharts.Pathfinder.algorithms.fastAvoid
 *
 * @param {Highcharts.PositionObject} start
 *        Starting coordinate, object with x/y props.
 *
 * @param {Highcharts.PositionObject} end
 *        Ending coordinate, object with x/y props.
 *
 * @param {Object} options
 *        Options for the algorithm.
 *        - chartObstacles:  Array of chart obstacles to avoid
 *        - lineObstacles:   Array of line obstacles to jump over
 *        - obstacleMetrics: Object with metrics of chartObstacles cached
 *        - hardBounds:      Hard boundaries to not cross
 *        - obstacleOptions: Options for the obstacles, including margin
 *        - startDirectionX: Optional. True if starting in the X direction.
 *                           If not provided, the algorithm starts in the
 *                           direction that is the furthest between
 *                           start/end.
 *
 * @return {Object}
 *         An object with the SVG path in Array form as accepted by the SVG
 *         renderer, as well as an array of new obstacles making up this
 *         path.
 */
function fastAvoid(start, end, options) {
    /*
        Algorithm rules/description
        - Find initial direction
        - Determine soft/hard max for each direction.
        - Move along initial direction until obstacle.
        - Change direction.
        - If hitting obstacle, first try to change length of previous line
            before changing direction again.

        Soft min/max x = start/destination x +/- widest obstacle + margin
        Soft min/max y = start/destination y +/- tallest obstacle + margin

        @todo:
            - Make retrospective, try changing prev segment to reduce
                corners
            - Fix logic for breaking out of end-points - not always picking
                the best direction currently
            - When going around the end obstacle we should not always go the
                shortest route, rather pick the one closer to the end point
    */
    var dirIsX = PathfinderAlgorithms_pick(options.startDirectionX,
        abs(end.x - start.x) > abs(end.y - start.y)),
        dir = dirIsX ? 'x' : 'y',
        endSegments = [], 
        // Boundaries to stay within. If beyond soft boundary, prefer to
        // change direction ASAP. If at hard max, always change immediately.
        metrics = options.obstacleMetrics,
        softMinX = PathfinderAlgorithms_min(start.x,
        end.x) - metrics.maxWidth - 10,
        softMaxX = PathfinderAlgorithms_max(start.x,
        end.x) + metrics.maxWidth + 10,
        softMinY = PathfinderAlgorithms_min(start.y,
        end.y) - metrics.maxHeight - 10,
        softMaxY = PathfinderAlgorithms_max(start.y,
        end.y) + metrics.maxHeight + 10;
    var segments,
        useMax,
        extractedEndPoint,
        forceObstacleBreak = false, // Used in clearPathTo to keep track of
        // when to force break through an obstacle.
        // Obstacles
        chartObstacles = options.chartObstacles,
        endObstacleIx = findLastObstacleBefore(chartObstacles,
        softMaxX);
    var startObstacleIx = findLastObstacleBefore(chartObstacles,
        softMinX);
    // eslint-disable-next-line valid-jsdoc
    /**
     * How far can you go between two points before hitting an obstacle?
     * Does not work for diagonal lines (because it doesn't have to).
     * @private
     */
    function pivotPoint(fromPoint, toPoint, directionIsX) {
        var searchDirection = fromPoint.x < toPoint.x ? 1 : -1;
        var firstPoint,
            lastPoint,
            highestPoint,
            lowestPoint;
        if (fromPoint.x < toPoint.x) {
            firstPoint = fromPoint;
            lastPoint = toPoint;
        }
        else {
            firstPoint = toPoint;
            lastPoint = fromPoint;
        }
        if (fromPoint.y < toPoint.y) {
            lowestPoint = fromPoint;
            highestPoint = toPoint;
        }
        else {
            lowestPoint = toPoint;
            highestPoint = fromPoint;
        }
        // Go through obstacle range in reverse if toPoint is before
        // fromPoint in the X-dimension.
        var i = searchDirection < 0 ?
                // Searching backwards, start at last obstacle before last point
                PathfinderAlgorithms_min(findLastObstacleBefore(chartObstacles,
            lastPoint.x),
            chartObstacles.length - 1) :
                // Forwards. Since we're not sorted by xMax, we have to look
                // at all obstacles.
                0;
        // Go through obstacles in this X range
        while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x ||
            searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) {
            // If this obstacle is between from and to points in a straight
            // line, pivot at the intersection.
            if (chartObstacles[i].xMin <= lastPoint.x &&
                chartObstacles[i].xMax >= firstPoint.x &&
                chartObstacles[i].yMin <= highestPoint.y &&
                chartObstacles[i].yMax >= lowestPoint.y) {
                if (directionIsX) {
                    return {
                        y: fromPoint.y,
                        x: fromPoint.x < toPoint.x ?
                            chartObstacles[i].xMin - 1 :
                            chartObstacles[i].xMax + 1,
                        obstacle: chartObstacles[i]
                    };
                }
                // Else ...
                return {
                    x: fromPoint.x,
                    y: fromPoint.y < toPoint.y ?
                        chartObstacles[i].yMin - 1 :
                        chartObstacles[i].yMax + 1,
                    obstacle: chartObstacles[i]
                };
            }
            i += searchDirection;
        }
        return toPoint;
    }
    /**
     * Decide in which direction to dodge or get out of an obstacle.
     * Considers desired direction, which way is shortest, soft and hard
     * bounds.
     *
     * (? Returns a string, either xMin, xMax, yMin or yMax.)
     *
     * @private
     * @function
     *
     * @param {Object} obstacle
     *        Obstacle to dodge/escape.
     *
     * @param {Object} fromPoint
     *        Point with x/y props that's dodging/escaping.
     *
     * @param {Object} toPoint
     *        Goal point.
     *
     * @param {boolean} dirIsX
     *        Dodge in X dimension.
     *
     * @param {Object} bounds
     *        Hard and soft boundaries.
     *
     * @return {boolean}
     *         Use max or not.
     */
    function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) {
        var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, maxOutOfSoftBounds = obstacle[dir + 'Max'] >=
                softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <=
                softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >=
                hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <=
                hardBounds[dir + 'Min'], 
            // Find out if we should prefer one direction over the other if
            // we can choose freely
            minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]);
        var // If it's a small difference, pick the one leading towards dest
            // point. Otherwise pick the shortest distance
            useMax = abs(minDistance - maxDistance) < 10 ?
                fromPoint[dir] < toPoint[dir] :
                maxDistance < minDistance;
        // Check if we hit any obstacles trying to go around in either
        // direction.
        toPointMin[dir] = obstacle[dir + 'Min'];
        toPointMax[dir] = obstacle[dir + 'Max'];
        var minPivot = pivotPoint(fromPoint,
            toPointMin,
            dirIsX)[dir] !==
                toPointMin[dir],
            maxPivot = pivotPoint(fromPoint,
            toPointMax,
            dirIsX)[dir] !==
                toPointMax[dir];
        useMax = minPivot ?
            (maxPivot ? useMax : true) :
            (maxPivot ? false : useMax);
        // `useMax` now contains our preferred choice, bounds not taken into
        // account. If both or neither direction is out of bounds we want to
        // use this.
        // Deal with soft bounds
        useMax = minOutOfSoftBounds ?
            (maxOutOfSoftBounds ? useMax : true) : // Out on min
            (maxOutOfSoftBounds ? false : useMax); // Not out on min
        // Deal with hard bounds
        useMax = minOutOfHardBounds ?
            (maxOutOfHardBounds ? useMax : true) : // Out on min
            (maxOutOfHardBounds ? false : useMax); // Not out on min
        return useMax;
    }
    // eslint-disable-next-line valid-jsdoc
    /**
     * Find a clear path between point.
     * @private
     */
    function clearPathTo(fromPoint, toPoint, dirIsX) {
        // Don't waste time if we've hit goal
        if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) {
            return [];
        }
        var dir = dirIsX ? 'x' : 'y',
            obstacleMargin = options.obstacleOptions.margin,
            bounds = {
                soft: {
                    xMin: softMinX,
                    xMax: softMaxX,
                    yMin: softMinY,
                    yMax: softMaxY
                },
                hard: options.hardBounds
            };
        var pivot,
            segments,
            waypoint,
            waypointUseMax,
            envelopingObstacle,
            secondEnvelopingObstacle,
            envelopWaypoint;
        // If fromPoint is inside an obstacle we have a problem. Break out
        // by just going to the outside of this obstacle. We prefer to go to
        // the nearest edge in the chosen direction.
        envelopingObstacle =
            findObstacleFromPoint(chartObstacles, fromPoint);
        if (envelopingObstacle > -1) {
            envelopingObstacle = chartObstacles[envelopingObstacle];
            waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds);
            // Cut obstacle to hard bounds to make sure we stay within
            limitObstacleToBounds(envelopingObstacle, options.hardBounds);
            envelopWaypoint = dirIsX ? {
                y: fromPoint.y,
                x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] +
                    (waypointUseMax ? 1 : -1)
            } : {
                x: fromPoint.x,
                y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] +
                    (waypointUseMax ? 1 : -1)
            };
            // If we crashed into another obstacle doing this, we put the
            // waypoint between them instead
            secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint);
            if (secondEnvelopingObstacle > -1) {
                secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle];
                // Cut obstacle to hard bounds
                limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds);
                // Modify waypoint to lay between obstacles
                envelopWaypoint[dir] = waypointUseMax ? PathfinderAlgorithms_max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] +
                    envelopingObstacle[dir + 'Max']) / 2) :
                    PathfinderAlgorithms_min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] +
                        envelopingObstacle[dir + 'Min']) / 2));
                // We are not going anywhere. If this happens for the first
                // time, do nothing. Otherwise, try to go to the extreme of
                // the obstacle pair in the current direction.
                if (fromPoint.x === envelopWaypoint.x &&
                    fromPoint.y === envelopWaypoint.y) {
                    if (forceObstacleBreak) {
                        envelopWaypoint[dir] = waypointUseMax ?
                            PathfinderAlgorithms_max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 :
                            PathfinderAlgorithms_min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1;
                    }
                    // Toggle on if off, and the opposite
                    forceObstacleBreak = !forceObstacleBreak;
                }
                else {
                    // This point is not identical to previous.
                    // Clear break trigger.
                    forceObstacleBreak = false;
                }
            }
            segments = [{
                    start: fromPoint,
                    end: envelopWaypoint
                }];
        }
        else { // If not enveloping, use standard pivot calculation
            pivot = pivotPoint(fromPoint, {
                x: dirIsX ? toPoint.x : fromPoint.x,
                y: dirIsX ? fromPoint.y : toPoint.y
            }, dirIsX);
            segments = [{
                    start: fromPoint,
                    end: {
                        x: pivot.x,
                        y: pivot.y
                    }
                }];
            // Pivot before goal, use a waypoint to dodge obstacle
            if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) {
                // Find direction of waypoint
                waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds);
                // Cut waypoint to hard bounds
                limitObstacleToBounds(pivot.obstacle, options.hardBounds);
                waypoint = {
                    x: dirIsX ?
                        pivot.x :
                        pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] +
                            (waypointUseMax ? 1 : -1),
                    y: dirIsX ?
                        pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] +
                            (waypointUseMax ? 1 : -1) :
                        pivot.y
                };
                // We're changing direction here, store that to make sure we
                // also change direction when adding the last segment array
                // after handling waypoint.
                dirIsX = !dirIsX;
                segments = segments.concat(clearPathTo({
                    x: pivot.x,
                    y: pivot.y
                }, waypoint, dirIsX));
            }
        }
        // Get segments for the other direction too
        // Recursion is our friend
        segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX));
        return segments;
    }
    // eslint-disable-next-line valid-jsdoc
    /**
     * Extract point to outside of obstacle in whichever direction is
     * closest. Returns new point outside obstacle.
     * @private
     */
    function extractFromObstacle(obstacle, point, goalPoint) {
        var dirIsX = PathfinderAlgorithms_min(obstacle.xMax - point.x,
            point.x - obstacle.xMin) <
                PathfinderAlgorithms_min(obstacle.yMax - point.y,
            point.y - obstacle.yMin),
            bounds = {
                soft: options.hardBounds,
                hard: options.hardBounds
            },
            useMax = getDodgeDirection(obstacle,
            point,
            goalPoint,
            dirIsX,
            bounds);
        return dirIsX ? {
            y: point.y,
            x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1)
        } : {
            x: point.x,
            y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1)
        };
    }
    // Cut the obstacle array to soft bounds for optimization in large
    // datasets.
    chartObstacles =
        chartObstacles.slice(startObstacleIx, endObstacleIx + 1);
    // If an obstacle envelops the end point, move it out of there and add
    // a little segment to where it was.
    if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) {
        extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start);
        endSegments.push({
            end: end,
            start: extractedEndPoint
        });
        end = extractedEndPoint;
    }
    // If it's still inside one or more obstacles, get out of there by
    // force-moving towards the start point.
    while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) {
        useMax = end[dir] - start[dir] < 0;
        extractedEndPoint = {
            x: end.x,
            y: end.y
        };
        extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1);
        endSegments.push({
            end: end,
            start: extractedEndPoint
        });
        end = extractedEndPoint;
    }
    // Find the path
    segments = clearPathTo(start, end, dirIsX);
    // Add the end-point segments
    segments = segments.concat(endSegments.reverse());
    return {
        path: pathFromSegments(segments),
        obstacles: segments
    };
}
fastAvoid.requiresObstacles = true;
/* *
 *
 *  Default Export
 *
 * */
// Define the available pathfinding algorithms.
// Algorithms take up to 3 arguments: starting point, ending point, and an
// options object.
var algorithms = {
    fastAvoid: fastAvoid,
    straight: straight,
    simpleConnect: simpleConnect
};
/* harmony default export */ var PathfinderAlgorithms = (algorithms);

;// ./code/es5/es-modules/Gantt/ConnectorsDefaults.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Øystein Moseng, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

/* *
 *
 *  API Defaults
 *
 * */
/*
 @todo:
     - Document how to write your own algorithms
     - Consider adding a Point.pathTo method that wraps creating a connection
       and rendering it
*/
var connectorsDefaults = {
    /**
     * The Pathfinder module allows you to define connections between any two
     * points, represented as lines - optionally with markers for the start
     * and/or end points. Multiple algorithms are available for calculating how
     * the connecting lines are drawn.
     *
     * Connector functionality requires Highcharts Gantt to be loaded. In Gantt
     * charts, the connectors are used to draw dependencies between tasks.
     *
     * @see [dependency](series.gantt.data.dependency)
     *
     * @sample gantt/pathfinder/demo
     *         Pathfinder connections
     *
     * @declare      Highcharts.ConnectorsOptions
     * @product      gantt
     * @optionparent connectors
     */
    connectors: {
        /**
         * Enable connectors for this chart. Requires Highcharts Gantt.
         *
         * @type      {boolean}
         * @default   true
         * @since     6.2.0
         * @apioption connectors.enabled
         */
        /**
         * Set the default dash style for this chart's connecting lines.
         *
         * @type      {string}
         * @default   solid
         * @since     6.2.0
         * @apioption connectors.dashStyle
         */
        /**
         * Set the default color for this chart's Pathfinder connecting lines.
         * Defaults to the color of the point being connected.
         *
         * @type      {Highcharts.ColorString}
         * @since     6.2.0
         * @apioption connectors.lineColor
         */
        /**
         * Set the default pathfinder margin to use, in pixels. Some Pathfinder
         * algorithms attempt to avoid obstacles, such as other points in the
         * chart. These algorithms use this margin to determine how close lines
         * can be to an obstacle. The default is to compute this automatically
         * from the size of the obstacles in the chart.
         *
         * To draw connecting lines close to existing points, set this to a low
         * number. For more space around existing points, set this number
         * higher.
         *
         * @sample gantt/pathfinder/algorithm-margin
         *         Small algorithmMargin
         *
         * @type      {number}
         * @since     6.2.0
         * @apioption connectors.algorithmMargin
         */
        /**
         * Set the default pathfinder algorithm to use for this chart. It is
         * possible to define your own algorithms by adding them to the
         * Highcharts.Pathfinder.prototype.algorithms object before the chart
         * has been created.
         *
         * The default algorithms are as follows:
         *
         * `straight`:      Draws a straight line between the connecting
         *                  points. Does not avoid other points when drawing.
         *
         * `simpleConnect`: Finds a path between the points using right angles
         *                  only. Takes only starting/ending points into
         *                  account, and will not avoid other points.
         *
         * `fastAvoid`:     Finds a path between the points using right angles
         *                  only. Will attempt to avoid other points, but its
         *                  focus is performance over accuracy. Works well with
         *                  less dense datasets.
         *
         * Default value: `straight` is used as default for most series types,
         * while `simpleConnect` is used as default for Gantt series, to show
         * dependencies between points.
         *
         * @sample gantt/pathfinder/demo
         *         Different types used
         *
         * @type    {Highcharts.PathfinderTypeValue}
         * @default undefined
         * @since   6.2.0
         */
        type: 'straight',
        /**
         * The corner radius for the connector line.
         *
         * @since 11.2.0
         */
        radius: 0,
        /**
         * Set the default pixel width for this chart's Pathfinder connecting
         * lines.
         *
         * @since 6.2.0
         */
        lineWidth: 1,
        /**
         * Marker options for this chart's Pathfinder connectors. Note that
         * this option is overridden by the `startMarker` and `endMarker`
         * options.
         *
         * @declare Highcharts.ConnectorsMarkerOptions
         * @since   6.2.0
         */
        marker: {
            /**
             * Set the radius of the connector markers. The default is
             * automatically computed based on the algorithmMargin setting.
             *
             * Setting marker.width and marker.height will override this
             * setting.
             *
             * @type      {number}
             * @since     6.2.0
             * @apioption connectors.marker.radius
             */
            /**
             * Set the width of the connector markers. If not supplied, this
             * is inferred from the marker radius.
             *
             * @type      {number}
             * @since     6.2.0
             * @apioption connectors.marker.width
             */
            /**
             * Set the height of the connector markers. If not supplied, this
             * is inferred from the marker radius.
             *
             * @type      {number}
             * @since     6.2.0
             * @apioption connectors.marker.height
             */
            /**
             * Set the color of the connector markers. By default this is the
             * same as the connector color.
             *
             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
             * @since     6.2.0
             * @apioption connectors.marker.color
             */
            /**
             * Set the line/border color of the connector markers. By default
             * this is the same as the marker color.
             *
             * @type      {Highcharts.ColorString}
             * @since     6.2.0
             * @apioption connectors.marker.lineColor
             */
            /**
             * Enable markers for the connectors.
             */
            enabled: false,
            /**
             * Horizontal alignment of the markers relative to the points.
             *
             * @type {Highcharts.AlignValue}
             */
            align: 'center',
            /**
             * Vertical alignment of the markers relative to the points.
             *
             * @type {Highcharts.VerticalAlignValue}
             */
            verticalAlign: 'middle',
            /**
             * Whether or not to draw the markers inside the points.
             */
            inside: false,
            /**
             * Set the line/border width of the pathfinder markers.
             */
            lineWidth: 1
        },
        /**
         * Marker options specific to the start markers for this chart's
         * Pathfinder connectors. Overrides the generic marker options.
         *
         * @declare Highcharts.ConnectorsStartMarkerOptions
         * @extends connectors.marker
         * @since   6.2.0
         */
        startMarker: {
            /**
             * Set the symbol of the connector start markers.
             */
            symbol: 'diamond'
        },
        /**
         * Marker options specific to the end markers for this chart's
         * Pathfinder connectors. Overrides the generic marker options.
         *
         * @declare Highcharts.ConnectorsEndMarkerOptions
         * @extends connectors.marker
         * @since   6.2.0
         */
        endMarker: {
            /**
             * Set the symbol of the connector end markers.
             */
            symbol: 'arrow-filled'
        }
    }
};
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var ConnectorsDefaults = (connectorsDefaults);
/* *
 *
 *  API Options
 *
 * */
/**
 * Override Pathfinder connector options for a series. Requires Highcharts Gantt
 * to be loaded.
 *
 * @declare   Highcharts.SeriesConnectorsOptionsObject
 * @extends   connectors
 * @since     6.2.0
 * @excluding enabled, algorithmMargin
 * @product   gantt
 * @apioption plotOptions.series.connectors
 */
/**
 * Connect to a point. This option can be either a string, referring to the ID
 * of another point, or an object, or an array of either. If the option is an
 * array, each element defines a connection.
 *
 * @sample gantt/pathfinder/demo
 *         Different connection types
 *
 * @declare   Highcharts.XrangePointConnectorsOptionsObject
 * @type      {string|Array<string|*>|*}
 * @extends   plotOptions.series.connectors
 * @since     6.2.0
 * @excluding enabled
 * @product   gantt
 * @requires  highcharts-gantt
 * @apioption series.xrange.data.connect
 */
/**
 * The ID of the point to connect to.
 *
 * @type      {string}
 * @since     6.2.0
 * @product   gantt
 * @apioption series.xrange.data.connect.to
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Gantt/PathfinderComposition.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Øystein Moseng, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var PathfinderComposition_setOptions = Defaults.setOptions;

var PathfinderComposition_defined = Core_Utilities.defined, PathfinderComposition_error = Core_Utilities.error, PathfinderComposition_merge = Core_Utilities.merge;
/* *
 *
 *  Functions
 *
 * */
/**
 * Get point bounding box using plotX/plotY and shapeArgs. If using
 * graphic.getBBox() directly, the bbox will be affected by animation.
 *
 * @private
 * @function
 *
 * @param {Highcharts.Point} point
 *        The point to get BB of.
 *
 * @return {Highcharts.Dictionary<number>|null}
 *         Result xMax, xMin, yMax, yMin.
 */
function getPointBB(point) {
    var shapeArgs = point.shapeArgs;
    // Prefer using shapeArgs (columns)
    if (shapeArgs) {
        return {
            xMin: shapeArgs.x || 0,
            xMax: (shapeArgs.x || 0) + (shapeArgs.width || 0),
            yMin: shapeArgs.y || 0,
            yMax: (shapeArgs.y || 0) + (shapeArgs.height || 0)
        };
    }
    // Otherwise use plotX/plotY and bb
    var bb = point.graphic && point.graphic.getBBox();
    return bb ? {
        xMin: point.plotX - bb.width / 2,
        xMax: point.plotX + bb.width / 2,
        yMin: point.plotY - bb.height / 2,
        yMax: point.plotY + bb.height / 2
    } : null;
}
/**
 * Warn if using legacy options. Copy the options over. Note that this will
 * still break if using the legacy options in chart.update, addSeries etc.
 * @private
 */
function warnLegacy(chart) {
    if (chart.options.pathfinder ||
        chart.series.reduce(function (acc, series) {
            if (series.options) {
                PathfinderComposition_merge(true, (series.options.connectors = series.options.connectors ||
                    {}), series.options.pathfinder);
            }
            return acc || series.options && series.options.pathfinder;
        }, false)) {
        PathfinderComposition_merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder);
        PathfinderComposition_error('WARNING: Pathfinder options have been renamed. ' +
            'Use "chart.connectors" or "series.connectors" instead.');
    }
}
/* *
 *
 *  Composition
 *
 * */
var ConnectionComposition;
(function (ConnectionComposition) {
    /* *
     *
     *  Functions
     *
     * */
    /** @private */
    function compose(ChartClass, PathfinderClass, PointClass) {
        var pointProto = PointClass.prototype;
        if (!pointProto.getPathfinderAnchorPoint) {
            // Initialize Pathfinder for charts
            ChartClass.prototype.callbacks.push(function (chart) {
                var options = chart.options;
                if (options.connectors.enabled !== false) {
                    warnLegacy(chart);
                    this.pathfinder = new PathfinderClass(this);
                    this.pathfinder.update(true); // First draw, defer render
                }
            });
            pointProto.getMarkerVector = pointGetMarkerVector;
            pointProto.getPathfinderAnchorPoint = pointGetPathfinderAnchorPoint;
            pointProto.getRadiansToVector = pointGetRadiansToVector;
            // Set default Pathfinder options
            PathfinderComposition_setOptions(ConnectorsDefaults);
        }
    }
    ConnectionComposition.compose = compose;
    /**
     * Get coordinates of anchor point for pathfinder connection.
     *
     * @private
     * @function Highcharts.Point#getPathfinderAnchorPoint
     *
     * @param {Highcharts.ConnectorsMarkerOptions} markerOptions
     *        Connection options for position on point.
     *
     * @return {Highcharts.PositionObject}
     *         An object with x/y properties for the position. Coordinates are
     *         in plot values, not relative to point.
     */
    function pointGetPathfinderAnchorPoint(markerOptions) {
        var bb = getPointBB(this);
        var x,
            y;
        switch (markerOptions.align) { // eslint-disable-line default-case
            case 'right':
                x = 'xMax';
                break;
            case 'left':
                x = 'xMin';
        }
        switch (markerOptions.verticalAlign) { // eslint-disable-line default-case
            case 'top':
                y = 'yMin';
                break;
            case 'bottom':
                y = 'yMax';
        }
        return {
            x: x ? bb[x] : (bb.xMin + bb.xMax) / 2,
            y: y ? bb[y] : (bb.yMin + bb.yMax) / 2
        };
    }
    /**
     * Utility to get the angle from one point to another.
     *
     * @private
     * @function Highcharts.Point#getRadiansToVector
     *
     * @param {Highcharts.PositionObject} v1
     *        The first vector, as an object with x/y properties.
     *
     * @param {Highcharts.PositionObject} v2
     *        The second vector, as an object with x/y properties.
     *
     * @return {number}
     *         The angle in degrees
     */
    function pointGetRadiansToVector(v1, v2) {
        var box;
        if (!PathfinderComposition_defined(v2)) {
            box = getPointBB(this);
            if (box) {
                v2 = {
                    x: (box.xMin + box.xMax) / 2,
                    y: (box.yMin + box.yMax) / 2
                };
            }
        }
        return Math.atan2(v2.y - v1.y, v1.x - v2.x);
    }
    /**
     * Utility to get the position of the marker, based on the path angle and
     * the marker's radius.
     *
     * @private
     * @function Highcharts.Point#getMarkerVector
     *
     * @param {number} radians
     *        The angle in radians from the point center to another vector.
     *
     * @param {number} markerRadius
     *        The radius of the marker, to calculate the additional distance to
     *        the center of the marker.
     *
     * @param {Object} anchor
     *        The anchor point of the path and marker as an object with x/y
     *        properties.
     *
     * @return {Object}
     *         The marker vector as an object with x/y properties.
     */
    function pointGetMarkerVector(radians, markerRadius, anchor) {
        var twoPI = Math.PI * 2.0, bb = getPointBB(this), rectWidth = bb.xMax - bb.xMin, rectHeight = bb.yMax - bb.yMin, rAtan = Math.atan2(rectHeight, rectWidth), rectHalfWidth = rectWidth / 2.0, rectHalfHeight = rectHeight / 2.0, rectHorizontalCenter = bb.xMin + rectHalfWidth, rectVerticalCenter = bb.yMin + rectHalfHeight, edgePoint = {
                x: rectHorizontalCenter,
                y: rectVerticalCenter
            };
        var theta = radians,
            tanTheta = 1,
            leftOrRightRegion = false,
            xFactor = 1,
            yFactor = 1;
        while (theta < -Math.PI) {
            theta += twoPI;
        }
        while (theta > Math.PI) {
            theta -= twoPI;
        }
        tanTheta = Math.tan(theta);
        if ((theta > -rAtan) && (theta <= rAtan)) {
            // Right side
            yFactor = -1;
            leftOrRightRegion = true;
        }
        else if (theta > rAtan && theta <= (Math.PI - rAtan)) {
            // Top side
            yFactor = -1;
        }
        else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) {
            // Left side
            xFactor = -1;
            leftOrRightRegion = true;
        }
        else {
            // Bottom side
            xFactor = -1;
        }
        // Correct the edgePoint according to the placement of the marker
        if (leftOrRightRegion) {
            edgePoint.x += xFactor * (rectHalfWidth);
            edgePoint.y += yFactor * (rectHalfWidth) * tanTheta;
        }
        else {
            edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta));
            edgePoint.y += yFactor * (rectHalfHeight);
        }
        if (anchor.x !== rectHorizontalCenter) {
            edgePoint.x = anchor.x;
        }
        if (anchor.y !== rectVerticalCenter) {
            edgePoint.y = anchor.y;
        }
        return {
            x: edgePoint.x + (markerRadius * Math.cos(theta)),
            y: edgePoint.y - (markerRadius * Math.sin(theta))
        };
    }
})(ConnectionComposition || (ConnectionComposition = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var PathfinderComposition = (ConnectionComposition);

;// ./code/es5/es-modules/Gantt/Pathfinder.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Øystein Moseng, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */






var Pathfinder_addEvent = Core_Utilities.addEvent, Pathfinder_defined = Core_Utilities.defined, Pathfinder_pick = Core_Utilities.pick, Pathfinder_splat = Core_Utilities.splat;
/* *
 *
 *  Constants
 *
 * */
var Pathfinder_max = Math.max, Pathfinder_min = Math.min;
/* *
 *
 *  Functions
 *
 * */
/**
 * Get point bounding box using plotX/plotY and shapeArgs. If using
 * graphic.getBBox() directly, the bbox will be affected by animation.
 *
 * @private
 * @function
 *
 * @param {Highcharts.Point} point
 *        The point to get BB of.
 *
 * @return {Highcharts.Dictionary<number>|null}
 *         Result xMax, xMin, yMax, yMin.
 */
function Pathfinder_getPointBB(point) {
    var shapeArgs = point.shapeArgs;
    // Prefer using shapeArgs (columns)
    if (shapeArgs) {
        return {
            xMin: shapeArgs.x || 0,
            xMax: (shapeArgs.x || 0) + (shapeArgs.width || 0),
            yMin: shapeArgs.y || 0,
            yMax: (shapeArgs.y || 0) + (shapeArgs.height || 0)
        };
    }
    // Otherwise use plotX/plotY and bb
    var bb = point.graphic && point.graphic.getBBox();
    return bb ? {
        xMin: point.plotX - bb.width / 2,
        xMax: point.plotX + bb.width / 2,
        yMin: point.plotY - bb.height / 2,
        yMax: point.plotY + bb.height / 2
    } : null;
}
/**
 * Compute smallest distance between two rectangles.
 * @private
 */
function calculateObstacleDistance(a, b, bbMargin) {
    // Count the distance even if we are slightly off
    var margin = Pathfinder_pick(bbMargin, 10),
        yOverlap = a.yMax + margin > b.yMin - margin &&
            a.yMin - margin < b.yMax + margin,
        xOverlap = a.xMax + margin > b.xMin - margin &&
            a.xMin - margin < b.xMax + margin,
        xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity,
        yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity;
    // If the rectangles collide, try recomputing with smaller margin.
    // If they collide anyway, discard the obstacle.
    if (xOverlap && yOverlap) {
        return (margin ?
            calculateObstacleDistance(a, b, Math.floor(margin / 2)) :
            Infinity);
    }
    return Pathfinder_min(xDistance, yDistance);
}
/**
 * Calculate margin to place around obstacles for the pathfinder in pixels.
 * Returns a minimum of 1 pixel margin.
 *
 * @private
 * @function
 *
 * @param {Array<object>} obstacles
 *        Obstacles to calculate margin from.
 *
 * @return {number}
 *         The calculated margin in pixels. At least 1.
 */
function calculateObstacleMargin(obstacles) {
    var len = obstacles.length,
        distances = [];
    var onstacleDistance;
    // Go over all obstacles and compare them to the others.
    for (var i = 0; i < len; ++i) {
        // Compare to all obstacles ahead. We will already have compared this
        // obstacle to the ones before.
        for (var j = i + 1; j < len; ++j) {
            onstacleDistance =
                calculateObstacleDistance(obstacles[i], obstacles[j]);
            // TODO: Magic number 80
            if (onstacleDistance < 80) { // Ignore large distances
                distances.push(onstacleDistance);
            }
        }
    }
    // Ensure we always have at least one value, even in very spacious charts
    distances.push(80);
    return Pathfinder_max(Math.floor(distances.sort(function (a, b) {
        return (a - b);
    })[
    // Discard first 10% of the relevant distances, and then grab
    // the smallest one.
    Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1.
    ), 1 // 1 is the minimum margin
    );
}
/* *
 *
 *  Class
 *
 * */
/**
 * The Pathfinder class.
 *
 * @private
 * @class
 * @name Highcharts.Pathfinder
 *
 * @param {Highcharts.Chart} chart
 *        The chart to operate on.
 */
var Pathfinder = /** @class */ (function () {
    /* *
     *
     *  Constructor
     *
     * */
    function Pathfinder(chart) {
        this.init(chart);
    }
    /* *
     *
     *  Static Functions
     *
     * */
    Pathfinder.compose = function (ChartClass, PointClass) {
        PathfinderComposition.compose(ChartClass, Pathfinder, PointClass);
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Initialize the Pathfinder object.
     *
     * @function Highcharts.Pathfinder#init
     *
     * @param {Highcharts.Chart} chart
     *        The chart context.
     */
    Pathfinder.prototype.init = function (chart) {
        // Initialize pathfinder with chart context
        this.chart = chart;
        // Init connection reference list
        this.connections = [];
        // Recalculate paths/obstacles on chart redraw
        Pathfinder_addEvent(chart, 'redraw', function () {
            this.pathfinder.update();
        });
    };
    /**
     * Update Pathfinder connections from scratch.
     *
     * @function Highcharts.Pathfinder#update
     *
     * @param {boolean} [deferRender]
     *        Whether or not to defer rendering of connections until
     *        series.afterAnimate event has fired. Used on first render.
     */
    Pathfinder.prototype.update = function (deferRender) {
        var chart = this.chart,
            pathfinder = this,
            oldConnections = pathfinder.connections;
        // Rebuild pathfinder connections from options
        pathfinder.connections = [];
        chart.series.forEach(function (series) {
            if (series.visible && !series.options.isInternal) {
                series.points.forEach(function (point) {
                    var _a;
                    var ganttPointOptions = point.options;
                    // For Gantt series the connect could be
                    // defined as a dependency
                    if (ganttPointOptions && ganttPointOptions.dependency) {
                        ganttPointOptions.connect = ganttPointOptions
                            .dependency;
                    }
                    var connects = ((_a = point.options) === null || _a === void 0 ? void 0 : _a.connect) ?
                            Pathfinder_splat(point.options.connect) :
                            [];
                    var to;
                    if (point.visible && point.isInside !== false) {
                        connects.forEach(function (connect) {
                            var toId = typeof connect === 'string' ?
                                    connect :
                                    connect.to;
                            if (toId) {
                                to = chart.get(toId);
                            }
                            if (to instanceof Series_Point &&
                                to.series.visible &&
                                to.visible &&
                                to.isInside !== false) {
                                // Add new connection
                                pathfinder.connections.push(new Gantt_Connection(point, // From
                                to, typeof connect === 'string' ?
                                    {} :
                                    connect));
                            }
                        });
                    }
                });
            }
        });
        // Clear connections that should not be updated, and move old info over
        // to new connections.
        for (var j = 0, k = void 0, found = void 0, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) {
            found = false;
            var oldCon = oldConnections[j];
            for (k = 0; k < lenNew; ++k) {
                var newCon = pathfinder.connections[k];
                if ((oldCon.options && oldCon.options.type) ===
                    (newCon.options && newCon.options.type) &&
                    oldCon.fromPoint === newCon.fromPoint &&
                    oldCon.toPoint === newCon.toPoint) {
                    newCon.graphics = oldCon.graphics;
                    found = true;
                    break;
                }
            }
            if (!found) {
                oldCon.destroy();
            }
        }
        // Clear obstacles to force recalculation. This must be done on every
        // redraw in case positions have changed. Recalculation is handled in
        // Connection.getPath on demand.
        delete this.chartObstacles;
        delete this.lineObstacles;
        // Draw the pending connections
        pathfinder.renderConnections(deferRender);
    };
    /**
     * Draw the chart's connecting paths.
     *
     * @function Highcharts.Pathfinder#renderConnections
     *
     * @param {boolean} [deferRender]
     *        Whether or not to defer render until series animation is finished.
     *        Used on first render.
     */
    Pathfinder.prototype.renderConnections = function (deferRender) {
        if (deferRender) {
            // Render after series are done animating
            this.chart.series.forEach(function (series) {
                var render = function () {
                        // Find pathfinder connections belonging to this series
                        // that haven't rendered, and render them now.
                        var pathfinder = series.chart.pathfinder,
                    conns = pathfinder && pathfinder.connections || [];
                    conns.forEach(function (connection) {
                        if (connection.fromPoint &&
                            connection.fromPoint.series === series) {
                            connection.render();
                        }
                    });
                    if (series.pathfinderRemoveRenderEvent) {
                        series.pathfinderRemoveRenderEvent();
                        delete series.pathfinderRemoveRenderEvent;
                    }
                };
                if (series.options.animation === false) {
                    render();
                }
                else {
                    series.pathfinderRemoveRenderEvent = Pathfinder_addEvent(series, 'afterAnimate', render);
                }
            });
        }
        else {
            // Go through connections and render them
            this.connections.forEach(function (connection) {
                connection.render();
            });
        }
    };
    /**
     * Get obstacles for the points in the chart. Does not include connecting
     * lines from Pathfinder. Applies algorithmMargin to the obstacles.
     *
     * @function Highcharts.Pathfinder#getChartObstacles
     *
     * @param {Object} options
     *        Options for the calculation. Currently only
     *        `options.algorithmMargin`.
     *
     * @param {number} options.algorithmMargin
     *        The algorithm margin to use for the obstacles.

    * @return {Array<object>}
     *         An array of calculated obstacles. Each obstacle is defined as an
     *         object with xMin, xMax, yMin and yMax properties.
     */
    Pathfinder.prototype.getChartObstacles = function (options) {
        var series = this.chart.series,
            margin = Pathfinder_pick(options.algorithmMargin, 0);
        var obstacles = [],
            calculatedMargin;
        for (var i = 0, sLen = series.length; i < sLen; ++i) {
            if (series[i].visible && !series[i].options.isInternal) {
                for (var j = 0, pLen = series[i].points.length, bb = void 0, point = void 0; j < pLen; ++j) {
                    point = series[i].points[j];
                    if (point.visible) {
                        bb = Pathfinder_getPointBB(point);
                        if (bb) {
                            obstacles.push({
                                xMin: bb.xMin - margin,
                                xMax: bb.xMax + margin,
                                yMin: bb.yMin - margin,
                                yMax: bb.yMax + margin
                            });
                        }
                    }
                }
            }
        }
        // Sort obstacles by xMin for optimization
        obstacles = obstacles.sort(function (a, b) {
            return a.xMin - b.xMin;
        });
        // Add auto-calculated margin if the option is not defined
        if (!Pathfinder_defined(options.algorithmMargin)) {
            calculatedMargin =
                options.algorithmMargin =
                    calculateObstacleMargin(obstacles);
            obstacles.forEach(function (obstacle) {
                obstacle.xMin -= calculatedMargin;
                obstacle.xMax += calculatedMargin;
                obstacle.yMin -= calculatedMargin;
                obstacle.yMax += calculatedMargin;
            });
        }
        return obstacles;
    };
    /**
     * Utility function to get metrics for obstacles:
     * - Widest obstacle width
     * - Tallest obstacle height
     *
     * @function Highcharts.Pathfinder#getObstacleMetrics
     *
     * @param {Array<object>} obstacles
     *        An array of obstacles to inspect.
     *
     * @return {Object}
     *         The calculated metrics, as an object with maxHeight and maxWidth
     *         properties.
     */
    Pathfinder.prototype.getObstacleMetrics = function (obstacles) {
        var maxWidth = 0,
            maxHeight = 0,
            width,
            height,
            i = obstacles.length;
        while (i--) {
            width = obstacles[i].xMax - obstacles[i].xMin;
            height = obstacles[i].yMax - obstacles[i].yMin;
            if (maxWidth < width) {
                maxWidth = width;
            }
            if (maxHeight < height) {
                maxHeight = height;
            }
        }
        return {
            maxHeight: maxHeight,
            maxWidth: maxWidth
        };
    };
    /**
     * Utility to get which direction to start the pathfinding algorithm
     * (X vs Y), calculated from a set of marker options.
     *
     * @function Highcharts.Pathfinder#getAlgorithmStartDirection
     *
     * @param {Highcharts.ConnectorsMarkerOptions} markerOptions
     *        Marker options to calculate from.
     *
     * @return {boolean}
     *         Returns true for X, false for Y, and undefined for autocalculate.
     */
    Pathfinder.prototype.getAlgorithmStartDirection = function (markerOptions) {
        var xCenter = markerOptions.align !== 'left' &&
                markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' &&
                markerOptions.verticalAlign !== 'bottom';
        return xCenter ?
            (yCenter ? void 0 : false) : // When x is centered
            (yCenter ? true : void 0); // When x is off-center
    };
    return Pathfinder;
}());
/**
 * @name Highcharts.Pathfinder#algorithms
 * @type {Highcharts.Dictionary<Function>}
 */
Pathfinder.prototype.algorithms = PathfinderAlgorithms;
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Gantt_Pathfinder = (Pathfinder);
/* *
 *
 *  API Options
 *
 * */
/**
 * The default pathfinder algorithm to use for a chart. It is possible to define
 * your own algorithms by adding them to the
 * `Highcharts.Pathfinder.prototype.algorithms`
 * object before the chart has been created.
 *
 * The default algorithms are as follows:
 *
 * `straight`:      Draws a straight line between the connecting
 *                  points. Does not avoid other points when drawing.
 *
 * `simpleConnect`: Finds a path between the points using right angles
 *                  only. Takes only starting/ending points into
 *                  account, and will not avoid other points.
 *
 * `fastAvoid`:     Finds a path between the points using right angles
 *                  only. Will attempt to avoid other points, but its
 *                  focus is performance over accuracy. Works well with
 *                  less dense datasets.
 *
 * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/masters/modules/pathfinder.src.js
/**
 * @license Highcharts Gantt JS v12.1.2 (2025-01-09)
 * @module highcharts/modules/pathfinder
 * @requires highcharts
 *
 * Pathfinder
 *
 * (c) 2016-2024 Øystein Moseng
 *
 * License: www.highcharts.com/license
 */




var pathfinder_src_G = Core_Globals;
pathfinder_src_G.Pathfinder = pathfinder_src_G.Pathfinder || Gantt_Pathfinder;
Extensions_ArrowSymbols.compose(pathfinder_src_G.SVGRenderer);
pathfinder_src_G.Pathfinder.compose(pathfinder_src_G.Chart, pathfinder_src_G.Point);
/* harmony default export */ var pathfinder_src = ((/* unused pure expression or super */ null && (Highcharts)));

;// ./code/es5/es-modules/Extensions/StaticScale.js
/* *
 *
 *  (c) 2016-2024 Torstein Honsi, Lars Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var StaticScale_addEvent = Core_Utilities.addEvent, StaticScale_defined = Core_Utilities.defined, StaticScale_isNumber = Core_Utilities.isNumber, StaticScale_pick = Core_Utilities.pick;
/* *
 *
 *  Composition
 *
 * */
/** @private */
function StaticScale_compose(AxisClass, ChartClass) {
    var chartProto = ChartClass.prototype;
    if (!chartProto.adjustHeight) {
        StaticScale_addEvent(AxisClass, 'afterSetOptions', StaticScale_onAxisAfterSetOptions);
        chartProto.adjustHeight = chartAdjustHeight;
        StaticScale_addEvent(ChartClass, 'render', chartProto.adjustHeight);
    }
}
/** @private */
function StaticScale_onAxisAfterSetOptions() {
    var chartOptions = this.chart.options.chart;
    if (!this.horiz &&
        StaticScale_isNumber(this.options.staticScale) &&
        (!chartOptions.height ||
            (chartOptions.scrollablePlotArea &&
                chartOptions.scrollablePlotArea.minHeight))) {
        this.staticScale = this.options.staticScale;
    }
}
/** @private */
function chartAdjustHeight() {
    var chart = this;
    if (chart.redrawTrigger !== 'adjustHeight') {
        var _loop_1 = function (axis) {
                var chart_1 = axis.chart,
            animate = !!chart_1.initiatedScale &&
                    chart_1.options.animation,
            staticScale = axis.options.staticScale;
            if (axis.staticScale && StaticScale_defined(axis.min)) {
                var height = StaticScale_pick(axis.brokenAxis && axis.brokenAxis.unitLength,
                    axis.max + axis.tickInterval - axis.min) * staticScale;
                // Minimum height is 1 x staticScale.
                height = Math.max(height, staticScale);
                var diff = height - chart_1.plotHeight;
                if (!chart_1.scrollablePixelsY && Math.abs(diff) >= 1) {
                    chart_1.plotHeight = height;
                    chart_1.redrawTrigger = 'adjustHeight';
                    chart_1.setSize(void 0, chart_1.chartHeight + diff, animate);
                }
                // Make sure clip rects have the right height before initial
                // animation.
                axis.series.forEach(function (series) {
                    var clipRect = series.sharedClipKey &&
                            chart_1.sharedClips[series.sharedClipKey];
                    if (clipRect) {
                        clipRect.attr(chart_1.inverted ? {
                            width: chart_1.plotHeight
                        } : {
                            height: chart_1.plotHeight
                        });
                    }
                });
            }
        };
        for (var _i = 0, _a = (chart.axes || []); _i < _a.length; _i++) {
            var axis = _a[_i];
            _loop_1(axis);
        }
        this.initiatedScale = true;
    }
    this.redrawTrigger = null;
}
/* *
 *
 *  Default Export
 *
 * */
var StaticScale = {
    compose: StaticScale_compose
};
/* harmony default export */ var Extensions_StaticScale = (StaticScale);
/* *
 *
 *  API Options
 *
 * */
/**
 * For vertical axes only. Setting the static scale ensures that each tick unit
 * is translated into a fixed pixel height. For example, setting the static
 * scale to 24 results in each Y axis category taking up 24 pixels, and the
 * height of the chart adjusts. Adding or removing items will make the chart
 * resize.
 *
 * @sample gantt/xrange-series/demo/
 *         X-range series with static scale
 *
 * @type      {number}
 * @default   50
 * @since     6.2.0
 * @product   gantt
 * @apioption yAxis.staticScale
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/masters/modules/static-scale.src.js
/**
 * @license Highcharts Gantt JS v12.1.2 (2025-01-09)
 * @module highcharts/modules/static-scale
 * @requires highcharts
 *
 * StaticScale
 *
 * (c) 2016-2024 Torstein Honsi, Lars A. V. Cabrera
 *
 * License: www.highcharts.com/license
 */



var static_scale_src_G = Core_Globals;
Extensions_StaticScale.compose(static_scale_src_G.Axis, static_scale_src_G.Chart);
/* harmony default export */ var static_scale_src = ((/* unused pure expression or super */ null && (Highcharts)));

;// ./code/es5/es-modules/Series/XRange/XRangeSeriesDefaults.js
/* *
 *
 *  X-range series module
 *
 *  (c) 2010-2024 Torstein Honsi, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var XRangeSeriesDefaults_correctFloat = Core_Utilities.correctFloat, XRangeSeriesDefaults_isNumber = Core_Utilities.isNumber, XRangeSeriesDefaults_isObject = Core_Utilities.isObject;
/* *
 *
 *  Constants
 *
 * */
/**
 * The X-range series displays ranges on the X axis, typically time
 * intervals with a start and end date.
 *
 * @sample {highcharts} highcharts/demo/x-range/
 *         X-range
 * @sample {highcharts} highcharts/css/x-range/
 *         Styled mode X-range
 * @sample {highcharts} highcharts/chart/inverted-xrange/
 *         Inverted X-range
 *
 * @extends      plotOptions.column
 * @since        6.0.0
 * @product      highcharts highstock gantt
 * @excluding    boostThreshold, crisp, cropThreshold, depth, edgeColor,
 *               edgeWidth, findNearestPointBy, getExtremesFromAll,
 *               negativeColor, pointInterval, pointIntervalUnit,
 *               pointPlacement, pointRange, pointStart, softThreshold,
 *               stacking, threshold, data, dataSorting, boostBlending
 * @requires     modules/xrange
 * @optionparent plotOptions.xrange
 */
var XRangeSeriesDefaults = {
    /**
     * A partial fill for each point, typically used to visualize how much
     * of a task is performed. The partial fill object can be set either on
     * series or point level.
     *
     * @sample {highcharts} highcharts/demo/x-range
     *         X-range with partial fill
     *
     * @product   highcharts highstock gantt
     * @apioption plotOptions.xrange.partialFill
     */
    /**
     * The fill color to be used for partial fills. Defaults to a darker
     * shade of the point color.
     *
     * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
     * @product   highcharts highstock gantt
     * @apioption plotOptions.xrange.partialFill.fill
     */
    /**
     * A partial fill for each point, typically used to visualize how much
     * of a task is performed. See [completed](series.gantt.data.completed).
     *
     * @sample gantt/demo/progress-indicator
     *         Gantt with progress indicator
     *
     * @product   gantt
     * @apioption plotOptions.gantt.partialFill
     */
    /**
     * In an X-range series, this option makes all points of the same Y-axis
     * category the same color.
     */
    colorByPoint: true,
    dataLabels: {
        formatter: function () {
            var amount = this.partialFill;
            if (XRangeSeriesDefaults_isObject(amount)) {
                amount = amount.amount;
            }
            if (XRangeSeriesDefaults_isNumber(amount) && amount > 0) {
                return XRangeSeriesDefaults_correctFloat(amount * 100) + '%';
            }
        },
        inside: true,
        verticalAlign: 'middle',
        style: {
            whiteSpace: 'nowrap'
        }
    },
    tooltip: {
        headerFormat: '<span style="font-size: 0.8em">{ucfirst point.x} - {point.x2}</span><br/>',
        pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.yCategory}</b><br/>'
    },
    borderRadius: 3,
    pointRange: 0
};
/* *
 *
 *  Export Default
 *
 * */
/* harmony default export */ var XRange_XRangeSeriesDefaults = (XRangeSeriesDefaults);
/* *
 *
 * API Options
 *
 * */
/**
 * An `xrange` series. If the [type](#series.xrange.type) option is not
 * specified, it is inherited from [chart.type](#chart.type).
 *
 * @extends   series,plotOptions.xrange
 * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth,
 *            findNearestPointBy, getExtremesFromAll, negativeColor,
 *            pointInterval, pointIntervalUnit, pointPlacement, pointRange,
 *            pointStart, softThreshold, stacking, threshold, dataSorting,
 *            boostBlending
 * @product   highcharts highstock gantt
 * @requires  modules/xrange
 * @apioption series.xrange
 */
/**
 * An array of data points for the series. For the `xrange` series type,
 * points can be given in the following ways:
 *
 * 1. An array of objects with named values. The objects are point configuration
 *    objects as seen below.
 *    ```js
 *    data: [{
 *        x: Date.UTC(2017, 0, 1),
 *        x2: Date.UTC(2017, 0, 3),
 *        name: "Test",
 *        y: 0,
 *        color: "#00FF00"
 *    }, {
 *        x: Date.UTC(2017, 0, 4),
 *        x2: Date.UTC(2017, 0, 5),
 *        name: "Deploy",
 *        y: 1,
 *        color: "#FF0000"
 *    }]
 *    ```
 *
 * @sample {highcharts} highcharts/series/data-array-of-objects/
 *         Config objects
 *
 * @declare   Highcharts.XrangePointOptionsObject
 * @type      {Array<*>}
 * @extends   series.line.data
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data
 */
/**
 * The starting X value of the range point.
 *
 * @sample {highcharts} highcharts/demo/x-range
 *         X-range
 *
 * @type      {number}
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.x
 */
/**
 * The ending X value of the range point.
 *
 * @sample {highcharts} highcharts/demo/x-range
 *         X-range
 *
 * @type      {number}
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.x2
 */
/**
 * The Y value of the range point.
 *
 * @sample {highcharts} highcharts/demo/x-range
 *         X-range
 *
 * @type      {number}
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.y
 */
/**
 * A partial fill for each point, typically used to visualize how much of
 * a task is performed. The partial fill object can be set either on series
 * or point level.
 *
 * @sample {highcharts} highcharts/demo/x-range
 *         X-range with partial fill
 *
 * @declare   Highcharts.XrangePointPartialFillOptionsObject
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.partialFill
 */
/**
 * The amount of the X-range point to be filled. Values can be 0-1 and are
 * converted to percentages in the default data label formatter.
 *
 * @type      {number}
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.partialFill.amount
 */
/**
 * The fill color to be used for partial fills. Defaults to a darker shade
 * of the point color.
 *
 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
 * @product   highcharts highstock gantt
 * @apioption series.xrange.data.partialFill.fill
 */
(''); // Adds doclets above to transpiled file

;// ./code/es5/es-modules/Series/XRange/XRangePoint.js
/* *
 *
 *  X-range series module
 *
 *  (c) 2010-2024 Torstein Honsi, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var XRangePoint_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var ColumnPoint = Series_SeriesRegistry.seriesTypes.column.prototype.pointClass;

var XRangePoint_extend = Core_Utilities.extend;
/* *
 *
 *  Class
 *
 * */
var XRangePoint = /** @class */ (function (_super) {
    XRangePoint_extends(XRangePoint, _super);
    /**
     * Extend init to have y default to 0.
     *
     * @private
     */
    function XRangePoint(series, options) {
        var _this = _super.call(this,
            series,
            options) || this;
        if (!_this.y) {
            _this.y = 0;
        }
        return _this;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * Return color of a point based on its category.
     *
     * @private
     * @function getColorByCategory
     *
     * @param {object} series
     *        The series which the point belongs to.
     *
     * @param {object} point
     *        The point to calculate its color for.
     *
     * @return {object}
     *         Returns an object containing the properties color and colorIndex.
     */
    XRangePoint.getColorByCategory = function (series, point) {
        var colors = series.options.colors || series.chart.options.colors,
            colorCount = colors ?
                colors.length :
                series.chart.options.chart.colorCount,
            colorIndex = point.y % colorCount,
            color = colors && colors[colorIndex];
        return {
            colorIndex: colorIndex,
            color: color
        };
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    XRangePoint.prototype.resolveColor = function () {
        var series = this.series;
        if (series.options.colorByPoint && !this.options.color) {
            var colorByPoint = XRangePoint.getColorByCategory(series,
                this);
            if (!series.chart.styledMode) {
                this.color = colorByPoint.color;
            }
            if (!this.options.colorIndex) {
                this.colorIndex = colorByPoint.colorIndex;
            }
        }
        else {
            this.color = this.options.color || series.color;
        }
    };
    /**
     * Extend applyOptions to handle time strings for x2
     *
     * @private
     */
    XRangePoint.prototype.applyOptions = function (options, x) {
        var _a;
        _super.prototype.applyOptions.call(this, options, x);
        this.x2 = this.series.chart.time.parse(this.x2);
        this.isNull = !((_a = this.isValid) === null || _a === void 0 ? void 0 : _a.call(this));
        return this;
    };
    /**
     * @private
     */
    XRangePoint.prototype.setState = function () {
        _super.prototype.setState.apply(this, arguments);
        this.series.drawPoint(this, this.series.getAnimationVerb());
    };
    /**
     * @private
     */
    XRangePoint.prototype.isValid = function () {
        return typeof this.x === 'number' &&
            typeof this.x2 === 'number';
    };
    return XRangePoint;
}(ColumnPoint));
XRangePoint_extend(XRangePoint.prototype, {
    ttBelow: false,
    tooltipDateKeys: ['x', 'x2']
});
/* *
 *
 *  Class Namespace
 *
 * */
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var XRange_XRangePoint = (XRangePoint);
/* *
 *
 *  API Declarations
 *
 * */
/**
 * The ending X value of the range point.
 * @name Highcharts.Point#x2
 * @type {number|undefined}
 * @requires modules/xrange
 */
/**
 * @interface Highcharts.PointOptionsObject in parts/Point.ts
 */ /**
* The ending X value of the range point.
* @name Highcharts.PointOptionsObject#x2
* @type {number|undefined}
* @requires modules/xrange
*/
(''); // Keeps doclets above in JS file

;// ./code/es5/es-modules/Series/XRange/XRangeSeries.js
/* *
 *
 *  X-range series module
 *
 *  (c) 2010-2024 Torstein Honsi, Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var XRangeSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var XRangeSeries_composed = Core_Globals.composed, XRangeSeries_noop = Core_Globals.noop;

var XRangeSeries_color = Color_Color.parse;

var XRangeSeries_ColumnSeries = Series_SeriesRegistry.seriesTypes.column;

var XRangeSeries_addEvent = Core_Utilities.addEvent, XRangeSeries_clamp = Core_Utilities.clamp, XRangeSeries_crisp = Core_Utilities.crisp, XRangeSeries_defined = Core_Utilities.defined, XRangeSeries_extend = Core_Utilities.extend, XRangeSeries_find = Core_Utilities.find, XRangeSeries_isNumber = Core_Utilities.isNumber, XRangeSeries_isObject = Core_Utilities.isObject, XRangeSeries_merge = Core_Utilities.merge, XRangeSeries_pick = Core_Utilities.pick, XRangeSeries_pushUnique = Core_Utilities.pushUnique, XRangeSeries_relativeLength = Core_Utilities.relativeLength;


/* *
 *
 *  Functions
 *
 * */
/**
 * Max x2 should be considered in xAxis extremes
 * @private
 */
function onAxisAfterGetSeriesExtremes() {
    var dataMax,
        modMax;
    if (this.isXAxis) {
        dataMax = XRangeSeries_pick(this.dataMax, -Number.MAX_VALUE);
        for (var _i = 0, _a = this.series; _i < _a.length; _i++) {
            var series = _a[_i];
            var column = (series.dataTable.getColumn('x2',
                true) ||
                    series.dataTable.getColumn('end',
                true));
            if (column) {
                for (var _b = 0, _c = column; _b < _c.length; _b++) {
                    var val = _c[_b];
                    if (XRangeSeries_isNumber(val) && val > dataMax) {
                        dataMax = val;
                        modMax = true;
                    }
                }
            }
        }
        if (modMax) {
            this.dataMax = dataMax;
        }
    }
}
/* *
 *
 *  Class
 *
 * */
/**
 * @private
 * @class
 * @name Highcharts.seriesTypes.xrange
 *
 * @augments Highcharts.Series
 */
var XRangeSeries = /** @class */ (function (_super) {
    XRangeSeries_extends(XRangeSeries, _super);
    function XRangeSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    XRangeSeries.compose = function (AxisClass) {
        if (XRangeSeries_pushUnique(XRangeSeries_composed, 'Series.XRange')) {
            XRangeSeries_addEvent(AxisClass, 'afterGetSeriesExtremes', onAxisAfterGetSeriesExtremes);
        }
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * @private
     */
    XRangeSeries.prototype.init = function () {
        _super.prototype.init.apply(this, arguments);
        this.options.stacking = void 0; // #13161
    };
    /**
     * Borrow the column series metrics, but with swapped axes. This gives
     * free access to features like groupPadding, grouping, pointWidth etc.
     * @private
     */
    XRangeSeries.prototype.getColumnMetrics = function () {
        var _this = this;
        var swapAxes = function () {
                for (var _i = 0,
            _a = _this.chart.series; _i < _a.length; _i++) {
                    var series = _a[_i];
                var xAxis = series.xAxis;
                series.xAxis = series.yAxis;
                series.yAxis = xAxis;
            }
        };
        swapAxes();
        var metrics = _super.prototype.getColumnMetrics.call(this);
        swapAxes();
        return metrics;
    };
    /**
     * Override cropData to show a point where x or x2 is outside visible range,
     * but one of them is inside.
     * @private
     */
    XRangeSeries.prototype.cropData = function (table, min, max) {
        // Replace xData with x2Data to find the appropriate cropStart
        var xData = table.getColumn('x') || [], x2Data = table.getColumn('x2');
        table.setColumn('x', x2Data, void 0, { silent: true });
        var croppedData = _super.prototype.cropData.call(this,
            table,
            min,
            max);
        // Re-insert the cropped xData
        table.setColumn('x', xData.slice(croppedData.start, croppedData.end), void 0, { silent: true });
        return croppedData;
    };
    /**
     * Finds the index of an existing point that matches the given point
     * options.
     *
     * @private
     *
     * @param {Highcharts.XRangePointOptions} options
     *        The options of the point.
     *
     * @return {number|undefined}
     *         Returns index of a matching point, or undefined if no match is
     *         found.
     */
    XRangeSeries.prototype.findPointIndex = function (options) {
        var _a = this,
            cropStart = _a.cropStart,
            points = _a.points;
        var id = options.id;
        var pointIndex;
        if (id) {
            var point = XRangeSeries_find(points,
                function (point) { return point.id === id; });
            pointIndex = point ? point.index : void 0;
        }
        if (typeof pointIndex === 'undefined') {
            var point = XRangeSeries_find(points,
                function (point) { return (point.x === options.x &&
                    point.x2 === options.x2 &&
                    !point.touched); });
            pointIndex = point ? point.index : void 0;
        }
        // Reduce pointIndex if data is cropped
        if (this.cropped &&
            XRangeSeries_isNumber(pointIndex) &&
            XRangeSeries_isNumber(cropStart) &&
            pointIndex >= cropStart) {
            pointIndex -= cropStart;
        }
        return pointIndex;
    };
    XRangeSeries.prototype.alignDataLabel = function (point) {
        var _a;
        var oldPlotX = point.plotX;
        point.plotX = XRangeSeries_pick(point.dlBox && point.dlBox.centerX, point.plotX);
        if (point.dataLabel && ((_a = point.shapeArgs) === null || _a === void 0 ? void 0 : _a.width)) {
            point.dataLabel.css({
                width: "" + point.shapeArgs.width + "px"
            });
        }
        _super.prototype.alignDataLabel.apply(this, arguments);
        point.plotX = oldPlotX;
    };
    /**
     * @private
     */
    XRangeSeries.prototype.translatePoint = function (point) {
        var _a,
            _b;
        var xAxis = this.xAxis,
            yAxis = this.yAxis,
            metrics = this.columnMetrics,
            options = this.options,
            minPointLength = options.minPointLength || 0,
            oldColWidth = (point.shapeArgs && point.shapeArgs.width || 0) / 2,
            seriesXOffset = this.pointXOffset = metrics.offset,
            posX = XRangeSeries_pick(point.x2,
            point.x + (point.len || 0)),
            borderRadius = options.borderRadius,
            plotTop = this.chart.plotTop,
            plotLeft = this.chart.plotLeft;
        var plotX = point.plotX,
            plotX2 = xAxis.translate(posX, 0, 0, 0, 1);
        var length = Math.abs(plotX2 - plotX),
            inverted = this.chart.inverted,
            borderWidth = XRangeSeries_pick(options.borderWidth, 1);
        var widthDifference,
            partialFill,
            yOffset = metrics.offset,
            pointHeight = Math.round(metrics.width),
            dlLeft,
            dlRight,
            dlWidth,
            clipRectWidth;
        if (minPointLength) {
            widthDifference = minPointLength - length;
            if (widthDifference < 0) {
                widthDifference = 0;
            }
            plotX -= widthDifference / 2;
            plotX2 += widthDifference / 2;
        }
        plotX = Math.max(plotX, -10);
        plotX2 = XRangeSeries_clamp(plotX2, -10, xAxis.len + 10);
        // Handle individual pointWidth
        if (XRangeSeries_defined(point.options.pointWidth)) {
            yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2);
            pointHeight = Math.ceil(point.options.pointWidth);
        }
        // Apply pointPlacement to the Y axis
        if (options.pointPlacement &&
            XRangeSeries_isNumber(point.plotY) &&
            yAxis.categories) {
            point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement);
        }
        var x = XRangeSeries_crisp(Math.min(plotX,
            plotX2),
            borderWidth),
            x2 = XRangeSeries_crisp(Math.max(plotX,
            plotX2),
            borderWidth),
            width = x2 - x;
        var r = Math.min(XRangeSeries_relativeLength((typeof borderRadius === 'object' ?
                borderRadius.radius :
                borderRadius || 0),
            pointHeight),
            Math.min(width,
            pointHeight) / 2);
        var shapeArgs = {
                x: x,
                y: XRangeSeries_crisp((point.plotY || 0) + yOffset,
            borderWidth),
                width: width,
                height: pointHeight,
                r: r
            };
        point.shapeArgs = shapeArgs;
        // Move tooltip to default position
        if (!inverted) {
            point.tooltipPos[0] -= oldColWidth +
                seriesXOffset -
                shapeArgs.width / 2;
        }
        else {
            point.tooltipPos[1] += seriesXOffset +
                oldColWidth;
        }
        // Align data labels inside the shape and inside the plot area
        dlLeft = shapeArgs.x;
        dlRight = dlLeft + shapeArgs.width;
        if (dlLeft < 0 || dlRight > xAxis.len) {
            dlLeft = XRangeSeries_clamp(dlLeft, 0, xAxis.len);
            dlRight = XRangeSeries_clamp(dlRight, 0, xAxis.len);
            dlWidth = dlRight - dlLeft;
            point.dlBox = XRangeSeries_merge(shapeArgs, {
                x: dlLeft,
                width: dlRight - dlLeft,
                centerX: dlWidth ? dlWidth / 2 : null
            });
        }
        else {
            point.dlBox = null;
        }
        // Tooltip position
        var tooltipPos = point.tooltipPos;
        var xIndex = !inverted ? 0 : 1;
        var yIndex = !inverted ? 1 : 0;
        var tooltipYOffset = (this.columnMetrics ?
                this.columnMetrics.offset :
                -metrics.width / 2);
        // Centering tooltip position (#14147)
        if (inverted) {
            tooltipPos[xIndex] += shapeArgs.width / 2;
        }
        else {
            tooltipPos[xIndex] = XRangeSeries_clamp(tooltipPos[xIndex] +
                (xAxis.reversed ? -1 : 0) * shapeArgs.width, xAxis.left - plotLeft, xAxis.left + xAxis.len - plotLeft - 1);
        }
        tooltipPos[yIndex] = XRangeSeries_clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), yAxis.top - plotTop, yAxis.top + yAxis.len - plotTop - 1);
        // Add a partShapeArgs to the point, based on the shapeArgs property
        partialFill = point.partialFill;
        if (partialFill) {
            // Get the partial fill amount
            if (XRangeSeries_isObject(partialFill)) {
                partialFill = partialFill.amount;
            }
            // If it was not a number, assume 0
            if (!XRangeSeries_isNumber(partialFill)) {
                partialFill = 0;
            }
            point.partShapeArgs = XRangeSeries_merge(shapeArgs);
            clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX -
                plotX), 0);
            point.clipRectArgs = {
                x: xAxis.reversed ? // #10717
                    shapeArgs.x + length - clipRectWidth :
                    shapeArgs.x,
                y: shapeArgs.y,
                width: clipRectWidth,
                height: shapeArgs.height
            };
        }
        // Add formatting keys for tooltip and data labels. Use 'category' as
        // 'key' to ensure tooltip datetime formatting. Use 'name' only when
        // 'category' is undefined.
        point.key = point.category || point.name;
        point.yCategory = (_a = yAxis.categories) === null || _a === void 0 ? void 0 : _a[(_b = point.y) !== null && _b !== void 0 ? _b : -1];
    };
    /**
     * @private
     */
    XRangeSeries.prototype.translate = function () {
        _super.prototype.translate.apply(this, arguments);
        for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
            var point = _a[_i];
            this.translatePoint(point);
        }
    };
    /**
     * Draws a single point in the series. Needed for partial fill.
     *
     * This override turns point.graphic into a group containing the
     * original graphic and an overlay displaying the partial fill.
     *
     * @private
     *
     * @param {Highcharts.Point} point
     *        An instance of Point in the series.
     *
     * @param {"animate"|"attr"} verb
     *        'animate' (animates changes) or 'attr' (sets options)
     */
    XRangeSeries.prototype.drawPoint = function (point, verb) {
        var seriesOpts = this.options,
            renderer = this.chart.renderer,
            type = point.shapeType,
            shapeArgs = point.shapeArgs,
            partShapeArgs = point.partShapeArgs,
            clipRectArgs = point.clipRectArgs,
            pointState = point.state,
            stateOpts = (seriesOpts.states[pointState || 'normal'] ||
                {}),
            pointStateVerb = typeof pointState === 'undefined' ?
                'attr' : verb,
            pointAttr = this.pointAttribs(point,
            pointState),
            animation = XRangeSeries_pick(this.chart.options.chart.animation,
            stateOpts.animation);
        var graphic = point.graphic,
            pfOptions = point.partialFill;
        if (!point.isNull && point.visible !== false) {
            // Original graphic
            if (graphic) { // Update
                graphic.rect[verb](shapeArgs);
            }
            else {
                point.graphic = graphic = renderer.g('point')
                    .addClass(point.getClassName())
                    .add(point.group || this.group);
                graphic.rect = renderer[type](XRangeSeries_merge(shapeArgs))
                    .addClass(point.getClassName())
                    .addClass('highcharts-partfill-original')
                    .add(graphic);
            }
            // Partial fill graphic
            if (partShapeArgs) {
                if (graphic.partRect) {
                    graphic.partRect[verb](XRangeSeries_merge(partShapeArgs));
                    graphic.partialClipRect[verb](XRangeSeries_merge(clipRectArgs));
                }
                else {
                    graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height);
                    graphic.partRect =
                        renderer[type](partShapeArgs)
                            .addClass('highcharts-partfill-overlay')
                            .add(graphic)
                            .clip(graphic.partialClipRect);
                }
            }
            // Presentational
            if (!this.chart.styledMode) {
                graphic
                    .rect[verb](pointAttr, animation)
                    .shadow(seriesOpts.shadow);
                if (partShapeArgs) {
                    // Ensure pfOptions is an object
                    if (!XRangeSeries_isObject(pfOptions)) {
                        pfOptions = {};
                    }
                    if (XRangeSeries_isObject(seriesOpts.partialFill)) {
                        pfOptions = XRangeSeries_merge(seriesOpts.partialFill, pfOptions);
                    }
                    var fill = (pfOptions.fill ||
                            XRangeSeries_color(pointAttr.fill).brighten(-0.3).get() ||
                            XRangeSeries_color(point.color || this.color)
                                .brighten(-0.3).get());
                    pointAttr.fill = fill;
                    graphic
                        .partRect[pointStateVerb](pointAttr, animation)
                        .shadow(seriesOpts.shadow);
                }
            }
        }
        else if (graphic) {
            point.graphic = graphic.destroy(); // #1269
        }
    };
    /**
     * @private
     */
    XRangeSeries.prototype.drawPoints = function () {
        var verb = this.getAnimationVerb();
        // Draw the columns
        for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
            var point = _a[_i];
            this.drawPoint(point, verb);
        }
    };
    /**
     * Returns "animate", or "attr" if the number of points is above the
     * animation limit.
     *
     * @private
     */
    XRangeSeries.prototype.getAnimationVerb = function () {
        return (this.chart.pointCount < (this.options.animationLimit || 250) ?
            'animate' :
            'attr');
    };
    /**
     * @private
     */
    XRangeSeries.prototype.isPointInside = function (point) {
        var shapeArgs = point.shapeArgs,
            plotX = point.plotX,
            plotY = point.plotY;
        if (!shapeArgs) {
            return _super.prototype.isPointInside.apply(this, arguments);
        }
        var isInside = typeof plotX !== 'undefined' &&
                typeof plotY !== 'undefined' &&
                plotY >= 0 &&
                plotY <= this.yAxis.len &&
                (shapeArgs.x || 0) + (shapeArgs.width || 0) >= 0 &&
                plotX <= this.xAxis.len;
        return isInside;
    };
    /* *
     *
     *  Static Properties
     *
     * */
    XRangeSeries.defaultOptions = XRangeSeries_merge(XRangeSeries_ColumnSeries.defaultOptions, XRange_XRangeSeriesDefaults);
    return XRangeSeries;
}(XRangeSeries_ColumnSeries));
XRangeSeries_extend(XRangeSeries.prototype, {
    pointClass: XRange_XRangePoint,
    pointArrayMap: ['x2', 'y'],
    getExtremesFromAll: true,
    keysAffectYAxis: ['y'],
    parallelArrays: ['x', 'x2', 'y'],
    requireSorting: false,
    type: 'xrange',
    animate: Series_SeriesRegistry.series.prototype.animate,
    autoIncrement: XRangeSeries_noop,
    buildKDTree: XRangeSeries_noop
});
Series_SeriesRegistry.registerSeriesType('xrange', XRangeSeries);
/* *
 *
 * Default Export
 *
 * */
/* harmony default export */ var XRange_XRangeSeries = (XRangeSeries);

;// ./code/es5/es-modules/masters/modules/xrange.src.js
/**
 * @license Highcharts JS v12.1.2 (2025-01-09)
 * @module highcharts/modules/xrange
 * @requires highcharts
 *
 * X-range series
 *
 * (c) 2010-2024 Torstein Honsi, Lars A. V. Cabrera
 *
 * License: www.highcharts.com/license
 */



var xrange_src_G = Core_Globals;
XRange_XRangeSeries.compose(xrange_src_G.Axis);
/* harmony default export */ var xrange_src = ((/* unused pure expression or super */ null && (Highcharts)));

;// ./code/es5/es-modules/Series/Gantt/GanttPoint.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Author: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var GanttPoint_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();

var GanttPoint_XRangePoint = Series_SeriesRegistry.seriesTypes.xrange.prototype.pointClass;
/* *
 *
 *  Class
 *
 * */
var GanttPoint = /** @class */ (function (_super) {
    GanttPoint_extends(GanttPoint, _super);
    function GanttPoint() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * @private
     */
    GanttPoint.setGanttPointAliases = function (options, chart) {
        var _a,
            _b,
            _c;
        options.x = options.start = chart.time.parse((_a = options.start) !== null && _a !== void 0 ? _a : options.x);
        options.x2 = options.end = chart.time.parse((_b = options.end) !== null && _b !== void 0 ? _b : options.x2);
        options.partialFill = options.completed =
            (_c = options.completed) !== null && _c !== void 0 ? _c : options.partialFill;
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Applies the options containing the x and y data and possible some
     * extra properties. This is called on point init or from point.update.
     *
     * @private
     * @function Highcharts.Point#applyOptions
     *
     * @param {Object} options
     *        The point options
     *
     * @param {number} x
     *        The x value
     *
     * @return {Highcharts.Point}
     *         The Point instance
     */
    GanttPoint.prototype.applyOptions = function (options, x) {
        var _a;
        var ganttPoint = _super.prototype.applyOptions.call(this,
            options,
            x);
        GanttPoint.setGanttPointAliases(ganttPoint, ganttPoint.series.chart);
        this.isNull = !((_a = this.isValid) === null || _a === void 0 ? void 0 : _a.call(this));
        return ganttPoint;
    };
    GanttPoint.prototype.isValid = function () {
        return ((typeof this.start === 'number' ||
            typeof this.x === 'number') &&
            (typeof this.end === 'number' ||
                typeof this.x2 === 'number' ||
                this.milestone));
    };
    return GanttPoint;
}(GanttPoint_XRangePoint));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Gantt_GanttPoint = (GanttPoint);

;// ./code/es5/es-modules/Series/Gantt/GanttSeriesDefaults.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Author: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var GanttSeriesDefaults_isNumber = Core_Utilities.isNumber;
/* *
 *
 *  API Options
 *
 * */
/**
 * A `gantt` series. If the [type](#series.gantt.type) option is not specified,
 * it is inherited from [chart.type](#chart.type).
 *
 * @extends      plotOptions.xrange
 * @product      gantt
 * @requires     highcharts-gantt
 * @optionparent plotOptions.gantt
 */
var GanttSeriesDefaults = {
    // Options - default options merged with parent
    grouping: false,
    dataLabels: {
        enabled: true
    },
    tooltip: {
        headerFormat: '<span style="font-size: 0.8em">{series.name}</span><br/>',
        pointFormat: null,
        pointFormatter: function () {
            var point = this,
                series = point.series,
                xAxis = series.xAxis,
                formats = series.tooltipOptions.dateTimeLabelFormats,
                startOfWeek = xAxis.options.startOfWeek,
                ttOptions = series.tooltipOptions,
                milestone = point.options.milestone;
            var format = ttOptions.xDateFormat,
                retVal = '<b>' + (point.name || point.yCategory) + '</b>';
            if (ttOptions.pointFormat) {
                return point.tooltipFormatter(ttOptions.pointFormat);
            }
            if (!format && GanttSeriesDefaults_isNumber(point.start)) {
                format = series.chart.time.getDateFormat(xAxis.closestPointRange, point.start, startOfWeek, formats || {});
            }
            var start = series.chart.time.dateFormat(format,
                point.start),
                end = series.chart.time.dateFormat(format,
                point.end);
            retVal += '<br/>';
            if (!milestone) {
                retVal += 'Start: ' + start + '<br/>';
                retVal += 'End: ' + end + '<br/>';
            }
            else {
                retVal += start + '<br/>';
            }
            return retVal;
        }
    },
    connectors: {
        type: 'simpleConnect',
        /**
         * @declare Highcharts.ConnectorsAnimationOptionsObject
         */
        animation: {
            reversed: true // Dependencies go from child to parent
        },
        radius: 0,
        startMarker: {
            enabled: true,
            symbol: 'arrow-filled',
            radius: 4,
            fill: '#fa0',
            align: 'left'
        },
        endMarker: {
            enabled: false, // Only show arrow on the dependent task
            align: 'right'
        }
    }
};
/**
 * A `gantt` series.
 *
 * @extends   series,plotOptions.gantt
 * @excluding boostThreshold, dashStyle, findNearestPointBy,
 *            getExtremesFromAll, marker, negativeColor, pointInterval,
 *            pointIntervalUnit, pointPlacement, pointStart
 * @product   gantt
 * @requires  highcharts-gantt
 * @apioption series.gantt
 */
/**
 * Data for a Gantt series.
 *
 * @declare   Highcharts.GanttPointOptionsObject
 * @type      {Array<*>}
 * @extends   series.xrange.data
 * @excluding className, connect, dataLabels, events,
 *            partialFill, selected, x, x2
 * @product   gantt
 * @apioption series.gantt.data
 */
/**
 * Whether the grid node belonging to this point should start as collapsed. Used
 * in axes of type treegrid.
 *
 * @sample {gantt} gantt/treegrid-axis/collapsed/
 *         Start as collapsed
 *
 * @type      {boolean}
 * @default   false
 * @product   gantt
 * @apioption series.gantt.data.collapsed
 */
/**
 * The start time of a task. May be a timestamp or a date string.
 *
 * @type      {number|string}
 * @product   gantt
 * @apioption series.gantt.data.start
 */
/**
 * The end time of a task. May be a timestamp or a date string.
 *
 * @type      {number|string}
 * @product   gantt
 * @apioption series.gantt.data.end
 */
/**
 * The Y value of a task.
 *
 * @type      {number}
 * @product   gantt
 * @apioption series.gantt.data.y
 */
/**
 * The name of a task. If a `treegrid` y-axis is used (default in Gantt charts),
 * this will be picked up automatically, and used to calculate the y-value.
 *
 * @type      {string}
 * @product   gantt
 * @apioption series.gantt.data.name
 */
/**
 * Progress indicator, how much of the task completed. If it is a number, the
 * `fill` will be applied automatically.
 *
 * @sample {gantt} gantt/demo/progress-indicator
 *         Progress indicator
 *
 * @type      {number|*}
 * @extends   series.xrange.data.partialFill
 * @product   gantt
 * @apioption series.gantt.data.completed
 */
/**
 * The amount of the progress indicator, ranging from 0 (not started) to 1
 * (finished).
 *
 * @type      {number}
 * @default   0
 * @apioption series.gantt.data.completed.amount
 */
/**
 * The fill of the progress indicator. Defaults to a darkened variety of the
 * main color.
 *
 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
 * @apioption series.gantt.data.completed.fill
 */
/**
 * The ID of the point (task) that this point depends on in Gantt charts.
 * Aliases [connect](series.xrange.data.connect). Can also be an object,
 * specifying further connecting [options](series.gantt.connectors) between the
 * points. Multiple connections can be specified by providing an array.
 *
 * @sample gantt/demo/project-management
 *         Dependencies
 * @sample gantt/pathfinder/demo
 *         Different connection types
 *
 * @type      {string|Array<string|*>|*}
 * @extends   series.xrange.data.connect
 * @since     6.2.0
 * @product   gantt
 * @apioption series.gantt.data.dependency
 */
/**
 * Whether this point is a milestone. If so, only the `start` option is handled,
 * while `end` is ignored.
 *
 * @sample gantt/gantt/milestones
 *         Milestones
 *
 * @type      {boolean}
 * @since     6.2.0
 * @product   gantt
 * @apioption series.gantt.data.milestone
 */
/**
 * The ID of the parent point (task) of this point in Gantt charts.
 *
 * @sample gantt/demo/subtasks
 *         Gantt chart with subtasks
 *
 * @type      {string}
 * @since     6.2.0
 * @product   gantt
 * @apioption series.gantt.data.parent
 */
/**
 * @excluding afterAnimate
 * @apioption series.gantt.events
 */
''; // Detachs doclets above
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Gantt_GanttSeriesDefaults = (GanttSeriesDefaults);

;// ./code/es5/es-modules/Core/Axis/BrokenAxis.js
/* *
 *
 *  (c) 2009-2024 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var BrokenAxis_addEvent = Core_Utilities.addEvent, BrokenAxis_find = Core_Utilities.find, BrokenAxis_fireEvent = Core_Utilities.fireEvent, BrokenAxis_isArray = Core_Utilities.isArray, BrokenAxis_isNumber = Core_Utilities.isNumber, BrokenAxis_pick = Core_Utilities.pick;
/* *
 *
 *  Composition
 *
 * */
/**
 * Axis with support of broken data rows.
 * @private
 */
var BrokenAxis;
(function (BrokenAxis) {
    /* *
     *
     *  Declarations
     *
     * */
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Adds support for broken axes.
     * @private
     */
    function compose(AxisClass, SeriesClass) {
        if (!AxisClass.keepProps.includes('brokenAxis')) {
            AxisClass.keepProps.push('brokenAxis');
            BrokenAxis_addEvent(AxisClass, 'init', onAxisInit);
            BrokenAxis_addEvent(AxisClass, 'afterInit', onAxisAfterInit);
            BrokenAxis_addEvent(AxisClass, 'afterSetTickPositions', onAxisAfterSetTickPositions);
            BrokenAxis_addEvent(AxisClass, 'afterSetOptions', onAxisAfterSetOptions);
            var seriesProto = SeriesClass.prototype;
            seriesProto.drawBreaks = seriesDrawBreaks;
            seriesProto.gappedPath = seriesGappedPath;
            BrokenAxis_addEvent(SeriesClass, 'afterGeneratePoints', onSeriesAfterGeneratePoints);
            BrokenAxis_addEvent(SeriesClass, 'afterRender', onSeriesAfterRender);
        }
        return AxisClass;
    }
    BrokenAxis.compose = compose;
    /**
     * @private
     */
    function onAxisAfterInit() {
        if (typeof this.brokenAxis !== 'undefined') {
            this.brokenAxis.setBreaks(this.options.breaks, false);
        }
    }
    /**
     * Force Axis to be not-ordinal when breaks are defined.
     * @private
     */
    function onAxisAfterSetOptions() {
        var _a;
        var axis = this;
        if ((_a = axis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks) {
            axis.options.ordinal = false;
        }
    }
    /**
     * @private
     */
    function onAxisAfterSetTickPositions() {
        var axis = this,
            brokenAxis = axis.brokenAxis;
        if (brokenAxis === null || brokenAxis === void 0 ? void 0 : brokenAxis.hasBreaks) {
            var tickPositions = axis.tickPositions,
                info = axis.tickPositions.info,
                newPositions = [];
            for (var i = 0; i < tickPositions.length; i++) {
                if (!brokenAxis.isInAnyBreak(tickPositions[i])) {
                    newPositions.push(tickPositions[i]);
                }
            }
            axis.tickPositions = newPositions;
            axis.tickPositions.info = info;
        }
    }
    /**
     * @private
     */
    function onAxisInit() {
        var axis = this;
        if (!axis.brokenAxis) {
            axis.brokenAxis = new Additions(axis);
        }
    }
    /**
     * @private
     */
    function onSeriesAfterGeneratePoints() {
        var _a,
            _b;
        var _c = this,
            isDirty = _c.isDirty,
            connectNulls = _c.options.connectNulls,
            points = _c.points,
            xAxis = _c.xAxis,
            yAxis = _c.yAxis;
        // Set, or reset visibility of the points. Axis.setBreaks marks
        // the series as isDirty
        if (isDirty) {
            var i = points.length;
            while (i--) {
                var point = points[i];
                // Respect nulls inside the break (#4275)
                var nullGap = point.y === null && connectNulls === false;
                var isPointInBreak = (!nullGap && (((_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis.brokenAxis) === null || _a === void 0 ? void 0 : _a.isInAnyBreak(point.x,
                    true)) ||
                        ((_b = yAxis === null || yAxis === void 0 ? void 0 : yAxis.brokenAxis) === null || _b === void 0 ? void 0 : _b.isInAnyBreak(point.y,
                    true))));
                // Set point.visible if in any break.
                // If not in break, reset visible to original value.
                point.visible = isPointInBreak ?
                    false :
                    point.options.visible !== false;
            }
        }
    }
    /**
     * @private
     */
    function onSeriesAfterRender() {
        this.drawBreaks(this.xAxis, ['x']);
        this.drawBreaks(this.yAxis, BrokenAxis_pick(this.pointArrayMap, ['y']));
    }
    /**
     * @private
     */
    function seriesDrawBreaks(axis, keys) {
        var _a;
        var series = this,
            points = series.points;
        var breaks,
            threshold,
            y;
        if ((_a = axis === null || axis === void 0 ? void 0 : axis.brokenAxis) === null || _a === void 0 ? void 0 : _a.hasBreaks) {
            var brokenAxis_1 = axis.brokenAxis;
            keys.forEach(function (key) {
                var _a,
                    _b;
                breaks = (brokenAxis_1 === null || brokenAxis_1 === void 0 ? void 0 : brokenAxis_1.breakArray) || [];
                threshold = axis.isXAxis ?
                    axis.min :
                    BrokenAxis_pick(series.options.threshold, axis.min);
                // Array of breaks that have been "zoomed-out" which means that
                // they were shown previously, but now after zoom, they are not
                // (#19885).
                var breaksOutOfRange = (_b = (_a = axis === null || axis === void 0 ? void 0 : axis.options) === null || _a === void 0 ? void 0 : _a.breaks) === null || _b === void 0 ? void 0 : _b.filter(function (brk) {
                        var isOut = true;
                    // Iterate to see if "brk" is in axis range
                    for (var i = 0; i < breaks.length; i++) {
                        var otherBreak = breaks[i];
                        if (otherBreak.from === brk.from &&
                            otherBreak.to === brk.to) {
                            isOut = false;
                            break;
                        }
                    }
                    return isOut;
                });
                points.forEach(function (point) {
                    y = BrokenAxis_pick(point['stack' + key.toUpperCase()], point[key]);
                    breaks.forEach(function (brk) {
                        if (BrokenAxis_isNumber(threshold) && BrokenAxis_isNumber(y)) {
                            var eventName = '';
                            if ((threshold < brk.from && y > brk.to) ||
                                (threshold > brk.from && y < brk.from)) {
                                eventName = 'pointBreak';
                            }
                            else if ((threshold < brk.from &&
                                y > brk.from &&
                                y < brk.to) || (threshold > brk.from &&
                                y > brk.to &&
                                y < brk.from)) {
                                eventName = 'pointInBreak';
                            }
                            if (eventName) {
                                BrokenAxis_fireEvent(axis, eventName, { point: point, brk: brk });
                            }
                        }
                    });
                    breaksOutOfRange === null || breaksOutOfRange === void 0 ? void 0 : breaksOutOfRange.forEach(function (brk) {
                        BrokenAxis_fireEvent(axis, 'pointOutsideOfBreak', { point: point, brk: brk });
                    });
                });
            });
        }
    }
    /**
     * Extend getGraphPath by identifying gaps in the data so that we
     * can draw a gap in the line or area. This was moved from ordinal
     * axis module to broken axis module as of #5045.
     *
     * @private
     * @function Highcharts.Series#gappedPath
     *
     * @return {Highcharts.SVGPathArray}
     * Gapped path
     */
    function seriesGappedPath() {
        var currentDataGrouping = this.currentDataGrouping,
            groupingSize = currentDataGrouping === null || currentDataGrouping === void 0 ? void 0 : currentDataGrouping.gapSize,
            points = this.points.slice(),
            yAxis = this.yAxis;
        var gapSize = this.options.gapSize,
            i = points.length - 1,
            stack;
        /**
         * Defines when to display a gap in the graph, together with the
         * [gapUnit](plotOptions.series.gapUnit) option.
         *
         * In case when `dataGrouping` is enabled, points can be grouped
         * into a larger time span. This can make the grouped points to
         * have a greater distance than the absolute value of `gapSize`
         * property, which will result in disappearing graph completely.
         * To prevent this situation the mentioned distance between
         * grouped points is used instead of previously defined
         * `gapSize`.
         *
         * In practice, this option is most often used to visualize gaps
         * in time series. In a stock chart, intraday data is available
         * for daytime hours, while gaps will appear in nights and
         * weekends.
         *
         * @see [gapUnit](plotOptions.series.gapUnit)
         * @see [xAxis.breaks](#xAxis.breaks)
         *
         * @sample {highstock} stock/plotoptions/series-gapsize/
         * Setting the gap size to 2 introduces gaps for weekends in
         * daily datasets.
         *
         * @type      {number}
         * @default   0
         * @product   highstock
         * @requires  modules/broken-axis
         * @apioption plotOptions.series.gapSize
         */
        /**
         * Together with [gapSize](plotOptions.series.gapSize), this
         * option defines where to draw gaps in the graph.
         *
         * When the `gapUnit` is `"relative"` (default), a gap size of 5
         * means that if the distance between two points is greater than
         * 5 times that of the two closest points, the graph will be
         * broken.
         *
         * When the `gapUnit` is `"value"`, the gap is based on absolute
         * axis values, which on a datetime axis is milliseconds. This
         * also applies to the navigator series that inherits gap
         * options from the base series.
         *
         * @see [gapSize](plotOptions.series.gapSize)
         *
         * @type       {string}
         * @default    relative
         * @since      5.0.13
         * @product    highstock
         * @validvalue ["relative", "value"]
         * @requires   modules/broken-axis
         * @apioption  plotOptions.series.gapUnit
         */
        if (gapSize && i > 0) { // #5008
            // Gap unit is relative
            if (this.options.gapUnit !== 'value') {
                gapSize *= this.basePointRange;
            }
            // Setting a new gapSize in case dataGrouping is enabled
            // (#7686)
            if (groupingSize &&
                groupingSize > gapSize &&
                // Except when DG is forced (e.g. from other series)
                // and has lower granularity than actual points (#11351)
                groupingSize >= this.basePointRange) {
                gapSize = groupingSize;
            }
            // Extension for ordinal breaks
            var current = void 0,
                next = void 0;
            while (i--) {
                // Reassign next if it is not visible
                if (!(next && next.visible !== false)) {
                    next = points[i + 1];
                }
                current = points[i];
                // Skip iteration if one of the points is not visible
                if (next.visible === false || current.visible === false) {
                    continue;
                }
                if (next.x - current.x > gapSize) {
                    var xRange = (current.x + next.x) / 2;
                    points.splice(// Insert after this one
                    i + 1, 0, {
                        isNull: true,
                        x: xRange
                    });
                    // For stacked chart generate empty stack items, #6546
                    if (yAxis.stacking && this.options.stacking) {
                        stack = yAxis.stacking.stacks[this.stackKey][xRange] = new Stacking_StackItem(yAxis, yAxis.options.stackLabels, false, xRange, this.stack);
                        stack.total = 0;
                    }
                }
                // Assign current to next for the upcoming iteration
                next = current;
            }
        }
        // Call base method
        return this.getGraphPath(points);
    }
    /* *
     *
     *  Class
     *
     * */
    /**
     * Provides support for broken axes.
     * @private
     * @class
     */
    var Additions = /** @class */ (function () {
            /* *
             *
             *  Constructors
             *
             * */
            function Additions(axis) {
                this.hasBreaks = false;
            this.axis = axis;
        }
        /* *
         *
         *  Static Functions
         *
         * */
        /**
         * @private
         */
        Additions.isInBreak = function (brk, val) {
            var repeat = brk.repeat || Infinity,
                from = brk.from,
                length = brk.to - brk.from,
                test = (val >= from ?
                    (val - from) % repeat :
                    repeat - ((from - val) % repeat));
            var ret;
            if (!brk.inclusive) {
                ret = test < length && test !== 0;
            }
            else {
                ret = test <= length;
            }
            return ret;
        };
        /**
         * @private
         */
        Additions.lin2Val = function (val) {
            var axis = this;
            var brokenAxis = axis.brokenAxis;
            var breakArray = brokenAxis && brokenAxis.breakArray;
            if (!breakArray || !BrokenAxis_isNumber(val)) {
                return val;
            }
            var nval = val,
                brk,
                i;
            for (i = 0; i < breakArray.length; i++) {
                brk = breakArray[i];
                if (brk.from >= nval) {
                    break;
                }
                else if (brk.to < nval) {
                    nval += brk.len;
                }
                else if (Additions.isInBreak(brk, nval)) {
                    nval += brk.len;
                }
            }
            return nval;
        };
        /**
         * @private
         */
        Additions.val2Lin = function (val) {
            var axis = this;
            var brokenAxis = axis.brokenAxis;
            var breakArray = brokenAxis && brokenAxis.breakArray;
            if (!breakArray || !BrokenAxis_isNumber(val)) {
                return val;
            }
            var nval = val,
                brk,
                i;
            for (i = 0; i < breakArray.length; i++) {
                brk = breakArray[i];
                if (brk.to <= val) {
                    nval -= brk.len;
                }
                else if (brk.from >= val) {
                    break;
                }
                else if (Additions.isInBreak(brk, val)) {
                    nval -= (val - brk.from);
                    break;
                }
            }
            return nval;
        };
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Returns the first break found where the x is larger then break.from
         * and smaller then break.to.
         *
         * @param {number} x
         * The number which should be within a break.
         *
         * @param {Array<Highcharts.XAxisBreaksOptions>} breaks
         * The array of breaks to search within.
         *
         * @return {Highcharts.XAxisBreaksOptions|undefined}
         * Returns the first break found that matches, returns false if no break
         * is found.
         */
        Additions.prototype.findBreakAt = function (x, breaks) {
            return BrokenAxis_find(breaks, function (b) {
                return b.from < x && x < b.to;
            });
        };
        /**
         * @private
         */
        Additions.prototype.isInAnyBreak = function (val, testKeep) {
            var brokenAxis = this,
                axis = brokenAxis.axis,
                breaks = axis.options.breaks || [];
            var i = breaks.length,
                inbrk,
                keep,
                ret;
            if (i && BrokenAxis_isNumber(val)) {
                while (i--) {
                    if (Additions.isInBreak(breaks[i], val)) {
                        inbrk = true;
                        if (!keep) {
                            keep = BrokenAxis_pick(breaks[i].showPoints, !axis.isXAxis);
                        }
                    }
                }
                if (inbrk && testKeep) {
                    ret = inbrk && !keep;
                }
                else {
                    ret = inbrk;
                }
            }
            return ret;
        };
        /**
         * Dynamically set or unset breaks in an axis. This function in lighter
         * than using Axis.update, and it also preserves animation.
         *
         * @private
         * @function Highcharts.Axis#setBreaks
         *
         * @param {Array<Highcharts.XAxisBreaksOptions>} [breaks]
         * The breaks to add. When `undefined` it removes existing breaks.
         *
         * @param {boolean} [redraw=true]
         * Whether to redraw the chart immediately.
         */
        Additions.prototype.setBreaks = function (breaks, redraw) {
            var brokenAxis = this,
                axis = brokenAxis.axis,
                time = axis.chart.time,
                hasBreaks = BrokenAxis_isArray(breaks) &&
                    !!breaks.length &&
                    !!Object.keys(breaks[0]).length; // Check for [{}], #16368.
                axis.isDirty = brokenAxis.hasBreaks !== hasBreaks;
            brokenAxis.hasBreaks = hasBreaks;
            // Compile string dates
            breaks === null || breaks === void 0 ? void 0 : breaks.forEach(function (brk) {
                brk.from = time.parse(brk.from) || 0;
                brk.to = time.parse(brk.to) || 0;
            });
            if (breaks !== axis.options.breaks) {
                axis.options.breaks = axis.userOptions.breaks = breaks;
            }
            axis.forceRedraw = true; // Force recalculation in setScale
            // Recalculate series related to the axis.
            axis.series.forEach(function (series) {
                series.isDirty = true;
            });
            if (!hasBreaks && axis.val2lin === Additions.val2Lin) {
                // Revert to prototype functions
                delete axis.val2lin;
                delete axis.lin2val;
            }
            if (hasBreaks) {
                axis.userOptions.ordinal = false;
                axis.lin2val = Additions.lin2Val;
                axis.val2lin = Additions.val2Lin;
                axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) {
                    // If trying to set extremes inside a break, extend min to
                    // after, and max to before the break ( #3857 )
                    if (brokenAxis.hasBreaks) {
                        var breaks_1 = (this.options.breaks || []);
                        var axisBreak = void 0;
                        while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks_1))) {
                            newMin = axisBreak.to;
                        }
                        while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks_1))) {
                            newMax = axisBreak.from;
                        }
                        // If both min and max is within the same break.
                        if (newMax < newMin) {
                            newMax = newMin;
                        }
                    }
                    axis.constructor.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments);
                };
                axis.setAxisTranslation = function () {
                    axis.constructor.prototype.setAxisTranslation.call(this);
                    brokenAxis.unitLength = void 0;
                    if (brokenAxis.hasBreaks) {
                        var breaks_2 = axis.options.breaks || [], 
                            // Temporary one:
                            breakArrayT_1 = [],
                            breakArray_1 = [],
                            pointRangePadding = BrokenAxis_pick(axis.pointRangePadding, 0);
                        var length_1 = 0,
                            inBrk_1,
                            repeat_1,
                            min_1 = axis.userMin || axis.min,
                            max_1 = axis.userMax || axis.max,
                            start_1,
                            i_1;
                        // Min & max check (#4247)
                        breaks_2.forEach(function (brk) {
                            repeat_1 = brk.repeat || Infinity;
                            if (BrokenAxis_isNumber(min_1) && BrokenAxis_isNumber(max_1)) {
                                if (Additions.isInBreak(brk, min_1)) {
                                    min_1 += ((brk.to % repeat_1) -
                                        (min_1 % repeat_1));
                                }
                                if (Additions.isInBreak(brk, max_1)) {
                                    max_1 -= ((max_1 % repeat_1) -
                                        (brk.from % repeat_1));
                                }
                            }
                        });
                        // Construct an array holding all breaks in the axis
                        breaks_2.forEach(function (brk) {
                            start_1 = brk.from;
                            repeat_1 = brk.repeat || Infinity;
                            if (BrokenAxis_isNumber(min_1) && BrokenAxis_isNumber(max_1)) {
                                while (start_1 - repeat_1 > min_1) {
                                    start_1 -= repeat_1;
                                }
                                while (start_1 < min_1) {
                                    start_1 += repeat_1;
                                }
                                for (i_1 = start_1; i_1 < max_1; i_1 += repeat_1) {
                                    breakArrayT_1.push({
                                        value: i_1,
                                        move: 'in'
                                    });
                                    breakArrayT_1.push({
                                        value: i_1 + brk.to - brk.from,
                                        move: 'out',
                                        size: brk.breakSize
                                    });
                                }
                            }
                        });
                        breakArrayT_1.sort(function (a, b) {
                            return ((a.value === b.value) ?
                                ((a.move === 'in' ? 0 : 1) -
                                    (b.move === 'in' ? 0 : 1)) :
                                a.value - b.value);
                        });
                        // Simplify the breaks
                        inBrk_1 = 0;
                        start_1 = min_1;
                        breakArrayT_1.forEach(function (brk) {
                            inBrk_1 += (brk.move === 'in' ? 1 : -1);
                            if (inBrk_1 === 1 && brk.move === 'in') {
                                start_1 = brk.value;
                            }
                            if (inBrk_1 === 0 && BrokenAxis_isNumber(start_1)) {
                                breakArray_1.push({
                                    from: start_1,
                                    to: brk.value,
                                    len: brk.value - start_1 - (brk.size || 0)
                                });
                                length_1 += (brk.value -
                                    start_1 -
                                    (brk.size || 0));
                            }
                        });
                        brokenAxis.breakArray = breakArray_1;
                        // Used with staticScale, and below the actual axis
                        // length, when breaks are subtracted.
                        if (BrokenAxis_isNumber(min_1) &&
                            BrokenAxis_isNumber(max_1) &&
                            BrokenAxis_isNumber(axis.min)) {
                            brokenAxis.unitLength = max_1 - min_1 - length_1 +
                                pointRangePadding;
                            BrokenAxis_fireEvent(axis, 'afterBreaks');
                            if (axis.staticScale) {
                                axis.transA = axis.staticScale;
                            }
                            else if (brokenAxis.unitLength) {
                                axis.transA *=
                                    (max_1 - axis.min + pointRangePadding) /
                                        brokenAxis.unitLength;
                            }
                            if (pointRangePadding) {
                                axis.minPixelPadding =
                                    axis.transA * (axis.minPointOffset || 0);
                            }
                            axis.min = min_1;
                            axis.max = max_1;
                        }
                    }
                };
            }
            if (BrokenAxis_pick(redraw, true)) {
                axis.chart.redraw();
            }
        };
        return Additions;
    }());
    BrokenAxis.Additions = Additions;
})(BrokenAxis || (BrokenAxis = {}));
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Axis_BrokenAxis = (BrokenAxis);

;// ./code/es5/es-modules/Core/Axis/GridAxis.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var GridAxis_dateFormats = Core_Globals.dateFormats;

var GridAxis_addEvent = Core_Utilities.addEvent, GridAxis_defined = Core_Utilities.defined, GridAxis_erase = Core_Utilities.erase, GridAxis_find = Core_Utilities.find, GridAxis_isArray = Core_Utilities.isArray, GridAxis_isNumber = Core_Utilities.isNumber, GridAxis_merge = Core_Utilities.merge, GridAxis_pick = Core_Utilities.pick, GridAxis_timeUnits = Core_Utilities.timeUnits, GridAxis_wrap = Core_Utilities.wrap;
/* *
 *
 *  Enums
 *
 * */
/**
 * Enum for which side the axis is on. Maps to axis.side.
 * @private
 */
var GridAxisSide;
(function (GridAxisSide) {
    GridAxisSide[GridAxisSide["top"] = 0] = "top";
    GridAxisSide[GridAxisSide["right"] = 1] = "right";
    GridAxisSide[GridAxisSide["bottom"] = 2] = "bottom";
    GridAxisSide[GridAxisSide["left"] = 3] = "left";
})(GridAxisSide || (GridAxisSide = {}));
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function argsToArray(args) {
    return Array.prototype.slice.call(args, 1);
}
/**
 * @private
 */
function GridAxis_isObject(x) {
    // Always use strict mode
    return Core_Utilities.isObject(x, true);
}
/**
 * @private
 */
function applyGridOptions(axis) {
    var options = axis.options;
    // Center-align by default
    /*
    if (!options.labels) {
        options.labels = {};
    }
    */
    options.labels.align = GridAxis_pick(options.labels.align, 'center');
    // @todo: Check against tickLabelPlacement between/on etc
    /* Prevents adding the last tick label if the axis is not a category
       axis.
       Since numeric labels are normally placed at starts and ends of a
       range of value, and this module makes the label point at the value,
       an "extra" label would appear. */
    if (!axis.categories) {
        options.showLastLabel = false;
    }
    // Prevents rotation of labels when squished, as rotating them would not
    // help.
    axis.labelRotation = 0;
    options.labels.rotation = 0;
    // Allow putting ticks closer than their data points.
    options.minTickInterval = 1;
}
/**
 * Extends axis class with grid support.
 * @private
 */
function GridAxis_compose(AxisClass, ChartClass, TickClass) {
    if (!AxisClass.keepProps.includes('grid')) {
        AxisClass.keepProps.push('grid');
        AxisClass.prototype.getMaxLabelDimensions = getMaxLabelDimensions;
        GridAxis_wrap(AxisClass.prototype, 'unsquish', wrapUnsquish);
        GridAxis_wrap(AxisClass.prototype, 'getOffset', wrapGetOffset);
        // Add event handlers
        GridAxis_addEvent(AxisClass, 'init', onInit);
        GridAxis_addEvent(AxisClass, 'afterGetTitlePosition', onAfterGetTitlePosition);
        GridAxis_addEvent(AxisClass, 'afterInit', onAfterInit);
        GridAxis_addEvent(AxisClass, 'afterRender', onAfterRender);
        GridAxis_addEvent(AxisClass, 'afterSetAxisTranslation', onAfterSetAxisTranslation);
        GridAxis_addEvent(AxisClass, 'afterSetOptions', onAfterSetOptions);
        GridAxis_addEvent(AxisClass, 'afterSetOptions', onAfterSetOptions2);
        GridAxis_addEvent(AxisClass, 'afterSetScale', onAfterSetScale);
        GridAxis_addEvent(AxisClass, 'afterTickSize', onAfterTickSize);
        GridAxis_addEvent(AxisClass, 'trimTicks', onTrimTicks);
        GridAxis_addEvent(AxisClass, 'destroy', onDestroy);
        GridAxis_addEvent(ChartClass, 'afterSetChartSize', GridAxis_onChartAfterSetChartSize);
        GridAxis_addEvent(TickClass, 'afterGetLabelPosition', onTickAfterGetLabelPosition);
        GridAxis_addEvent(TickClass, 'labelFormat', onTickLabelFormat);
    }
    return AxisClass;
}
/**
 * Get the largest label width and height.
 *
 * @private
 * @function Highcharts.Axis#getMaxLabelDimensions
 *
 * @param {Highcharts.Dictionary<Highcharts.Tick>} ticks
 * All the ticks on one axis.
 *
 * @param {Array<number|string>} tickPositions
 * All the tick positions on one axis.
 *
 * @return {Highcharts.SizeObject}
 * Object containing the properties height and width.
 *
 * @todo Move this to the generic axis implementation, as it is used there.
 */
function getMaxLabelDimensions(ticks, tickPositions) {
    var dimensions = {
            width: 0,
            height: 0
        };
    tickPositions.forEach(function (pos) {
        var tick = ticks[pos];
        var labelHeight = 0,
            labelWidth = 0,
            label;
        if (GridAxis_isObject(tick)) {
            label = GridAxis_isObject(tick.label) ? tick.label : {};
            // Find width and height of label
            labelHeight = label.getBBox ? label.getBBox().height : 0;
            if (label.textStr && !GridAxis_isNumber(label.textPxLength)) {
                label.textPxLength = label.getBBox().width;
            }
            labelWidth = GridAxis_isNumber(label.textPxLength) ?
                // Math.round ensures crisp lines
                Math.round(label.textPxLength) :
                0;
            if (label.textStr) {
                // Set the tickWidth same as the label width after ellipsis
                // applied #10281
                labelWidth = Math.round(label.getBBox().width);
            }
            // Update the result if width and/or height are larger
            dimensions.height = Math.max(labelHeight, dimensions.height);
            dimensions.width = Math.max(labelWidth, dimensions.width);
        }
    });
    // For tree grid, add indentation
    if (this.type === 'treegrid' &&
        this.treeGrid &&
        this.treeGrid.mapOfPosToGridNode) {
        var treeDepth = this.treeGrid.mapOfPosToGridNode[-1].height || 0;
        dimensions.width += (this.options.labels.indentation *
            (treeDepth - 1));
    }
    return dimensions;
}
/**
 * Handle columns and getOffset.
 * @private
 */
function wrapGetOffset(proceed) {
    var grid = this.grid, 
        // On the left side we handle the columns first because the offset is
        // calculated from the plot area and out
        columnsFirst = this.side === 3;
    if (!columnsFirst) {
        proceed.apply(this);
    }
    if (!(grid === null || grid === void 0 ? void 0 : grid.isColumn)) {
        var columns = (grid === null || grid === void 0 ? void 0 : grid.columns) || [];
        if (columnsFirst) {
            columns = columns.slice().reverse();
        }
        columns
            .forEach(function (column) {
            column.getOffset();
        });
    }
    if (columnsFirst) {
        proceed.apply(this);
    }
}
/**
 * @private
 */
function onAfterGetTitlePosition(e) {
    var axis = this;
    var options = axis.options;
    var gridOptions = options.grid || {};
    if (gridOptions.enabled === true) {
        // Compute anchor points for each of the title align options
        var axisTitle = axis.axisTitle,
            axisHeight = axis.height,
            horiz = axis.horiz,
            axisLeft = axis.left,
            offset = axis.offset,
            opposite = axis.opposite,
            options_1 = axis.options,
            axisTop = axis.top,
            axisWidth = axis.width;
        var tickSize = axis.tickSize();
        var titleWidth = axisTitle && axisTitle.getBBox().width;
        var xOption = options_1.title.x;
        var yOption = options_1.title.y;
        var titleMargin = GridAxis_pick(options_1.title.margin,
            horiz ? 5 : 10);
        var titleFontSize = axisTitle ? axis.chart.renderer.fontMetrics(axisTitle).f : 0;
        var crispCorr = tickSize ? tickSize[0] / 2 : 0;
        // TODO account for alignment
        // the position in the perpendicular direction of the axis
        var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) +
                (horiz ? 1 : -1) * // Horizontal axis reverses the margin
                    (opposite ? -1 : 1) * // So does opposite axes
                    crispCorr +
                (axis.side === GridAxisSide.bottom ? titleFontSize : 0));
        e.titlePosition.x = horiz ?
            axisLeft - (titleWidth || 0) / 2 - titleMargin + xOption :
            offAxis + (opposite ? axisWidth : 0) + offset + xOption;
        e.titlePosition.y = horiz ?
            (offAxis -
                (opposite ? axisHeight : 0) +
                (opposite ? titleFontSize : -titleFontSize) / 2 +
                offset +
                yOption) :
            axisTop - titleMargin + yOption;
    }
}
/**
 * @private
 */
function onAfterInit() {
    var axis = this;
    var chart = axis.chart,
        _a = axis.options.grid,
        gridOptions = _a === void 0 ? {} : _a,
        userOptions = axis.userOptions;
    if (gridOptions.enabled) {
        applyGridOptions(axis);
    }
    if (gridOptions.columns) {
        var columns = axis.grid.columns = [];
        var columnIndex = axis.grid.columnIndex = 0;
        // Handle columns, each column is a grid axis
        while (++columnIndex < gridOptions.columns.length) {
            var columnOptions = GridAxis_merge(userOptions,
                gridOptions.columns[columnIndex], {
                    isInternal: true,
                    linkedTo: 0,
                    // Disable by default the scrollbar on the grid axis
                    scrollbar: {
                        enabled: false
                    }
                }, 
                // Avoid recursion
                {
                    grid: {
                        columns: void 0
                    }
                });
            var column = new Axis_Axis(axis.chart,
                columnOptions, 'yAxis');
            column.grid.isColumn = true;
            column.grid.columnIndex = columnIndex;
            // Remove column axis from chart axes array, and place it
            // in the columns array.
            GridAxis_erase(chart.axes, column);
            GridAxis_erase(chart[axis.coll] || [], column);
            columns.push(column);
        }
    }
}
/**
 * Draw an extra line on the far side of the outermost axis,
 * creating floor/roof/wall of a grid. And some padding.
 * ```
 * Make this:
 *             (axis.min) __________________________ (axis.max)
 *                           |    |    |    |    |
 * Into this:
 *             (axis.min) __________________________ (axis.max)
 *                        ___|____|____|____|____|__
 * ```
 * @private
 */
function onAfterRender() {
    var axis = this,
        axisTitle = axis.axisTitle,
        grid = axis.grid,
        options = axis.options,
        gridOptions = options.grid || {};
    if (gridOptions.enabled === true) {
        var min = axis.min || 0,
            max = axis.max || 0,
            firstTick = axis.ticks[axis.tickPositions[0]];
        // Adjust the title max width to the column width (#19657)
        if (axisTitle &&
            !axis.chart.styledMode &&
            (firstTick === null || firstTick === void 0 ? void 0 : firstTick.slotWidth) &&
            !axis.options.title.style.width) {
            axisTitle.css({ width: "" + firstTick.slotWidth + "px" });
        }
        // @todo actual label padding (top, bottom, left, right)
        axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions);
        // Remove right wall before rendering if updating
        if (axis.rightWall) {
            axis.rightWall.destroy();
        }
        /*
        Draw an extra axis line on outer axes
                    >
        Make this:    |______|______|______|___

                    > _________________________
        Into this:    |______|______|______|__|
                                                */
        if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) {
            var lineWidth = options.lineWidth;
            if (lineWidth) {
                var linePath = axis.getLinePath(lineWidth),
                    startPoint = linePath[0],
                    endPoint = linePath[1], 
                    // Negate distance if top or left axis
                    // Subtract 1px to draw the line at the end of the tick
                    tickLength = (axis.tickSize('tick') || [1])[0],
                    distance = tickLength * ((axis.side === GridAxisSide.top ||
                        axis.side === GridAxisSide.left) ? -1 : 1);
                // If axis is horizontal, reposition line path vertically
                if (startPoint[0] === 'M' && endPoint[0] === 'L') {
                    if (axis.horiz) {
                        startPoint[2] += distance;
                        endPoint[2] += distance;
                    }
                    else {
                        startPoint[1] += distance;
                        endPoint[1] += distance;
                    }
                }
                // If it doesn't exist, add an upper and lower border
                // for the vertical grid axis.
                if (!axis.horiz && axis.chart.marginRight) {
                    var upperBorderStartPoint = startPoint,
                        upperBorderEndPoint = [
                            'L',
                            axis.left,
                            startPoint[2] || 0
                        ],
                        upperBorderPath = [
                            upperBorderStartPoint,
                            upperBorderEndPoint
                        ],
                        lowerBorderEndPoint = [
                            'L',
                            axis.chart.chartWidth - axis.chart.marginRight,
                            axis.toPixels(max + axis.tickmarkOffset)
                        ],
                        lowerBorderStartPoint = [
                            'M',
                            endPoint[1] || 0,
                            axis.toPixels(max + axis.tickmarkOffset)
                        ],
                        lowerBorderPath = [
                            lowerBorderStartPoint,
                            lowerBorderEndPoint
                        ];
                    if (!axis.grid.upperBorder && min % 1 !== 0) {
                        axis.grid.upperBorder = axis.grid.renderBorder(upperBorderPath);
                    }
                    if (axis.grid.upperBorder) {
                        axis.grid.upperBorder.attr({
                            stroke: options.lineColor,
                            'stroke-width': options.lineWidth
                        });
                        axis.grid.upperBorder.animate({
                            d: upperBorderPath
                        });
                    }
                    if (!axis.grid.lowerBorder && max % 1 !== 0) {
                        axis.grid.lowerBorder = axis.grid.renderBorder(lowerBorderPath);
                    }
                    if (axis.grid.lowerBorder) {
                        axis.grid.lowerBorder.attr({
                            stroke: options.lineColor,
                            'stroke-width': options.lineWidth
                        });
                        axis.grid.lowerBorder.animate({
                            d: lowerBorderPath
                        });
                    }
                }
                // Render an extra line parallel to the existing axes, to
                // close the grid.
                if (!axis.grid.axisLineExtra) {
                    axis.grid.axisLineExtra = axis.grid.renderBorder(linePath);
                }
                else {
                    axis.grid.axisLineExtra.attr({
                        stroke: options.lineColor,
                        'stroke-width': options.lineWidth
                    });
                    axis.grid.axisLineExtra.animate({
                        d: linePath
                    });
                }
                // Show or hide the line depending on options.showEmpty
                axis.axisLine[axis.showAxis ? 'show' : 'hide']();
            }
        }
        (grid && grid.columns || []).forEach(function (column) { return column.render(); });
        // Manipulate the tick mark visibility
        // based on the axis.max- allows smooth scrolling.
        if (!axis.horiz &&
            axis.chart.hasRendered &&
            (axis.scrollbar ||
                (axis.linkedParent && axis.linkedParent.scrollbar)) &&
            axis.tickPositions.length) {
            var tickmarkOffset = axis.tickmarkOffset,
                lastTick = axis.tickPositions[axis.tickPositions.length - 1],
                firstTick_1 = axis.tickPositions[0];
            var label = void 0,
                tickMark = void 0;
            while ((label = axis.hiddenLabels.pop()) && label.element) {
                label.show(); // #15453
            }
            while ((tickMark = axis.hiddenMarks.pop()) &&
                tickMark.element) {
                tickMark.show(); // #16439
            }
            // Hide/show first tick label.
            label = axis.ticks[firstTick_1].label;
            if (label) {
                if (min - firstTick_1 > tickmarkOffset) {
                    axis.hiddenLabels.push(label.hide());
                }
                else {
                    label.show();
                }
            }
            // Hide/show last tick mark/label.
            label = axis.ticks[lastTick].label;
            if (label) {
                if (lastTick - max > tickmarkOffset) {
                    axis.hiddenLabels.push(label.hide());
                }
                else {
                    label.show();
                }
            }
            var mark = axis.ticks[lastTick].mark;
            if (mark &&
                lastTick - max < tickmarkOffset &&
                lastTick - max > 0 && axis.ticks[lastTick].isLast) {
                axis.hiddenMarks.push(mark.hide());
            }
        }
    }
}
/**
 * @private
 */
function onAfterSetAxisTranslation() {
    var axis = this;
    var tickInfo = axis.tickPositions && axis.tickPositions.info;
    var options = axis.options;
    var gridOptions = options.grid || {};
    var userLabels = axis.userOptions.labels || {};
    // Fire this only for the Gantt type chart, #14868.
    if (gridOptions.enabled) {
        if (axis.horiz) {
            axis.series.forEach(function (series) {
                series.options.pointRange = 0;
            });
            // Lower level time ticks, like hours or minutes, represent
            // points in time and not ranges. These should be aligned
            // left in the grid cell by default. The same applies to
            // years of higher order.
            if (tickInfo &&
                options.dateTimeLabelFormats &&
                options.labels &&
                !GridAxis_defined(userLabels.align) &&
                (options.dateTimeLabelFormats[tickInfo.unitName]
                    .range === false ||
                    tickInfo.count > 1 // Years
                )) {
                options.labels.align = 'left';
                if (!GridAxis_defined(userLabels.x)) {
                    options.labels.x = 3;
                }
            }
        }
        else {
            // Don't trim ticks which not in min/max range but
            // they are still in the min/max plus tickInterval.
            if (this.type !== 'treegrid' &&
                axis.grid &&
                axis.grid.columns) {
                this.minPointOffset = this.tickInterval;
            }
        }
    }
}
/**
 * Creates a left and right wall on horizontal axes:
 * - Places leftmost tick at the start of the axis, to create a left
 *   wall
 * - Ensures that the rightmost tick is at the end of the axis, to
 *   create a right wall.
 * @private
 */
function onAfterSetOptions(e) {
    var options = this.options,
        userOptions = e.userOptions,
        gridOptions = ((options && GridAxis_isObject(options.grid)) ? options.grid : {});
    var gridAxisOptions;
    if (gridOptions.enabled === true) {
        // Merge the user options into default grid axis options so
        // that when a user option is set, it takes precedence.
        gridAxisOptions = GridAxis_merge(true, {
            className: ('highcharts-grid-axis ' + (userOptions.className || '')),
            dateTimeLabelFormats: {
                hour: {
                    list: ['%[HM]', '%[H]']
                },
                day: {
                    list: ['%[AeB]', '%[aeb]', '%[E]']
                },
                week: {
                    list: ['Week %W', 'W%W']
                },
                month: {
                    list: ['%[B]', '%[b]', '%o']
                }
            },
            grid: {
                borderWidth: 1
            },
            labels: {
                padding: 2,
                style: {
                    fontSize: '0.9em'
                }
            },
            margin: 0,
            title: {
                text: null,
                reserveSpace: false,
                rotation: 0,
                style: {
                    textOverflow: 'ellipsis'
                }
            },
            // In a grid axis, only allow one unit of certain types,
            // for example we shouldn't have one grid cell spanning
            // two days.
            units: [[
                    'millisecond', // Unit name
                    [1, 10, 100]
                ], [
                    'second',
                    [1, 10]
                ], [
                    'minute',
                    [1, 5, 15]
                ], [
                    'hour',
                    [1, 6]
                ], [
                    'day',
                    [1]
                ], [
                    'week',
                    [1]
                ], [
                    'month',
                    [1]
                ], [
                    'year',
                    null
                ]]
        }, userOptions);
        // X-axis specific options
        if (this.coll === 'xAxis') {
            // For linked axes, tickPixelInterval is used only if
            // the tickPositioner below doesn't run or returns
            // undefined (like multiple years)
            if (GridAxis_defined(userOptions.linkedTo) &&
                !GridAxis_defined(userOptions.tickPixelInterval)) {
                gridAxisOptions.tickPixelInterval = 350;
            }
            // For the secondary grid axis, use the primary axis'
            // tick intervals and return ticks one level higher.
            if (
            // Check for tick pixel interval in options
            !GridAxis_defined(userOptions.tickPixelInterval) &&
                // Only for linked axes
                GridAxis_defined(userOptions.linkedTo) &&
                !GridAxis_defined(userOptions.tickPositioner) &&
                !GridAxis_defined(userOptions.tickInterval) &&
                !GridAxis_defined(userOptions.units)) {
                gridAxisOptions.tickPositioner = function (min, max) {
                    var parentInfo = (this.linkedParent &&
                            this.linkedParent.tickPositions &&
                            this.linkedParent.tickPositions.info);
                    if (parentInfo) {
                        var units = (gridAxisOptions.units || []);
                        var unitIdx = void 0,
                            count = 1,
                            unitName = 'year';
                        for (var i = 0; i < units.length; i++) {
                            var unit_1 = units[i];
                            if (unit_1 && unit_1[0] === parentInfo.unitName) {
                                unitIdx = i;
                                break;
                            }
                        }
                        // Get the first allowed count on the next unit.
                        var unit = (GridAxis_isNumber(unitIdx) && units[unitIdx + 1]);
                        if (unit) {
                            unitName = unit[0] || 'year';
                            var counts = unit[1];
                            count = counts && counts[0] || 1;
                            // In case the base X axis shows years, make the
                            // secondary axis show ten times the years (#11427)
                        }
                        else if (parentInfo.unitName === 'year') {
                            // `unitName` is 'year'
                            count = parentInfo.count * 10;
                        }
                        var unitRange = GridAxis_timeUnits[unitName];
                        this.tickInterval = unitRange * count;
                        return this.chart.time.getTimeTicks({ unitRange: unitRange, count: count, unitName: unitName }, min, max, this.options.startOfWeek);
                    }
                };
            }
        }
        // Now merge the combined options into the axis options
        GridAxis_merge(true, this.options, gridAxisOptions);
        if (this.horiz) {
            /*               _________________________
            Make this:    ___|_____|_____|_____|__|
                            ^                     ^
                            _________________________
            Into this:    |_____|_____|_____|_____|
                                ^                 ^    */
            options.minPadding = GridAxis_pick(userOptions.minPadding, 0);
            options.maxPadding = GridAxis_pick(userOptions.maxPadding, 0);
        }
        // If borderWidth is set, then use its value for tick and
        // line width.
        if (GridAxis_isNumber(options.grid.borderWidth)) {
            options.tickWidth = options.lineWidth =
                gridOptions.borderWidth;
        }
    }
}
/**
 * @private
 */
function onAfterSetOptions2(e) {
    var axis = this;
    var userOptions = e.userOptions;
    var gridOptions = userOptions && userOptions.grid || {};
    var columns = gridOptions.columns;
    // Add column options to the parent axis. Children has their column options
    // set on init in onGridAxisAfterInit.
    if (gridOptions.enabled && columns) {
        GridAxis_merge(true, axis.options, columns[0]);
    }
}
/**
 * Handle columns and setScale.
 * @private
 */
function onAfterSetScale() {
    var axis = this;
    (axis.grid.columns || []).forEach(function (column) { return column.setScale(); });
}
/**
 * Draw vertical axis ticks extra long to create cell floors and roofs.
 * Overrides the tickLength for vertical axes.
 * @private
 */
function onAfterTickSize(e) {
    var _a = this,
        horiz = _a.horiz,
        maxLabelDimensions = _a.maxLabelDimensions,
        _b = _a.options.grid,
        gridOptions = _b === void 0 ? {} : _b;
    if (gridOptions.enabled && maxLabelDimensions) {
        var labelPadding = this.options.labels.distance * 2;
        var distance = horiz ?
                (gridOptions.cellHeight ||
                    labelPadding + maxLabelDimensions.height) :
                labelPadding + maxLabelDimensions.width;
        if (GridAxis_isArray(e.tickSize)) {
            e.tickSize[0] = distance;
        }
        else {
            e.tickSize = [distance, 0];
        }
    }
}
/**
 * @private
 */
function GridAxis_onChartAfterSetChartSize() {
    this.axes.forEach(function (axis) {
        (axis.grid && axis.grid.columns || []).forEach(function (column) {
            column.setAxisSize();
            column.setAxisTranslation();
        });
    });
}
/**
 * @private
 */
function onDestroy(e) {
    var grid = this.grid;
    (grid.columns || []).forEach(function (column) { return column.destroy(e.keepEvents); });
    grid.columns = void 0;
}
/**
 * Wraps axis init to draw cell walls on vertical axes.
 * @private
 */
function onInit(e) {
    var axis = this;
    var userOptions = e.userOptions || {};
    var gridOptions = userOptions.grid || {};
    if (gridOptions.enabled && GridAxis_defined(gridOptions.borderColor)) {
        userOptions.tickColor = userOptions.lineColor = (gridOptions.borderColor);
    }
    if (!axis.grid) {
        axis.grid = new GridAxisAdditions(axis);
    }
    axis.hiddenLabels = [];
    axis.hiddenMarks = [];
}
/**
 * Center tick labels in cells.
 * @private
 */
function onTickAfterGetLabelPosition(e) {
    var tick = this,
        label = tick.label,
        axis = tick.axis,
        reversed = axis.reversed,
        chart = axis.chart,
        options = axis.options,
        gridOptions = options.grid || {},
        labelOpts = axis.options.labels,
        align = labelOpts.align, 
        // `verticalAlign` is currently not supported for axis.labels.
        verticalAlign = 'middle', // LabelOpts.verticalAlign,
        side = GridAxisSide[axis.side],
        tickmarkOffset = e.tickmarkOffset,
        tickPositions = axis.tickPositions,
        tickPos = tick.pos - tickmarkOffset,
        nextTickPos = (GridAxis_isNumber(tickPositions[e.index + 1]) ?
            tickPositions[e.index + 1] - tickmarkOffset :
            (axis.max || 0) + tickmarkOffset),
        tickSize = axis.tickSize('tick'),
        tickWidth = tickSize ? tickSize[0] : 0,
        crispCorr = tickSize ? tickSize[1] / 2 : 0;
    // Only center tick labels in grid axes
    if (gridOptions.enabled === true) {
        var bottom = void 0,
            top_1,
            left = void 0,
            right = void 0;
        // Calculate top and bottom positions of the cell.
        if (side === 'top') {
            bottom = axis.top + axis.offset;
            top_1 = bottom - tickWidth;
        }
        else if (side === 'bottom') {
            top_1 = chart.chartHeight - axis.bottom + axis.offset;
            bottom = top_1 + tickWidth;
        }
        else {
            bottom = axis.top + axis.len - (axis.translate(reversed ? nextTickPos : tickPos) || 0);
            top_1 = axis.top + axis.len - (axis.translate(reversed ? tickPos : nextTickPos) || 0);
        }
        // Calculate left and right positions of the cell.
        if (side === 'right') {
            left = chart.chartWidth - axis.right + axis.offset;
            right = left + tickWidth;
        }
        else if (side === 'left') {
            right = axis.left + axis.offset;
            left = right - tickWidth;
        }
        else {
            left = Math.round(axis.left + (axis.translate(reversed ? nextTickPos : tickPos) || 0)) - crispCorr;
            right = Math.min(// #15742
            Math.round(axis.left + (axis.translate(reversed ? tickPos : nextTickPos) || 0)) - crispCorr, axis.left + axis.len);
        }
        tick.slotWidth = right - left;
        // Calculate the positioning of the label based on
        // alignment.
        e.pos.x = (align === 'left' ?
            left :
            align === 'right' ?
                right :
                left + ((right - left) / 2) // Default to center
        );
        e.pos.y = (verticalAlign === 'top' ?
            top_1 :
            verticalAlign === 'bottom' ?
                bottom :
                top_1 + ((bottom - top_1) / 2) // Default to middle
        );
        if (label) {
            var lblMetrics = chart.renderer.fontMetrics(label),
                labelHeight = label.getBBox().height;
            // Adjustment to y position to align the label correctly.
            // Would be better to have a setter or similar for this.
            if (!labelOpts.useHTML) {
                var lines = Math.round(labelHeight / lblMetrics.h);
                e.pos.y += (
                // Center the label
                // TODO: why does this actually center the label?
                ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) +
                    // Adjust for height of additional lines.
                    -(((lines - 1) * lblMetrics.h) / 2));
            }
            else {
                e.pos.y += (
                // Readjust yCorr in htmlUpdateTransform
                lblMetrics.b +
                    // Adjust for height of html label
                    -(labelHeight / 2));
            }
        }
        e.pos.x += (axis.horiz && labelOpts.x) || 0;
    }
}
/**
 * @private
 */
function onTickLabelFormat(ctx) {
    var axis = ctx.axis,
        value = ctx.value;
    if (axis.options.grid &&
        axis.options.grid.enabled) {
        var tickPos = axis.tickPositions;
        var series = (axis.linkedParent || axis).series[0];
        var isFirst = value === tickPos[0];
        var isLast = value === tickPos[tickPos.length - 1];
        var point = series && GridAxis_find(series.options.data,
            function (p) {
                return p[axis.isXAxis ? 'x' : 'y'] === value;
        });
        var pointCopy = void 0;
        if (point && series.is('gantt')) {
            // For the Gantt set point aliases to the pointCopy
            // to do not change the original point
            pointCopy = GridAxis_merge(point);
            Core_Globals.seriesTypes.gantt.prototype.pointClass
                .setGanttPointAliases(pointCopy, axis.chart);
        }
        // Make additional properties available for the
        // formatter
        ctx.isFirst = isFirst;
        ctx.isLast = isLast;
        ctx.point = pointCopy;
    }
}
/**
 * Makes tick labels which are usually ignored in a linked axis
 * displayed if they are within range of linkedParent.min.
 * ```
 *                        _____________________________
 *                        |   |       |       |       |
 * Make this:             |   |   2   |   3   |   4   |
 *                        |___|_______|_______|_______|
 *                          ^
 *                        _____________________________
 *                        |   |       |       |       |
 * Into this:             | 1 |   2   |   3   |   4   |
 *                        |___|_______|_______|_______|
 *                          ^
 * ```
 * @private
 * @todo Does this function do what the drawing says? Seems to affect
 *       ticks and not the labels directly?
 */
function onTrimTicks() {
    var axis = this,
        options = axis.options,
        gridOptions = options.grid || {},
        categoryAxis = axis.categories,
        tickPositions = axis.tickPositions,
        firstPos = tickPositions[0],
        secondPos = tickPositions[1],
        lastPos = tickPositions[tickPositions.length - 1],
        beforeLastPos = tickPositions[tickPositions.length - 2],
        linkedMin = axis.linkedParent && axis.linkedParent.min,
        linkedMax = axis.linkedParent && axis.linkedParent.max,
        min = linkedMin || axis.min,
        max = linkedMax || axis.max,
        tickInterval = axis.tickInterval,
        startLessThanMin = ( // #19845
        GridAxis_isNumber(min) &&
            min >= firstPos + tickInterval &&
            min < secondPos),
        endMoreThanMin = (GridAxis_isNumber(min) &&
            firstPos < min &&
            firstPos + tickInterval > min),
        startLessThanMax = (GridAxis_isNumber(max) &&
            lastPos > max &&
            lastPos - tickInterval < max),
        endMoreThanMax = (GridAxis_isNumber(max) &&
            max <= lastPos - tickInterval &&
            max > beforeLastPos);
    if (gridOptions.enabled === true &&
        !categoryAxis &&
        (axis.isXAxis || axis.isLinked)) {
        if ((endMoreThanMin || startLessThanMin) && !options.startOnTick) {
            tickPositions[0] = min;
        }
        if ((startLessThanMax || endMoreThanMax) && !options.endOnTick) {
            tickPositions[tickPositions.length - 1] = max;
        }
    }
}
/**
 * Avoid altering tickInterval when reserving space.
 * @private
 */
function wrapUnsquish(proceed) {
    var axis = this;
    var _a = axis.options.grid,
        gridOptions = _a === void 0 ? {} : _a;
    if (gridOptions.enabled === true && axis.categories) {
        return axis.tickInterval;
    }
    return proceed.apply(axis, argsToArray(arguments));
}
/* *
 *
 *  Class
 *
 * */
/**
 * Additions for grid axes.
 * @private
 * @class
 */
var GridAxisAdditions = /** @class */ (function () {
    /* *
    *
    *  Constructors
    *
    * */
    function GridAxisAdditions(axis) {
        this.axis = axis;
    }
    /* *
    *
    *  Functions
    *
    * */
    /**
     * Checks if an axis is the outer axis in its dimension. Since
     * axes are placed outwards in order, the axis with the highest
     * index is the outermost axis.
     *
     * Example: If there are multiple x-axes at the top of the chart,
     * this function returns true if the axis supplied is the last
     * of the x-axes.
     *
     * @private
     *
     * @return {boolean}
     * True if the axis is the outermost axis in its dimension; false if
     * not.
     */
    GridAxisAdditions.prototype.isOuterAxis = function () {
        var _a;
        var axis = this.axis;
        var chart = axis.chart;
        var columnIndex = axis.grid.columnIndex;
        var columns = (((_a = axis.linkedParent) === null || _a === void 0 ? void 0 : _a.grid.columns) ||
                axis.grid.columns ||
                []);
        var parentAxis = columnIndex ? axis.linkedParent : axis;
        var thisIndex = -1,
            lastIndex = 0;
        // On the left side, when we have columns (not only multiple axes), the
        // main axis is to the left
        if (axis.side === 3 && !chart.inverted && columns.length) {
            return !axis.linkedParent;
        }
        (chart[axis.coll] || []).forEach(function (otherAxis, index) {
            if (otherAxis.side === axis.side &&
                !otherAxis.options.isInternal) {
                lastIndex = index;
                if (otherAxis === parentAxis) {
                    // Get the index of the axis in question
                    thisIndex = index;
                }
            }
        });
        return (lastIndex === thisIndex &&
            (GridAxis_isNumber(columnIndex) ?
                columns.length === columnIndex :
                true));
    };
    /**
     * Add extra border based on the provided path.
     * @private
     * @param {SVGPath} path
     * The path of the border.
     * @return {Highcharts.SVGElement}
     * Border
     */
    GridAxisAdditions.prototype.renderBorder = function (path) {
        var axis = this.axis,
            renderer = axis.chart.renderer,
            options = axis.options,
            extraBorderLine = renderer.path(path)
                .addClass('highcharts-axis-line')
                .add(axis.axisGroup);
        if (!renderer.styledMode) {
            extraBorderLine.attr({
                stroke: options.lineColor,
                'stroke-width': options.lineWidth,
                zIndex: 7
            });
        }
        return extraBorderLine;
    };
    return GridAxisAdditions;
}());
/* *
 *
 *  Registry
 *
 * */
// First letter of the day of the week, e.g. 'M' for 'Monday'.
GridAxis_dateFormats.E = function (timestamp) {
    return this.dateFormat('%a', timestamp, true).charAt(0);
};
// Adds week date format
GridAxis_dateFormats.W = function (timestamp) {
    var d = this.toParts(timestamp),
        firstDay = (d[7] + 6) % 7,
        thursday = d.slice(0);
    thursday[2] = d[2] - firstDay + 3;
    var firstThursday = this.toParts(this.makeTime(thursday[0], 0, 1));
    if (firstThursday[7] !== 4) {
        d[1] = 0; // Set month to January
        d[2] = 1 + (11 - firstThursday[7]) % 7;
    }
    var thursdayTS = this.makeTime(thursday[0],
        thursday[1],
        thursday[2]),
        firstThursdayTS = this.makeTime(firstThursday[0],
        firstThursday[1],
        firstThursday[2]);
    return (1 +
        Math.floor((thursdayTS - firstThursdayTS) / 604800000)).toString();
};
/* *
 *
 *  Default Export
 *
 * */
var GridAxis = {
    compose: GridAxis_compose
};
/* harmony default export */ var Axis_GridAxis = (GridAxis);
/* *
 *
 *  API Options
 *
 * */
/**
 * @productdesc {gantt}
 * For grid axes (like in Gantt charts),
 * it is possible to declare as a list to provide different
 * formats depending on available space.
 *
 * Defaults to:
 * ```js
 * {
 *     hour: { list: ['%H:%M', '%H'] },
 *     day: { list: ['%A, %e. %B', '%a, %e. %b', '%E'] },
 *     week: { list: ['Week %W', 'W%W'] },
 *     month: { list: ['%B', '%b', '%o'] }
 * }
 * ```
 *
 * @sample {gantt} gantt/grid-axis/date-time-label-formats
 *         Gantt chart with custom axis date format.
 *
 * @apioption xAxis.dateTimeLabelFormats
 */
/**
 * Set grid options for the axis labels. Requires Highcharts Gantt.
 *
 * @since     6.2.0
 * @product   gantt
 * @apioption xAxis.grid
 */
/**
 * Enable grid on the axis labels. Defaults to true for Gantt charts.
 *
 * @type      {boolean}
 * @default   true
 * @since     6.2.0
 * @product   gantt
 * @apioption xAxis.grid.enabled
 */
/**
 * Set specific options for each column (or row for horizontal axes) in the
 * grid. Each extra column/row is its own axis, and the axis options can be set
 * here.
 *
 * @sample gantt/demo/left-axis-table
 *         Left axis as a table
 * @sample gantt/demo/treegrid-columns
 *         Collapsible tree grid with columns
 *
 * @type      {Array<Highcharts.XAxisOptions>}
 * @apioption xAxis.grid.columns
 */
/**
 * Set border color for the label grid lines.
 *
 * @type      {Highcharts.ColorString}
 * @default   #e6e6e6
 * @apioption xAxis.grid.borderColor
 */
/**
 * Set border width of the label grid lines.
 *
 * @type      {number}
 * @default   1
 * @apioption xAxis.grid.borderWidth
 */
/**
 * Set cell height for grid axis labels. By default this is calculated from font
 * size. This option only applies to horizontal axes. For vertical axes, check
 * the [#yAxis.staticScale](yAxis.staticScale) option.
 *
 * @sample gantt/grid-axis/cellheight
 *         Gant chart with custom cell height
 * @type      {number}
 * @apioption xAxis.grid.cellHeight
 */
''; // Keeps doclets above in JS file

;// ./code/es5/es-modules/Gantt/Tree.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Authors: Jon Arild Nygard
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var __rest = (undefined && undefined.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
/* *
 *
 *  Imports
 *
 * */

var Tree_extend = Core_Utilities.extend, Tree_isNumber = Core_Utilities.isNumber, Tree_pick = Core_Utilities.pick;
/* *
 *
 *  Functions
 *
 * */
/**
 * Creates an object map from parent id to children's index.
 *
 * @private
 * @function Highcharts.Tree#getListOfParents
 *
 * @param {Array<*>} data
 *        List of points set in options. `Array.parent` is parent id of point.
 *
 * @return {Highcharts.Dictionary<Array<*>>}
 * Map from parent id to children index in data
 */
function getListOfParents(data) {
    var root = '',
        ids = [],
        listOfParents = data.reduce(function (prev,
        curr) {
            var _a = curr.parent,
        parent = _a === void 0 ? '' : _a,
        id = curr.id;
        if (typeof prev[parent] === 'undefined') {
            prev[parent] = [];
        }
        prev[parent].push(curr);
        if (id) {
            ids.push(id);
        }
        return prev;
    }, {});
    Object.keys(listOfParents).forEach(function (node) {
        var _a;
        if ((node !== root) && (ids.indexOf(node) === -1)) {
            var adoptedByRoot = listOfParents[node].map(function (orphan) {
                    var parentExcluded = __rest(orphan,
                []); // #15196
                    return parentExcluded;
            });
            (_a = listOfParents[root]).push.apply(_a, adoptedByRoot);
            delete listOfParents[node];
        }
    });
    return listOfParents;
}
/** @private */
function getNode(id, parent, level, data, mapOfIdToChildren, options) {
    var after = options && options.after,
        before = options && options.before,
        node = {
            data: data,
            depth: level - 1,
            id: id,
            level: level,
            parent: (parent || '')
        };
    var descendants = 0,
        height = 0,
        start,
        end;
    // Allow custom logic before the children has been created.
    if (typeof before === 'function') {
        before(node, options);
    }
    // Call getNode recursively on the children. Calculate the height of the
    // node, and the number of descendants.
    var children = ((mapOfIdToChildren[id] || [])).map(function (child) {
            var node = getNode(child.id,
        id, (level + 1),
        child,
        mapOfIdToChildren,
        options),
        childStart = child.start || NaN,
        childEnd = (child.milestone === true ?
                childStart :
                child.end ||
                    NaN);
        // Start should be the lowest child.start.
        start = ((!Tree_isNumber(start) || childStart < start) ?
            childStart :
            start);
        // End should be the largest child.end.
        // If child is milestone, then use start as end.
        end = ((!Tree_isNumber(end) || childEnd > end) ?
            childEnd :
            end);
        descendants = descendants + 1 + node.descendants;
        height = Math.max(node.height + 1, height);
        return node;
    });
    // Calculate start and end for point if it is not already explicitly set.
    if (data) {
        data.start = Tree_pick(data.start, start);
        data.end = Tree_pick(data.end, end);
    }
    Tree_extend(node, {
        children: children,
        descendants: descendants,
        height: height
    });
    // Allow custom logic after the children has been created.
    if (typeof after === 'function') {
        after(node, options);
    }
    return node;
}
/** @private */
function getTree(data, options) {
    return getNode('', null, 1, null, getListOfParents(data), options);
}
/* *
 *
 *  Default Export
 *
 * */
var Tree = {
    getNode: getNode,
    getTree: getTree
};
/* harmony default export */ var Gantt_Tree = (Tree);

;// ./code/es5/es-modules/Core/Axis/TreeGrid/TreeGridTick.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Jon Arild Nygard
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */


var TreeGridTick_addEvent = Core_Utilities.addEvent, TreeGridTick_removeEvent = Core_Utilities.removeEvent, TreeGridTick_isObject = Core_Utilities.isObject, TreeGridTick_isNumber = Core_Utilities.isNumber, TreeGridTick_pick = Core_Utilities.pick, TreeGridTick_wrap = Core_Utilities.wrap;
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function onTickInit() {
    var tick = this;
    if (!tick.treeGrid) {
        tick.treeGrid = new TreeGridTickAdditions(tick);
    }
}
/**
 * @private
 */
function onTickHover(label) {
    label.addClass('highcharts-treegrid-node-active');
    if (!label.renderer.styledMode) {
        label.css({
            textDecoration: 'underline'
        });
    }
}
/**
 * @private
 */
function onTickHoverExit(label, options) {
    var css = TreeGridTick_isObject(options.style) ? options.style : {};
    label.removeClass('highcharts-treegrid-node-active');
    if (!label.renderer.styledMode) {
        label.css({ textDecoration: (css.textDecoration || 'none') });
    }
}
/**
 * @private
 */
function renderLabelIcon(tick, params) {
    var _a;
    var treeGrid = tick.treeGrid,
        isNew = !treeGrid.labelIcon,
        renderer = params.renderer,
        labelBox = params.xy,
        options = params.options,
        width = options.width || 0,
        height = options.height || 0,
        padding = ((_a = options.padding) !== null && _a !== void 0 ? _a : tick.axis.linkedParent) ? 0 : 5,
        iconCenter = {
            x: labelBox.x - (width / 2) - padding,
            y: labelBox.y - (height / 2)
        },
        rotation = params.collapsed ? 90 : 180,
        shouldRender = params.show && TreeGridTick_isNumber(iconCenter.y);
    var icon = treeGrid.labelIcon;
    if (!icon) {
        treeGrid.labelIcon = icon = renderer
            .path(renderer.symbols[options.type](options.x || 0, options.y || 0, width, height))
            .addClass('highcharts-label-icon')
            .add(params.group);
    }
    // Set the new position, and show or hide
    icon[shouldRender ? 'show' : 'hide'](); // #14904, #1338
    // Presentational attributes
    if (!renderer.styledMode) {
        icon
            .attr({
            cursor: 'pointer',
            'fill': TreeGridTick_pick(params.color, "#666666" /* Palette.neutralColor60 */),
            'stroke-width': 1,
            stroke: options.lineColor,
            strokeWidth: options.lineWidth || 0
        });
    }
    // Update the icon positions
    icon[isNew ? 'attr' : 'animate']({
        translateX: iconCenter.x,
        translateY: iconCenter.y,
        rotation: rotation
    });
}
/**
 * @private
 */
function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
    var tick = this,
        lbOptions = TreeGridTick_pick(tick.options && tick.options.labels,
        labelOptions),
        pos = tick.pos,
        axis = tick.axis,
        isTreeGrid = axis.type === 'treegrid',
        result = proceed.apply(tick,
        [x,
        y,
        label,
        horiz,
        lbOptions,
        tickmarkOffset,
        index,
        step]);
    var mapOfPosToGridNode,
        node,
        level;
    if (isTreeGrid) {
        var _a = (lbOptions && TreeGridTick_isObject(lbOptions.symbol,
            true) ?
                lbOptions.symbol :
                {}),
            _b = _a.width,
            width = _b === void 0 ? 0 : _b,
            _c = _a.padding,
            padding = _c === void 0 ? axis.linkedParent ? 0 : 5 : _c,
            indentation = (lbOptions && TreeGridTick_isNumber(lbOptions.indentation) ?
                lbOptions.indentation :
                0);
        mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode;
        node = mapOfPosToGridNode && mapOfPosToGridNode[pos];
        level = (node && node.depth) || 1;
        result.x += (
        // Add space for symbols
        (width + (padding * 2)) +
            // Apply indentation
            ((level - 1) * indentation));
    }
    return result;
}
/**
 * @private
 */
function wrapRenderLabel(proceed) {
    var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, tickGrid = tick.treeGrid, tickOptions = tick.options, icon = tickGrid === null || tickGrid === void 0 ? void 0 : tickGrid.labelIcon, labelElement = label === null || label === void 0 ? void 0 : label.element, axisGrid = axis.treeGrid, axisOptions = axis.options, chart = axis.chart, tickPositions = axis.tickPositions, mapOfPosToGridNode = axisGrid.mapOfPosToGridNode, labelOptions = TreeGridTick_pick(tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.labels, axisOptions === null || axisOptions === void 0 ? void 0 : axisOptions.labels), symbolOptions = (labelOptions && TreeGridTick_isObject(labelOptions.symbol, true) ?
            labelOptions.symbol :
            {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], _a = node || {}, descendants = _a.descendants, depth = _a.depth, hasDescendants = node && descendants && descendants > 0, level = depth, isTreeGridElement = (axis.type === 'treegrid') && labelElement, shouldRender = tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', prefixLevelClass = prefixClassName + 'level-', styledMode = chart.styledMode;
    var collapsed,
        addClassName,
        removeClassName;
    if (isTreeGridElement && node) {
        // Add class name for hierarchical styling.
        label
            .removeClass(new RegExp(prefixLevelClass + '.*'))
            .addClass(prefixLevelClass + level);
    }
    proceed.apply(tick, Array.prototype.slice.call(arguments, 1));
    if (isTreeGridElement && hasDescendants) {
        collapsed = axisGrid.isCollapsed(node);
        renderLabelIcon(tick, {
            color: (!styledMode &&
                label.styles.color ||
                ''),
            collapsed: collapsed,
            group: label.parentGroup,
            options: symbolOptions,
            renderer: label.renderer,
            show: shouldRender,
            xy: label.xy
        });
        // Add class name for the node.
        addClassName = prefixClassName +
            (collapsed ? 'collapsed' : 'expanded');
        removeClassName = prefixClassName +
            (collapsed ? 'expanded' : 'collapsed');
        label
            .addClass(addClassName)
            .removeClass(removeClassName);
        if (!styledMode) {
            label.css({
                cursor: 'pointer'
            });
        }
        // Add events to both label text and icon
        [label, icon].forEach(function (object) {
            if (object && !object.attachedTreeGridEvents) {
                // On hover
                TreeGridTick_addEvent(object.element, 'mouseover', function () {
                    onTickHover(label);
                });
                // On hover out
                TreeGridTick_addEvent(object.element, 'mouseout', function () {
                    onTickHoverExit(label, labelOptions);
                });
                TreeGridTick_addEvent(object.element, 'click', function () {
                    tickGrid.toggleCollapse();
                });
                object.attachedTreeGridEvents = true;
            }
        });
    }
    else if (icon) {
        TreeGridTick_removeEvent(labelElement);
        label === null || label === void 0 ? void 0 : label.css({ cursor: 'default' });
        icon.destroy();
    }
}
/* *
 *
 *  Classes
 *
 * */
/**
 * @private
 * @class
 */
var TreeGridTickAdditions = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    /**
     * @private
     */
    function TreeGridTickAdditions(tick) {
        this.tick = tick;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * @private
     */
    TreeGridTickAdditions.compose = function (TickClass) {
        var tickProto = TickClass.prototype;
        if (!tickProto.toggleCollapse) {
            TreeGridTick_addEvent(TickClass, 'init', onTickInit);
            TreeGridTick_wrap(tickProto, 'getLabelPosition', wrapGetLabelPosition);
            TreeGridTick_wrap(tickProto, 'renderLabel', wrapRenderLabel);
            // Backwards compatibility
            tickProto.collapse = function (redraw) {
                this.treeGrid.collapse(redraw);
            };
            tickProto.expand = function (redraw) {
                this.treeGrid.expand(redraw);
            };
            tickProto.toggleCollapse = function (redraw) {
                this.treeGrid.toggleCollapse(redraw);
            };
        }
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Collapse the grid cell. Used when axis is of type treegrid.
     *
     * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
     *
     * @private
     * @function Highcharts.Tick#collapse
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart or wait for an explicit call to
     * {@link Highcharts.Chart#redraw}
     */
    TreeGridTickAdditions.prototype.collapse = function (redraw) {
        var tick = this.tick,
            axis = tick.axis,
            brokenAxis = axis.brokenAxis;
        if (brokenAxis &&
            axis.treeGrid.mapOfPosToGridNode) {
            var pos = tick.pos,
                node = axis.treeGrid.mapOfPosToGridNode[pos],
                breaks = axis.treeGrid.collapse(node);
            brokenAxis.setBreaks(breaks, TreeGridTick_pick(redraw, true));
        }
    };
    /**
     * Destroy remaining labelIcon if exist.
     *
     * @private
     * @function Highcharts.Tick#destroy
     */
    TreeGridTickAdditions.prototype.destroy = function () {
        if (this.labelIcon) {
            this.labelIcon.destroy();
        }
    };
    /**
     * Expand the grid cell. Used when axis is of type treegrid.
     *
     * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
     *
     * @private
     * @function Highcharts.Tick#expand
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart or wait for an explicit call to
     * {@link Highcharts.Chart#redraw}
     */
    TreeGridTickAdditions.prototype.expand = function (redraw) {
        var _a = this.tick,
            pos = _a.pos,
            axis = _a.axis,
            treeGrid = axis.treeGrid,
            brokenAxis = axis.brokenAxis,
            posMappedNodes = treeGrid.mapOfPosToGridNode;
        if (brokenAxis && posMappedNodes) {
            var node = posMappedNodes[pos],
                breaks = treeGrid.expand(node);
            brokenAxis.setBreaks(breaks, TreeGridTick_pick(redraw, true));
        }
    };
    /**
     * Toggle the collapse/expand state of the grid cell. Used when axis is
     * of type treegrid.
     *
     * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
     *
     * @private
     * @function Highcharts.Tick#toggleCollapse
     *
     * @param {boolean} [redraw=true]
     * Whether to redraw the chart or wait for an explicit call to
     * {@link Highcharts.Chart#redraw}
     */
    TreeGridTickAdditions.prototype.toggleCollapse = function (redraw) {
        var tick = this.tick,
            axis = tick.axis,
            brokenAxis = axis.brokenAxis;
        if (brokenAxis &&
            axis.treeGrid.mapOfPosToGridNode) {
            var pos = tick.pos,
                node = axis.treeGrid.mapOfPosToGridNode[pos],
                breaks = axis.treeGrid.toggleCollapse(node);
            brokenAxis.setBreaks(breaks, TreeGridTick_pick(redraw, true));
        }
    };
    return TreeGridTickAdditions;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var TreeGridTick = (TreeGridTickAdditions);

;// ./code/es5/es-modules/Series/TreeUtilities.js
/* *
 *
 *  (c) 2014-2024 Highsoft AS
 *
 *  Authors: Jon Arild Nygard / Oystein Moseng
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */



var TreeUtilities_extend = Core_Utilities.extend, TreeUtilities_isArray = Core_Utilities.isArray, TreeUtilities_isNumber = Core_Utilities.isNumber, TreeUtilities_isObject = Core_Utilities.isObject, TreeUtilities_merge = Core_Utilities.merge, TreeUtilities_pick = Core_Utilities.pick, TreeUtilities_relativeLength = Core_Utilities.relativeLength;
/* *
 *
 *  Functions
 *
 * */
/* eslint-disable valid-jsdoc */
/**
 * @private
 */
function getColor(node, options) {
    var index = options.index,
        mapOptionsToLevel = options.mapOptionsToLevel,
        parentColor = options.parentColor,
        parentColorIndex = options.parentColorIndex,
        series = options.series,
        colors = options.colors,
        siblings = options.siblings,
        points = series.points,
        chartOptionsChart = series.chart.options.chart;
    var getColorByPoint,
        point,
        level,
        colorByPoint,
        colorIndexByPoint,
        color,
        colorIndex;
    /**
     * @private
     */
    var variateColor = function (color) {
            var colorVariation = level && level.colorVariation;
        if (colorVariation &&
            colorVariation.key === 'brightness' &&
            index &&
            siblings) {
            return Color_Color.parse(color).brighten(colorVariation.to * (index / siblings)).get();
        }
        return color;
    };
    if (node) {
        point = points[node.i];
        level = mapOptionsToLevel[node.level] || {};
        getColorByPoint = point && level.colorByPoint;
        if (getColorByPoint) {
            colorIndexByPoint = point.index % (colors ?
                colors.length :
                chartOptionsChart.colorCount);
            colorByPoint = colors && colors[colorIndexByPoint];
        }
        // Select either point color, level color or inherited color.
        if (!series.chart.styledMode) {
            color = TreeUtilities_pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variateColor(parentColor), series.color);
        }
        colorIndex = TreeUtilities_pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex);
    }
    return {
        color: color,
        colorIndex: colorIndex
    };
}
/**
 * Creates a map from level number to its given options.
 *
 * @private
 *
 * @param {Object} params
 * Object containing parameters.
 * - `defaults` Object containing default options. The default options are
 *   merged with the userOptions to get the final options for a specific
 *   level.
 * - `from` The lowest level number.
 * - `levels` User options from series.levels.
 * - `to` The highest level number.
 *
 * @return {Highcharts.Dictionary<object>|null}
 * Returns a map from level number to its given options.
 */
function getLevelOptions(params) {
    var result = {};
    var defaults,
        converted,
        i,
        from,
        to,
        levels;
    if (TreeUtilities_isObject(params)) {
        from = TreeUtilities_isNumber(params.from) ? params.from : 1;
        levels = params.levels;
        converted = {};
        defaults = TreeUtilities_isObject(params.defaults) ? params.defaults : {};
        if (TreeUtilities_isArray(levels)) {
            converted = levels.reduce(function (obj, item) {
                var level,
                    levelIsConstant,
                    options;
                if (TreeUtilities_isObject(item) && TreeUtilities_isNumber(item.level)) {
                    options = TreeUtilities_merge({}, item);
                    levelIsConstant = TreeUtilities_pick(options.levelIsConstant, defaults.levelIsConstant);
                    // Delete redundant properties.
                    delete options.levelIsConstant;
                    delete options.level;
                    // Calculate which level these options apply to.
                    level = item.level + (levelIsConstant ? 0 : from - 1);
                    if (TreeUtilities_isObject(obj[level])) {
                        TreeUtilities_merge(true, obj[level], options); // #16329
                    }
                    else {
                        obj[level] = options;
                    }
                }
                return obj;
            }, {});
        }
        to = TreeUtilities_isNumber(params.to) ? params.to : 1;
        for (i = 0; i <= to; i++) {
            result[i] = TreeUtilities_merge({}, defaults, TreeUtilities_isObject(converted[i]) ? converted[i] : {});
        }
    }
    return result;
}
/**
 * @private
 * @todo Combine buildTree and buildNode with setTreeValues
 * @todo Remove logic from Treemap and make it utilize this mixin.
 */
function setTreeValues(tree, options) {
    var before = options.before,
        idRoot = options.idRoot,
        mapIdToNode = options.mapIdToNode,
        nodeRoot = mapIdToNode[idRoot],
        levelIsConstant = (options.levelIsConstant !== false),
        points = options.points,
        point = points[tree.i],
        optionsPoint = point && point.options || {},
        children = [];
    var childrenTotal = 0;
    tree.levelDynamic = tree.level - (levelIsConstant ? 0 : nodeRoot.level);
    tree.name = TreeUtilities_pick(point && point.name, '');
    tree.visible = (idRoot === tree.id ||
        options.visible === true);
    if (typeof before === 'function') {
        tree = before(tree, options);
    }
    // First give the children some values
    tree.children.forEach(function (child, i) {
        var newOptions = TreeUtilities_extend({},
            options);
        TreeUtilities_extend(newOptions, {
            index: i,
            siblings: tree.children.length,
            visible: tree.visible
        });
        child = setTreeValues(child, newOptions);
        children.push(child);
        if (child.visible) {
            childrenTotal += child.val;
        }
    });
    // Set the values
    var value = TreeUtilities_pick(optionsPoint.value,
        childrenTotal);
    tree.visible = value >= 0 && (childrenTotal > 0 || tree.visible);
    tree.children = children;
    tree.childrenTotal = childrenTotal;
    tree.isLeaf = tree.visible && !childrenTotal;
    tree.val = value;
    return tree;
}
/**
 * Update the rootId property on the series. Also makes sure that it is
 * accessible to exporting.
 *
 * @private
 *
 * @param {Object} series
 * The series to operate on.
 *
 * @return {string}
 * Returns the resulting rootId after update.
 */
function updateRootId(series) {
    var rootId,
        options;
    if (TreeUtilities_isObject(series)) {
        // Get the series options.
        options = TreeUtilities_isObject(series.options) ? series.options : {};
        // Calculate the rootId.
        rootId = TreeUtilities_pick(series.rootNode, options.rootId, '');
        // Set rootId on series.userOptions to pick it up in exporting.
        if (TreeUtilities_isObject(series.userOptions)) {
            series.userOptions.rootId = rootId;
        }
        // Set rootId on series to pick it up on next update.
        series.rootNode = rootId;
    }
    return rootId;
}
/**
 * Get the node width, which relies on the plot width and the nodeDistance
 * option.
 *
 * @private
 */
function getNodeWidth(series, columnCount) {
    var chart = series.chart,
        options = series.options,
        _a = options.nodeDistance,
        nodeDistance = _a === void 0 ? 0 : _a,
        _b = options.nodeWidth,
        nodeWidth = _b === void 0 ? 0 : _b,
        _c = chart.plotSizeX,
        plotSizeX = _c === void 0 ? 1 : _c;
    // Node width auto means they are evenly distributed along the width of
    // the plot area
    if (nodeWidth === 'auto') {
        if (typeof nodeDistance === 'string' && /%$/.test(nodeDistance)) {
            var fraction = parseFloat(nodeDistance) / 100,
                total = columnCount + fraction * (columnCount - 1);
            return plotSizeX / total;
        }
        var nDistance = Number(nodeDistance);
        return ((plotSizeX + nDistance) /
            (columnCount || 1)) - nDistance;
    }
    return TreeUtilities_relativeLength(nodeWidth, plotSizeX);
}
/* *
 *
 *  Default Export
 *
 * */
var TreeUtilities = {
    getColor: getColor,
    getLevelOptions: getLevelOptions,
    getNodeWidth: getNodeWidth,
    setTreeValues: setTreeValues,
    updateRootId: updateRootId
};
/* harmony default export */ var Series_TreeUtilities = (TreeUtilities);

;// ./code/es5/es-modules/Core/Axis/TreeGrid/TreeGridAxis.js
/* *
 *
 *  (c) 2016 Highsoft AS
 *  Authors: Jon Arild Nygard
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */






var TreeGridAxis_getLevelOptions = Series_TreeUtilities.getLevelOptions;

var TreeGridAxis_addEvent = Core_Utilities.addEvent, TreeGridAxis_isArray = Core_Utilities.isArray, TreeGridAxis_splat = Core_Utilities.splat, TreeGridAxis_find = Core_Utilities.find, TreeGridAxis_fireEvent = Core_Utilities.fireEvent, TreeGridAxis_isObject = Core_Utilities.isObject, TreeGridAxis_isString = Core_Utilities.isString, TreeGridAxis_merge = Core_Utilities.merge, TreeGridAxis_pick = Core_Utilities.pick, TreeGridAxis_removeEvent = Core_Utilities.removeEvent, TreeGridAxis_wrap = Core_Utilities.wrap;
/* *
 *
 *  Variables
 *
 * */
var TickConstructor;
/* *
 *
 *  Functions
 *
 * */
/**
 * @private
 */
function getBreakFromNode(node, max) {
    var to = node.collapseEnd || 0;
    var from = node.collapseStart || 0;
    // In broken-axis, the axis.max is minimized until it is not within a
    // break. Therefore, if break.to is larger than axis.max, the axis.to
    // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break
    // larger than axis.max.
    // TODO consider simplifying broken-axis and this might solve itself
    if (to >= max) {
        from -= 0.5;
    }
    return {
        from: from,
        to: to,
        showPoints: false
    };
}
/**
 * Creates a tree structure of the data, and the treegrid. Calculates
 * categories, and y-values of points based on the tree.
 *
 * @private
 * @function getTreeGridFromData
 *
 * @param {Array<Highcharts.GanttPointOptions>} data
 * All the data points to display in the axis.
 *
 * @param {boolean} uniqueNames
 * Whether or not the data node with the same name should share grid cell. If
 * true they do share cell. False by default.
 *
 * @param {number} numberOfSeries
 *
 * @return {Object}
 * Returns an object containing categories, mapOfIdToNode,
 * mapOfPosToGridNode, and tree.
 *
 * @todo There should be only one point per line.
 * @todo It should be optional to have one category per point, or merge
 *       cells
 * @todo Add unit-tests.
 */
function getTreeGridFromData(data, uniqueNames, numberOfSeries) {
    var categories = [],
        collapsedNodes = [],
        mapOfIdToNode = {},
        uniqueNamesEnabled = uniqueNames || false;
    var mapOfPosToGridNode = {},
        posIterator = -1;
    // Build the tree from the series data.
    var treeParams = {
            // After the children has been created.
            after: function (node) {
                var gridNode = mapOfPosToGridNode[node.pos];
            var height = 0,
                descendants = 0;
            gridNode.children.forEach(function (child) {
                descendants += (child.descendants || 0) + 1;
                height = Math.max((child.height || 0) + 1, height);
            });
            gridNode.descendants = descendants;
            gridNode.height = height;
            if (gridNode.collapsed) {
                collapsedNodes.push(gridNode);
            }
        },
        // Before the children has been created.
        before: function (node) {
            var data = TreeGridAxis_isObject(node.data,
                true) ?
                    node.data :
                    {},
                name = TreeGridAxis_isString(data.name) ? data.name : '',
                parentNode = mapOfIdToNode[node.parent],
                parentGridNode = (TreeGridAxis_isObject(parentNode,
                true) ?
                    mapOfPosToGridNode[parentNode.pos] :
                    null),
                hasSameName = function (x) {
                    return x.name === name;
            };
            var gridNode,
                pos;
            // If not unique names, look for sibling node with the same name
            if (uniqueNamesEnabled &&
                TreeGridAxis_isObject(parentGridNode, true) &&
                !!(gridNode = TreeGridAxis_find(parentGridNode.children, hasSameName))) {
                // If there is a gridNode with the same name, reuse position
                pos = gridNode.pos;
                // Add data node to list of nodes in the grid node.
                gridNode.nodes.push(node);
            }
            else {
                // If it is a new grid node, increment position.
                pos = posIterator++;
            }
            // Add new grid node to map.
            if (!mapOfPosToGridNode[pos]) {
                mapOfPosToGridNode[pos] = gridNode = {
                    depth: parentGridNode ? parentGridNode.depth + 1 : 0,
                    name: name,
                    id: data.id,
                    nodes: [node],
                    children: [],
                    pos: pos
                };
                // If not root, then add name to categories.
                if (pos !== -1) {
                    categories.push(name);
                }
                // Add name to list of children.
                if (TreeGridAxis_isObject(parentGridNode, true)) {
                    parentGridNode.children.push(gridNode);
                }
            }
            // Add data node to map
            if (TreeGridAxis_isString(node.id)) {
                mapOfIdToNode[node.id] = node;
            }
            // If one of the points are collapsed, then start the grid node
            // in collapsed state.
            if (gridNode &&
                data.collapsed === true) {
                gridNode.collapsed = true;
            }
            // Assign pos to data node
            node.pos = pos;
        }
    };
    var updateYValuesAndTickPos = function (map,
        numberOfSeries) {
            var setValues = function (gridNode,
        start,
        result) {
                var nodes = gridNode.nodes,
        padding = 0.5;
            var end = start + (start === -1 ? 0 : numberOfSeries - 1);
            var diff = (end - start) / 2,
                pos = start + diff;
            nodes.forEach(function (node) {
                var data = node.data;
                if (TreeGridAxis_isObject(data, true)) {
                    // Update point
                    data.y = start + (data.seriesIndex || 0);
                    // Remove the property once used
                    delete data.seriesIndex;
                }
                node.pos = pos;
            });
            result[pos] = gridNode;
            gridNode.pos = pos;
            gridNode.tickmarkOffset = diff + padding;
            gridNode.collapseStart = end + padding;
            gridNode.children.forEach(function (child) {
                setValues(child, end + 1, result);
                end = (child.collapseEnd || 0) - padding;
            });
            // Set collapseEnd to the end of the last child node.
            gridNode.collapseEnd = end + padding;
            return result;
        };
        return setValues(map['-1'], -1, {});
    };
    // Create tree from data
    var tree = Gantt_Tree.getTree(data,
        treeParams);
    // Update y values of data, and set calculate tick positions.
    mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries);
    // Return the resulting data.
    return {
        categories: categories,
        mapOfIdToNode: mapOfIdToNode,
        mapOfPosToGridNode: mapOfPosToGridNode,
        collapsedNodes: collapsedNodes,
        tree: tree
    };
}
/**
 * Builds the tree of categories and calculates its positions.
 * @private
 * @param {Object} e Event object
 * @param {Object} e.target The chart instance which the event was fired on.
 * @param {object[]} e.target.axes The axes of the chart.
 */
function onBeforeRender(e) {
    var chart = e.target,
        axes = chart.axes;
    axes.filter(function (axis) { return axis.type === 'treegrid'; }).forEach(function (axis) {
        var options = axis.options || {},
            labelOptions = options.labels,
            uniqueNames = axis.uniqueNames,
            max = chart.time.parse(options.max), 
            // Check whether any of series is rendering for the first
            // time, visibility has changed, or its data is dirty, and
            // only then update. #10570, #10580. Also check if
            // mapOfPosToGridNode exists. #10887
            isDirty = (!axis.treeGrid.mapOfPosToGridNode ||
                axis.series.some(function (series) {
                    return !series.hasRendered ||
                        series.isDirtyData ||
                        series.isDirty;
            }));
        var numberOfSeries = 0,
            data,
            treeGrid;
        if (isDirty) {
            var seriesHasPrimitivePoints_1 = [];
            // Concatenate data from all series assigned to this axis.
            data = axis.series.reduce(function (arr, s) {
                var seriesData = (s.options.data || []),
                    firstPoint = seriesData[0], 
                    // Check if the first point is a simple array of values.
                    // If so we assume that this is the case for all points.
                    foundPrimitivePoint = (Array.isArray(firstPoint) &&
                        !firstPoint.find(function (value) { return (typeof value === 'object'); }));
                seriesHasPrimitivePoints_1.push(foundPrimitivePoint);
                if (s.visible) {
                    // Push all data to array
                    seriesData.forEach(function (pointOptions) {
                        // For using keys, or when using primitive points,
                        // rebuild the data structure
                        if (foundPrimitivePoint ||
                            (s.options.keys && s.options.keys.length)) {
                            pointOptions = s.pointClass.prototype
                                .optionsToObject
                                .call({ series: s }, pointOptions);
                            s.pointClass.setGanttPointAliases(pointOptions, chart);
                        }
                        if (TreeGridAxis_isObject(pointOptions, true)) {
                            // Set series index on data. Removed again
                            // after use.
                            pointOptions.seriesIndex = (numberOfSeries);
                            arr.push(pointOptions);
                        }
                    });
                    // Increment series index
                    if (uniqueNames === true) {
                        numberOfSeries++;
                    }
                }
                return arr;
            }, []);
            // If max is higher than set data - add a
            // dummy data to render categories #10779
            if (max && data.length < max) {
                for (var i = data.length; i <= max; i++) {
                    data.push({
                        // Use the zero-width character
                        // to avoid conflict with uniqueNames
                        name: i + '\u200B'
                    });
                }
            }
            // `setScale` is fired after all the series is initialized,
            // which is an ideal time to update the axis.categories.
            treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1);
            // Assign values to the axis.
            axis.categories = treeGrid.categories;
            axis.treeGrid.mapOfPosToGridNode = (treeGrid.mapOfPosToGridNode);
            axis.hasNames = true;
            axis.treeGrid.tree = treeGrid.tree;
            // Update yData now that we have calculated the y values
            axis.series.forEach(function (series, index) {
                var axisData = (series.options.data || []).map(function (d) {
                        if (seriesHasPrimitivePoints_1[index] ||
                            (TreeGridAxis_isArray(d) &&
                                series.options.keys &&
                                series.options.keys.length)) {
                            // Get the axisData from the data array used to
                            // build the treeGrid where has been modified
                            data.forEach(function (point) {
                                var toArray = TreeGridAxis_splat(d);
                            if (toArray.indexOf(point.x || 0) >= 0 &&
                                toArray.indexOf(point.x2 || 0) >= 0) {
                                d = point;
                            }
                        });
                    }
                    return TreeGridAxis_isObject(d, true) ? TreeGridAxis_merge(d) : d;
                });
                // Avoid destroying points when series is not visible
                if (series.visible) {
                    series.setData(axisData, false);
                }
            });
            // Calculate the label options for each level in the tree.
            axis.treeGrid.mapOptionsToLevel =
                TreeGridAxis_getLevelOptions({
                    defaults: labelOptions,
                    from: 1,
                    levels: labelOptions && labelOptions.levels,
                    to: axis.treeGrid.tree && axis.treeGrid.tree.height
                });
            // Setting initial collapsed nodes
            if (e.type === 'beforeRender') {
                axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes;
            }
        }
    });
}
/**
 * Generates a tick for initial positioning.
 *
 * @private
 * @function Highcharts.GridAxis#generateTick
 *
 * @param {Function} proceed
 * The original generateTick function.
 *
 * @param {number} pos
 * The tick position in axis values.
 */
function wrapGenerateTick(proceed, pos) {
    var axis = this,
        mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {},
        isTreeGrid = axis.type === 'treegrid',
        ticks = axis.ticks;
    var tick = ticks[pos],
        levelOptions,
        options,
        gridNode;
    if (isTreeGrid &&
        axis.treeGrid.mapOfPosToGridNode) {
        gridNode = axis.treeGrid.mapOfPosToGridNode[pos];
        levelOptions = mapOptionsToLevel[gridNode.depth];
        if (levelOptions) {
            options = {
                labels: levelOptions
            };
        }
        if (!tick &&
            TickConstructor) {
            ticks[pos] = tick =
                new TickConstructor(axis, pos, void 0, void 0, {
                    category: gridNode.name,
                    tickmarkOffset: gridNode.tickmarkOffset,
                    options: options
                });
        }
        else {
            // Update labels depending on tick interval
            tick.parameters.category = gridNode.name;
            tick.options = options;
            tick.addLabel();
        }
    }
    else {
        proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
    }
}
/**
 * @private
 */
function wrapInit(proceed, chart, userOptions, coll) {
    var axis = this,
        isTreeGrid = userOptions.type === 'treegrid';
    if (!axis.treeGrid) {
        axis.treeGrid = new TreeGridAxisAdditions(axis);
    }
    // Set default and forced options for TreeGrid
    if (isTreeGrid) {
        // Add event for updating the categories of a treegrid.
        // NOTE Preferably these events should be set on the axis.
        TreeGridAxis_addEvent(chart, 'beforeRender', onBeforeRender);
        TreeGridAxis_addEvent(chart, 'beforeRedraw', onBeforeRender);
        // Add new collapsed nodes on addseries
        TreeGridAxis_addEvent(chart, 'addSeries', function (e) {
            if (e.options.data) {
                var treeGrid = getTreeGridFromData(e.options.data,
                    userOptions.uniqueNames || false, 1);
                axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes);
            }
        });
        // Collapse all nodes in axis.treegrid.collapsednodes
        // where collapsed equals true.
        TreeGridAxis_addEvent(axis, 'foundExtremes', function () {
            if (axis.treeGrid.collapsedNodes) {
                axis.treeGrid.collapsedNodes.forEach(function (node) {
                    var breaks = axis.treeGrid.collapse(node);
                    if (axis.brokenAxis) {
                        axis.brokenAxis.setBreaks(breaks, false);
                        // Remove the node from the axis collapsedNodes
                        if (axis.treeGrid.collapsedNodes) {
                            axis.treeGrid.collapsedNodes = axis.treeGrid
                                .collapsedNodes
                                .filter(function (n) { return ((node.collapseStart !==
                                n.collapseStart) ||
                                node.collapseEnd !== n.collapseEnd); });
                        }
                    }
                });
            }
        });
        // If staticScale is not defined on the yAxis
        // and chart height is set, set axis.isDirty
        // to ensure collapsing works (#12012)
        TreeGridAxis_addEvent(axis, 'afterBreaks', function () {
            if (axis.coll === 'yAxis' &&
                !axis.staticScale &&
                axis.chart.options.chart.height) {
                axis.isDirty = true;
            }
        });
        userOptions = TreeGridAxis_merge({
            // Default options
            grid: {
                enabled: true
            },
            // TODO: add support for align in treegrid.
            labels: {
                align: 'left',
                /**
                * Set options on specific levels in a tree grid axis. Takes
                * precedence over labels options.
                *
                * @sample {gantt} gantt/treegrid-axis/labels-levels
                *         Levels on TreeGrid Labels
                *
                * @type      {Array<*>}
                * @product   gantt
                * @apioption yAxis.labels.levels
                *
                * @private
                */
                levels: [{
                        /**
                        * Specify the level which the options within this object
                        * applies to.
                        *
                        * @type      {number}
                        * @product   gantt
                        * @apioption yAxis.labels.levels.level
                        *
                        * @private
                        */
                        level: void 0
                    }, {
                        level: 1,
                        /**
                         * @type      {Highcharts.CSSObject}
                         * @product   gantt
                         * @apioption yAxis.labels.levels.style
                         *
                         * @private
                         */
                        style: {
                            /** @ignore-option */
                            fontWeight: 'bold'
                        }
                    }],
                /**
                 * The symbol for the collapse and expand icon in a
                 * treegrid.
                 *
                 * @product      gantt
                 * @optionparent yAxis.labels.symbol
                 *
                 * @private
                 */
                symbol: {
                    /**
                     * The symbol type. Points to a definition function in
                     * the `Highcharts.Renderer.symbols` collection.
                     *
                     * @type {Highcharts.SymbolKeyValue}
                     *
                     * @private
                     */
                    type: 'triangle',
                    x: -5,
                    y: -5,
                    height: 10,
                    width: 10
                }
            },
            uniqueNames: false
        }, userOptions, {
            // Forced options
            reversed: true
        });
    }
    // Now apply the original function with the original arguments, which are
    // sliced off this function's arguments
    proceed.apply(axis, [chart, userOptions, coll]);
    if (isTreeGrid) {
        axis.hasNames = true;
        axis.options.showLastLabel = true;
    }
}
/**
 * Set the tick positions, tickInterval, axis min and max.
 *
 * @private
 * @function Highcharts.GridAxis#setTickInterval
 *
 * @param {Function} proceed
 * The original setTickInterval function.
 */
function wrapSetTickInterval(proceed) {
    var _a,
        _b,
        _c,
        _d,
        _e;
    var axis = this,
        options = axis.options,
        time = axis.chart.time,
        linkedParent = typeof options.linkedTo === 'number' ?
            (_a = this.chart[axis.coll]) === null || _a === void 0 ? void 0 : _a[options.linkedTo] :
            void 0,
        isTreeGrid = axis.type === 'treegrid';
    if (isTreeGrid) {
        axis.min = (_c = (_b = axis.userMin) !== null && _b !== void 0 ? _b : time.parse(options.min)) !== null && _c !== void 0 ? _c : axis.dataMin;
        axis.max = (_e = (_d = axis.userMax) !== null && _d !== void 0 ? _d : time.parse(options.max)) !== null && _e !== void 0 ? _e : axis.dataMax;
        TreeGridAxis_fireEvent(axis, 'foundExtremes');
        // `setAxisTranslation` modifies the min and max according to axis
        // breaks.
        axis.setAxisTranslation();
        axis.tickInterval = 1;
        axis.tickmarkOffset = 0.5;
        axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ?
            axis.treeGrid.getTickPositions() :
            [];
        if (linkedParent) {
            var linkedParentExtremes = linkedParent.getExtremes();
            axis.min = TreeGridAxis_pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);
            axis.max = TreeGridAxis_pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);
            axis.tickPositions = linkedParent.tickPositions;
        }
        axis.linkedParent = linkedParent;
    }
    else {
        proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
    }
}
/**
 * Wrap axis redraw to remove TreeGrid events from ticks
 *
 * @private
 * @function Highcharts.GridAxis#redraw
 *
 * @param {Function} proceed
 * The original setTickInterval function.
 */
function wrapRedraw(proceed) {
    var axis = this,
        isTreeGrid = this.type === 'treegrid';
    if (isTreeGrid && axis.visible) {
        axis.tickPositions.forEach(function (pos) {
            var tick = axis.ticks[pos];
            if (tick.label && tick.label.attachedTreeGridEvents) {
                TreeGridAxis_removeEvent(tick.label.element);
                tick.label.attachedTreeGridEvents = false;
            }
        });
    }
    proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
}
/* *
 *
 *  Classes
 *
 * */
/**
 * @private
 * @class
 */
var TreeGridAxisAdditions = /** @class */ (function () {
    /* *
     *
     *  Constructors
     *
     * */
    /**
     * @private
     */
    function TreeGridAxisAdditions(axis) {
        this.axis = axis;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    /**
     * @private
     */
    TreeGridAxisAdditions.compose = function (AxisClass, ChartClass, SeriesClass, TickClass) {
        if (!AxisClass.keepProps.includes('treeGrid')) {
            var axisProps = AxisClass.prototype;
            AxisClass.keepProps.push('treeGrid');
            TreeGridAxis_wrap(axisProps, 'generateTick', wrapGenerateTick);
            TreeGridAxis_wrap(axisProps, 'init', wrapInit);
            TreeGridAxis_wrap(axisProps, 'setTickInterval', wrapSetTickInterval);
            TreeGridAxis_wrap(axisProps, 'redraw', wrapRedraw);
            // Make utility functions available for testing.
            axisProps.utils = {
                getNode: Gantt_Tree.getNode
            };
            if (!TickConstructor) {
                TickConstructor = TickClass;
            }
        }
        Axis_GridAxis.compose(AxisClass, ChartClass, TickClass);
        Axis_BrokenAxis.compose(AxisClass, SeriesClass);
        TreeGridTick.compose(TickClass);
        return AxisClass;
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Set the collapse status.
     *
     * @private
     *
     * @param {Highcharts.Axis} axis
     * The axis to check against.
     *
     * @param {Highcharts.GridNode} node
     * The node to collapse.
     */
    TreeGridAxisAdditions.prototype.setCollapsedStatus = function (node) {
        var axis = this.axis,
            chart = axis.chart;
        axis.series.forEach(function (series) {
            var data = series.options.data;
            if (node.id && data) {
                var point = chart.get(node.id),
                    dataPoint = data[series.data.indexOf(point)];
                if (point && dataPoint) {
                    point.collapsed = node.collapsed;
                    dataPoint.collapsed = node.collapsed;
                }
            }
        });
    };
    /**
     * Calculates the new axis breaks to collapse a node.
     *
     * @private
     *
     * @param {Highcharts.Axis} axis
     * The axis to check against.
     *
     * @param {Highcharts.GridNode} node
     * The node to collapse.
     *
     * @param {number} pos
     * The tick position to collapse.
     *
     * @return {Array<object>}
     * Returns an array of the new breaks for the axis.
     */
    TreeGridAxisAdditions.prototype.collapse = function (node) {
        var axis = this.axis,
            breaks = (axis.options.breaks || []),
            obj = getBreakFromNode(node,
            axis.max);
        breaks.push(obj);
        // Change the collapsed flag #13838
        node.collapsed = true;
        axis.treeGrid.setCollapsedStatus(node);
        return breaks;
    };
    /**
     * Calculates the new axis breaks to expand a node.
     *
     * @private
     *
     * @param {Highcharts.Axis} axis
     * The axis to check against.
     *
     * @param {Highcharts.GridNode} node
     * The node to expand.
     *
     * @param {number} pos
     * The tick position to expand.
     *
     * @return {Array<object>}
     * Returns an array of the new breaks for the axis.
     */
    TreeGridAxisAdditions.prototype.expand = function (node) {
        var axis = this.axis,
            breaks = (axis.options.breaks || []),
            obj = getBreakFromNode(node,
            axis.max);
        // Change the collapsed flag #13838
        node.collapsed = false;
        axis.treeGrid.setCollapsedStatus(node);
        // Remove the break from the axis breaks array.
        return breaks.reduce(function (arr, b) {
            if (b.to !== obj.to || b.from !== obj.from) {
                arr.push(b);
            }
            return arr;
        }, []);
    };
    /**
     * Creates a list of positions for the ticks on the axis. Filters out
     * positions that are outside min and max, or is inside an axis break.
     *
     * @private
     *
     * @return {Array<number>}
     * List of positions.
     */
    TreeGridAxisAdditions.prototype.getTickPositions = function () {
        var axis = this.axis, roundedMin = Math.floor(axis.min / axis.tickInterval) * axis.tickInterval, roundedMax = Math.ceil(axis.max / axis.tickInterval) * axis.tickInterval;
        return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) {
            var pos = +key;
            if (pos >= roundedMin &&
                pos <= roundedMax &&
                !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) {
                arr.push(pos);
            }
            return arr;
        }, []);
    };
    /**
     * Check if a node is collapsed.
     *
     * @private
     *
     * @param {Highcharts.Axis} axis
     * The axis to check against.
     *
     * @param {Object} node
     * The node to check if is collapsed.
     *
     * @param {number} pos
     * The tick position to collapse.
     *
     * @return {boolean}
     * Returns true if collapsed, false if expanded.
     */
    TreeGridAxisAdditions.prototype.isCollapsed = function (node) {
        var axis = this.axis,
            breaks = (axis.options.breaks || []),
            obj = getBreakFromNode(node,
            axis.max);
        return breaks.some(function (b) {
            return b.from === obj.from && b.to === obj.to;
        });
    };
    /**
     * Calculates the new axis breaks after toggling the collapse/expand
     * state of a node. If it is collapsed it will be expanded, and if it is
     * expanded it will be collapsed.
     *
     * @private
     *
     * @param {Highcharts.Axis} axis
     * The axis to check against.
     *
     * @param {Highcharts.GridNode} node
     * The node to toggle.
     *
     * @return {Array<object>}
     * Returns an array of the new breaks for the axis.
     */
    TreeGridAxisAdditions.prototype.toggleCollapse = function (node) {
        return (this.isCollapsed(node) ?
            this.expand(node) :
            this.collapse(node));
    };
    return TreeGridAxisAdditions;
}());
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var TreeGridAxis = (TreeGridAxisAdditions);

;// ./code/es5/es-modules/Series/Gantt/GanttSeries.js
/* *
 *
 *  (c) 2016-2024 Highsoft AS
 *
 *  Author: Lars A. V. Cabrera
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */

var GanttSeries_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 (Object.prototype.hasOwnProperty.call(b,
        p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();




var GanttSeries_Series = Series_SeriesRegistry.series, GanttSeries_XRangeSeries = Series_SeriesRegistry.seriesTypes.xrange;



var GanttSeries_extend = Core_Utilities.extend, GanttSeries_isNumber = Core_Utilities.isNumber, GanttSeries_merge = Core_Utilities.merge;
/* *
 *
 *  Class
 *
 * */
/**
 * @private
 * @class
 * @name Highcharts.seriesTypes.gantt
 *
 * @augments Highcharts.Series
 */
var GanttSeries = /** @class */ (function (_super) {
    GanttSeries_extends(GanttSeries, _super);
    function GanttSeries() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    /* *
     *
     *  Static Functions
     *
     * */
    GanttSeries.compose = function (AxisClass, ChartClass, SeriesClass, TickClass) {
        GanttSeries_XRangeSeries.compose(AxisClass);
        if (!ChartClass) {
            return;
        }
        Extensions_StaticScale.compose(AxisClass, ChartClass);
        if (!SeriesClass) {
            return;
        }
        Gantt_Pathfinder.compose(ChartClass, SeriesClass.prototype.pointClass);
        if (!TickClass) {
            return;
        }
        TreeGridAxis.compose(AxisClass, ChartClass, SeriesClass, TickClass);
    };
    /* *
     *
     *  Functions
     *
     * */
    /**
     * Draws a single point in the series.
     *
     * This override draws the point as a diamond if point.options.milestone
     * is true, and uses the original drawPoint() if it is false or not set.
     *
     * @requires highcharts-gantt
     *
     * @private
     * @function Highcharts.seriesTypes.gantt#drawPoint
     *
     * @param {Highcharts.Point} point
     *        An instance of Point in the series
     *
     * @param {"animate"|"attr"} verb
     *        'animate' (animates changes) or 'attr' (sets options)
     */
    GanttSeries.prototype.drawPoint = function (point, verb) {
        var series = this,
            seriesOpts = series.options,
            renderer = series.chart.renderer,
            shapeArgs = point.shapeArgs,
            plotY = point.plotY,
            state = point.selected && 'select',
            cutOff = seriesOpts.stacking && !seriesOpts.borderRadius;
        var graphic = point.graphic,
            diamondShape;
        if (point.options.milestone) {
            if (GanttSeries_isNumber(plotY) &&
                point.y !== null &&
                point.visible !== false) {
                diamondShape = renderer.symbols.diamond(shapeArgs.x || 0, shapeArgs.y || 0, shapeArgs.width || 0, shapeArgs.height || 0);
                if (graphic) {
                    graphic[verb]({
                        d: diamondShape
                    });
                }
                else {
                    point.graphic = graphic = renderer.path(diamondShape)
                        .addClass(point.getClassName(), true)
                        .add(point.group || series.group);
                }
                // Presentational
                if (!series.chart.styledMode) {
                    point.graphic
                        .attr(series.pointAttribs(point, state))
                        .shadow(seriesOpts.shadow, null, cutOff);
                }
            }
            else if (graphic) {
                point.graphic = graphic.destroy(); // #1269
            }
        }
        else {
            _super.prototype.drawPoint.call(this, point, verb);
        }
    };
    /**
     * Handle milestones, as they have no x2.
     * @private
     */
    GanttSeries.prototype.translatePoint = function (point) {
        var shapeArgs,
            size;
        _super.prototype.translatePoint.call(this, point);
        if (point.options.milestone) {
            shapeArgs = point.shapeArgs;
            size = shapeArgs.height || 0;
            point.shapeArgs = {
                x: (shapeArgs.x || 0) - (size / 2),
                y: shapeArgs.y,
                width: size,
                height: size
            };
        }
    };
    /* *
     *
     *  Static Properties
     *
     * */
    GanttSeries.defaultOptions = GanttSeries_merge(GanttSeries_XRangeSeries.defaultOptions, Gantt_GanttSeriesDefaults);
    return GanttSeries;
}(GanttSeries_XRangeSeries));
GanttSeries_extend(GanttSeries.prototype, {
    pointArrayMap: ['start', 'end', 'y'],
    pointClass: Gantt_GanttPoint,
    setData: GanttSeries_Series.prototype.setData
});
Series_SeriesRegistry.registerSeriesType('gantt', GanttSeries);
/* *
 *
 *  Default Export
 *
 * */
/* harmony default export */ var Gantt_GanttSeries = (GanttSeries);

;// ./code/es5/es-modules/masters/modules/gantt.src.js
/**
 * @license Highcharts Gantt JS v12.1.2 (2025-01-09)
 * @module highcharts/modules/gantt
 * @requires highcharts
 *
 * Gantt series
 *
 * (c) 2016-2024 Lars A. V. Cabrera
 *
 * License: www.highcharts.com/license
 */











// Series


var gantt_src_G = Core_Globals;
// Classes
gantt_src_G.Connection = gantt_src_G.Connection || Gantt_Connection;
gantt_src_G.GanttChart = gantt_src_G.GanttChart || Chart_GanttChart;
gantt_src_G.Navigator = gantt_src_G.Navigator || Navigator_Navigator;
gantt_src_G.RangeSelector = gantt_src_G.RangeSelector || RangeSelector_RangeSelector;
gantt_src_G.Scrollbar = gantt_src_G.Scrollbar || Scrollbar_Scrollbar;
// Functions
gantt_src_G.ganttChart = gantt_src_G.GanttChart.ganttChart;
// Compositions
Extensions_ArrowSymbols.compose(gantt_src_G.SVGRenderer);
Extensions_CurrentDateIndication.compose(gantt_src_G.Axis, gantt_src_G.PlotLineOrBand);
Gantt_GanttSeries.compose(gantt_src_G.Axis, gantt_src_G.Chart, gantt_src_G.Series, gantt_src_G.Tick);
gantt_src_G.Navigator.compose(gantt_src_G.Chart, gantt_src_G.Axis, gantt_src_G.Series);
gantt_src_G.RangeSelector.compose(gantt_src_G.Axis, gantt_src_G.Chart);
gantt_src_G.Scrollbar.compose(gantt_src_G.Axis);
/* harmony default export */ var gantt_src = ((/* unused pure expression or super */ null && (Highcharts)));

;// ./code/es5/es-modules/masters/highcharts-gantt.src.js
/**
 * @license Highcharts Gantt JS v12.1.2 (2025-01-09)
 * @module highcharts/highcharts-gantt
 *
 * (c) 2017-2024 Lars Cabrera, Torstein Honsi, Jon Arild Nygard & Oystein Moseng
 *
 * License: www.highcharts.com/license
 */



highcharts_src.product = 'Highcharts Gantt';
/* harmony default export */ var highcharts_gantt_src = (highcharts_src);

__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});

Hacked By AnonymousFox1.0, Coded By AnonymousFox