UNPKG

@highcharts/dashboards

Version:
22,110 lines 882 kB
/**
 * @license Highcharts Dashboards v3.5.0 (2025-07-14)
 *
 * (c) 2009-2025 Highsoft AS
 *
 * License: www.highcharts.com/license
 */
(function (root, factory) {
    if (typeof module === 'object' && module.exports) {
        factory['default'] = factory;
        module.exports = (root && root.document) ?
            factory(root) :
            factory;
    } else if (typeof define === 'function' && define.amd) {
        define('datagrid/datagrid', function () {
            return factory(root);
        });
    } else {
        if (root.DataGrid) {
            root.DataGrid.error(16, true);
        }
        root.DataGrid = factory(root);
    }
}(typeof window !== 'undefined' ? window : this, function (window) {
    'use strict';
    var _modules = {};
    function _registerModule(obj, path, args, fn) {
        if (!obj.hasOwnProperty(path)) {
            obj[path] = fn.apply(null, args);

            if (window && typeof CustomEvent === 'function') {
                window.dispatchEvent(new CustomEvent(
                    'DataGridModuleLoaded',
                    { detail: { path: path, module: obj[path] } }
                ));
            }
        }
    }
    _registerModule(_modules, 'Core/Globals.js', [], function () {
        /* *
         *
         *  (c) 2010-2025 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
             *
             * */
            Globals.SVG_NS = 'http://www.w3.org/2000/svg', Globals.product = 'Highcharts', Globals.version = '3.5.0', Globals.win = (typeof window !== 'undefined' ?
                window :
                {}), // eslint-disable-line node/no-unsupported-features/es-builtins
            Globals.doc = Globals.win.document, Globals.svg = !!Globals.doc?.createElementNS?.(Globals.SVG_NS, 'svg')?.createSVGRect, Globals.pageLang = Globals.doc?.documentElement?.closest('[lang]')?.lang, Globals.userAgent = 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).
                let 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) {
                    const 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
         *
         * */
        /* *
         *
         *  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

        return Globals;
    });
    _registerModule(_modules, 'Core/Utilities.js', [_modules['Core/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { charts, doc, win } = H;
        /* *
         *
         *  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) {
            const severity = stop ? 'Highcharts error' : 'Highcharts warning';
            if (code === 32) {
                code = `${severity}: Deprecated member`;
            }
            const isCode = isNumber(code);
            let message = isCode ?
                `${severity} #${code}: www.highcharts.com/errors/${code}/` :
                code.toString();
            const 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') {
                let additionalMessages = '';
                if (isCode) {
                    message += '?';
                }
                objectEach(params, function (value, key) {
                    additionalMessages += `\n - ${key}: ${value}`;
                    if (isCode) {
                        message += encodeURI(key) + '=' + encodeURI(value);
                    }
                });
                message += additionalMessages;
            }
            fireEvent(H, 'displayError', { chart, code, message, 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, ...sources) {
            let i, args = [extendOrSource, ...sources], ret = {};
            const 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
            const 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 = 0, inverted) {
            const 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) {
            const 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) {
                const 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 (let 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) {
            const 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) {
            const c = obj?.constructor;
            return !!(isObject(obj, true) &&
                !isDOMElement(obj) &&
                (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) {
            let 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) {
            const indexOption = item.options.index, length = collection.length;
            let 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) {
            const isGetter = isString(keyOrAttribs) && !defined(value);
            let ret;
            const attrSingle = (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 */
            let 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() {
            const args = arguments;
            const length = args.length;
            for (let i = 0; i < length; i++) {
                const 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) {
            const 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) {
            const 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, ...replacements) {
            let previous, replacement;
            do {
                previous = text;
                for (replacement of replacements) {
                    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) {
            const proceed = obj[method];
            obj[method] = function () {
                const 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) {
            let i, retInterval = interval;
            // Round to a tenfold of 1, 2, 2.5 or 5
            magnitude = pick(magnitude, getMagnitude(interval));
            const 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
            const length = arr.length;
            let 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) {
            let 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) {
            let 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?.destroy) {
                    // Invoke the destroy
                    val.destroy();
                }
                // Delete the property from the object
                if (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) {
            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
         */
        const 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
         */
        const getAlignFactor = (align = '') => ({
            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) {
            const allowNegative = !onError;
            let closest, loopLength, distance, i;
            arrays.forEach((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?.();
                            // 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) {
            const pathElements = path.split('.');
            while (pathElements.length && defined(parent)) {
                const pathElement = pathElements.shift();
                // Filter on the key
                if (typeof pathElement === 'undefined' ||
                    pathElement === '__proto__') {
                    return; // Undefined
                }
                if (pathElement === 'this') {
                    let thisProp;
                    if (isObject(parent)) {
                        thisProp = parent['@this'];
                    }
                    return thisProp ?? parent;
                }
                const 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) {
            let style;
            // For width and height, return the actual inner pixel size (#4913)
            if (prop === 'width') {
                let 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) ...
                const boundingClientRectWidth = 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
            const 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.
         */
        const find = Array.prototype.find ?
            function (arr, callback) {
                return arr.find(callback);
            } :
            // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
            function (arr, callback) {
                let i;
                const 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) {
            const 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 (const 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 */
            // 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).
            const owner = typeof el === 'function' && el.prototype || el;
            if (!Object.hasOwnProperty.call(owner, 'hcEvents')) {
                owner.hcEvents = {};
            }
            const 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 (H.Point && // Without H a dependency loop occurs
                el instanceof H.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).
            const addEventListener = el.addEventListener;
            if (addEventListener) {
                addEventListener.call(el, type, fn, H.supportsPassiveEvents ? {
                    passive: options.passive === void 0 ?
                        type.indexOf('touch') !== -1 : options.passive,
                    capture: false
                } : false);
            }
            if (!events[type]) {
                events[type] = [];
            }
            const eventObject = {
                fn,
                order: typeof options.order === 'number' ? options.order : Infinity
            };
            events[type].push(eventObject);
            // Order the calls
            events[type].sort((a, b) => 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) {
                const removeEventListener = el.removeEventListener;
                if (removeEventListener) {
                    removeEventListener.call(el, type, fn, false);
                }
            }
            /**
             * @private
             */
            function removeAllEvents(eventCollection) {
                let 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);
                        }
                    }
                });
            }
            const owner = typeof el === 'function' && el.prototype || el;
            if (Object.hasOwnProperty.call(owner, 'hcEvents')) {
                const events = owner.hcEvents;
                if (type) {
                    const 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 !== H))) {
                const 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
                    });
                }
                const events = [];
                let object = el;
                let 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((a, b) => a.order - b.order);
                }
                // Call the collected event handlers
                events.forEach((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);
            }
        }
        let 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.
         */
        const uniqueKey = (function () {
            const hash = Math.random().toString(36).substring(2, 9) + '-';
            let 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 () {
                const args = [].slice.call(arguments);
                if (this[0]) { // `this[0]` is the renderTo div
                    // Create the chart
                    if (args[0]) {
                        new H[ // 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.
        const Utilities = {
            addEvent,
            arrayMax,
            arrayMin,
            attr,
            clamp,
            clearTimeout: internalClearTimeout,
            correctFloat,
            createElement,
            crisp,
            css,
            defined,
            destroyObjectProperties,
            diffObjects,
            discardElement,
            erase,
            error,
            extend,
            extendClass,
            find,
            fireEvent,
            getAlignFactor,
            getClosestDistance,
            getMagnitude,
            getNestedProperty,
            getStyle,
            insertItem,
            isArray,
            isClass,
            isDOMElement,
            isFunction,
            isNumber,
            isObject,
            isString,
            merge,
            normalizeTickInterval,
            objectEach,
            offset,
            pad,
            pick,
            pInt,
            pushUnique,
            relativeLength,
            removeEvent,
            replaceNested,
            splat,
            stableSort,
            syncTimeout,
            timeUnits,
            ucfirst,
            uniqueKey,
            useSerialIds,
            wrap
        };
        /* *
         *
         *  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

        return Utilities;
    });
    _registerModule(_modules, 'Core/Renderer/HTML/AST.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { SVG_NS, win } = H;
        const { attr, createElement, css, error, isFunction, isString, objectEach, splat } = U;
        const { trustedTypes } = win;
        /* *
         *
         *  Constants
         *
         * */
        // Create the trusted type policy. This should not be exposed.
        const trustedTypesPolicy = (trustedTypes &&
            isFunction(trustedTypes.createPolicy) &&
            trustedTypes.createPolicy('highcharts', {
                createHTML: (s) => s
            }));
        const 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.
         */
        class AST {
            /* *
             *
             *  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
             */
            static filterUserAttributes(attributes) {
                objectEach(attributes, (val, key) => {
                    let valid = true;
                    if (AST.allowedAttributes.indexOf(key) === -1) {
                        valid = false;
                    }
                    if (['background', 'dynsrc', 'href', 'lowsrc', 'src']
                        .indexOf(key) !== -1) {
                        valid = isString(val) && AST.allowedReferences.some((ref) => val.indexOf(ref) === 0);
                    }
                    if (!valid) {
                        error(33, false, void 0, {
                            'Invalid attribute in config': `${key}`
                        });
                        delete attributes[key];
                    }
                    // #17753, < is not allowed in SVG attributes
                    if (isString(val) && attributes[key]) {
                        attributes[key] = val.replace(/</g, '&lt;');
                    }
                });
                return attributes;
            }
            static parseStyle(style) {
                return style
                    .split(';')
                    .reduce((styles, line) => {
                    const pair = line.split(':').map((s) => s.trim()), key = pair.shift();
                    if (key && pair.length) {
                        styles[key.replace(/-([a-z])/g, (g) => 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
             */
            static setElementHTML(el, html) {
                el.innerHTML = AST.emptyHTML; // Clear previous
                if (html) {
                    const ast = new AST(html);
                    ast.addToDOM(el);
                }
            }
            /* *
             *
             *  Constructor
             *
             * */
            // Construct an AST from HTML markup, or wrap an array of existing AST nodes
            constructor(source) {
                this.nodes = typeof source === 'string' ?
                    this.parseMarkup(source) : source;
            }
            /* *
             *
             *  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.
             */
            addToDOM(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) {
                    let ret;
                    splat(subtree).forEach(function (item) {
                        const tagName = item.tagName;
                        const textNode = item.textContent ?
                            H.doc.createTextNode(item.textContent) :
                            void 0;
                        // Whether to ignore the AST filtering totally, #15345
                        const bypassHTMLFiltering = AST.bypassHTMLFiltering;
                        let node;
                        if (tagName) {
                            if (tagName === '#text') {
                                node = textNode;
                            }
                            else if (AST.allowedTags.indexOf(tagName) !== -1 ||
                                bypassHTMLFiltering) {
                                const NS = tagName === 'svg' ?
                                    SVG_NS :
                                    (subParent.namespaceURI || SVG_NS);
                                const element = H.doc.createElementNS(NS, tagName);
                                const attributes = item.attributes || {};
                                // Apply attributes from root of AST node, legacy from
                                // from before TextBuilder
                                objectEach(item, function (val, key) {
                                    if (key !== 'tagName' &&
                                        key !== 'attributes' &&
                                        key !== 'children' &&
                                        key !== 'style' &&
                                        key !== 'textContent') {
                                        attributes[key] = val;
                                    }
                                });
                                attr(element, bypassHTMLFiltering ?
                                    attributes :
                                    AST.filterUserAttributes(attributes));
                                if (item.style) {
                                    css(element, item.style);
                                }
                                // Add text content
                                if (textNode) {
                                    element.appendChild(textNode);
                                }
                                // Recurse
                                recurse(item.children || [], element);
                                node = element;
                            }
                            else {
                                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.
             */
            parseMarkup(markup) {
                const 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');
                let 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) {
                    const body = createElement('div');
                    body.innerHTML = markup;
                    doc = { body };
                }
                const appendChildNodes = (node, addTo) => {
                    const tagName = node.nodeName.toLowerCase();
                    // Add allowed tags
                    const astNode = {
                        tagName
                    };
                    if (tagName === '#text') {
                        astNode.textContent = node.textContent || '';
                    }
                    const parsedAttributes = node.attributes;
                    // Add attributes
                    if (parsedAttributes) {
                        const attributes = {};
                        [].forEach.call(parsedAttributes, (attrib) => {
                            if (attrib.name === 'data-style') {
                                astNode.style = AST.parseStyle(attrib.value);
                            }
                            else {
                                attributes[attrib.name] = attrib.value;
                            }
                        });
                        astNode.attributes = attributes;
                    }
                    // Handle children
                    if (node.childNodes.length) {
                        const children = [];
                        [].forEach.call(node.childNodes, (childNode) => {
                            appendChildNodes(childNode, children);
                        });
                        if (children.length) {
                            astNode.children = children;
                        }
                    }
                    addTo.push(astNode);
                };
                [].forEach.call(doc.body.childNodes, (childNode) => 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',
            'disabled',
            'dx',
            'dy',
            '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',
            'result',
            'role',
            'rowspan',
            'scope',
            'slope',
            'src',
            'startOffset',
            'stdDeviation',
            'stroke-linecap',
            'stroke-width',
            'stroke',
            'style',
            'summary',
            'tabindex',
            'tableValues',
            'target',
            '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 = [
            '#text',
            'a',
            'abbr',
            'b',
            'br',
            'button',
            'caption',
            'circle',
            'clipPath',
            'code',
            'dd',
            'defs',
            'div',
            'dl',
            'dt',
            'em',
            'feComponentTransfer',
            'feComposite',
            'feDropShadow',
            'feFlood',
            'feFuncA',
            'feFuncB',
            'feFuncG',
            'feFuncR',
            'feGaussianBlur',
            'feMerge',
            'feMergeNode',
            'feMorphology',
            'feOffset',
            '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',
            'tbody',
            'td',
            'text',
            'textPath',
            'th',
            'thead',
            'title',
            'tr',
            'tspan',
            'u',
            'ul'
        ];
        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;
        /* *
         *
         *  Default Export
         *
         * */
        /* *
         *
         *  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

        return AST;
    });
    _registerModule(_modules, 'Core/Chart/ChartDefaults.js', [], function () {
        /* *
         *
         *  (c) 2010-2025 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
         */
        const 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.
                 *
                 * **Note:** For non-cartesian series, the only supported panning type
                 * is `xy`, as zooming in a single direction is not applicable due to
                 * the radial nature of the coordinate system.
                 *
                 * @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.seriesGroupShadow
             */
            /**
             * 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
             *
             * @sample     highcharts/plotoptions/sankey-node-color
             *             Zooming in sankey series
             * @sample     highcharts/series-treegraph/link-types
             *             Zooming in treegraph series
             */
            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`.
                 *
                 * **Note:** For non-cartesian series, the only supported zooming type
                 * is `xy`, as zooming in a single direction is not applicable due to
                 * the radial nature of the coordinate system.
                 *
                 * @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
         *
         * */

        return ChartDefaults;
    });
    _registerModule(_modules, 'Core/Color/Palettes.js', [], function () {
        /**
         * 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.
         * @private
         */
        const SeriesPalettes = {
            /**
             * Colors for data series and points
             */
            colors: [
                '#2caffe',
                '#544fc5',
                '#00e272',
                '#fe6a35',
                '#6b8abc',
                '#d568fb',
                '#2ee0ca',
                '#fa4b42',
                '#feb56a',
                '#91e8e1'
            ]
        };

        return SeriesPalettes;
    });
    _registerModule(_modules, 'Shared/TimeBase.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { pageLang, win } = H;
        const { defined, error, extend, isNumber, isObject, isString, merge, objectEach, pad, splat, timeUnits, ucfirst } = U;
        /* *
         *
         *  Constants
         *
         * */
        // To do: Remove this when we no longer need support for Safari < v14.1
        const hasOldSafariBug = H.isSafari &&
            win.Intl &&
            !win.Intl.DateTimeFormat.prototype.formatRange;
        const isDateTimeFormatOptions = (obj) => obj.main === void 0;
        /* *
         *
         *  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).
         */
        class TimeBase {
            /* *
             *
             *  Constructors
             *
             * */
            constructor(options, lang) {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.options = {
                    timezone: 'UTC'
                };
                this.variableTimezone = false;
                this.Date = win.Date;
                this.update(options);
                this.lang = lang;
            }
            /* *
             *
             *  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]
             *
             */
            update(options = {}) {
                this.dTLCache = {};
                this.options = options = merge(true, this.options, options);
                const { timezoneOffset, useUTC, locale } = options;
                // Allow using a different Date class
                this.Date = options.Date || win.Date || Date;
                // Assign the time zone. Handle the legacy, deprecated `useUTC` option.
                let timezone = options.timezone;
                if (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?.indexOf('Etc/GMT') !== 0;
                this.timezone = timezone;
                // Update locale.
                if (this.lang && locale) {
                    this.lang.locale = locale;
                }
                // Assign default time formats from locale strings
                ['months', 'shortMonths', 'weekdays', 'shortWeekdays'].forEach((name) => {
                    const 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((position) => 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.
             */
            toParts(timestamp) {
                const [weekday, dayOfMonth, month, year, hours, minutes, seconds] = this.dateTimeFormat({
                    weekday: 'narrow',
                    day: 'numeric',
                    month: 'numeric',
                    year: 'numeric',
                    hour: 'numeric',
                    minute: 'numeric',
                    second: 'numeric'
                }, timestamp, 'es')
                    // The ', ' splitter is for all modern browsers:
                    //      L, 6/3/2023, 14:30:00
                    // The ' ' splitter is for legacy Safari with no comma between date
                    // and time (#22445):
                    //      L, 6/3/2023 14:30:00
                    .split(/(?:, | |\/|:)/g);
                return [
                    year,
                    +month - 1,
                    dayOfMonth,
                    hours,
                    minutes,
                    seconds,
                    // Milliseconds
                    Math.floor(Number(timestamp) || 0) % 1000,
                    // Spanish weekday index
                    'DLMXJVS'.indexOf(weekday)
                ].map(Number);
            }
            /**
             * Shorthand to get a cached `Intl.DateTimeFormat` instance.
             */
            dateTimeFormat(options, timestamp, locale = this.options.locale || pageLang) {
                const cacheKey = JSON.stringify(options) + locale;
                if (isString(options)) {
                    options = this.str2dtf(options);
                }
                let dTL = this.dTLCache[cacheKey];
                if (!dTL) {
                    options.timeZone ?? (options.timeZone = this.timezone);
                    try {
                        dTL = new Intl.DateTimeFormat(locale, options);
                    }
                    catch (e) {
                        if (/Invalid time zone/i.test(e.message)) {
                            error(34);
                            options.timeZone = 'UTC';
                            dTL = new Intl.DateTimeFormat(locale, options);
                        }
                        else {
                            error(e.message, false);
                        }
                    }
                }
                this.dTLCache[cacheKey] = dTL;
                return dTL?.format(timestamp) || '';
            }
            /**
             * Take a locale-aware string format and return a full DateTimeFormat in
             * object form.
             */
            str2dtf(s, dtf = {}) {
                const 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((key) => {
                    if (s.indexOf(key) !== -1) {
                        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.
             */
            makeTime(year, month, date = 1, hours = 0, minutes, seconds, milliseconds) {
                // eslint-disable-next-line new-cap
                let d = this.Date.UTC(year, month, date, hours, minutes || 0, seconds || 0, milliseconds || 0);
                if (this.timezone !== 'UTC') {
                    const 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)) {
                        const 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
             */
            parse(s) {
                if (!isString(s)) {
                    return 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
                const hasTimezone = s.indexOf('Z') > -1 ||
                    /([+-][0-9]{2}):?[0-9]{2}$/.test(s), 
                // YYYY-MM-DD and YYYY-MM are always UTC
                isYYYYMMDD = /^[0-9]{4}-[0-9]{2}(-[0-9]{2}|)$/.test(s);
                if (!hasTimezone && !isYYYYMMDD) {
                    s += 'Z';
                }
                const ts = Date.parse(s);
                if (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.
             */
            getTimezoneOffset(timestamp) {
                if (this.timezone !== 'UTC') {
                    // eslint-disable-next-line @typescript-eslint/no-unused-vars
                    const [date, gmt, hours, colon, minutes = 0] = this.dateTimeFormat({ timeZoneName: 'shortOffset' }, timestamp, 'en')
                        .split(/(GMT|:)/)
                        .map(Number), offset = -(hours + minutes / 60) * 60 * 60000;
                    // Possible future NaNs stop here
                    if (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   |
             * | `%v` | The prefix "week from", read from `lang.weekFrom` | 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.
             */
            dateFormat(format, timestamp, upperCaseFirst) {
                const lang = this.lang;
                if (!defined(timestamp) || isNaN(timestamp)) {
                    return lang?.invalidDate || '';
                }
                format = format ?? '%Y-%m-%d %H:%M:%S';
                // First, identify and replace locale-aware formats like %[Ymd]
                if (isString(format)) {
                    const localeAwareRegex = /%\[([a-zA-Z]+)\]/g;
                    let match;
                    while ((match = localeAwareRegex.exec(format))) {
                        format = format.replace(match[0], this.dateTimeFormat(match[1], timestamp, lang?.locale));
                    }
                }
                // Then, replace static formats like %Y, %m, %d etc.
                if (isString(format) && format.indexOf('%') !== -1) {
                    const time = this, [fullYear, month, dayOfMonth, hours, minutes, seconds, milliseconds, weekday] = this.toParts(timestamp), langWeekdays = lang?.weekdays || this.weekdays, shortWeekdays = lang?.shortWeekdays || this.shortWeekdays, months = lang?.months || this.months, shortMonths = lang?.shortMonths || this.shortMonths, 
                    // List all format keys. Custom formats can be added from the
                    // outside.
                    replacements = 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: pad(dayOfMonth),
                        // Day of the month, 1 through 31
                        e: pad(dayOfMonth, 2, ' '),
                        // Day of the week, 0 through 6
                        w: weekday,
                        // Week (none implemented)
                        // 'W': weekNumber(),
                        v: lang?.weekFrom ?? '',
                        // Month
                        // Short month, like 'Jan'
                        b: shortMonths[month],
                        // Long month, like 'January'
                        B: months[month],
                        // Two digit month number, 01 through 12
                        m: 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: pad(hours),
                        // Hours in 24h format, 0 through 23
                        k: hours,
                        // Two digits hours in 12h format, 00 through 11
                        I: pad((hours % 12) || 12),
                        // Hours in 12h format, 1 through 12
                        l: (hours % 12) || 12,
                        // Two digits minutes, 00 through 59
                        M: 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: pad(seconds),
                        // Milliseconds (naming from Ruby)
                        L: pad(milliseconds, 3)
                    }, H.dateFormats);
                    // Do the replaces
                    objectEach(replacements, function (val, key) {
                        if (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, timestamp) :
                                    val);
                            }
                        }
                    });
                }
                else if (isObject(format)) {
                    const tzHours = (this.getTimezoneOffset(timestamp) || 0) /
                        (60000 * 60), timeZone = this.timezone || ('Etc/GMT' + (tzHours >= 0 ? '+' : '') + tzHours), { prefix = '', suffix = '' } = format;
                    format = prefix + this.dateTimeFormat(extend({ timeZone }, format), timestamp) + suffix;
                }
                // Optionally sentence-case the string and return
                return upperCaseFirst ? 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
             */
            resolveDTLFormat(f) {
                if (!isObject(f, true)) { // Check for string or array
                    f = splat(f);
                    return {
                        main: f[0],
                        from: f[1],
                        to: f[2]
                    };
                }
                // Type-check DateTimeFormatOptions against DateTimeLabelFormatObject
                if (isObject(f, true) && isDateTimeFormatOptions(f)) {
                    return { main: f };
                }
                return f;
            }
            /**
             * 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.
             */
            getDateFormat(range, timestamp, startOfWeek, dateTimeLabelFormats) {
                const 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
                };
                let n = 'millisecond', 
                // For sub-millisecond data, #4223
                lastN = n;
                for (n in 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 &&
                        range === 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 (range && 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;
            }
        }
        /* *
         *
         * Default export
         *
         * */
        /* *
         *
         * 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

        return TimeBase;
    });
    _registerModule(_modules, 'Core/Time.js', [_modules['Shared/TimeBase.js'], _modules['Core/Utilities.js']], function (TimeBase, U) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { defined, extend, timeUnits } = U;
        /* *
         *
         *  Constants
         *
         * */
        class Time extends TimeBase {
            /**
             * 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
             */
            getTimeTicks(normalizedInterval, min, max, startOfWeek) {
                const time = this, tickPositions = [], higherRanks = {}, { count = 1, unitRange } = normalizedInterval;
                let [year, month, dayOfMonth, hours, minutes, seconds] = time.toParts(min), milliseconds = (min || 0) % 1000, variableDayLength;
                startOfWeek ?? (startOfWeek = 1);
                if (defined(min)) { // #1300
                    milliseconds = unitRange >= timeUnits.second ?
                        0 : // #3935
                        count * Math.floor(milliseconds / count);
                    if (unitRange >= timeUnits.second) { // Second
                        seconds = unitRange >= timeUnits.minute ?
                            0 : // #3935
                            count * Math.floor(seconds / count);
                    }
                    if (unitRange >= timeUnits.minute) { // Minute
                        minutes = unitRange >= timeUnits.hour ?
                            0 :
                            count * Math.floor(minutes / count);
                    }
                    if (unitRange >= timeUnits.hour) { // Hour
                        hours = unitRange >= timeUnits.day ?
                            0 :
                            count * Math.floor(hours / count);
                    }
                    if (unitRange >= timeUnits.day) { // Day
                        dayOfMonth = unitRange >= timeUnits.month ?
                            1 :
                            Math.max(1, count * Math.floor(dayOfMonth / count));
                    }
                    if (unitRange >= timeUnits.month) { // Month
                        month = unitRange >= timeUnits.year ? 0 :
                            count * Math.floor(month / count);
                    }
                    if (unitRange >= timeUnits.year) { // Year
                        year -= year % count;
                    }
                    // Week is a special case that runs outside the hierarchy
                    if (unitRange === timeUnits.week) {
                        if (count) {
                            min = time.makeTime(year, month, dayOfMonth, hours, minutes, seconds, milliseconds);
                        }
                        // Get start of current week, independent of count
                        const weekday = this.dateTimeFormat({
                            timeZone: this.timezone,
                            weekday: 'narrow'
                        }, min, 'es'), 
                        // Spanish weekday index
                        weekdayNo = 'DLMXJVS'.indexOf(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 && 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 * 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
                    let t = min, i = 1;
                    while (t < max) {
                        tickPositions.push(t);
                        // Increase the years
                        if (unitRange === timeUnits.year) {
                            t = time.makeTime(year + i * count, 0);
                            // Increase the months
                        }
                        else if (unitRange === 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 === timeUnits.day ||
                            unitRange === timeUnits.week)) {
                            t = time.makeTime(year, month, dayOfMonth +
                                i * count * (unitRange === timeUnits.day ? 1 : 7));
                        }
                        else if (variableDayLength &&
                            unitRange === 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 <= timeUnits.hour && tickPositions.length < 10000) {
                        tickPositions.forEach((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 = extend(normalizedInterval, {
                    higherRanks,
                    totalRange: unitRange * count
                });
                return tickPositions;
            }
        }
        /* *
         *
         * Default export
         *
         * */

        return Time;
    });
    _registerModule(_modules, 'Core/Defaults.js', [_modules['Core/Chart/ChartDefaults.js'], _modules['Core/Globals.js'], _modules['Core/Color/Palettes.js'], _modules['Core/Time.js'], _modules['Core/Utilities.js']], function (ChartDefaults, H, Palettes, Time, U) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { isTouchDevice } = H;
        const { fireEvent, merge } = U;
        /* *
         *
         *  API Options
         *
         * */
        /**
         * Global default settings.
         *
         * @name Highcharts.defaultOptions
         * @type {Highcharts.Options}
         */ /**
        * @optionparent
        * @private
        */
        const 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'
             *     }
             * });
             * ```
             *
             * @optionparent lang
             */
            lang: {
                weekFrom: 'week from',
                /**
                 * The default chart title.
                 *
                 * @since 12.2.0
                 */
                chartTitle: 'Chart title',
                /**
                 * 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,
                /**
                 * [Format string](https://www.highcharts.com/docs/chart-concepts/templating) for the default series name.
                 *
                 * @since 12.2.0
                 */
                seriesName: 'Series {add index 1}',
                /**
                 * 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 default name for a pie slice (point).
                 * @since 12.2.0
                 */
                pieSliceName: 'Slice',
                /**
                 * 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
                 */
                /**
                 * The default title of the Y axis
                 *
                 * @since 12.2.0
                 */
                yAxisTitle: 'Values',
                resetZoomTitle: 'Reset zoom level 1:1'
            },
            /**
             * Global options that don't apply to each chart. These 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: 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: {
                /**
                 * 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
                 */
                /**
                 * 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 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
                         */
                        color: "#333333" /* Palette.neutralColor80 */,
                        /**
                         * @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 be fixed to one position in the chart, or
                 * located next to the point or mouse. When the tooltip is fixed, the
                 * position can be further specified with the
                 * [tooltip.position](#tooltip.position) options set.
                 *
                 * @sample    highcharts/tooltip/fixed/
                 *            Fixed tooltip and position options
                 * @sample    {highstock} stock/tooltip/fixed/
                 *            Stock chart with fixed tooltip
                 * @sample    {highmaps} maps/tooltip/fixed/
                 *            Map with fixed tooltip
                 *
                 * @type      {boolean}
                 * @default   false
                 * @since 12.2.0
                 * @apioption tooltip.fixed
                 */
                /**
                 * 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 }`
                 *
                 * Since v12.2, the [tooltip.fixed](#tooltip.fixed) option combined with
                 * [tooltip.position](#tooltip.position) covers most of the use cases
                 * for custom tooltip positioning.
                 *
                 * 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
                 *
                 * @see [position](#tooltip.position)
                 *
                 * @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: (x) => 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: '%v %[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,
                /**
                 * Positioning options for fixed tooltip, taking effect only when
                 * [tooltip.fixed](#tooltip.fixed) is `true`.
                 *
                 * @sample {highcharts} highcharts/tooltip/fixed/
                 *         Fixed tooltip and position options
                 * @sample {highstock} stock/tooltip/fixed/
                 *         Stock chart with fixed tooltip
                 * @sample {highmaps} maps/tooltip/fixed/
                 *         Map with fixed tooltip
                 *
                 * @since 12.2.0
                 */
                position: {
                    /**
                     * The horizontal alignment of the fixed tooltip.
                     *
                     * @sample highcharts/tooltip/fixed/
                     *         Fixed tooltip
                     * @sample {highstock} stock/tooltip/fixed/
                     *         Stock chart with fixed tooltip
                     *
                     * @type {Highcharts.AlignValue}
                     * @default left
                     * @apioption tooltip.position.align
                     */
                    /**
                     * The vertical alignment of the fixed tooltip.
                     *
                     * @sample highcharts/tooltip/fixed/
                     *         Fixed tooltip
                     * @sample {highstock} stock/tooltip/fixed/
                     *         Stock chart with fixed tooltip
                     *
                     * @type {Highcharts.VerticalAlignValue}
                     * @default top
                     * @apioption tooltip.position.verticalAlign
                     */
                    /**
                     * What the fixed tooltip alignment should be relative to.
                     *
                     * The default, `pane`, means that it is aligned within the plot
                     * area for that given series. If the tooltip is split (as default
                     * in Stock charts), each partial tooltip is aligned within the
                     * series' pane.
                     *
                     * @sample highcharts/tooltip/fixed/
                     *         Fixed tooltip
                     * @sample {highstock} stock/tooltip/fixed/
                     *         Stock chart with fixed tooltip
                     *
                     * @type {string}
                     * @default pane
                     * @validvalue ["pane", "chart", "plotBox", "spacingBox"]
                     * @apioption tooltip.position.relativeTo
                     */
                    /**
                     * X pixel offset from the given position. Can be used to shy away
                     * from axis lines, grid lines etc to avoid the tooltip overlapping
                     * other elements.
                     *
                     * @sample highcharts/tooltip/fixed/
                     *         Fixed tooltip
                     * @sample {highstock} stock/tooltip/fixed/
                     *         Stock chart with fixed tooltip
                     */
                    x: 0,
                    /**
                     * Y pixel offset from the given position. Can be used to shy away
                     * from axis lines, grid lines etc to avoid the tooltip overlapping
                     * other elements.
                     *
                     * @sample highcharts/tooltip/fixed/
                     *         Fixed tooltip
                     * @sample {highstock} stock/tooltip/fixed/
                     *         Stock chart with fixed tooltip
                     */
                    y: 3
                },
                /**
                 * 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).
                 *
                 * Defaults to `callout` for floating tooltip, `rect` for
                 * [fixed](#tooltip.fixed) tooltip.
                 *
                 * @type  {Highcharts.TooltipShapeValue}
                 * @since 4.0
                 * @default undefined
                 * @apioption tooltip.shape
                 */
                /**
                 * 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/series/null-interaction
                 *         Line chart with null interaction
                 * @sample {highcharts} highcharts/plotoptions/series-nullformat
                 *         Heatmap with null interaction
                 *
                 * @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 fixed tooltips, otherwise 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. Defaults to true,
                 * unless the tooltip is [fixed](#tooltip.fixed).
                 *
                 * @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}
                 * @default undefined
                 * @apioption tooltip.shadow
                 */
                /**
                 * 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'
            }
        };
        const defaultTime = new Time(defaultOptions.time, defaultOptions.lang);
        /**
         * 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) {
            fireEvent(H, 'setOptions', { options });
            // Copy in the default options
            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
                });
            }
            if (options.lang?.chartTitle) {
                defaultOptions.title = {
                    ...defaultOptions.title,
                    text: options.lang.chartTitle
                };
            }
            return defaultOptions;
        }
        /* *
         *
         *  Default Export
         *
         * */
        const DefaultOptions = {
            defaultOptions,
            defaultTime,
            getOptions,
            setOptions
        };
        /* *
         *
         *  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

        return DefaultOptions;
    });
    _registerModule(_modules, 'Core/Templating.js', [_modules['Core/Defaults.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (D, G, U) {
        /* *
         *
         *  (c) 2010-2025 Torstein Honsi
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { defaultOptions, defaultTime } = D;
        const { pageLang } = G;
        const { extend, getNestedProperty, isArray, isNumber, isObject, isString, pick, ucfirst } = U;
        const helpers = {
            // Built-in helpers
            add: (a, b) => a + b,
            divide: (a, b) => (b !== 0 ? a / b : ''),
            // eslint-disable-next-line eqeqeq
            eq: (a, b) => a == b,
            each: function (arr) {
                const match = arguments[arguments.length - 1];
                return isArray(arr) ?
                    arr.map((item, i) => format(match.body, extend(isObject(item) ? item : { '@this': item }, {
                        '@index': i,
                        '@first': i === 0,
                        '@last': i === arr.length - 1
                    }))).join('') :
                    false;
            },
            ge: (a, b) => a >= b,
            gt: (a, b) => a > b,
            'if': (condition) => !!condition,
            le: (a, b) => a <= b,
            lt: (a, b) => a < b,
            multiply: (a, b) => a * b,
            // eslint-disable-next-line eqeqeq
            ne: (a, b) => a != b,
            subtract: (a, b) => a - b,
            ucfirst,
            unless: (condition) => !condition
        };
        const numberFormatCache = {};
        /* *
         *
         *  Functions
         *
         * */
        // Internal convenience function
        const isQuotedString = (str) => /^["'].+["']$/.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 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} [owner]
         *        A `Chart` or `DataGrid` instance used to get numberFormatter and time.
         *
         * @return {string}
         *         The formatted string.
         */
        function format(str = '', ctx, owner) {
            // Notice: using u flag will require a refactor for ES5 (#22450).
            const regex = /\{([a-zA-Z\u00C0-\u017F\d:\.,;\-\/<>\[\]%_@+"'’= #\(\)]+)\}/g, // eslint-disable-line max-len
            // 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 = /\(([a-zA-Z\u00C0-\u017F\d:\.,;\-\/<>\[\]%_@+"'= ]+)\)/g, matches = [], floatRegex = /f$/, decRegex = /\.(\d)/, lang = owner?.options?.lang || defaultOptions.lang, time = owner?.time || defaultTime, numberFormatter = owner?.numberFormatter || numberFormat.bind(owner);
            /*
             * 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.
             */
            const resolveProperty = (key = '') => {
                let 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 getNestedProperty(key, ctx);
            };
            let 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.
                const mainMatch = match, subMatch = subRegex.exec(match[1]);
                if (subMatch) {
                    match = subMatch;
                    hasSub = true;
                }
                if (!currentMatch?.isBlock) {
                    currentMatch = {
                        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
                const 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
                const startingElseSection = match[1] === 'else';
                if (currentMatch.isBlock &&
                    currentMatch.fn && (match[1] === `/${currentMatch.fn}` ||
                    startingElseSection)) {
                    if (!depth) { // === 0
                        const 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?.isBlock) {
                    break;
                }
            }
            // Execute
            matches.forEach((match) => {
                const { body, elseBody, expression, fn } = match;
                let replacement, i;
                // Helper function
                if (fn) {
                    // Pass the helpers the amount of arguments defined by the function,
                    // then the match as the last argument.
                    const args = [match], parts = [], len = expression.length;
                    let start = 0, startChar;
                    for (i = 0; i <= len; i++) {
                        const 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, owner);
                    }
                    // Simple variable replacement
                }
                else {
                    const valueAndFormat = isQuotedString(expression) ?
                        [expression] : expression.split(':');
                    replacement = resolveProperty(valueAndFormat.shift() || '');
                    // Format the replacement
                    const isFloat = replacement % 1 !== 0;
                    if (typeof replacement === 'number' &&
                        (valueAndFormat.length || isFloat)) {
                        const segment = valueAndFormat.join(':');
                        if (floatRegex.test(segment) || isFloat) { // Float
                            const 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) && isString(replacement)) {
                        replacement = `"${replacement}"`;
                    }
                }
                str = str.replace(match.find, pick(replacement, ''));
            });
            return hasSub ? format(str, ctx, owner) : 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) {
            number = +number || 0;
            decimals = +decimals;
            let ret, fractionDigits, [mantissa, exp] = number.toString().split('e').map(Number);
            const lang = this?.options?.lang || defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, firstDecimals = decimals, options = {};
            decimalPoint ?? (decimalPoint = lang.decimalPoint);
            thousandsSep ?? (thousandsSep = lang.thousandsSep);
            if (decimals === -1) {
                // Preserve decimals. Not huge numbers (#3793).
                decimals = Math.min(origDec, 20);
            }
            else if (!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 ?? (decimals = 2);
                number = mantissa;
            }
            if (isNumber(decimals) && decimals >= 0) {
                options.minimumFractionDigits = decimals;
                options.maximumFractionDigits = decimals;
            }
            if (thousandsSep === '') {
                options.useGrouping = false;
            }
            const hasSeparators = thousandsSep || decimalPoint, locale = hasSeparators ?
                'en' : (this?.locale || lang.locale || pageLang), cacheKey = JSON.stringify(options) + locale, nf = numberFormatCache[cacheKey] ?? (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 ?? ',')
                    .replace('_.', 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
         *
         * */
        const Templating = {
            dateFormat,
            format,
            helpers,
            numberFormat
        };
        /* *
         * API Declarations
         * */
        /**
         * @interface Highcharts.Templating
         *
         * The Highcharts.Templating interface provides a structure for defining
         * helpers. Helpers can be used as conditional blocks or functions within
         * expressions. Highcharts includes several built-in helpers and supports
         * the addition of custom helpers.
         *
         * @see [More information](
         * https://www.highcharts.com/docs/chart-concepts/templating#helpers)
         *
         * @example
         * // Define a custom helper to return the absolute value of a number
         * Highcharts.Templating.helpers.abs = value => Math.abs(value);
         *
         * // Usage in a format string
         * format: 'Absolute value: {abs point.y}'
         *
         * @name Highcharts.Templating#helpers
         * @type {Record<string, Function>}
         */
        (''); // Keeps doclets above in file

        return Templating;
    });
    _registerModule(_modules, 'Grid/Core/Table/ColumnDistribution/ColumnDistributionStrategy.js', [_modules['Core/Utilities.js']], function (U) {
        /* *
         *
         *  Column Distribution Strategy abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { getStyle } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a column distribution strategy.
         */
        class ColumnDistributionStrategy {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Creates a new column distribution strategy.
             *
             * @param viewport
             * The table that the column distribution strategy is applied to.
             */
            constructor(viewport) {
                /**
                 * The current widths values of the columns.
                 */
                this.columnWidths = {};
                this.viewport = viewport;
            }
            /**
             * Loads the column to the distribution strategy. Should be called before
             * the table is rendered.
             */
            loadColumns() {
                const { columns } = this.viewport;
                for (let i = 0, iEnd = columns.length; i < iEnd; ++i) {
                    this.loadColumn(columns[i]);
                }
            }
            /**
             * Recaulculates the changing dimentions of the table.
             */
            reflow() {
                if (this.type === 'full') {
                    return;
                }
                const vp = this.viewport;
                let rowsWidth = 0;
                for (let i = 0, iEnd = vp.columns.length; i < iEnd; ++i) {
                    rowsWidth += this.getColumnWidth(vp.columns[i]);
                }
                vp.rowsWidth = rowsWidth;
            }
            /* *
             *
             * Static Methods
             *
             * */
            /**
             * Returns the minimum width of the column.
             *
             * @param column
             * The column to get the minimum width for.
             *
             * @returns
             * The minimum width in pixels.
             */
            static getMinWidth(column) {
                const tableColumnEl = column.cells[0]?.htmlElement;
                const headerColumnEl = column.header?.htmlElement;
                const getElPaddings = (el) => ((getStyle(el, 'padding-left', true) || 0) +
                    (getStyle(el, 'padding-right', true) || 0) +
                    (getStyle(el, 'border-left', true) || 0) +
                    (getStyle(el, 'border-right', true) || 0));
                let result = ColumnDistributionStrategy.MIN_COLUMN_WIDTH;
                if (tableColumnEl) {
                    result = Math.max(result, getElPaddings(tableColumnEl));
                }
                if (headerColumnEl) {
                    result = Math.max(result, getElPaddings(headerColumnEl));
                }
                return result;
            }
        }
        /* *
        *
        *  Static Properties
        *
        * */
        /**
         * The minimum width of a column.
         * @internal
         */
        ColumnDistributionStrategy.MIN_COLUMN_WIDTH = 20;
        /* *
         *
         *  Default Export
         *
         * */

        return ColumnDistributionStrategy;
    });
    _registerModule(_modules, 'Grid/Core/Table/ColumnDistribution/MixedDistributionStrategy.js', [_modules['Grid/Core/Table/ColumnDistribution/ColumnDistributionStrategy.js'], _modules['Core/Utilities.js']], function (DistributionStrategy, U) {
        /* *
         *
         *  Mixed Distribution Strategy class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { defined } = U;
        /* *
         *
         *  Class
         *
         * */
        class MixedDistributionStrategy extends DistributionStrategy {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                super(...arguments);
                this.type = 'mixed';
                /**
                 * Array of units for each column width value. Codified as:
                 * - `0` - px
                 * - `1` - %
                 */
                this.columnWidthUnits = {};
            }
            /* *
             *
             *  Methods
             *
             * */
            loadColumn(column) {
                const rawWidth = column.options.width;
                if (!rawWidth) {
                    return;
                }
                let value;
                let unitCode = 0;
                if (typeof rawWidth === 'number') {
                    value = rawWidth;
                    unitCode = 0;
                }
                else {
                    value = parseFloat(rawWidth);
                    unitCode = rawWidth.charAt(rawWidth.length - 1) === '%' ? 1 : 0;
                }
                this.columnWidthUnits[column.id] = unitCode;
                this.columnWidths[column.id] = value;
            }
            getColumnWidth(column) {
                const vp = this.viewport;
                const widthValue = this.columnWidths[column.id];
                const minWidth = DistributionStrategy.getMinWidth(column);
                if (!defined(widthValue)) {
                    const freeWidth = vp.tbodyElement.clientWidth - this.calculateOccupiedWidth();
                    const freeColumns = (vp.grid.enabledColumns?.length || 0) -
                        Object.keys(this.columnWidths).length;
                    // If undefined width:
                    return Math.max(freeWidth / freeColumns, minWidth);
                }
                if (this.columnWidthUnits[column.id] === 0) {
                    // If px:
                    return widthValue;
                }
                // If %:
                return Math.max(vp.getWidthFromRatio(widthValue / 100), minWidth);
            }
            resize(resizer, diff) {
                const vp = this.viewport;
                const column = resizer.draggedColumn;
                if (!column) {
                    return;
                }
                const colW = resizer.columnStartWidth ?? 0;
                const minWidth = DistributionStrategy.getMinWidth(column);
                const nextCol = vp.columns[column.index + 1];
                const newW = Math.round(Math.max(colW + diff, minWidth) * 10) / 10;
                this.columnWidths[column.id] = newW;
                this.columnWidthUnits[column.id] = 0; // Always save in px
                column.update({ width: newW }, false);
                if (nextCol) {
                    const newNextW = this.columnWidths[nextCol.id] = Math.round(Math.max((resizer.nextColumnStartWidth ?? 0) + colW - newW, minWidth) * 10) / 10;
                    this.columnWidthUnits[nextCol.id] = 0; // Always save in px
                    nextCol.update({ width: newNextW }, false);
                }
            }
            /**
             * Calculates defined (px and %) widths of all defined columns in the grid.
             * Total in px.
             */
            calculateOccupiedWidth() {
                const vp = this.viewport;
                let occupiedWidth = 0;
                let unit, width;
                const columnIds = Object.keys(this.columnWidths);
                let columnId;
                for (let i = 0, iEnd = columnIds.length; i < iEnd; ++i) {
                    columnId = columnIds[i];
                    unit = this.columnWidthUnits[columnId];
                    if (unit === 0) {
                        occupiedWidth += this.columnWidths[columnId];
                        continue;
                    }
                    width = this.columnWidths[columnId];
                    occupiedWidth += vp.getWidthFromRatio(width / 100);
                }
                return occupiedWidth;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return MixedDistributionStrategy;
    });
    _registerModule(_modules, 'Grid/Core/Globals.js', [], function () {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Globals Grid namespace.
         */
        var Globals;
        (function (Globals) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Constants
             *
             * */
            Globals.classNamePrefix = 'hcg-';
            Globals.rawClassNames = {
                container: 'container',
                tableElement: 'table',
                captionElement: 'caption',
                descriptionElement: 'description',
                theadElement: 'thead',
                tbodyElement: 'tbody',
                rowElement: 'row',
                rowEven: 'row-even',
                rowOdd: 'row-odd',
                hoveredRow: 'hovered-row',
                columnElement: 'column',
                hoveredCell: 'hovered-cell',
                hoveredColumn: 'hovered-column',
                syncedRow: 'synced-row',
                syncedCell: 'synced-cell',
                syncedColumn: 'synced-column',
                editedCell: 'edited-cell',
                mockedRow: 'mocked-row',
                rowsContentNowrap: 'rows-content-nowrap',
                virtualization: 'virtualization',
                scrollableContent: 'scrollable-content',
                headerCell: 'header-cell',
                headerCellContent: 'header-cell-content',
                headerRow: 'head-row-content',
                noData: 'no-data',
                noPadding: 'no-padding',
                columnFirst: 'column-first',
                columnSortable: 'column-sortable',
                columnSortableIcon: 'column-sortable-icon',
                columnSortedAsc: 'column-sorted-asc',
                columnSortedDesc: 'column-sorted-desc',
                resizableContent: 'resizable-content',
                resizerHandles: 'column-resizer',
                resizedColumn: 'column-resized',
                creditsContainer: 'credits-container',
                creditsText: 'credits',
                creditsPro: 'credits-pro',
                visuallyHidden: 'visually-hidden',
                lastHeaderCellInRow: 'last-header-cell-in-row',
                loadingWrapper: 'loading-wrapper',
                loadingSpinner: 'spinner',
                loadingMessage: 'loading-message'
            };
            Globals.win = window;
            Globals.composed = [];
            Globals.userAgent = (Globals.win.navigator && Globals.win.navigator.userAgent) || '';
            Globals.isChrome = Globals.userAgent.indexOf('Chrome') !== -1;
            Globals.isSafari = !Globals.isChrome && Globals.userAgent.indexOf('Safari') !== -1;
            Globals.getClassName = (classNameKey) => Globals.classNamePrefix + Globals.rawClassNames[classNameKey];
        })(Globals || (Globals = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return Globals;
    });
    _registerModule(_modules, 'Grid/Core/GridUtils.js', [_modules['Core/Renderer/HTML/AST.js']], function (AST) {
        /* *
         *
         *  Grid utilities
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        AST.allowedAttributes.push('srcset', 'media');
        AST.allowedTags.push('picture', 'source');
        /* *
         *
         *  Namespace
         *
         * */
        var GridUtils;
        (function (GridUtils) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Creates a HTML element with the provided options.
             *
             * @param tagName
             * The tag name of the element.
             *
             * @param params
             * The parameters of the element.
             *
             * @param parent
             * The parent element.
             */
            function makeHTMLElement(tagName, params, parent) {
                const element = document.createElement(tagName);
                if (params) {
                    const paramsKeys = Object.keys(params);
                    for (let i = 0; i < paramsKeys.length; i++) {
                        const key = paramsKeys[i];
                        const value = params[key];
                        if (value !== void 0) {
                            if (key === 'style') {
                                Object.assign(element.style, value);
                            }
                            else {
                                element[key] = value;
                            }
                        }
                    }
                }
                if (parent) {
                    parent.appendChild(element);
                }
                return element;
            }
            GridUtils.makeHTMLElement = makeHTMLElement;
            /**
             * Creates a div element with the provided class name and id.
             *
             * @param className
             * The class name of the div.
             *
             * @param id
             * The id of the element.
             */
            function makeDiv(className, id) {
                return makeHTMLElement('div', { className, id });
            }
            GridUtils.makeDiv = makeDiv;
            /**
             * Check if there's a possibility that the given string is an HTML
             * (contains '<').
             *
             * @param str
             * Text to verify.
             */
            function isHTML(str) {
                return str.indexOf('<') !== -1;
            }
            GridUtils.isHTML = isHTML;
            /**
             * Returns a string containing plain text format by removing HTML tags
             *
             * @param text
             * String to be sanitized
             *
             * @returns
             * Sanitized plain text string
             */
            function sanitizeText(text) {
                try {
                    return new DOMParser().parseFromString(text, 'text/html')
                        .body.textContent || '';
                }
                catch (error) {
                    return '';
                }
            }
            GridUtils.sanitizeText = sanitizeText;
            /**
             * Sets an element's content, checking whether it is HTML or plain text.
             * Should be used instead of element.innerText when the content can be HTML.
             *
             * @param element
             * Parent element where the content should be.
             *
             * @param content
             * Content to render.
             */
            function setHTMLContent(element, content) {
                if (isHTML(content)) {
                    element.innerHTML = AST.emptyHTML;
                    const formattedNodes = new AST(content);
                    formattedNodes.addToDOM(element);
                }
                else {
                    element.innerText = content;
                }
            }
            GridUtils.setHTMLContent = setHTMLContent;
        })(GridUtils || (GridUtils = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return GridUtils;
    });
    _registerModule(_modules, 'Grid/Core/Table/ColumnDistribution/FixedDistributionStrategy.js', [_modules['Grid/Core/Table/ColumnDistribution/ColumnDistributionStrategy.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Core/GridUtils.js']], function (DistributionStrategy, Globals, GridUtils) {
        /* *
         *
         *  Fixed Distribution Strategy class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { makeHTMLElement } = GridUtils;
        /* *
         *
         *  Class
         *
         * */
        class FixedDistributionStrategy extends DistributionStrategy {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                super(...arguments);
                this.type = 'fixed';
                /**
                 * Array of units for each column width value. Codified as:
                 * - `0` - px
                 * - `1` - %
                 */
                this.columnWidthUnits = {};
            }
            /* *
             *
             *  Methods
             *
             * */
            loadColumn(column) {
                const rawWidth = column.options.width;
                if (!rawWidth) {
                    this.columnWidths[column.id] = this.getInitialColumnWidth(column);
                    this.columnWidthUnits[column.id] = 0;
                    return;
                }
                let value;
                let unitCode = 0;
                if (typeof rawWidth === 'number') {
                    value = rawWidth;
                    unitCode = 0;
                }
                else {
                    value = parseFloat(rawWidth);
                    unitCode = rawWidth.charAt(rawWidth.length - 1) === '%' ? 1 : 0;
                }
                this.columnWidthUnits[column.id] = unitCode;
                this.columnWidths[column.id] = value;
            }
            getColumnWidth(column) {
                const vp = this.viewport;
                const widthValue = this.columnWidths[column.id];
                const minWidth = DistributionStrategy.getMinWidth(column);
                if (this.columnWidthUnits[column.id] === 1) {
                    // If %:
                    return Math.max(vp.getWidthFromRatio(widthValue / 100), minWidth);
                }
                // If px:
                return widthValue || 100; // Default to 100px if not defined
            }
            resize(resizer, diff) {
                const column = resizer.draggedColumn;
                if (!column) {
                    return;
                }
                const width = this.columnWidths[column.id] = Math.round(Math.max((resizer.columnStartWidth || 0) + diff, DistributionStrategy.getMinWidth(column)) * 10) / 10;
                this.columnWidthUnits[column.id] = 0; // Always save in px
                column.update({ width }, false);
            }
            /**
             * Creates a mock element to measure the width of the column from the CSS.
             * The element is appended to the viewport container and then removed.
             * It should be called only once for each column.
             *
             * @param column
             * The column for which the initial width is being calculated.
             *
             * @returns The initial width of the column.
             */
            getInitialColumnWidth(column) {
                const { viewport } = this;
                // Set the initial width of the column.
                const mock = makeHTMLElement('div', {
                    className: Globals.getClassName('columnElement')
                }, viewport.grid.container);
                mock.setAttribute('data-column-id', column.id);
                if (column.options.className) {
                    mock.classList.add(...column.options.className.split(/\s+/g));
                }
                const result = mock.offsetWidth || 100;
                mock.remove();
                return result;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return FixedDistributionStrategy;
    });
    _registerModule(_modules, 'Grid/Core/Table/ColumnDistribution/FullDistributionStrategy.js', [_modules['Grid/Core/Table/ColumnDistribution/ColumnDistributionStrategy.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Core/GridUtils.js']], function (DistributionStrategy, Globals, GridUtils) {
        /* *
         *
         *  Full Distribution Strategy class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { makeHTMLElement } = GridUtils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * @deprecated
         * This strategy is deprecated and will be removed in the future.
         */
        class FullDistributionStrategy extends DistributionStrategy {
            constructor() {
                /* *
                *
                *  Properties
                *
                * */
                super(...arguments);
                this.type = 'full';
                this.allPreviousWidths = 0;
            }
            /* *
            *
            *  Methods
            *
            * */
            loadColumn(column) {
                const width = this.getInitialColumnWidth(column);
                this.allPreviousWidths += width;
                this.columnWidths[column.id] = width;
            }
            getColumnWidth(column) {
                return this.viewport.getWidthFromRatio(this.columnWidths[column.id] || 0);
            }
            resize(resizer, diff) {
                const vp = this.viewport;
                const column = resizer.draggedColumn;
                if (!column) {
                    return;
                }
                const nextColumn = vp.columns[column.index + 1];
                if (!nextColumn) {
                    return;
                }
                const leftColW = resizer.columnStartWidth ?? 0;
                const rightColW = resizer.nextColumnStartWidth ?? 0;
                const minWidth = DistributionStrategy.getMinWidth(column);
                let newLeftW = leftColW + diff;
                let newRightW = rightColW - diff;
                if (newLeftW < minWidth) {
                    newLeftW = minWidth;
                    newRightW = leftColW + rightColW - minWidth;
                }
                if (newRightW < minWidth) {
                    newRightW = minWidth;
                    newLeftW = leftColW + rightColW - minWidth;
                }
                const leftW = this.columnWidths[column.id] =
                    vp.getRatioFromWidth(newLeftW);
                const rightW = this.columnWidths[nextColumn.id] =
                    vp.getRatioFromWidth(newRightW);
                column.update({ width: (leftW * 100).toFixed(4) + '%' }, false);
                nextColumn.update({ width: (rightW * 100).toFixed(4) + '%' }, false);
            }
            /**
             * The initial width of the column in the full distribution mode. The last
             * column in the viewport will have to fill the remaining space.
             *
             * @param column
             * The column to measure the width.
             *
             * @param mock
             * The mock element to measure the width.
             */
            getInitialFullDistWidth(column, mock) {
                const vp = column.viewport;
                const columnsCount = vp.grid.enabledColumns?.length ?? 0;
                if (column.index < columnsCount - 1) {
                    return vp.getRatioFromWidth(mock.offsetWidth) || 1 / columnsCount;
                }
                const result = 1 - this.allPreviousWidths;
                if (result < 0) {
                    // eslint-disable-next-line no-console
                    console.warn('The sum of the columns\' widths exceeds the ' +
                        'viewport width. It may cause unexpected behavior in the ' +
                        'full distribution mode. Check the CSS styles of the ' +
                        'columns. Corrections may be needed.');
                }
                return result;
            }
            /**
             * Creates a mock element to measure the width of the column from the CSS.
             * The element is appended to the viewport container and then removed.
             * It should be called only once for each column.
             *
             * @param column
             * The column to measure the width.
             *
             * @returns The initial width of the column.
             */
            getInitialColumnWidth(column) {
                const { viewport } = column;
                // Set the initial width of the column.
                const mock = makeHTMLElement('div', {
                    className: Globals.getClassName('columnElement')
                }, viewport.grid.container);
                mock.setAttribute('data-column-id', column.id);
                if (column.options.className) {
                    mock.classList.add(...column.options.className.split(/\s+/g));
                }
                const result = this.getInitialFullDistWidth(column, mock);
                mock.remove();
                return result;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return FullDistributionStrategy;
    });
    _registerModule(_modules, 'Grid/Core/Table/ColumnDistribution/ColumnDistribution.js', [_modules['Grid/Core/Table/ColumnDistribution/ColumnDistributionStrategy.js'], _modules['Grid/Core/Table/ColumnDistribution/MixedDistributionStrategy.js'], _modules['Grid/Core/Table/ColumnDistribution/FixedDistributionStrategy.js'], _modules['Grid/Core/Table/ColumnDistribution/FullDistributionStrategy.js'], _modules['Core/Utilities.js']], function (DistributionStrategy, MixedDistributionStrategy, FixedDistributionStrategy, FullDistributionStrategy, U) {
        /* *
         *
         *  Column Distribution namespace
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { defined } = U;
        /* *
         *
         *  Namespace
         *
         * */
        var ColumnDistribution;
        (function (ColumnDistribution) {
            /**
             * Abstract class representing a column distribution strategy.
             */
            ColumnDistribution.AbstractStrategy = DistributionStrategy;
            /**
             * Registry of column distribution strategies.
             */
            ColumnDistribution.types = {
                mixed: MixedDistributionStrategy,
                fixed: FixedDistributionStrategy,
                full: FullDistributionStrategy
            };
            /**
             * Returns the column distribution of the table according to the options:
             * 1. If `columns.resizing.mode` defined, use it. If not:
             * 2. If any column has a width defined, use `mixed`. If not:
             * 3. Use `full`.
             *
             * @param viewport
             * The table that the column distribution strategy is applied to.
             */
            function assumeDistributionType(viewport) {
                const { options } = viewport.grid;
                const colRendering = options?.rendering?.columns;
                const result = colRendering?.resizing?.mode ||
                    colRendering?.distribution;
                if (result) {
                    return result;
                }
                if (options?.columns?.some((column) => defined(column.width)) || defined(options?.columnDefaults?.width)) {
                    return 'mixed';
                }
                return 'full';
            }
            /**
             * Creates a new column distribution strategy instance based on the
             * viewport's options.
             *
             * @param viewport
             * The table that the column distribution strategy is applied to.
             *
             * @returns
             * The proper column distribution strategy.
             */
            function initStrategy(viewport) {
                return new ColumnDistribution.types[assumeDistributionType(viewport)](viewport);
            }
            ColumnDistribution.initStrategy = initStrategy;
        })(ColumnDistribution || (ColumnDistribution = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return ColumnDistribution;
    });
    _registerModule(_modules, 'Data/Modifiers/DataModifier.js', [_modules['Core/Utilities.js']], function (U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Gøran Slettemark
         *
         * */
        const { addEvent, fireEvent, merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Abstract class to provide an interface for modifying a table.
         *
         */
        class DataModifier {
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Runs a timed execution of the modifier on the given datatable.
             * Can be configured to run multiple times.
             *
             * @param {DataTable} dataTable
             * The datatable to execute
             *
             * @param {DataModifier.BenchmarkOptions} options
             * Options. Currently supports `iterations` for number of iterations.
             *
             * @return {Array<number>}
             * An array of times in milliseconds
             *
             */
            benchmark(dataTable, options) {
                const results = [];
                const modifier = this;
                const execute = () => {
                    modifier.modifyTable(dataTable);
                    modifier.emit({
                        type: 'afterBenchmarkIteration'
                    });
                };
                const defaultOptions = {
                    iterations: 1
                };
                const { iterations } = merge(defaultOptions, options);
                modifier.on('afterBenchmarkIteration', () => {
                    if (results.length === iterations) {
                        modifier.emit({
                            type: 'afterBenchmark',
                            results
                        });
                        return;
                    }
                    // Run again
                    execute();
                });
                const times = {
                    startTime: 0,
                    endTime: 0
                };
                // Add timers
                modifier.on('modify', () => {
                    times.startTime = window.performance.now();
                });
                modifier.on('afterModify', () => {
                    times.endTime = window.performance.now();
                    results.push(times.endTime - times.startTime);
                });
                // Initial run
                execute();
                return results;
            }
            /**
             * Emits an event on the modifier to all registered callbacks of this event.
             *
             * @param {DataModifier.Event} [e]
             * Event object containing additonal event information.
             */
            emit(e) {
                fireEvent(this, e.type, e);
            }
            /**
             * Returns a modified copy of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Table to modify.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Promise<Highcharts.DataTable>}
             * Table with `modified` property as a reference.
             */
            modify(table, eventDetail) {
                const modifier = this;
                return new Promise((resolve, reject) => {
                    if (table.modified === table) {
                        table.modified = table.clone(false, eventDetail);
                    }
                    try {
                        resolve(modifier.modifyTable(table, eventDetail));
                    }
                    catch (e) {
                        modifier.emit({
                            type: 'error',
                            detail: eventDetail,
                            table
                        });
                        reject(e);
                    }
                });
            }
            /**
             * Applies partial modifications of a cell change to the property `modified`
             * of the given modified table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {string} columnName
             * Column name of changed cell.
             *
             * @param {number|undefined} rowIndex
             * Row index of changed cell.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Changed cell value.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyCell(table, 
            /* eslint-disable @typescript-eslint/no-unused-vars */
            columnName, rowIndex, cellValue, eventDetail
            /* eslint-enable @typescript-eslint/no-unused-vars */
            ) {
                return this.modifyTable(table);
            }
            /**
             * Applies partial modifications of column changes to the property
             * `modified` of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Highcharts.DataTableColumnCollection} columns
             * Changed columns as a collection, where the keys are the column names.
             *
             * @param {number} [rowIndex=0]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyColumns(table, 
            /* eslint-disable @typescript-eslint/no-unused-vars */
            columns, rowIndex, eventDetail
            /* eslint-enable @typescript-eslint/no-unused-vars */
            ) {
                return this.modifyTable(table);
            }
            /**
             * Applies partial modifications of row changes to the property `modified`
             * of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
             * Changed rows.
             *
             * @param {number} [rowIndex]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyRows(table, 
            /* eslint-disable @typescript-eslint/no-unused-vars */
            rows, rowIndex, eventDetail
            /* eslint-enable @typescript-eslint/no-unused-vars */
            ) {
                return this.modifyTable(table);
            }
            /**
             * Registers a callback for a specific modifier event.
             *
             * @param {string} type
             * Event type as a string.
             *
             * @param {DataEventEmitter.Callback} callback
             * Function to register for an modifier callback.
             *
             * @return {Function}
             * Function to unregister callback from the modifier event.
             */
            on(type, callback) {
                return addEvent(this, type, callback);
            }
        }
        /* *
         *
         *  Class Namespace
         *
         * */
        /**
         * Additionally provided types for modifier events and options.
         */
        (function (DataModifier) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Constants
             *
             * */
            /**
             * Registry as a record object with modifier names and their class
             * constructor.
             */
            DataModifier.types = {};
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Adds a modifier class to the registry. The modifier class has to provide
             * the `DataModifier.options` property and the `DataModifier.modifyTable`
             * method to modify the table.
             *
             * @private
             *
             * @param {string} key
             * Registry key of the modifier class.
             *
             * @param {DataModifierType} DataModifierClass
             * Modifier class (aka class constructor) to register.
             *
             * @return {boolean}
             * Returns true, if the registration was successful. False is returned, if
             * their is already a modifier registered with this key.
             */
            function registerType(key, DataModifierClass) {
                return (!!key &&
                    !DataModifier.types[key] &&
                    !!(DataModifier.types[key] = DataModifierClass));
            }
            DataModifier.registerType = registerType;
        })(DataModifier || (DataModifier = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return DataModifier;
    });
    _registerModule(_modules, 'Data/ColumnUtils.js', [], function () {
        /* *
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /**
         * Utility functions for columns that can be either arrays or typed arrays.
         * @private
         */
        var ColumnUtils;
        (function (ColumnUtils) {
            /* *
            *
            *  Declarations
            *
            * */
            /* *
            *
            * Functions
            *
            * */
            /**
             * Sets the length of the column array.
             *
             * @param {DataTable.Column} column
             * Column to be modified.
             *
             * @param {number} length
             * New length of the column.
             *
             * @param {boolean} asSubarray
             * If column is a typed array, return a subarray instead of a new array. It
             * is faster `O(1)`, but the entire buffer will be kept in memory until all
             * views to it are destroyed. Default is `false`.
             *
             * @return {DataTable.Column}
             * Modified column.
             *
             * @private
             */
            function setLength(column, length, asSubarray) {
                if (Array.isArray(column)) {
                    column.length = length;
                    return column;
                }
                return column[asSubarray ? 'subarray' : 'slice'](0, length);
            }
            ColumnUtils.setLength = setLength;
            /**
             * Splices a column array.
             *
             * @param {DataTable.Column} column
             * Column to be modified.
             *
             * @param {number} start
             * Index at which to start changing the array.
             *
             * @param {number} deleteCount
             * An integer indicating the number of old array elements to remove.
             *
             * @param {boolean} removedAsSubarray
             * If column is a typed array, return a subarray instead of a new array. It
             * is faster `O(1)`, but the entire buffer will be kept in memory until all
             * views to it are destroyed. Default is `true`.
             *
             * @param {Array<number>|TypedArray} items
             * The elements to add to the array, beginning at the start index. If you
             * don't specify any elements, `splice()` will only remove elements from the
             * array.
             *
             * @return {SpliceResult}
             * Object containing removed elements and the modified column.
             *
             * @private
             */
            function splice(column, start, deleteCount, removedAsSubarray, items = []) {
                if (Array.isArray(column)) {
                    if (!Array.isArray(items)) {
                        items = Array.from(items);
                    }
                    return {
                        removed: column.splice(start, deleteCount, ...items),
                        array: column
                    };
                }
                const Constructor = Object.getPrototypeOf(column)
                    .constructor;
                const removed = column[removedAsSubarray ? 'subarray' : 'slice'](start, start + deleteCount);
                const newLength = column.length - deleteCount + items.length;
                const result = new Constructor(newLength);
                result.set(column.subarray(0, start), 0);
                result.set(items, start);
                result.set(column.subarray(start + deleteCount), start + items.length);
                return {
                    removed: removed,
                    array: result
                };
            }
            ColumnUtils.splice = splice;
        })(ColumnUtils || (ColumnUtils = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return ColumnUtils;
    });
    _registerModule(_modules, 'Data/DataTableCore.js', [_modules['Data/ColumnUtils.js'], _modules['Core/Utilities.js']], function (ColumnUtils, U) {
        /* *
         *
         *  (c) 2009-2025 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
         *
         * */
        const { setLength, splice } = ColumnUtils;
        const { fireEvent, objectEach, uniqueKey } = U;
        /* *
         *
         *  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.
         */
        class DataTableCore {
            /**
             * 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.
             */
            constructor(options = {}) {
                /**
                 * 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 identification purposes.
                 *
                 * @name Highcharts.DataTable#id
                 * @type {string}
                 */
                this.id = (options.id || uniqueKey());
                this.modified = this;
                this.rowCount = 0;
                this.versionTag = uniqueKey();
                let rowCount = 0;
                objectEach(options.columns || {}, (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.
             */
            applyRowCount(rowCount) {
                this.rowCount = rowCount;
                objectEach(this.columns, (column, columnName) => {
                    if (column.length !== rowCount) {
                        this.columns[columnName] = setLength(column, rowCount);
                    }
                });
            }
            /**
             * Delete rows. Simplified version of the full
             * `DataTable.deleteRows` method.
             *
             * @param {number} rowIndex
             * The start row index
             *
             * @param {number} [rowCount=1]
             * The number of rows to delete
             *
             * @return {void}
             *
             * @emits #afterDeleteRows
             */
            deleteRows(rowIndex, rowCount = 1) {
                if (rowCount > 0 && rowIndex < this.rowCount) {
                    let length = 0;
                    objectEach(this.columns, (column, columnName) => {
                        this.columns[columnName] =
                            splice(column, rowIndex, rowCount).array;
                        length = column.length;
                    });
                    this.rowCount = length;
                }
                fireEvent(this, 'afterDeleteRows', { rowIndex, rowCount });
                this.versionTag = uniqueKey();
            }
            /**
             * 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.
             */
            getColumn(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`.
             */
            getColumns(columnNames, 
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            asReference) {
                return (columnNames || Object.keys(this.columns)).reduce((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.
             */
            getRow(rowIndex, columnNames) {
                return (columnNames || Object.keys(this.columns)).map((key) => this.columns[key]?.[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]
             * 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
             */
            setColumn(columnName, column = [], rowIndex = 0, eventDetail) {
                this.setColumns({ [columnName]: column }, rowIndex, eventDetail);
            }
            /**
             * Sets cell values for multiple columns. Will insert new columns, if not
             * found. Simplified version of the full `DataTableCore.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. Ignored in the `DataTableCore`, as it
             * always replaces the full column.
             *
             * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail]
             * Custom information for pending events.
             *
             * @emits #setColumns
             * @emits #afterSetColumns
             */
            setColumns(columns, rowIndex, eventDetail) {
                let rowCount = this.rowCount;
                objectEach(columns, (column, columnName) => {
                    this.columns[columnName] = column.slice();
                    rowCount = column.length;
                });
                this.applyRowCount(rowCount);
                if (!eventDetail?.silent) {
                    fireEvent(this, 'afterSetColumns');
                    this.versionTag = 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 `undefined` 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
             */
            setRow(row, rowIndex = this.rowCount, insert, eventDetail) {
                const { columns } = this, indexRowCount = insert ? this.rowCount + 1 : rowIndex + 1;
                objectEach(row, (cellValue, columnName) => {
                    let column = columns[columnName] ||
                        eventDetail?.addColumns !== false && new Array(indexRowCount);
                    if (column) {
                        if (insert) {
                            column = splice(column, rowIndex, 0, true, [cellValue]).array;
                        }
                        else {
                            column[rowIndex] = cellValue;
                        }
                        columns[columnName] = column;
                    }
                });
                if (indexRowCount > this.rowCount) {
                    this.applyRowCount(indexRowCount);
                }
                if (!eventDetail?.silent) {
                    fireEvent(this, 'afterSetRows');
                    this.versionTag = uniqueKey();
                }
            }
        }
        /* *
         *
         *  Default Export
         *
         * */
        /* *
         *
         *  API Declarations
         *
         * */
        /**
         * A typed array.
         * @typedef {Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} Highcharts.TypedArray
         * //**
         * A column of values in a data table.
         * @typedef {Array<boolean|null|number|string|undefined>|Highcharts.TypedArray} 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

        return DataTableCore;
    });
    _registerModule(_modules, 'Data/DataTable.js', [_modules['Data/ColumnUtils.js'], _modules['Data/DataTableCore.js'], _modules['Core/Utilities.js']], function (CU, DataTableCore, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Gøran Slettemark
         *  - Jomar Hønsi
         *  - Dawid Dragula
         *
         * */
        const { addEvent, defined, extend, fireEvent, isNumber, uniqueKey } = U;
        /* *
         *
         *  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.
         */
        class DataTable extends DataTableCore {
            /* *
             *
             *  Static Functions
             *
             * */
            /**
             * Tests whether a row contains only `null` values or is equal to
             * DataTable.NULL. If all columns have `null` values, the function returns
             * `true`. Otherwise, it returns `false` to indicate that the row contains
             * at least one non-null value.
             *
             * @function Highcharts.DataTable.isNull
             *
             * @param {Highcharts.DataTableRow|Highcharts.DataTableRowObject} row
             * Row to test.
             *
             * @return {boolean}
             * Returns `true`, if the row contains only null, otherwise `false`.
             *
             * @example
             * if (DataTable.isNull(row)) {
             *   // handle null row
             * }
             */
            static isNull(row) {
                if (row === DataTable.NULL) {
                    return true;
                }
                if (row instanceof Array) {
                    if (!row.length) {
                        return false;
                    }
                    for (let i = 0, iEnd = row.length; i < iEnd; ++i) {
                        if (row[i] !== null) {
                            return false;
                        }
                    }
                }
                else {
                    const columnNames = Object.keys(row);
                    if (!columnNames.length) {
                        return false;
                    }
                    for (let i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
                        if (row[columnNames[i]] !== null) {
                            return false;
                        }
                    }
                }
                return true;
            }
            /* *
             *
             *  Constructor
             *
             * */
            constructor(options = {}) {
                super(options);
                this.modified = this;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Returns a clone of this table. The cloned table is completely independent
             * of the original, and any changes made to the clone will not affect
             * the original table.
             *
             * @function Highcharts.DataTable#clone
             *
             * @param {boolean} [skipColumns]
             * Whether to clone columns or not.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Clone of this data table.
             *
             * @emits #cloneTable
             * @emits #afterCloneTable
             */
            clone(skipColumns, eventDetail) {
                const table = this, tableOptions = {};
                table.emit({ type: 'cloneTable', detail: eventDetail });
                if (!skipColumns) {
                    tableOptions.columns = table.columns;
                }
                if (!table.autoId) {
                    tableOptions.id = table.id;
                }
                const tableClone = new DataTable(tableOptions);
                if (!skipColumns) {
                    tableClone.versionTag = table.versionTag;
                    tableClone.originalRowIndexes = table.originalRowIndexes;
                    tableClone.localRowIndexes = table.localRowIndexes;
                }
                table.emit({
                    type: 'afterCloneTable',
                    detail: eventDetail,
                    tableClone
                });
                return tableClone;
            }
            /**
             * Deletes columns from the table.
             *
             * @function Highcharts.DataTable#deleteColumns
             *
             * @param {Array<string>} [columnNames]
             * Names of columns to delete. If no array is provided, all
             * columns will be deleted.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTableColumnCollection|undefined}
             * Returns the deleted columns, if found.
             *
             * @emits #deleteColumns
             * @emits #afterDeleteColumns
             */
            deleteColumns(columnNames, eventDetail) {
                const table = this, columns = table.columns, deletedColumns = {}, modifiedColumns = {}, modifier = table.modifier, rowCount = table.rowCount;
                columnNames = (columnNames || Object.keys(columns));
                if (columnNames.length) {
                    table.emit({
                        type: 'deleteColumns',
                        columnNames,
                        detail: eventDetail
                    });
                    for (let i = 0, iEnd = columnNames.length, column, columnName; i < iEnd; ++i) {
                        columnName = columnNames[i];
                        column = columns[columnName];
                        if (column) {
                            deletedColumns[columnName] = column;
                            modifiedColumns[columnName] = new Array(rowCount);
                        }
                        delete columns[columnName];
                    }
                    if (!Object.keys(columns).length) {
                        table.rowCount = 0;
                        this.deleteRowIndexReferences();
                    }
                    if (modifier) {
                        modifier.modifyColumns(table, modifiedColumns, 0, eventDetail);
                    }
                    table.emit({
                        type: 'afterDeleteColumns',
                        columns: deletedColumns,
                        columnNames,
                        detail: eventDetail
                    });
                    return deletedColumns;
                }
            }
            /**
             * Deletes the row index references. This is useful when the original table
             * is deleted, and the references are no longer needed. This table is
             * then considered an original table or a table that has the same row's
             * order as the original table.
             */
            deleteRowIndexReferences() {
                delete this.originalRowIndexes;
                delete this.localRowIndexes;
                // Here, in case of future need, can be implemented updating of the
                // modified tables' row indexes references.
            }
            /**
             * Deletes rows in this table.
             *
             * @function Highcharts.DataTable#deleteRows
             *
             * @param {number} [rowIndex]
             * Index to start delete of rows. If not specified, all rows will be
             * deleted.
             *
             * @param {number} [rowCount=1]
             * Number of rows to delete.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Array<Highcharts.DataTableRow>}
             * Returns the deleted rows, if found.
             *
             * @emits #deleteRows
             * @emits #afterDeleteRows
             */
            deleteRows(rowIndex, rowCount = 1, eventDetail) {
                const table = this, deletedRows = [], modifiedRows = [], modifier = table.modifier;
                table.emit({
                    type: 'deleteRows',
                    detail: eventDetail,
                    rowCount,
                    rowIndex: (rowIndex || 0)
                });
                if (typeof rowIndex === 'undefined') {
                    rowIndex = 0;
                    rowCount = table.rowCount;
                }
                if (rowCount > 0 && rowIndex < table.rowCount) {
                    const columns = table.columns, columnNames = Object.keys(columns);
                    for (let i = 0, iEnd = columnNames.length, column, deletedCells, columnName; i < iEnd; ++i) {
                        columnName = columnNames[i];
                        column = columns[columnName];
                        const result = CU.splice(column, rowIndex, rowCount);
                        deletedCells = result.removed;
                        columns[columnName] = column = result.array;
                        if (!i) {
                            table.rowCount = column.length;
                        }
                        for (let j = 0, jEnd = deletedCells.length; j < jEnd; ++j) {
                            deletedRows[j] = (deletedRows[j] || []);
                            deletedRows[j][i] = deletedCells[j];
                        }
                        modifiedRows.push(new Array(iEnd));
                    }
                }
                if (modifier) {
                    modifier.modifyRows(table, modifiedRows, (rowIndex || 0), eventDetail);
                }
                table.emit({
                    type: 'afterDeleteRows',
                    detail: eventDetail,
                    rowCount,
                    rowIndex: (rowIndex || 0),
                    rows: deletedRows
                });
                return deletedRows;
            }
            /**
             * Emits an event on this table to all registered callbacks of the given
             * event.
             * @private
             *
             * @param {DataTable.Event} e
             * Event object with event information.
             */
            emit(e) {
                if ([
                    'afterDeleteColumns',
                    'afterDeleteRows',
                    'afterSetCell',
                    'afterSetColumns',
                    'afterSetRows'
                ].includes(e.type)) {
                    this.versionTag = uniqueKey();
                }
                fireEvent(this, e.type, e);
            }
            /**
             * Fetches a single cell value.
             *
             * @function Highcharts.DataTable#getCell
             *
             * @param {string} columnName
             * Column name of the cell to retrieve.
             *
             * @param {number} rowIndex
             * Row index of the cell to retrieve.
             *
             * @return {Highcharts.DataTableCellType|undefined}
             * Returns the cell value or `undefined`.
             */
            getCell(columnName, rowIndex) {
                const table = this;
                const column = table.columns[columnName];
                if (column) {
                    return column[rowIndex];
                }
            }
            /**
             * Fetches a cell value for the given row as a boolean.
             *
             * @function Highcharts.DataTable#getCellAsBoolean
             *
             * @param {string} columnName
             * Column name to fetch.
             *
             * @param {number} rowIndex
             * Row index to fetch.
             *
             * @return {boolean}
             * Returns the cell value of the row as a boolean.
             */
            getCellAsBoolean(columnName, rowIndex) {
                const table = this;
                const column = table.columns[columnName];
                return !!(column && column[rowIndex]);
            }
            /**
             * Fetches a cell value for the given row as a number.
             *
             * @function Highcharts.DataTable#getCellAsNumber
             *
             * @param {string} columnName
             * Column name or to fetch.
             *
             * @param {number} rowIndex
             * Row index to fetch.
             *
             * @param {boolean} [useNaN]
             * Whether to return NaN instead of `null` and `undefined`.
             *
             * @return {number|null}
             * Returns the cell value of the row as a number.
             */
            getCellAsNumber(columnName, rowIndex, useNaN) {
                const table = this;
                const column = table.columns[columnName];
                let cellValue = (column && column[rowIndex]);
                switch (typeof cellValue) {
                    case 'boolean':
                        return (cellValue ? 1 : 0);
                    case 'number':
                        return (isNaN(cellValue) && !useNaN ? null : cellValue);
                }
                cellValue = parseFloat(`${cellValue ?? ''}`);
                return (isNaN(cellValue) && !useNaN ? null : cellValue);
            }
            /**
             * Fetches a cell value for the given row as a string.
             *
             * @function Highcharts.DataTable#getCellAsString
             *
             * @param {string} columnName
             * Column name to fetch.
             *
             * @param {number} rowIndex
             * Row index to fetch.
             *
             * @return {string}
             * Returns the cell value of the row as a string.
             */
            getCellAsString(columnName, rowIndex) {
                const table = this;
                const column = table.columns[columnName];
                // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
                return `${(column && column[rowIndex])}`;
            }
            /**
             * Fetches the given column by the canonical column name.
             * This function is a simplified wrap of {@link getColumns}.
             *
             * @function Highcharts.DataTable#getColumn
             *
             * @param {string} columnName
             * Name of the column to get.
             *
             * @param {boolean} [asReference]
             * Whether to return the column as a readonly reference.
             *
             * @return {Highcharts.DataTableColumn|undefined}
             * A copy of the column, or `undefined` if not found.
             */
            getColumn(columnName, asReference) {
                return this.getColumns([columnName], asReference)[columnName];
            }
            /**
             * Fetches the given column by the canonical column name, and
             * validates the type of the first few cells. If the first defined cell is
             * of type number, it assumes for performance reasons, that all cells are of
             * type number or `null`. Otherwise it will convert all cells to number
             * type, except `null`.
             *
             * @deprecated
             *
             * @function Highcharts.DataTable#getColumnAsNumbers
             *
             * @param {string} columnName
             * Name of the column to get.
             *
             * @param {boolean} [useNaN]
             * Whether to use NaN instead of `null` and `undefined`.
             *
             * @return {Array<(number|null)>}
             * A copy of the column, or an empty array if not found.
             */
            getColumnAsNumbers(columnName, useNaN) {
                const table = this, columns = table.columns;
                const column = columns[columnName], columnAsNumber = [];
                if (column) {
                    const columnLength = column.length;
                    if (useNaN) {
                        for (let i = 0; i < columnLength; ++i) {
                            columnAsNumber.push(table.getCellAsNumber(columnName, i, true));
                        }
                    }
                    else {
                        for (let i = 0, cellValue; i < columnLength; ++i) {
                            cellValue = column[i];
                            if (typeof cellValue === 'number') {
                                // Assume unmixed data for performance reasons
                                return column.slice();
                            }
                            if (cellValue !== null &&
                                typeof cellValue !== 'undefined') {
                                break;
                            }
                        }
                        for (let i = 0; i < columnLength; ++i) {
                            columnAsNumber.push(table.getCellAsNumber(columnName, i));
                        }
                    }
                }
                return columnAsNumber;
            }
            /**
             * Fetches all column names.
             *
             * @function Highcharts.DataTable#getColumnNames
             *
             * @return {Array<string>}
             * Returns all column names.
             */
            getColumnNames() {
                return Object.keys(this.columns);
            }
            /**
             * Retrieves all or the given columns.
             *
             * @function Highcharts.DataTable#getColumns
             *
             * @param {Array<string>} [columnNames]
             * Column names to retrieve.
             *
             * @param {boolean} [asReference]
             * Whether to return columns as a readonly reference.
             *
             * @param {boolean} [asBasicColumns]
             * Whether to transform all typed array columns to normal arrays.
             *
             * @return {Highcharts.DataTableColumnCollection}
             * Collection of columns. If a requested column was not found, it is
             * `undefined`.
             */
            getColumns(columnNames, asReference, asBasicColumns) {
                const table = this, tableColumns = table.columns, columns = {};
                columnNames = (columnNames || Object.keys(tableColumns));
                for (let i = 0, iEnd = columnNames.length, column, columnName; i < iEnd; ++i) {
                    columnName = columnNames[i];
                    column = tableColumns[columnName];
                    if (column) {
                        if (asReference) {
                            columns[columnName] = column;
                        }
                        else if (asBasicColumns && !Array.isArray(column)) {
                            columns[columnName] = Array.from(column);
                        }
                        else {
                            columns[columnName] = column.slice();
                        }
                    }
                }
                return columns;
            }
            /**
             * Takes the original row index and returns the local row index in the
             * modified table for which this function is called.
             *
             * @param {number} originalRowIndex
             * Original row index to get the local row index for.
             *
             * @return {number|undefined}
             * Returns the local row index or `undefined` if not found.
             */
            getLocalRowIndex(originalRowIndex) {
                const { localRowIndexes } = this;
                if (localRowIndexes) {
                    return localRowIndexes[originalRowIndex];
                }
                return originalRowIndex;
            }
            /**
             * Retrieves the modifier for the table.
             * @private
             *
             * @return {Highcharts.DataModifier|undefined}
             * Returns the modifier or `undefined`.
             */
            getModifier() {
                return this.modifier;
            }
            /**
             * Takes the local row index and returns the index of the corresponding row
             * in the original table.
             *
             * @param {number} rowIndex
             * Local row index to get the original row index for.
             *
             * @return {number|undefined}
             * Returns the original row index or `undefined` if not found.
             */
            getOriginalRowIndex(rowIndex) {
                const { originalRowIndexes } = this;
                if (originalRowIndexes) {
                    return originalRowIndexes[rowIndex];
                }
                return rowIndex;
            }
            /**
             * Retrieves the row at a given index. This function is a simplified wrap of
             * {@link getRows}.
             *
             * @function Highcharts.DataTable#getRow
             *
             * @param {number} rowIndex
             * Row index to retrieve. First row has index 0.
             *
             * @param {Array<string>} [columnNames]
             * Column names in order to retrieve.
             *
             * @return {Highcharts.DataTableRow}
             * Returns the row values, or `undefined` if not found.
             */
            getRow(rowIndex, columnNames) {
                return this.getRows(rowIndex, 1, columnNames)[0];
            }
            /**
             * Returns the number of rows in this table.
             *
             * @function Highcharts.DataTable#getRowCount
             *
             * @return {number}
             * Number of rows in this table.
             */
            getRowCount() {
                // @todo Implement via property getter `.length` browsers supported
                return this.rowCount;
            }
            /**
             * Retrieves the index of the first row matching a specific cell value.
             *
             * @function Highcharts.DataTable#getRowIndexBy
             *
             * @param {string} columnName
             * Column to search in.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Cell value to search for. `NaN` and `undefined` are not supported.
             *
             * @param {number} [rowIndexOffset]
             * Index offset to start searching.
             *
             * @return {number|undefined}
             * Index of the first row matching the cell value.
             */
            getRowIndexBy(columnName, cellValue, rowIndexOffset) {
                const table = this;
                const column = table.columns[columnName];
                if (column) {
                    let rowIndex = -1;
                    if (Array.isArray(column)) {
                        // Normal array
                        rowIndex = column.indexOf(cellValue, rowIndexOffset);
                    }
                    else if (isNumber(cellValue)) {
                        // Typed array
                        rowIndex = column.indexOf(cellValue, rowIndexOffset);
                    }
                    if (rowIndex !== -1) {
                        return rowIndex;
                    }
                }
            }
            /**
             * Retrieves the row at a given index. This function is a simplified wrap of
             * {@link getRowObjects}.
             *
             * @function Highcharts.DataTable#getRowObject
             *
             * @param {number} rowIndex
             * Row index.
             *
             * @param {Array<string>} [columnNames]
             * Column names and their order to retrieve.
             *
             * @return {Highcharts.DataTableRowObject}
             * Returns the row values, or `undefined` if not found.
             */
            getRowObject(rowIndex, columnNames) {
                return this.getRowObjects(rowIndex, 1, columnNames)[0];
            }
            /**
             * Fetches all or a number of rows.
             *
             * @function Highcharts.DataTable#getRowObjects
             *
             * @param {number} [rowIndex]
             * Index of the first row to fetch. Defaults to first row at index `0`.
             *
             * @param {number} [rowCount]
             * Number of rows to fetch. Defaults to maximal number of rows.
             *
             * @param {Array<string>} [columnNames]
             * Column names and their order to retrieve.
             *
             * @return {Highcharts.DataTableRowObject}
             * Returns retrieved rows.
             */
            getRowObjects(rowIndex = 0, rowCount = (this.rowCount - rowIndex), columnNames) {
                const table = this, columns = table.columns, rows = new Array(rowCount);
                columnNames = (columnNames || Object.keys(columns));
                for (let i = rowIndex, i2 = 0, iEnd = Math.min(table.rowCount, (rowIndex + rowCount)), column, row; i < iEnd; ++i, ++i2) {
                    row = rows[i2] = {};
                    for (const columnName of columnNames) {
                        column = columns[columnName];
                        row[columnName] = (column ? column[i] : void 0);
                    }
                }
                return rows;
            }
            /**
             * Fetches all or a number of rows.
             *
             * @function Highcharts.DataTable#getRows
             *
             * @param {number} [rowIndex]
             * Index of the first row to fetch. Defaults to first row at index `0`.
             *
             * @param {number} [rowCount]
             * Number of rows to fetch. Defaults to maximal number of rows.
             *
             * @param {Array<string>} [columnNames]
             * Column names and their order to retrieve.
             *
             * @return {Highcharts.DataTableRow}
             * Returns retrieved rows.
             */
            getRows(rowIndex = 0, rowCount = (this.rowCount - rowIndex), columnNames) {
                const table = this, columns = table.columns, rows = new Array(rowCount);
                columnNames = (columnNames || Object.keys(columns));
                for (let i = rowIndex, i2 = 0, iEnd = Math.min(table.rowCount, (rowIndex + rowCount)), column, row; i < iEnd; ++i, ++i2) {
                    row = rows[i2] = [];
                    for (const columnName of columnNames) {
                        column = columns[columnName];
                        row.push(column ? column[i] : void 0);
                    }
                }
                return rows;
            }
            /**
             * Returns the unique version tag of the current state of the table.
             *
             * @function Highcharts.DataTable#getVersionTag
             *
             * @return {string}
             * Unique version tag.
             */
            getVersionTag() {
                return this.versionTag;
            }
            /**
             * Checks for given column names.
             *
             * @function Highcharts.DataTable#hasColumns
             *
             * @param {Array<string>} columnNames
             * Column names to check.
             *
             * @return {boolean}
             * Returns `true` if all columns have been found, otherwise `false`.
             */
            hasColumns(columnNames) {
                const table = this, columns = table.columns;
                for (let i = 0, iEnd = columnNames.length, columnName; i < iEnd; ++i) {
                    columnName = columnNames[i];
                    if (!columns[columnName]) {
                        return false;
                    }
                }
                return true;
            }
            /**
             * Searches for a specific cell value.
             *
             * @function Highcharts.DataTable#hasRowWith
             *
             * @param {string} columnName
             * Column to search in.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Cell value to search for. `NaN` and `undefined` are not supported.
             *
             * @return {boolean}
             * True, if a row has been found, otherwise false.
             */
            hasRowWith(columnName, cellValue) {
                const table = this;
                const column = table.columns[columnName];
                // Normal array
                if (Array.isArray(column)) {
                    return (column.indexOf(cellValue) !== -1);
                }
                // Typed array
                if (defined(cellValue) && Number.isFinite(cellValue)) {
                    return (column.indexOf(+cellValue) !== -1);
                }
                return false;
            }
            /**
             * Registers a callback for a specific event.
             *
             * @function Highcharts.DataTable#on
             *
             * @param {string} type
             * Event type as a string.
             *
             * @param {Highcharts.EventCallbackFunction<Highcharts.DataTable>} callback
             * Function to register for an event callback.
             *
             * @return {Function}
             * Function to unregister callback from the event.
             */
            on(type, callback) {
                return addEvent(this, type, callback);
            }
            /**
             * Renames a column of cell values.
             *
             * @function Highcharts.DataTable#renameColumn
             *
             * @param {string} columnName
             * Name of the column to be renamed.
             *
             * @param {string} newColumnName
             * New name of the column. An existing column with the same name will be
             * replaced.
             *
             * @return {boolean}
             * Returns `true` if successful, `false` if the column was not found.
             */
            renameColumn(columnName, newColumnName) {
                const table = this, columns = table.columns;
                if (columns[columnName]) {
                    if (columnName !== newColumnName) {
                        columns[newColumnName] = columns[columnName];
                        delete columns[columnName];
                    }
                    return true;
                }
                return false;
            }
            /**
             * Sets a cell value based on the row index and column.  Will
             * insert a new column, if not found.
             *
             * @function Highcharts.DataTable#setCell
             *
             * @param {string} columnName
             * Column name to set.
             *
             * @param {number|undefined} rowIndex
             * Row index to set.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Cell value to set.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits #setCell
             * @emits #afterSetCell
             */
            setCell(columnName, rowIndex, cellValue, eventDetail) {
                const table = this, columns = table.columns, modifier = table.modifier;
                let column = columns[columnName];
                if (column && column[rowIndex] === cellValue) {
                    return;
                }
                table.emit({
                    type: 'setCell',
                    cellValue,
                    columnName: columnName,
                    detail: eventDetail,
                    rowIndex
                });
                if (!column) {
                    column = columns[columnName] = new Array(table.rowCount);
                }
                if (rowIndex >= table.rowCount) {
                    table.rowCount = (rowIndex + 1);
                }
                column[rowIndex] = cellValue;
                if (modifier) {
                    modifier.modifyCell(table, columnName, rowIndex, cellValue);
                }
                table.emit({
                    type: 'afterSetCell',
                    cellValue,
                    columnName: columnName,
                    detail: eventDetail,
                    rowIndex
                });
            }
            /**
             * Sets cell values for multiple columns. Will insert new columns, if not
             * found.
             *
             * @function Highcharts.DataTable#setColumns
             *
             * @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 {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @param {boolean} [typeAsOriginal=false]
             * Determines whether the original column retains its type when data
             * replaced. If `true`, the original column keeps its type. If not
             * (default), the original column will adopt the type of the replacement
             * column.
             *
             * @emits #setColumns
             * @emits #afterSetColumns
             */
            setColumns(columns, rowIndex, eventDetail, typeAsOriginal) {
                const table = this, tableColumns = table.columns, tableModifier = table.modifier, columnNames = Object.keys(columns);
                let rowCount = table.rowCount;
                table.emit({
                    type: 'setColumns',
                    columns,
                    columnNames,
                    detail: eventDetail,
                    rowIndex
                });
                if (!defined(rowIndex) && !typeAsOriginal) {
                    super.setColumns(columns, rowIndex, extend(eventDetail, { silent: true }));
                }
                else {
                    for (let i = 0, iEnd = columnNames.length, column, tableColumn, columnName, ArrayConstructor; i < iEnd; ++i) {
                        columnName = columnNames[i];
                        column = columns[columnName];
                        tableColumn = tableColumns[columnName];
                        ArrayConstructor = Object.getPrototypeOf((tableColumn && typeAsOriginal) ? tableColumn : column).constructor;
                        if (!tableColumn) {
                            tableColumn = new ArrayConstructor(rowCount);
                        }
                        else if (ArrayConstructor === Array) {
                            if (!Array.isArray(tableColumn)) {
                                tableColumn = Array.from(tableColumn);
                            }
                        }
                        else if (tableColumn.length < rowCount) {
                            tableColumn =
                                new ArrayConstructor(rowCount);
                            tableColumn.set(tableColumns[columnName]);
                        }
                        tableColumns[columnName] = tableColumn;
                        for (let i = (rowIndex || 0), iEnd = column.length; i < iEnd; ++i) {
                            tableColumn[i] = column[i];
                        }
                        rowCount = Math.max(rowCount, column.length);
                    }
                    this.applyRowCount(rowCount);
                }
                if (tableModifier) {
                    tableModifier.modifyColumns(table, columns, rowIndex || 0);
                }
                table.emit({
                    type: 'afterSetColumns',
                    columns,
                    columnNames,
                    detail: eventDetail,
                    rowIndex
                });
            }
            /**
             * Sets or unsets the modifier for the table.
             *
             * @param {Highcharts.DataModifier} [modifier]
             * Modifier to set, or `undefined` to unset.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Promise<Highcharts.DataTable>}
             * Resolves to this table if successful, or rejects on failure.
             *
             * @emits #setModifier
             * @emits #afterSetModifier
             */
            setModifier(modifier, eventDetail) {
                const table = this;
                let promise;
                table.emit({
                    type: 'setModifier',
                    detail: eventDetail,
                    modifier,
                    modified: table.modified
                });
                table.modified = table;
                table.modifier = modifier;
                if (modifier) {
                    promise = modifier.modify(table);
                }
                else {
                    promise = Promise.resolve(table);
                }
                return promise
                    .then((table) => {
                    table.emit({
                        type: 'afterSetModifier',
                        detail: eventDetail,
                        modifier,
                        modified: table.modified
                    });
                    return table;
                })['catch']((error) => {
                    table.emit({
                        type: 'setModifierError',
                        error,
                        modifier,
                        modified: table.modified
                    });
                    throw error;
                });
            }
            /**
             * Sets the original row indexes for the table. It is used to keep the
             * reference to the original rows when modifying the table.
             *
             * @param {Array<number|undefined>} originalRowIndexes
             * Original row indexes array.
             *
             * @param {boolean} omitLocalRowIndexes
             * Whether to omit the local row indexes calculation. Defaults to `false`.
             */
            setOriginalRowIndexes(originalRowIndexes, omitLocalRowIndexes = false) {
                this.originalRowIndexes = originalRowIndexes;
                if (omitLocalRowIndexes) {
                    return;
                }
                const modifiedIndexes = this.localRowIndexes = [];
                for (let i = 0, iEnd = originalRowIndexes.length, originalIndex; i < iEnd; ++i) {
                    originalIndex = originalRowIndexes[i];
                    if (defined(originalIndex)) {
                        modifiedIndexes[originalIndex] = i;
                    }
                }
            }
            /**
             * 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.
             *
             * Note: This function is just a simplified wrap of
             * {@link Highcharts.DataTable#setRows}.
             *
             * @function Highcharts.DataTable#setRow
             *
             * @param {Highcharts.DataTableRow|Highcharts.DataTableRowObject} 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 {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits #setRows
             * @emits #afterSetRows
             */
            setRow(row, rowIndex, insert, eventDetail) {
                this.setRows([row], rowIndex, insert, eventDetail);
            }
            /**
             * Sets cell values for multiple rows. Will insert new rows, if no index was
             * was provided, or if the index is higher than the total number of table
             * rows.
             *
             * @function Highcharts.DataTable#setRows
             *
             * @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
             * Row values to set.
             *
             * @param {number} [rowIndex]
             * Index of the first row to set. Leave `undefined` to add as new rows.
             *
             * @param {boolean} [insert]
             * Whether to insert the row at the given index, or to overwrite the row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits #setRows
             * @emits #afterSetRows
             */
            setRows(rows, rowIndex = this.rowCount, insert, eventDetail) {
                const table = this, columns = table.columns, columnNames = Object.keys(columns), modifier = table.modifier, rowCount = rows.length;
                table.emit({
                    type: 'setRows',
                    detail: eventDetail,
                    rowCount,
                    rowIndex,
                    rows
                });
                for (let i = 0, i2 = rowIndex, row; i < rowCount; ++i, ++i2) {
                    row = rows[i];
                    if (row === DataTable.NULL) {
                        for (let j = 0, jEnd = columnNames.length; j < jEnd; ++j) {
                            const column = columns[columnNames[j]];
                            if (insert) {
                                columns[columnNames[j]] = CU.splice(column, i2, 0, true, [null]).array;
                            }
                            else {
                                column[i2] = null;
                            }
                        }
                    }
                    else if (row instanceof Array) {
                        for (let j = 0, jEnd = columnNames.length; j < jEnd; ++j) {
                            columns[columnNames[j]][i2] = row[j];
                        }
                    }
                    else {
                        super.setRow(row, i2, void 0, { silent: true });
                    }
                }
                const indexRowCount = insert ?
                    rowCount + rows.length :
                    rowIndex + rowCount;
                if (indexRowCount > table.rowCount) {
                    table.rowCount = indexRowCount;
                    for (let i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
                        const columnName = columnNames[i];
                        columns[columnName] = CU.setLength(columns[columnName], indexRowCount);
                    }
                }
                if (modifier) {
                    modifier.modifyRows(table, rows, rowIndex);
                }
                table.emit({
                    type: 'afterSetRows',
                    detail: eventDetail,
                    rowCount,
                    rowIndex,
                    rows
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Null state for a row record. In some cases, a row in a table may not
         * contain any data or may be invalid. In these cases, a null state can be
         * used to indicate that the row record is empty or invalid.
         *
         * @name Highcharts.DataTable.NULL
         * @type {Highcharts.DataTableRowObject}
         *
         * @see {@link Highcharts.DataTable.isNull} for a null test.
         *
         * @example
         * table.setRows([DataTable.NULL, DataTable.NULL], 10);
         */
        DataTable.NULL = {};
        /**
         * Semantic version string of the DataTable class.
         * @internal
         */
        DataTable.version = '1.0.0';
        /* *
         *
         *  Default Export
         *
         * */

        return DataTable;
    });
    _registerModule(_modules, 'Data/Connectors/DataConnector.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Data/DataTable.js'], _modules['Core/Utilities.js']], function (DataModifier, DataTable, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Wojciech Chmiel
         *  - Gøran Slettemark
         *
         * */
        const { addEvent, fireEvent, merge, pick } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Abstract class providing an interface for managing a DataConnector.
         *
         * @private
         */
        class DataConnector {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructor for the connector class.
             *
             * @param {DataConnector.UserOptions} [options]
             * Options to use in the connector.
             *
             * @param {Array<DataTableOptions>} [dataTables]
             * Multiple connector data tables options.
             */
            constructor(options = {}, dataTables = []) {
                /**
                 * Tables managed by this DataConnector instance.
                 */
                this.dataTables = {};
                /**
                 * Helper flag for detecting whether the data connector is loaded.
                 * @internal
                 */
                this.loaded = false;
                this.metadata = options.metadata || { columns: {} };
                // Create a data table for each defined in the dataTables user options.
                let dataTableIndex = 0;
                if (dataTables?.length > 0) {
                    for (let i = 0, iEnd = dataTables.length; i < iEnd; ++i) {
                        const dataTable = dataTables[i];
                        const key = dataTable?.key;
                        this.dataTables[key ?? dataTableIndex] =
                            new DataTable(dataTable);
                        if (!key) {
                            dataTableIndex++;
                        }
                    }
                    // If user options dataTables is not defined, generate a default table.
                }
                else {
                    this.dataTables[0] = new DataTable(options.dataTable);
                }
            }
            /**
             * Poll timer ID, if active.
             */
            get polling() {
                return !!this._polling;
            }
            /**
             * Gets the first data table.
             *
             * @return {DataTable}
             * The data table instance.
             */
            get table() {
                return this.getTable();
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Method for adding metadata for a single column.
             *
             * @param {string} name
             * The name of the column to be described.
             *
             * @param {DataConnector.MetaColumn} columnMeta
             * The metadata to apply to the column.
             */
            describeColumn(name, columnMeta) {
                const connector = this, columns = connector.metadata.columns;
                columns[name] = merge(columns[name] || {}, columnMeta);
            }
            /**
             * Method for applying columns meta information to the whole DataConnector.
             *
             * @param {Highcharts.Dictionary<DataConnector.MetaColumn>} columns
             * Pairs of column names and MetaColumn objects.
             */
            describeColumns(columns) {
                const connector = this, columnNames = Object.keys(columns);
                let columnName;
                while (typeof (columnName = columnNames.pop()) === 'string') {
                    connector.describeColumn(columnName, columns[columnName]);
                }
            }
            /**
             * Emits an event on the connector to all registered callbacks of this
             * event.
             *
             * @param {DataConnector.Event} [e]
             * Event object containing additional event information.
             */
            emit(e) {
                fireEvent(this, e.type, e);
            }
            /**
             * Returns the order of columns.
             *
             * @param {boolean} [usePresentationState]
             * Whether to use the column order of the presentation state of the table.
             *
             * @return {Array<string>|undefined}
             * Order of columns.
             */
            getColumnOrder(
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            usePresentationState) {
                const connector = this, columns = connector.metadata.columns, names = Object.keys(columns || {});
                if (names.length) {
                    return names.sort((a, b) => (pick(columns[a].index, 0) - pick(columns[b].index, 0)));
                }
            }
            /**
             * Returns a single data table instance based on the provided key.
             * Otherwise, returns the first data table.
             *
             * @param {string} [key]
             * The data table key.
             *
             * @return {DataTable}
             * The data table instance.
             */
            getTable(key) {
                if (key) {
                    return this.dataTables[key];
                }
                return Object.values(this.dataTables)[0];
            }
            /**
             * Retrieves the columns of the dataTable,
             * applies column order from meta.
             *
             * @param {boolean} [usePresentationOrder]
             * Whether to use the column order of the presentation state of the table.
             *
             * @return {Highcharts.DataTableColumnCollection}
             * An object with the properties `columnNames` and `columnValues`
             */
            getSortedColumns(usePresentationOrder) {
                return this.table.getColumns(this.getColumnOrder(usePresentationOrder));
            }
            /**
             * The default load method, which fires the `afterLoad` event
             *
             * @return {Promise<DataConnector>}
             * The loaded connector.
             *
             * @emits DataConnector#afterLoad
             */
            load() {
                fireEvent(this, 'afterLoad', { table: this.table });
                return Promise.resolve(this);
            }
            /**
             * Registers a callback for a specific connector event.
             *
             * @param {string} type
             * Event type as a string.
             *
             * @param {DataEventEmitter.Callback} callback
             * Function to register for the connector callback.
             *
             * @return {Function}
             * Function to unregister callback from the connector event.
             */
            on(type, callback) {
                return addEvent(this, type, callback);
            }
            /**
             * The default save method, which fires the `afterSave` event.
             *
             * @return {Promise<DataConnector>}
             * The saved connector.
             *
             * @emits DataConnector#afterSave
             * @emits DataConnector#saveError
             */
            save() {
                fireEvent(this, 'saveError', { table: this.table });
                return Promise.reject(new Error('Not implemented'));
            }
            /**
             * Sets the index and order of columns.
             *
             * @param {Array<string>} columnNames
             * Order of columns.
             */
            setColumnOrder(columnNames) {
                const connector = this;
                for (let i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
                    connector.describeColumn(columnNames[i], { index: i });
                }
            }
            async setModifierOptions(modifierOptions, tablesOptions) {
                for (const [key, table] of Object.entries(this.dataTables)) {
                    const tableOptions = tablesOptions?.find((dataTable) => dataTable.key === key);
                    const mergedModifierOptions = merge(tableOptions?.dataModifier, modifierOptions);
                    const ModifierClass = (mergedModifierOptions &&
                        DataModifier.types[mergedModifierOptions.type]);
                    await table.setModifier(ModifierClass ?
                        new ModifierClass(mergedModifierOptions) :
                        void 0);
                }
                return this;
            }
            /**
             * Starts polling new data after the specific time span in milliseconds.
             *
             * @param {number} refreshTime
             * Refresh time in milliseconds between polls.
             */
            startPolling(refreshTime = 1000) {
                const connector = this;
                const tables = connector.dataTables;
                // Assign a new abort controller.
                this.pollingController = new AbortController();
                // Clear the polling timeout.
                window.clearTimeout(connector._polling);
                connector._polling = window.setTimeout(() => connector
                    .load()['catch']((error) => connector.emit({
                    type: 'loadError',
                    error,
                    tables
                }))
                    .then(() => {
                    if (connector._polling) {
                        connector.startPolling(refreshTime);
                    }
                }), refreshTime);
            }
            /**
             * Stops polling data. Shouldn't be performed if polling is already stopped.
             */
            stopPolling() {
                const connector = this;
                if (!connector.polling) {
                    return;
                }
                // Abort the existing request.
                connector?.pollingController?.abort();
                // Clear the polling timeout.
                window.clearTimeout(connector._polling);
                delete connector._polling;
            }
            /**
             * Retrieves metadata from a single column.
             *
             * @param {string} name
             * The identifier for the column that should be described
             *
             * @return {DataConnector.MetaColumn|undefined}
             * Returns a MetaColumn object if found.
             */
            whatIs(name) {
                return this.metadata.columns[name];
            }
            /**
             * Iterates over the dataTables and initiates the corresponding converters.
             * Updates the dataTables and assigns the first converter.
             *
             * @param {T}[data]
             * Data specific to the corresponding converter.
             *
             * @param {DataConnector.CreateConverterFunction}[createConverter]
             * Creates a specific converter combining the dataTable options.
             *
             * @param {DataConnector.ParseDataFunction<T>}[parseData]
             * Runs the converter parse method with the specific data type.
             */
            initConverters(data, createConverter, parseData) {
                let index = 0;
                for (const [key, table] of Object.entries(this.dataTables)) {
                    // Create a proper converter and parse its data.
                    const converter = createConverter(key, table);
                    parseData(converter, data);
                    // Update the dataTable.
                    table.deleteColumns();
                    table.setColumns(converter.getTable().getColumns());
                    // Assign the first converter.
                    if (index === 0) {
                        this.converter = converter;
                    }
                    index++;
                }
            }
        }
        /* *
         *
         *  Class Namespace
         *
         * */
        (function (DataConnector) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Constants
             *
             * */
            /**
             * Registry as a record object with connector names and their class.
             */
            DataConnector.types = {};
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Adds a connector class to the registry. The connector has to provide the
             * `DataConnector.options` property and the `DataConnector.load` method to
             * modify the table.
             *
             * @private
             *
             * @param {string} key
             * Registry key of the connector class.
             *
             * @param {DataConnectorType} DataConnectorClass
             * Connector class (aka class constructor) to register.
             *
             * @return {boolean}
             * Returns true, if the registration was successful. False is returned, if
             * their is already a connector registered with this key.
             */
            function registerType(key, DataConnectorClass) {
                return (!!key &&
                    !DataConnector.types[key] &&
                    !!(DataConnector.types[key] = DataConnectorClass));
            }
            DataConnector.registerType = registerType;
        })(DataConnector || (DataConnector = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return DataConnector;
    });
    _registerModule(_modules, 'Data/Converters/DataConverter.js', [_modules['Data/DataTable.js'], _modules['Core/Utilities.js']], function (DataTable, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Sebastian Bochan
         *  - Gøran Slettemark
         *  - Torstein Hønsi
         *  - Wojciech Chmiel
         *  - Jomar Hønsi
         *
         * */
        const { addEvent, fireEvent, isNumber, merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Base class providing an interface and basic methods for a DataConverter
         *
         * @private
         */
        class DataConverter {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the DataConverter.
             *
             * @param {DataConverter.UserOptions} [options]
             * Options for the DataConverter.
             */
            constructor(options) {
                /* *
                 *
                 *  Properties
                 *
                 * */
                /**
                 * A collection of available date formats.
                 */
                this.dateFormats = {
                    'YYYY/mm/dd': {
                        regex: /^(\d{4})([\-\.\/])(\d{1,2})\2(\d{1,2})$/,
                        parser: function (match) {
                            return (match ?
                                Date.UTC(+match[1], match[3] - 1, +match[4]) :
                                NaN);
                        }
                    },
                    'dd/mm/YYYY': {
                        regex: /^(\d{1,2})([\-\.\/])(\d{1,2})\2(\d{4})$/,
                        parser: function (match) {
                            return (match ?
                                Date.UTC(+match[4], match[3] - 1, +match[1]) :
                                NaN);
                        },
                        alternative: 'mm/dd/YYYY' // Different format with the same regex
                    },
                    'mm/dd/YYYY': {
                        regex: /^(\d{1,2})([\-\.\/])(\d{1,2})\2(\d{4})$/,
                        parser: function (match) {
                            return (match ?
                                Date.UTC(+match[4], match[1] - 1, +match[3]) :
                                NaN);
                        }
                    },
                    'dd/mm/YY': {
                        regex: /^(\d{1,2})([\-\.\/])(\d{1,2})\2(\d{2})$/,
                        parser: function (match) {
                            const d = new Date();
                            if (!match) {
                                return NaN;
                            }
                            let year = +match[4];
                            if (year > (d.getFullYear() - 2000)) {
                                year += 1900;
                            }
                            else {
                                year += 2000;
                            }
                            return Date.UTC(year, match[3] - 1, +match[1]);
                        },
                        alternative: 'mm/dd/YY' // Different format with the same regex
                    },
                    'mm/dd/YY': {
                        regex: /^(\d{1,2})([\-\.\/])(\d{1,2})\2(\d{2})$/,
                        parser: function (match) {
                            return (match ?
                                Date.UTC(+match[4] + 2000, match[1] - 1, +match[3]) :
                                NaN);
                        }
                    }
                };
                const mergedOptions = merge(DataConverter.defaultOptions, options);
                let regExpPoint = mergedOptions.decimalPoint;
                if (regExpPoint === '.' || regExpPoint === ',') {
                    regExpPoint = regExpPoint === '.' ? '\\.' : ',';
                    this.decimalRegExp =
                        new RegExp('^(-?[0-9]+)' + regExpPoint + '([0-9]+)$');
                }
                this.options = mergedOptions;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Converts a value to a boolean.
             *
             * @param {DataConverter.Type} value
             * Value to convert.
             *
             * @return {boolean}
             * Converted value as a boolean.
             */
            asBoolean(value) {
                if (typeof value === 'boolean') {
                    return value;
                }
                if (typeof value === 'string') {
                    return value !== '' && value !== '0' && value !== 'false';
                }
                return !!this.asNumber(value);
            }
            /**
             * Converts a value to a Date.
             *
             * @param {DataConverter.Type} value
             * Value to convert.
             *
             * @return {globalThis.Date}
             * Converted value as a Date.
             */
            asDate(value) {
                let timestamp;
                if (typeof value === 'string') {
                    timestamp = this.parseDate(value);
                }
                else if (typeof value === 'number') {
                    timestamp = value;
                }
                else if (value instanceof Date) {
                    return value;
                }
                else {
                    timestamp = this.parseDate(this.asString(value));
                }
                return new Date(timestamp);
            }
            /**
             * Casts a string value to it's guessed type
             *
             * @param {*} value
             * The value to examine.
             *
             * @return {number|string|Date}
             * The converted value.
             */
            asGuessedType(value) {
                const converter = this, typeMap = {
                    'number': converter.asNumber,
                    'Date': converter.asDate,
                    'string': converter.asString
                };
                return typeMap[converter.guessType(value)].call(converter, value);
            }
            /**
             * Converts a value to a number.
             *
             * @param {DataConverter.Type} value
             * Value to convert.
             *
             * @return {number}
             * Converted value as a number.
             */
            asNumber(value) {
                if (typeof value === 'number') {
                    return value;
                }
                if (typeof value === 'boolean') {
                    return value ? 1 : 0;
                }
                if (typeof value === 'string') {
                    const decimalRegex = this.decimalRegExp;
                    if (value.indexOf(' ') > -1) {
                        value = value.replace(/\s+/g, '');
                    }
                    if (decimalRegex) {
                        if (!decimalRegex.test(value)) {
                            return NaN;
                        }
                        value = value.replace(decimalRegex, '$1.$2');
                    }
                    return parseFloat(value);
                }
                if (value instanceof Date) {
                    return value.getDate();
                }
                if (value) {
                    return value.getRowCount();
                }
                return NaN;
            }
            /**
             * Converts a value to a string.
             *
             * @param {DataConverter.Type} value
             * Value to convert.
             *
             * @return {string}
             * Converted value as a string.
             */
            asString(value) {
                return '' + value;
            }
            /**
             * Tries to guess the date format
             *  - Check if either month candidate exceeds 12
             *  - Check if year is missing (use current year)
             *  - Check if a shortened year format is used (e.g. 1/1/99)
             *  - If no guess can be made, the user must be prompted
             * data is the data to deduce a format based on
             * @private
             *
             * @param {Array<string>} data
             * Data to check the format.
             *
             * @param {number} limit
             * Max data to check the format.
             *
             * @param {boolean} save
             * Whether to save the date format in the converter options.
             */
            deduceDateFormat(data, limit, save) {
                const parser = this, stable = [], max = [];
                let format = 'YYYY/mm/dd', thing, guessedFormat = [], i = 0, madeDeduction = false, 
                /// candidates = {},
                elem, j;
                if (!limit || limit > data.length) {
                    limit = data.length;
                }
                for (; i < limit; i++) {
                    if (typeof data[i] !== 'undefined' &&
                        data[i] && data[i].length) {
                        thing = data[i]
                            .trim()
                            .replace(/[\-\.\/]/g, ' ')
                            .split(' ');
                        guessedFormat = [
                            '',
                            '',
                            ''
                        ];
                        for (j = 0; j < thing.length; j++) {
                            if (j < guessedFormat.length) {
                                elem = parseInt(thing[j], 10);
                                if (elem) {
                                    max[j] = (!max[j] || max[j] < elem) ? elem : max[j];
                                    if (typeof stable[j] !== 'undefined') {
                                        if (stable[j] !== elem) {
                                            stable[j] = false;
                                        }
                                    }
                                    else {
                                        stable[j] = elem;
                                    }
                                    if (elem > 31) {
                                        if (elem < 100) {
                                            guessedFormat[j] = 'YY';
                                        }
                                        else {
                                            guessedFormat[j] = 'YYYY';
                                        }
                                        /// madeDeduction = true;
                                    }
                                    else if (elem > 12 &&
                                        elem <= 31) {
                                        guessedFormat[j] = 'dd';
                                        madeDeduction = true;
                                    }
                                    else if (!guessedFormat[j].length) {
                                        guessedFormat[j] = 'mm';
                                    }
                                }
                            }
                        }
                    }
                }
                if (madeDeduction) {
                    // This handles a few edge cases with hard to guess dates
                    for (j = 0; j < stable.length; j++) {
                        if (stable[j] !== false) {
                            if (max[j] > 12 &&
                                guessedFormat[j] !== 'YY' &&
                                guessedFormat[j] !== 'YYYY') {
                                guessedFormat[j] = 'YY';
                            }
                        }
                        else if (max[j] > 12 && guessedFormat[j] === 'mm') {
                            guessedFormat[j] = 'dd';
                        }
                    }
                    // If the middle one is dd, and the last one is dd,
                    // the last should likely be year.
                    if (guessedFormat.length === 3 &&
                        guessedFormat[1] === 'dd' &&
                        guessedFormat[2] === 'dd') {
                        guessedFormat[2] = 'YY';
                    }
                    format = guessedFormat.join('/');
                    // If the caculated format is not valid, we need to present an
                    // error.
                }
                // Save the deduced format in the converter options.
                if (save) {
                    parser.options.dateFormat = format;
                }
                return format;
            }
            /**
             * Emits an event on the DataConverter instance.
             *
             * @param {DataConverter.Event} [e]
             * Event object containing additional event data
             */
            emit(e) {
                fireEvent(this, e.type, e);
            }
            /**
             * Initiates the data exporting. Should emit `exportError` on failure.
             *
             * @param {DataConnector} connector
             * Connector to export from.
             *
             * @param {DataConverter.Options} [options]
             * Options for the export.
             */
            export(
            /* eslint-disable @typescript-eslint/no-unused-vars */
            connector, options
            /* eslint-enable @typescript-eslint/no-unused-vars */
            ) {
                this.emit({
                    type: 'exportError',
                    columns: [],
                    headers: []
                });
                throw new Error('Not implemented');
            }
            /**
             * Getter for the data table.
             *
             * @return {DataTable}
             * Table of parsed data.
             */
            getTable() {
                throw new Error('Not implemented');
            }
            /**
             * Guesses the potential type of a string value for parsing CSV etc.
             *
             * @param {*} value
             * The value to examine.
             *
             * @return {'number'|'string'|'Date'}
             * Type string, either `string`, `Date`, or `number`.
             */
            guessType(value) {
                const converter = this;
                let result = 'string';
                if (typeof value === 'string') {
                    const trimedValue = converter.trim(`${value}`), decimalRegExp = converter.decimalRegExp;
                    let innerTrimedValue = converter.trim(trimedValue, true);
                    if (decimalRegExp) {
                        innerTrimedValue = (decimalRegExp.test(innerTrimedValue) ?
                            innerTrimedValue.replace(decimalRegExp, '$1.$2') :
                            '');
                    }
                    const floatValue = parseFloat(innerTrimedValue);
                    if (+innerTrimedValue === floatValue) {
                        // String is numeric
                        value = floatValue;
                    }
                    else {
                        // Determine if a date string
                        const dateValue = converter.parseDate(value);
                        result = isNumber(dateValue) ? 'Date' : 'string';
                    }
                }
                if (typeof value === 'number') {
                    // Greater than milliseconds in a year assumed timestamp
                    result = value > 365 * 24 * 3600 * 1000 ? 'Date' : 'number';
                }
                return result;
            }
            /**
             * Registers a callback for a specific event.
             *
             * @param {string} type
             * Event type as a string.
             *
             * @param {DataEventEmitter.Callback} callback
             * Function to register for an modifier callback.
             *
             * @return {Function}
             * Function to unregister callback from the modifier event.
             */
            on(type, callback) {
                return addEvent(this, type, callback);
            }
            /**
             * Initiates the data parsing. Should emit `parseError` on failure.
             *
             * @param {DataConverter.UserOptions} options
             * Options of the DataConverter.
             */
            parse(
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            options) {
                this.emit({
                    type: 'parseError',
                    columns: [],
                    headers: []
                });
                throw new Error('Not implemented');
            }
            /**
             * Parse a date and return it as a number.
             *
             * @param {string} value
             * Value to parse.
             *
             * @param {string} dateFormatProp
             * Which of the predefined date formats
             * to use to parse date values.
             */
            parseDate(value, dateFormatProp) {
                const converter = this, options = converter.options;
                let dateFormat = dateFormatProp || options.dateFormat, result = NaN, key, format, match;
                if (options.parseDate) {
                    result = options.parseDate(value);
                }
                else {
                    // Auto-detect the date format the first time
                    if (!dateFormat) {
                        for (key in converter.dateFormats) { // eslint-disable-line guard-for-in
                            format = converter.dateFormats[key];
                            match = value.match(format.regex);
                            if (match) {
                                // `converter.options.dateFormat` = dateFormat = key;
                                dateFormat = key;
                                // `converter.options.alternativeFormat` =
                                // format.alternative || '';
                                result = format.parser(match);
                                break;
                            }
                        }
                        // Next time, use the one previously found
                    }
                    else {
                        format = converter.dateFormats[dateFormat];
                        if (!format) {
                            // The selected format is invalid
                            format = converter.dateFormats['YYYY/mm/dd'];
                        }
                        match = value.match(format.regex);
                        if (match) {
                            result = format.parser(match);
                        }
                    }
                    // Fall back to Date.parse
                    if (!match) {
                        match = Date.parse(value);
                        // External tools like Date.js and MooTools extend Date object
                        // and returns a date.
                        if (typeof match === 'object' &&
                            match !== null &&
                            match.getTime) {
                            result = (match.getTime() -
                                match.getTimezoneOffset() *
                                    60000);
                            // Timestamp
                        }
                        else if (isNumber(match)) {
                            result = match - (new Date(match)).getTimezoneOffset() * 60000;
                            if ( // Reset dates without year in Chrome
                            value.indexOf('2001') === -1 &&
                                (new Date(result)).getFullYear() === 2001) {
                                result = NaN;
                            }
                        }
                    }
                }
                return result;
            }
            /**
             * Trim a string from whitespaces.
             *
             * @param {string} str
             * String to trim.
             *
             * @param {boolean} [inside=false]
             * Remove all spaces between numbers.
             *
             * @return {string}
             * Trimed string
             */
            trim(str, inside) {
                if (typeof str === 'string') {
                    str = str.replace(/^\s+|\s+$/g, '');
                    // Clear white space insdie the string, like thousands separators
                    if (inside && /^[\d\s]+$/.test(str)) {
                        str = str.replace(/\s/g, '');
                    }
                }
                return str;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options
         */
        DataConverter.defaultOptions = {
            dateFormat: '',
            alternativeFormat: '',
            startColumn: 0,
            endColumn: Number.MAX_VALUE,
            startRow: 0,
            endRow: Number.MAX_VALUE,
            firstRowAsNames: true,
            switchRowsAndColumns: false
        };
        /* *
         *
         *  Class Namespace
         *
         * */
        /**
         * Additionally provided types for events and conversion.
         */
        (function (DataConverter) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Constants
             *
             * */
            /**
             * Registry as a record object with connector names and their class.
             */
            DataConverter.types = {};
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Adds a converter class to the registry.
             *
             * @private
             *
             * @param {string} key
             * Registry key of the converter class.
             *
             * @param {DataConverterTypes} DataConverterClass
             * Connector class (aka class constructor) to register.
             *
             * @return {boolean}
             * Returns true, if the registration was successful. False is returned, if
             * their is already a converter registered with this key.
             */
            function registerType(key, DataConverterClass) {
                return (!!key &&
                    !DataConverter.types[key] &&
                    !!(DataConverter.types[key] = DataConverterClass));
            }
            DataConverter.registerType = registerType;
            /**
             * Converts an array of columns to a table instance. Second dimension of the
             * array are the row cells.
             *
             * @param {Array<DataTable.Column>} [columns]
             * Array to convert.
             *
             * @param {Array<string>} [headers]
             * Column names to use.
             *
             * @return {DataTable}
             * Table instance from the arrays.
             */
            function getTableFromColumns(columns = [], headers = []) {
                const table = new DataTable();
                for (let i = 0, iEnd = Math.max(headers.length, columns.length); i < iEnd; ++i) {
                    table.setColumn(headers[i] || `${i}`, columns[i]);
                }
                return table;
            }
            DataConverter.getTableFromColumns = getTableFromColumns;
        })(DataConverter || (DataConverter = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return DataConverter;
    });
    _registerModule(_modules, 'Data/DataCursor.js', [], function () {
        /* *
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * This class manages state cursors pointing on {@link Data.DataTable}. It
         * creates a relation between states of the user interface and the table cells,
         * columns, or rows.
         *
         * @class
         * @name Data.DataCursor
         */
        class DataCursor {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(stateMap = {}) {
                this.emittingRegister = [];
                this.listenerMap = {};
                this.stateMap = stateMap;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * This function registers a listener for a specific state and table.
             *
             * @example
             * ```TypeScript
             * dataCursor.addListener(myTable.id, 'hover', (e: DataCursor.Event) => {
             *     if (e.cursor.type === 'position') {
             *         console.log(`Hover over row #${e.cursor.row}.`);
             *     }
             * });
             * ```
             *
             * @function #addListener
             *
             * @param {Data.DataCursor.TableId} tableId
             * The ID of the table to listen to.
             *
             * @param {Data.DataCursor.State} state
             * The state on the table to listen to.
             *
             * @param {Data.DataCursor.Listener} listener
             * The listener to register.
             *
             * @return {Data.DataCursor}
             * Returns the DataCursor instance for a call chain.
             */
            addListener(tableId, state, listener) {
                const listenerMap = this.listenerMap[tableId] = (this.listenerMap[tableId] ||
                    {});
                const listeners = listenerMap[state] = (listenerMap[state] ||
                    []);
                listeners.push(listener);
                return this;
            }
            /**
             * @private
             */
            buildEmittingTag(e) {
                return (e.cursor.type === 'position' ?
                    [
                        e.table.id,
                        e.cursor.column,
                        e.cursor.row,
                        e.cursor.state,
                        e.cursor.type
                    ] :
                    [
                        e.table.id,
                        e.cursor.columns,
                        e.cursor.firstRow,
                        e.cursor.lastRow,
                        e.cursor.state,
                        e.cursor.type
                    ]).join('\0');
            }
            /**
             * This function emits a state cursor related to a table. It will provide
             * lasting state cursors of the table to listeners.
             *
             * @example
             * ```ts
             * dataCursor.emit(myTable, {
             *     type: 'position',
             *     column: 'city',
             *     row: 4,
             *     state: 'hover',
             * });
             * ```
             *
             * @param {Data.DataTable} table
             * The related table of the cursor.
             *
             * @param {Data.DataCursor.Type} cursor
             * The state cursor to emit.
             *
             * @param {Event} [event]
             * Optional event information from a related source.
             *
             * @param {boolean} [lasting]
             * Whether this state cursor should be kept until it is cleared with
             * {@link DataCursor#remitCursor}.
             *
             * @return {Data.DataCursor}
             * Returns the DataCursor instance for a call chain.
             */
            emitCursor(table, cursor, event, lasting) {
                const tableId = table.id, state = cursor.state, listeners = (this.listenerMap[tableId] &&
                    this.listenerMap[tableId][state]);
                if (listeners) {
                    const stateMap = this.stateMap[tableId] = (this.stateMap[tableId] ?? {});
                    const cursors = stateMap[cursor.state] || [];
                    if (lasting) {
                        if (!cursors.length) {
                            stateMap[cursor.state] = cursors;
                        }
                        if (DataCursor.getIndex(cursor, cursors) === -1) {
                            cursors.push(cursor);
                        }
                    }
                    const e = {
                        cursor,
                        cursors,
                        table
                    };
                    if (event) {
                        e.event = event;
                    }
                    const emittingRegister = this.emittingRegister, emittingTag = this.buildEmittingTag(e);
                    if (emittingRegister.indexOf(emittingTag) >= 0) {
                        // Break call stack loops
                        return this;
                    }
                    try {
                        this.emittingRegister.push(emittingTag);
                        for (let i = 0, iEnd = listeners.length; i < iEnd; ++i) {
                            listeners[i].call(this, e);
                        }
                    }
                    finally {
                        const index = this.emittingRegister.indexOf(emittingTag);
                        if (index >= 0) {
                            this.emittingRegister.splice(index, 1);
                        }
                    }
                }
                return this;
            }
            /**
             * Removes a lasting state cursor.
             *
             * @function #remitCursor
             *
             * @param {string} tableId
             * ID of the related cursor table.
             *
             * @param {Data.DataCursor.Type} cursor
             * Copy or reference of the cursor.
             *
             * @return {Data.DataCursor}
             * Returns the DataCursor instance for a call chain.
             */
            remitCursor(tableId, cursor) {
                const cursors = (this.stateMap[tableId] &&
                    this.stateMap[tableId][cursor.state]);
                if (cursors) {
                    const index = DataCursor.getIndex(cursor, cursors);
                    if (index >= 0) {
                        cursors.splice(index, 1);
                    }
                }
                return this;
            }
            /**
             * This function removes a listener.
             *
             * @function #addListener
             *
             * @param {Data.DataCursor.TableId} tableId
             * The ID of the table the listener is connected to.
             *
             * @param {Data.DataCursor.State} state
             * The state on the table the listener is listening to.
             *
             * @param {Data.DataCursor.Listener} listener
             * The listener to deregister.
             *
             * @return {Data.DataCursor}
             * Returns the DataCursor instance for a call chain.
             */
            removeListener(tableId, state, listener) {
                const listeners = (this.listenerMap[tableId] &&
                    this.listenerMap[tableId][state]);
                if (listeners) {
                    const index = listeners.indexOf(listener);
                    if (index >= 0) {
                        listeners.splice(index, 1);
                    }
                }
                return this;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Semantic version string of the DataCursor class.
         * @internal
         */
        DataCursor.version = '1.0.0';
        /* *
         *
         *  Class Namespace
         *
         * */
        /**
         * @class Data.DataCursor
         */
        (function (DataCursor) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Finds the index of an cursor in an array.
             * @private
             */
            function getIndex(needle, cursors) {
                if (needle.type === 'position') {
                    for (let cursor, i = 0, iEnd = cursors.length; i < iEnd; ++i) {
                        cursor = cursors[i];
                        if (cursor.type === 'position' &&
                            cursor.state === needle.state &&
                            cursor.column === needle.column &&
                            cursor.row === needle.row) {
                            return i;
                        }
                    }
                }
                else {
                    const columnNeedle = JSON.stringify(needle.columns);
                    for (let cursor, i = 0, iEnd = cursors.length; i < iEnd; ++i) {
                        cursor = cursors[i];
                        if (cursor.type === 'range' &&
                            cursor.state === needle.state &&
                            cursor.firstRow === needle.firstRow &&
                            cursor.lastRow === needle.lastRow &&
                            JSON.stringify(cursor.columns) === columnNeedle) {
                            return i;
                        }
                    }
                }
                return -1;
            }
            DataCursor.getIndex = getIndex;
            /**
             * Checks whether two cursor share the same properties.
             * @private
             */
            function isEqual(cursorA, cursorB) {
                if (cursorA.type === 'position' && cursorB.type === 'position') {
                    return (cursorA.column === cursorB.column &&
                        cursorA.row === cursorB.row &&
                        cursorA.state === cursorB.state);
                }
                if (cursorA.type === 'range' && cursorB.type === 'range') {
                    return (cursorA.firstRow === cursorB.firstRow &&
                        cursorA.lastRow === cursorB.lastRow &&
                        (JSON.stringify(cursorA.columns) ===
                            JSON.stringify(cursorB.columns)));
                }
                return false;
            }
            DataCursor.isEqual = isEqual;
            /**
             * Checks whether a cursor is in a range.
             * @private
             */
            function isInRange(needle, range) {
                if (range.type === 'position') {
                    range = toRange(range);
                }
                if (needle.type === 'position') {
                    needle = toRange(needle, range);
                }
                const needleColumns = needle.columns;
                const rangeColumns = range.columns;
                return (needle.firstRow >= range.firstRow &&
                    needle.lastRow <= range.lastRow &&
                    (!needleColumns ||
                        !rangeColumns ||
                        needleColumns.every((column) => rangeColumns.indexOf(column) >= 0)));
            }
            DataCursor.isInRange = isInRange;
            /**
             * @private
             */
            function toPositions(cursor) {
                if (cursor.type === 'position') {
                    return [cursor];
                }
                const columns = (cursor.columns || []);
                const positions = [];
                const state = cursor.state;
                for (let row = cursor.firstRow, rowEnd = cursor.lastRow; row < rowEnd; ++row) {
                    if (!columns.length) {
                        positions.push({
                            type: 'position',
                            row,
                            state
                        });
                        continue;
                    }
                    for (let column = 0, columnEnd = columns.length; column < columnEnd; ++column) {
                        positions.push({
                            type: 'position',
                            column: columns[column],
                            row,
                            state
                        });
                    }
                }
                return positions;
            }
            DataCursor.toPositions = toPositions;
            /**
             * @private
             */
            function toRange(cursor, defaultRange) {
                if (cursor.type === 'range') {
                    return cursor;
                }
                const range = {
                    type: 'range',
                    firstRow: (cursor.row ??
                        (defaultRange && defaultRange.firstRow) ??
                        0),
                    lastRow: (cursor.row ??
                        (defaultRange && defaultRange.lastRow) ??
                        Number.MAX_VALUE),
                    state: cursor.state
                };
                if (typeof cursor.column !== 'undefined') {
                    range.columns = [cursor.column];
                }
                return range;
            }
            DataCursor.toRange = toRange;
        })(DataCursor || (DataCursor = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return DataCursor;
    });
    _registerModule(_modules, 'Accessibility/HighContrastMode.js', [_modules['Core/Globals.js']], function (H) {
        /* *
         *
         *  (c) 2009-2025 Øystein Moseng
         *
         *  Handling for Windows High Contrast Mode.
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { doc, isMS, win } = H;
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Detect WHCM in the browser.
         *
         * @function Highcharts#isHighContrastModeActive
         * @private
         * @return {boolean} Returns true if the browser is in High Contrast mode.
         */
        function isHighContrastModeActive() {
            // Test BG image for IE
            if (isMS && win.getComputedStyle) {
                const testDiv = doc.createElement('div');
                const imageSrc = 'data:image/gif;base64,' +
                    'R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
                testDiv.style.backgroundImage = `url(${imageSrc})`; // #13071
                doc.body.appendChild(testDiv);
                const bi = (testDiv.currentStyle ||
                    win.getComputedStyle(testDiv)).backgroundImage;
                doc.body.removeChild(testDiv);
                return bi === 'none';
            }
            // Other browsers use the forced-colors standard
            return win.matchMedia && win.matchMedia('(forced-colors: active)').matches;
        }
        /**
         * Force high contrast theme for the chart. The default theme is defined in
         * a separate file.
         *
         * @function Highcharts#setHighContrastTheme
         * @private
         * @param {Highcharts.AccessibilityChart} chart The chart to set the theme of.
         * @return {void}
         */
        function setHighContrastTheme(chart) {
            // We might want to add additional functionality here in the future for
            // storing the old state so that we can reset the theme if HC mode is
            // disabled. For now, the user will have to reload the page.
            chart.highContrastModeActive = true;
            // Apply theme to chart
            const theme = (chart.options.accessibility.highContrastTheme);
            chart.update(theme, false);
            const hasCustomColors = theme.colors?.length > 1;
            // Force series colors (plotOptions is not enough)
            chart.series.forEach(function (s) {
                const plotOpts = theme.plotOptions[s.type] || {};
                const fillColor = hasCustomColors && s.colorIndex !== void 0 ?
                    theme.colors[s.colorIndex] :
                    plotOpts.color || 'window';
                const seriesOptions = {
                    color: plotOpts.color || 'windowText',
                    colors: hasCustomColors ?
                        theme.colors : [plotOpts.color || 'windowText'],
                    borderColor: plotOpts.borderColor || 'window',
                    fillColor
                };
                s.update(seriesOptions, false);
                if (s.points) {
                    // Force point colors if existing
                    s.points.forEach(function (p) {
                        if (p.options && p.options.color) {
                            p.update({
                                color: plotOpts.color || 'windowText',
                                borderColor: plotOpts.borderColor || 'window'
                            }, false);
                        }
                    });
                }
            });
            // The redraw for each series and after is required for 3D pie
            // (workaround)
            chart.redraw();
        }
        /* *
         *
         *  Default Export
         *
         * */
        const whcm = {
            isHighContrastModeActive,
            setHighContrastTheme
        };

        return whcm;
    });
    _registerModule(_modules, 'Grid/Core/Accessibility/Accessibility.js', [_modules['Accessibility/HighContrastMode.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Core/GridUtils.js']], function (whcm, Globals, GridUtils) {
        /* *
         *
         *  Grid Accessibility class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GridUtils;
        /**
         *  Representing the accessibility functionalities for the Data Grid.
         */
        class Accessibility {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Construct the accessibility object.
             *
             * @param grid
             * The Grid Table instance which the accessibility controller belong to.
             */
            constructor(grid) {
                this.grid = grid;
                this.element = document.createElement('div');
                this.element.classList.add(Globals.getClassName('visuallyHidden'));
                this.grid.container?.prepend(this.element);
                this.announcerElement = document.createElement('p');
                this.announcerElement.setAttribute('aria-atomic', 'true');
                this.announcerElement.setAttribute('aria-hidden', 'false');
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Add the 'sortable' hint span element for the sortable column.
             *
             * @param element
             * The element to add the description to.
             */
            addSortableColumnHint(element) {
                const sortableLang = this.grid.options?.lang?.accessibility?.sorting?.sortable;
                if (!sortableLang) {
                    return;
                }
                makeHTMLElement('span', {
                    className: Globals.getClassName('visuallyHidden'),
                    innerText: ', ' + sortableLang
                }, element);
            }
            /**
             * Add the description to the header cell.
             *
             * @param thElement
             * The header cell element to add the description to.
             *
             * @param description
             * The description to be added.
             */
            addHeaderCellDescription(thElement, description) {
                if (description) {
                    thElement.setAttribute('aria-description', description);
                }
            }
            /**
             * Announce the message to the screen reader.
             *
             * @param msg
             * The message to be announced.
             *
             * @param assertive
             * Whether the message should be assertive. Default is false.
             */
            announce(msg, assertive = false) {
                if (this.announcerTimeout) {
                    clearTimeout(this.announcerTimeout);
                }
                this.announcerElement.remove();
                this.announcerElement.setAttribute('aria-live', assertive ? 'assertive' : 'polite');
                this.element.appendChild(this.announcerElement);
                this.announcerElement.textContent = msg;
                this.announcerTimeout = setTimeout(() => {
                    this.announcerElement.remove();
                }, 3000);
            }
            /**
             * Announce the message to the screen reader that the user sorted the
             * column.
             *
             * @param order
             * The order of the sorting.
             */
            userSortedColumn(order) {
                const { options } = this.grid;
                const announcementsLang = options?.lang
                    ?.accessibility?.sorting?.announcements;
                if (!options?.accessibility?.announcements?.sorting) {
                    return;
                }
                let msg;
                switch (order) {
                    case 'asc':
                        msg = announcementsLang?.ascending;
                        break;
                    case 'desc':
                        msg = announcementsLang?.descending;
                        break;
                    default:
                        msg = announcementsLang?.none;
                }
                if (!msg) {
                    return;
                }
                this.announce(msg, true);
            }
            /**
             * Set the aria sort state of the column header cell element.
             *
             * @param thElement
             * The header cell element to set the `aria-sort` state to.
             *
             * @param state
             * The sort state to be set for the column header cell.
             */
            setColumnSortState(thElement, state) {
                thElement?.setAttribute('aria-sort', state);
            }
            /**
             * Adds high contrast CSS class, if the browser is in High Contrast mode.
             */
            addHighContrast() {
                const highContrastMode = this.grid.options?.accessibility?.highContrastMode;
                if (highContrastMode !== false && (whcm.isHighContrastModeActive() ||
                    highContrastMode === true)) {
                    this.grid.contentWrapper?.classList.add('hcg-theme-highcontrast');
                }
            }
            /**
             * Set the row index attribute for the row element.
             *
             * @param el
             * The row element to set the index to.
             *
             * @param idx
             * The index of the row in the data table.
             */
            setRowIndex(el, idx) {
                el.setAttribute('aria-rowindex', idx);
            }
            /**
             * Set a11y options for the Grid.
             */
            setA11yOptions() {
                const grid = this.grid;
                const tableEl = grid.tableElement;
                if (!tableEl) {
                    return;
                }
                tableEl.setAttribute('aria-rowcount', grid.dataTable?.getRowCount() || 0);
                if (grid.captionElement) {
                    tableEl.setAttribute('aria-labelledby', grid.captionElement.id);
                }
                if (grid.descriptionElement) {
                    tableEl.setAttribute('aria-describedby', grid.descriptionElement.id);
                }
                this.addHighContrast();
            }
            /**
             * Destroy the accessibility controller.
             */
            destroy() {
                this.element.remove();
                this.announcerElement.remove();
                clearTimeout(this.announcerTimeout);
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Accessibility;
    });
    _registerModule(_modules, 'Grid/Core/Defaults.js', [_modules['Core/Utilities.js']], function (Utils) {
        /* *
         *
         *  Grid default options
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { merge } = Utils;
        /**
         * Namespace for default options.
         */
        var Defaults;
        (function (Defaults) {
            /**
             * Default options for the Grid.
             * @internal
             */
            Defaults.defaultOptions = {
                accessibility: {
                    enabled: true,
                    highContrastMode: 'auto',
                    announcements: {
                        sorting: true
                    }
                },
                lang: {
                    accessibility: {
                        sorting: {
                            sortable: 'Sortable.',
                            announcements: {
                                ascending: 'Sorted ascending.',
                                descending: 'Sorted descending.',
                                none: 'Not sorted.'
                            }
                        }
                    },
                    loading: 'Loading...',
                    noData: 'No data to display'
                },
                time: {
                    timezone: 'UTC'
                },
                rendering: {
                    rows: {
                        bufferSize: 10,
                        minVisibleRows: 2,
                        strictHeights: false,
                        virtualizationThreshold: 50
                    },
                    header: {
                        enabled: true
                    },
                    columns: {
                        resizing: {
                            enabled: true
                        }
                    },
                    theme: 'hcg-theme-default'
                },
                columnDefaults: {
                    sorting: {
                        sortable: true
                    }
                }
            };
            /**
             * Merge the default options with custom options. Commonly used for defining
             * reusable templates.
             *
             * @param options
             * The new custom chart options.
             */
            function setOptions(options) {
                merge(true, Defaults.defaultOptions, options);
            }
            Defaults.setOptions = setOptions;
        })(Defaults || (Defaults = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return Defaults;
    });
    _registerModule(_modules, 'Grid/Core/Table/CellContent/CellContent.js', [], function () {
        /* *
         *
         *  Cell Content abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a cell content in the grid.
         */
        class CellContent {
            /**
             * Creates and renders the cell content.
             *
             * @param cell
             * The cell to which the content belongs.
             */
            constructor(cell) {
                this.cell = cell;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return CellContent;
    });
    _registerModule(_modules, 'Grid/Core/Table/CellContent/TextContent.js', [_modules['Core/Renderer/HTML/AST.js'], _modules['Grid/Core/Table/CellContent/CellContent.js'], _modules['Grid/Core/GridUtils.js'], _modules['Core/Utilities.js']], function (AST, CellContent, GridUtils, Utils) {
        /* *
         *
         *  Text Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { setHTMLContent } = GridUtils;
        const { defined } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a text type of content.
         */
        class TextContent extends CellContent {
            constructor(cell) {
                super(cell);
                this.add();
            }
            add() {
                this.update();
            }
            destroy() {
                this.cell.htmlElement.innerHTML = AST.emptyHTML;
            }
            update() {
                setHTMLContent(this.cell.htmlElement, this.format());
            }
            /**
             * Returns the formatted value of the cell.
             *
             * @internal
             */
            format() {
                const { cell } = this;
                const cellsDefaults = cell.row.viewport.grid.options?.columnDefaults?.cells || {};
                const { format, formatter } = cell.column.options.cells || {};
                let value = cell.value;
                if (!defined(value)) {
                    value = '';
                }
                let cellContent = '';
                if (!format && !formatter) {
                    return cell.format(TextContent.defaultFormatsForDataTypes[cell.column.dataType]);
                }
                const isDefaultFormat = cellsDefaults.format === format;
                const isDefaultFormatter = cellsDefaults.formatter === formatter;
                if (isDefaultFormat && isDefaultFormatter) {
                    cellContent = formatter ?
                        formatter.call(cell).toString() :
                        (format ? cell.format(format) : value + '');
                }
                else if (isDefaultFormat) {
                    cellContent = formatter?.call(cell).toString() || value + '';
                }
                else if (isDefaultFormatter) {
                    cellContent = format ? cell.format(format) : value + '';
                }
                return cellContent;
            }
        }
        /* *
         *
         *  Namespace
         *
         * */
        (function (TextContent) {
            /**
             * Default formats for data types.
             */
            TextContent.defaultFormatsForDataTypes = {
                string: '{value}',
                number: '{value}',
                'boolean': '{value}',
                datetime: '{value:%Y-%m-%d %H:%M:%S}'
            };
        })(TextContent || (TextContent = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return TextContent;
    });
    _registerModule(_modules, 'Grid/Core/Table/Column.js', [_modules['Core/Utilities.js'], _modules['Core/Templating.js'], _modules['Grid/Core/Table/CellContent/TextContent.js'], _modules['Grid/Core/Globals.js']], function (Utils, Templating, TextContent, Globals) {
        /* *
         *
         *  Grid Column class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { defined, merge, fireEvent } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a column in the data grid.
         */
        class Column {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a column in the data grid.
             *
             * @param viewport
             * The viewport (table) the column belongs to.
             *
             * @param id
             * The id of the column (`name` in the Data Table).
             *
             * @param index
             * The index of the column.
             */
            constructor(viewport, id, index) {
                /**
                 * The cells of the column.
                 */
                this.cells = [];
                const { grid } = viewport;
                this.id = id;
                this.index = index;
                this.viewport = viewport;
                this.loadData();
                this.dataType = this.assumeDataType();
                this.options = merge(grid.options?.columnDefaults ?? {}, grid.columnOptionsMap?.[id]?.options ?? {});
                fireEvent(this, 'afterInit');
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Loads the data of the column from the viewport's data table.
             */
            loadData() {
                this.data = this.viewport.dataTable.getColumn(this.id, true);
            }
            /**
             * Creates a cell content instance.
             *
             * @param cell
             * The cell that is to be edited.
             *
             */
            createCellContent(cell) {
                return new TextContent(cell);
            }
            /**
             * Assumes the data type of the column based on the options or data in the
             * column if not specified.
             */
            assumeDataType() {
                const { grid } = this.viewport;
                const type = grid.columnOptionsMap?.[this.id]?.options.dataType ??
                    grid.options?.columnDefaults?.dataType;
                if (type) {
                    return type;
                }
                if (!this.data) {
                    return 'string';
                }
                if (!Array.isArray(this.data)) {
                    // Typed array
                    return 'number';
                }
                for (let i = 0, iEnd = Math.min(this.data.length, 30); i < iEnd; ++i) {
                    if (!defined(this.data[i])) {
                        // If the data is null or undefined, we should look
                        // at the next value to determine the type.
                        continue;
                    }
                    switch (typeof this.data[i]) {
                        case 'number':
                            return 'number';
                        case 'boolean':
                            return 'boolean';
                        default:
                            return 'string';
                    }
                }
                // eslint-disable-next-line no-console
                console.warn(`Column "${this.id}" contains too few data points with ` +
                    'unambiguous types to correctly determine its dataType. It\'s ' +
                    'recommended to set the `dataType` option for it.');
                return 'string';
            }
            /**
             * Registers a cell in the column.
             *
             * @param cell
             * The cell to register.
             */
            registerCell(cell) {
                cell.htmlElement.setAttribute('data-column-id', this.id);
                if (this.options.className) {
                    cell.htmlElement.classList.add(...this.options.className.split(/\s+/g));
                }
                if (this.viewport.grid.hoveredColumnId === this.id) {
                    cell.htmlElement.classList.add(Globals.getClassName('hoveredColumn'));
                }
                this.cells.push(cell);
            }
            /**
             * Unregister a cell from the column.
             *
             * @param cell
             * The cell to unregister.
             */
            unregisterCell(cell) {
                const index = this.cells.indexOf(cell);
                if (index > -1) {
                    this.cells.splice(index, 1);
                }
            }
            /**
             * Returns the width of the column in pixels.
             */
            getWidth() {
                return this.viewport.columnDistribution.getColumnWidth(this);
            }
            /**
             * Adds or removes the hovered CSS class to the column element
             * and its cells.
             *
             * @param hovered
             * Whether the column should be hovered.
             */
            setHoveredState(hovered) {
                this.header?.htmlElement?.classList[hovered ? 'add' : 'remove'](Globals.getClassName('hoveredColumn'));
                for (let i = 0, iEnd = this.cells.length; i < iEnd; ++i) {
                    this.cells[i].htmlElement.classList[hovered ? 'add' : 'remove'](Globals.getClassName('hoveredColumn'));
                }
            }
            /**
             * Adds or removes the synced CSS class to the column element
             * and its cells.
             *
             * @param synced
             * Whether the column should have synced state.
             */
            setSyncedState(synced) {
                this.header?.htmlElement?.classList[synced ? 'add' : 'remove'](Globals.getClassName('syncedColumn'));
                for (let i = 0, iEnd = this.cells.length; i < iEnd; ++i) {
                    this.cells[i].htmlElement.classList[synced ? 'add' : 'remove'](Globals.getClassName('syncedColumn'));
                }
            }
            /**
             * Returns the formatted string where the templating context is the column.
             *
             * @param template
             * The template string.
             *
             * @return
             * The formatted string.
             */
            format(template) {
                return Templating.format(template, this, this.viewport.grid);
            }
            /**
             * Updates the column with new options.
             *
             * @param newOptions
             * The new options for the column.
             *
             * @param render
             * Whether to re-render after the update. If `false`, the update will just
             * extend the options object. Defaults to `true`.
             */
            async update(newOptions, render = true) {
                await this.viewport.grid.updateColumn(this.id, newOptions, render);
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Column;
    });
    _registerModule(_modules, 'Grid/Core/Table/Row.js', [_modules['Grid/Core/GridUtils.js']], function (GridUtils) {
        /* *
         *
         *  Grid Row abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GridUtils;
        /* *
         *
         *  Abstract Class of Row
         *
         * */
        /**
         * Represents a row in the data grid.
         */
        class Row {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a row in the data grid.
             *
             * @param viewport
             * The Grid Table instance which the row belongs to.
             */
            constructor(viewport) {
                /* *
                *
                *  Properties
                *
                * */
                /**
                 * The cells of the row.
                 */
                this.cells = [];
                this.viewport = viewport;
                this.htmlElement = makeHTMLElement('tr', {});
            }
            /**
             * Renders the row's content. It does not attach the row element to the
             * viewport nor pushes the rows to the viewport.rows array.
             */
            render() {
                const columns = this.viewport.columns;
                for (let i = 0, iEnd = columns.length; i < iEnd; i++) {
                    const cell = this.createCell(columns[i]);
                    cell.render();
                }
                this.rendered = true;
                if (this.viewport.grid.options?.rendering?.rows?.virtualization) {
                    this.reflow();
                }
            }
            /**
             * Reflows the row's content dimensions.
             */
            reflow() {
                for (let j = 0, jEnd = this.cells.length; j < jEnd; ++j) {
                    this.cells[j].reflow();
                }
                const vp = this.viewport;
                if (vp.rowsWidth) {
                    this.htmlElement.style.width = vp.rowsWidth + 'px';
                }
            }
            /**
             * Destroys the row.
             */
            destroy() {
                if (!this.htmlElement) {
                    return;
                }
                for (let i = this.cells.length - 1; i >= 0; --i) {
                    this.cells[i].destroy();
                }
                this.htmlElement.remove();
            }
            /**
             * Returns the cell with the given column ID.
             *
             * @param columnId
             * The column ID that the cell belongs to.
             *
             * @returns
             * The cell with the given column ID or undefined if not found.
             */
            getCell(columnId) {
                return this.cells.find((cell) => cell.column?.id === columnId);
            }
            /**
             * Registers a cell in the row.
             *
             * @param cell
             * The cell to register.
             */
            registerCell(cell) {
                this.cells.push(cell);
            }
            /**
             * Unregister a cell from the row.
             *
             * @param cell
             * The cell to unregister.
             */
            unregisterCell(cell) {
                const index = this.cells.indexOf(cell);
                if (index > -1) {
                    this.cells.splice(index, 1);
                }
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Row;
    });
    _registerModule(_modules, 'Grid/Core/Table/Cell.js', [_modules['Core/Templating.js']], function (Templating) {
        /* *
         *
         *  Grid Cell abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        /* *
         *
         *  Abstract Class of Cell
         *
         * */
        class Cell {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a cell in the data grid.
             *
             * @param row
             * The row of the cell.
             *
             * @param column
             * The column of the cell.
             */
            constructor(row, column) {
                /**
                 * Array of cell events to be removed when the cell is destroyed.
                 */
                this.cellEvents = [];
                this.column = column;
                this.row = row;
                this.row.registerCell(this);
                this.htmlElement = this.init();
                this.htmlElement.setAttribute('tabindex', '-1');
                this.initEvents();
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Init element.
             * @internal
             */
            init() {
                return document.createElement('td', {});
            }
            /**
             * Initialize event listeners. Events added to the `cellEvents` array will
             * be registered now and unregistered when the cell is destroyed.
             */
            initEvents() {
                this.cellEvents.push(['blur', () => this.onBlur()]);
                this.cellEvents.push(['focus', () => this.onFocus()]);
                this.cellEvents.push(['click', (e) => {
                        this.onClick(e);
                    }]);
                this.cellEvents.push(['keydown', (e) => {
                        this.onKeyDown(e);
                    }]);
                this.cellEvents.forEach((pair) => {
                    this.htmlElement.addEventListener(pair[0], pair[1]);
                });
            }
            /**
             * Handles the focus event on the cell.
             */
            onFocus() {
                const vp = this.row.viewport;
                const focusAnchor = vp.rowsVirtualizer.focusAnchorCell?.htmlElement;
                focusAnchor?.setAttribute('tabindex', '-1');
            }
            /**
             * Handles the blur event on the cell.
             */
            onBlur() {
                const vp = this.row.viewport;
                const focusAnchor = vp.rowsVirtualizer.focusAnchorCell?.htmlElement;
                focusAnchor?.setAttribute('tabindex', '0');
                delete vp.focusCursor;
            }
            /**
             * Handles user keydown on the cell.
             *
             * @param e
             * Keyboard event object.
             */
            onKeyDown(e) {
                const { row, column } = this;
                if (!column) {
                    return;
                }
                const vp = row.viewport;
                const changeFocusKeys = {
                    ArrowDown: [1, 0],
                    ArrowUp: [-1, 0],
                    ArrowLeft: [0, -1],
                    ArrowRight: [0, 1]
                };
                const dir = changeFocusKeys[e.key];
                if (dir) {
                    e.preventDefault();
                    e.stopPropagation();
                    const localRowIndex = row.index === void 0 ? -1 : (row.index - vp.rows[0].index);
                    const nextVerticalDir = localRowIndex + dir[0];
                    if (nextVerticalDir < 0 && vp.header) {
                        vp.columns[column.index + dir[1]]?.header?.htmlElement.focus();
                        return;
                    }
                    const nextRow = vp.rows[nextVerticalDir];
                    if (nextRow) {
                        nextRow.cells[column.index + dir[1]]?.htmlElement.focus();
                    }
                }
            }
            /**
             * Renders the cell by appending the HTML element to the row.
             */
            render() {
                this.row.htmlElement.appendChild(this.htmlElement);
                this.reflow();
            }
            /**
             * Reflows the cell dimensions.
             */
            reflow() {
                const column = this.column;
                if (!column) {
                    return;
                }
                const elementStyle = this.htmlElement.style;
                elementStyle.width = elementStyle.maxWidth = column.getWidth() + 'px';
            }
            /**
             * Returns the formatted string where the templating context is the cell.
             *
             * @param template
             * The template string.
             *
             * @return
             * The formatted string.
             */
            format(template) {
                return Templating.format(template, this, this.row.viewport.grid);
            }
            /**
             * Sets the custom class name of the cell based on the template.
             *
             * @param template
             * The template string.
             */
            setCustomClassName(template) {
                const element = this.htmlElement;
                if (this.customClassName) {
                    element.classList.remove(...this.customClassName.split(/\s+/g));
                }
                if (!template) {
                    delete this.customClassName;
                    return;
                }
                const newClassName = this.format(template);
                if (!newClassName) {
                    delete this.customClassName;
                    return;
                }
                element.classList.add(...newClassName.split(/\s+/g));
                this.customClassName = newClassName;
            }
            /**
             * Destroys the cell.
             */
            destroy() {
                this.cellEvents.forEach((pair) => {
                    this.htmlElement.removeEventListener(pair[0], pair[1]);
                });
                this.column?.unregisterCell(this);
                this.row.unregisterCell(this);
                this.htmlElement.remove();
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Cell;
    });
    _registerModule(_modules, 'Grid/Core/Table/Actions/ColumnSorting.js', [_modules['Grid/Core/GridUtils.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (GridUtils, Globals, U) {
        /* *
         *
         *  Grid ColumnSorting class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GridUtils;
        const { fireEvent } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that manages sorting for a dedicated column.
         */
        class ColumnSorting {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs sorting for a dedicated column.
             *
             * @param column
             * The column that be sorted.
             *
             * @param headerCellElement
             * The head element of the column.
             */
            constructor(column, headerCellElement) {
                /**
                 * Toggle sorting order for the column in the order: asc -> desc -> none
                 */
                this.toggle = () => {
                    const viewport = this.column.viewport;
                    const querying = viewport.grid.querying;
                    const sortingController = querying.sorting;
                    // Do not call sorting when cell is currently edited and validated.
                    if (viewport.validator?.errorCell) {
                        return;
                    }
                    const currentOrder = (sortingController.currentSorting?.columnId === this.column.id ?
                        sortingController.currentSorting.order : null) || 'none';
                    const consequents = {
                        none: 'asc',
                        asc: 'desc',
                        desc: null
                    };
                    void this.setOrder(consequents[currentOrder]);
                };
                this.column = column;
                this.headerCellElement = headerCellElement;
                this.addHeaderElementAttributes();
                if (column.options.sorting?.sortable) {
                    makeHTMLElement('span', {
                        className: Globals.getClassName('columnSortableIcon'),
                        innerText: '▲'
                    }, headerCellElement).setAttribute('aria-hidden', true);
                    headerCellElement.classList.add(Globals.getClassName('columnSortable'));
                }
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Adds attributes to the column header.
             */
            addHeaderElementAttributes() {
                const col = this.column;
                const a11y = col.viewport.grid.accessibility;
                const sortingOptions = col.options.sorting;
                const { currentSorting } = col.viewport.grid.querying.sorting;
                const sortedAscClassName = Globals.getClassName('columnSortedAsc');
                const sortedDescClassName = Globals.getClassName('columnSortedDesc');
                const el = this.headerCellElement;
                if (currentSorting?.columnId !== col.id || !currentSorting?.order) {
                    el.classList.remove(sortedAscClassName);
                    el.classList.remove(sortedDescClassName);
                    if (sortingOptions?.sortable) {
                        a11y?.setColumnSortState(el, 'none');
                    }
                    return;
                }
                switch (currentSorting?.order) {
                    case 'asc':
                        el.classList.add(sortedAscClassName);
                        el.classList.remove(sortedDescClassName);
                        a11y?.setColumnSortState(el, 'ascending');
                        break;
                    case 'desc':
                        el.classList.remove(sortedAscClassName);
                        el.classList.add(sortedDescClassName);
                        a11y?.setColumnSortState(el, 'descending');
                        break;
                }
            }
            /**
             * Set sorting order for the column. It will modify the presentation data
             * and rerender the rows.
             *
             * @param order
             * The order of sorting. It can be `'asc'`, `'desc'` or `null` if the
             * sorting should be disabled.
             */
            async setOrder(order) {
                const viewport = this.column.viewport;
                const querying = viewport.grid.querying;
                const sortingController = querying.sorting;
                const a11y = viewport.grid.accessibility;
                sortingController.setSorting(order, this.column.id);
                await viewport.updateRows();
                for (const col of viewport.columns) {
                    col.sorting?.addHeaderElementAttributes();
                }
                a11y?.userSortedColumn(order);
                fireEvent(this.column, 'afterSorting', {
                    target: this.column
                });
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return ColumnSorting;
    });
    _registerModule(_modules, 'Grid/Core/Table/Header/HeaderCell.js', [_modules['Grid/Core/Table/Cell.js'], _modules['Grid/Core/GridUtils.js'], _modules['Grid/Core/Table/Actions/ColumnSorting.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (Cell, GridUtils, ColumnSorting, Globals, Utilities) {
        /* *
         *
         *  Grid HeaderCell class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement, setHTMLContent } = GridUtils;
        const { fireEvent, merge, isString } = Utilities;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a cell in the data grid header.
         */
        class HeaderCell extends Cell {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a cell in the data grid header.
             *
             * @param row
             * The row of the cell.
             *
             * @param column
             * The column of the cell.
             *
             * @param columnsTree
             * If the cell is a wider than one column, this property contains the
             * structure of the columns that are subordinated to the header cell.
             */
            constructor(row, column, columnsTree) {
                super(row, column);
                /**
                 * Reference to options in settings header.
                 */
                this.options = {};
                /**
                 * List of columns that are subordinated to the header cell.
                 */
                this.columns = [];
                /**
                 * Content value of the header cell.
                 */
                this.value = '';
                if (column) {
                    column.header = this;
                    this.columns.push(column);
                }
                else if (columnsTree) {
                    const vp = this.row.viewport;
                    const columnIds = vp.grid.getColumnIds(columnsTree, true);
                    for (const columnId of columnIds) {
                        const column = vp.getColumn(columnId);
                        if (column) {
                            this.columns.push(column);
                        }
                    }
                }
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Init element.
             */
            init() {
                const elem = document.createElement('th', {});
                elem.classList.add(Globals.getClassName('headerCell'));
                return elem;
            }
            /**
             * Render the cell container.
             */
            render() {
                const { column } = this;
                const options = merge(column?.options || {}, this.options);
                const headerCellOptions = options.header || {};
                const isSortableData = options.sorting?.sortable && column?.data;
                if (headerCellOptions.formatter) {
                    this.value = headerCellOptions.formatter.call(this).toString();
                }
                else if (isString(headerCellOptions.format)) {
                    this.value = column ?
                        column.format(headerCellOptions.format) :
                        headerCellOptions.format;
                }
                else {
                    this.value = column?.id || '';
                }
                // Render content of th element
                this.row.htmlElement.appendChild(this.htmlElement);
                this.headerContent = makeHTMLElement('span', {
                    className: Globals.getClassName('headerCellContent')
                }, this.htmlElement);
                // Render the header cell element content.
                setHTMLContent(this.headerContent, this.value);
                this.htmlElement.setAttribute('scope', 'col');
                if (this.options.className) {
                    this.htmlElement.classList.add(...this.options.className.split(/\s+/g));
                }
                if (column) {
                    this.htmlElement.setAttribute('data-column-id', column.id);
                    if (isSortableData) {
                        column.viewport.grid.accessibility?.addSortableColumnHint(this.headerContent);
                    }
                    // Add user column classname
                    if (column.options.className) {
                        this.htmlElement.classList.add(...column.options.className.split(/\s+/g));
                    }
                    // Add resizing
                    column.viewport.columnsResizer?.renderColumnDragHandles(column, this);
                    // Add sorting
                    this.initColumnSorting();
                }
                this.setCustomClassName(options.header?.className);
                fireEvent(this, 'afterRender', {
                    target: column
                });
            }
            reflow() {
                const th = this.htmlElement;
                if (!th) {
                    return;
                }
                let width = 0;
                for (const column of this.columns) {
                    width += column.getWidth() || 0;
                }
                // Set the width of the column. Max width is needed for the
                // overflow: hidden to work.
                th.style.width = th.style.maxWidth = width + 'px';
            }
            onKeyDown(e) {
                if (!this.column || e.target !== this.htmlElement) {
                    return;
                }
                if (e.key === 'Enter') {
                    if (this.column.options.sorting?.sortable) {
                        this.column.sorting?.toggle();
                    }
                    return;
                }
                super.onKeyDown(e);
            }
            onClick(e) {
                const column = this.column;
                if (!column || (e.target !== this.htmlElement &&
                    e.target !== column.header?.headerContent) || column.viewport.columnsResizer?.isResizing) {
                    return;
                }
                if (column.options.sorting?.sortable) {
                    column.sorting?.toggle();
                }
                fireEvent(this, 'click', {
                    originalEvent: e,
                    target: this.column
                });
            }
            /**
             * Add sorting option to the column.
             */
            initColumnSorting() {
                const { column } = this;
                if (!column) {
                    return;
                }
                column.sorting = new ColumnSorting(column, this.htmlElement);
            }
            /**
             * Check if the cell is part of the last cell in the header.
             */
            isLastColumn() {
                const vp = this.row.viewport;
                const lastViewportColumn = vp.columns[vp.columns.length - 1];
                const lastCellColumn = this.columns?.[this.columns.length - 1];
                return lastViewportColumn === lastCellColumn;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return HeaderCell;
    });
    _registerModule(_modules, 'Grid/Core/Table/Header/HeaderRow.js', [_modules['Grid/Core/Table/Row.js'], _modules['Grid/Core/Table/Header/HeaderCell.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (Row, HeaderCell, Globals, Utils) {
        /* *
         *
         *  Grid HeaderRow class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { isString } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a row in the data grid header.
         */
        class HeaderRow extends Row {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a row in the data grid.
             *
             * @param viewport
             * The Grid Table instance which the row belongs to.
             *
             * @param level
             * The current level of header that is rendered.
             */
            constructor(viewport, level) {
                super(viewport);
                this.level = level;
                this.setRowAttributes();
            }
            /* *
            *
            *  Methods
            *
            * */
            createCell(column, columnsTree) {
                return new HeaderCell(this, column, columnsTree);
            }
            /**
             * Renders the row's content in the header.
             *
             * @param level
             * The current level in the header tree
             */
            renderMultipleLevel(level) {
                const header = this.viewport.grid.options?.header;
                const vp = this.viewport;
                const enabledColumns = vp.grid.enabledColumns;
                // Render element
                vp.theadElement?.appendChild(this.htmlElement);
                this.htmlElement.classList.add(Globals.getClassName('headerRow'));
                if (!header) {
                    super.render();
                }
                else {
                    const columnsOnLevel = this.getColumnsAtLevel(header, level);
                    for (let i = 0, iEnd = columnsOnLevel.length; i < iEnd; i++) {
                        const columnOnLevel = columnsOnLevel[i];
                        const colIsString = typeof columnOnLevel === 'string';
                        const colSpan = (!colIsString && columnOnLevel.columns) ?
                            vp.grid.getColumnIds(columnOnLevel.columns).length : 0;
                        const columnId = colIsString ?
                            columnOnLevel : columnOnLevel.columnId;
                        const dataColumn = columnId ?
                            vp.getColumn(columnId || '') : void 0;
                        const headerFormat = !colIsString ?
                            columnOnLevel.format : void 0;
                        const className = !colIsString ?
                            columnOnLevel.className : void 0;
                        // Skip hidden column or header when all columns are hidden.
                        if ((columnId && enabledColumns &&
                            enabledColumns.indexOf(columnId) < 0) || (!dataColumn && colSpan === 0)) {
                            continue;
                        }
                        const headerCell = this.createCell(dataColumn, !colIsString ? columnOnLevel.columns : void 0);
                        if (!colIsString) {
                            vp.grid.accessibility?.addHeaderCellDescription(headerCell.htmlElement, columnOnLevel.accessibility?.description);
                        }
                        if (isString(headerFormat)) {
                            if (!headerCell.options.header) {
                                headerCell.options.header = {};
                            }
                            headerCell.options.header.format = headerFormat;
                        }
                        if (className) {
                            headerCell.options.className = className;
                        }
                        // Add class to disable left border on first column
                        if (dataColumn?.index === 0 && i === 0) {
                            headerCell.htmlElement.classList.add(Globals.getClassName('columnFirst'));
                        }
                        headerCell.render();
                        if (columnId) {
                            headerCell.htmlElement.setAttribute('rowSpan', (this.viewport.header?.levels || 1) - level);
                        }
                        else {
                            if (colSpan > 1) {
                                headerCell.htmlElement.setAttribute('colSpan', colSpan);
                            }
                        }
                    }
                }
                const lastCell = this.cells[this.cells.length - 1];
                if (lastCell.isLastColumn()) {
                    lastCell.htmlElement.classList.add(Globals.getClassName('lastHeaderCellInRow'));
                }
            }
            reflow() {
                const row = this;
                for (let i = 0, iEnd = row.cells.length; i < iEnd; i++) {
                    const cell = row.cells[i];
                    cell.reflow();
                }
            }
            /**
             * Get all headers that should be rendered in a level.
             *
             * @param scope
             * Level that we start from
             *
             * @param targetLevel
             * Max level
             *
             * @param currentLevel
             * Current level
             *
             * @return
             * Array of headers that should be rendered in a level
             */
            getColumnsAtLevel(scope, targetLevel, currentLevel = 0) {
                let result = [];
                for (const column of scope) {
                    if (currentLevel === targetLevel) {
                        result.push(column);
                    }
                    if (typeof column !== 'string' && column.columns) {
                        result = result.concat(this.getColumnsAtLevel(column.columns, targetLevel, currentLevel + 1));
                    }
                }
                return result;
            }
            /**
             * Sets the row HTML element attributes and additional classes.
             */
            setRowAttributes() {
                const a11y = this.viewport.grid.accessibility;
                a11y?.setRowIndex(this.htmlElement, this.level);
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return HeaderRow;
    });
    _registerModule(_modules, 'Grid/Core/Table/Header/TableHeader.js', [_modules['Grid/Core/Table/Header/HeaderRow.js']], function (HeaderRow) {
        /* *
         *
         *  Grid TableHeader class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a table header row containing the cells (headers) with
         * column names.
         */
        class TableHeader {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a new table head.
             *
             * @param viewport
             * The viewport (table) the table head belongs to.
             */
            constructor(viewport) {
                /* *
                *
                *  Properties
                *
                * */
                /**
                 * The visible columns of the table.
                 */
                this.columns = [];
                /**
                 * The container of the table head.
                 */
                this.rows = [];
                /**
                 * Amount of levels in the header, that is used in creating correct rows.
                 */
                this.levels = 1;
                this.viewport = viewport;
                this.columns = viewport.columns;
                if (viewport.grid.options?.header) {
                    this.levels = this.getRowLevels(viewport.grid.options?.header);
                }
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Renders the table head content.
             */
            render() {
                const vp = this.viewport;
                if (!vp.grid.enabledColumns) {
                    return;
                }
                for (let i = 0, iEnd = this.levels; i < iEnd; i++) {
                    const row = new HeaderRow(vp, i + 1); // Avoid indexing from 0
                    row.renderMultipleLevel(i);
                    this.rows.push(row);
                }
            }
            /**
             * Reflows the table head's content dimensions.
             */
            reflow() {
                const vp = this.viewport;
                if (!vp.theadElement) {
                    return;
                }
                const { clientWidth, offsetWidth } = vp.tbodyElement;
                const header = vp.header;
                const rows = this.rows;
                const bordersWidth = offsetWidth - clientWidth;
                for (const row of rows) {
                    row.reflow();
                }
                if (vp.rowsWidth) {
                    vp.theadElement.style.width =
                        Math.max(vp.rowsWidth, clientWidth) + bordersWidth + 'px';
                }
                if (header &&
                    bordersWidth > 0 &&
                    this.viewport.columnDistribution.type === 'full') {
                    const row = this.columns[this.columns.length - 1].header?.row;
                    const lastCellEl = row?.cells[row.cells.length - 1]?.htmlElement;
                    if (lastCellEl) {
                        lastCellEl.style.width = lastCellEl.style.maxWidth =
                            lastCellEl.offsetWidth + bordersWidth + 'px';
                    }
                }
            }
            /**
             * Returns amount of rows for the current cell in header tree.
             *
             * @param scope
             * Structure of header
             *
             * @returns
             */
            getRowLevels(scope) {
                let maxDepth = 0;
                for (const item of scope) {
                    if (typeof item !== 'string' && item.columns) {
                        const depth = this.getRowLevels(item.columns);
                        if (depth > maxDepth) {
                            maxDepth = depth;
                        }
                    }
                }
                return maxDepth + 1;
            }
            /**
             * Scrolls the table head horizontally, only when the virtualization
             * is enabled.
             *
             * @param scrollLeft
             * The left scroll position.
             */
            scrollHorizontally(scrollLeft) {
                const el = this.viewport.theadElement;
                if (!el) {
                    return;
                }
                el.style.transform = `translateX(${-scrollLeft}px)`;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return TableHeader;
    });
    _registerModule(_modules, 'Grid/Core/Table/Body/TableCell.js', [_modules['Grid/Core/Table/Cell.js'], _modules['Core/Utilities.js']], function (Cell, Utils) {
        /* *
         *
         *  Grid class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { fireEvent } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a cell in the data grid.
         */
        class TableCell extends Cell {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a cell in the data grid.
             *
             * @param row
             * The row of the cell.
             *
             * @param column
             * The column of the cell.
             */
            constructor(row, column) {
                super(row, column);
                this.column = column;
                this.row = row;
                this.column.registerCell(this);
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Renders the cell by appending it to the row and setting its value.
             */
            render() {
                super.render();
                void this.setValue();
            }
            /**
             * Sets the cell value and updates its content with it.
             *
             * @param value
             * The raw value to set. If not provided, it will use the value from the
             * data table for the current row and column.
             *
             * @param updateTable
             * Whether to update the table after setting the content. Defaults to
             * `false`, meaning the table will not be updated.
             */
            async setValue(value = this.column.data?.[this.row.index], updateTable = false) {
                this.value = value;
                if (updateTable && await this.updateDataTable()) {
                    return;
                }
                if (this.content) {
                    this.content.update();
                }
                else {
                    this.content = this.column.createCellContent(this);
                }
                this.htmlElement.setAttribute('data-value', this.value + '');
                this.setCustomClassName(this.column.options.cells?.className);
                fireEvent(this, 'afterRender', { target: this });
            }
            /**
             * Updates the the data table so that it reflects the current state of
             * the grid.
             *
             * @returns
             * A promise that resolves to `true` if the cell triggered all the whole
             * viewport rows to be updated, or `false` if the only change should be
             * the cell's content.
             */
            async updateDataTable() {
                if (this.column.data?.[this.row.index] === this.value) {
                    // Abort if the value is the same as in the data table.
                    return false;
                }
                const vp = this.column.viewport;
                const { dataTable: originalDataTable } = vp.grid;
                const rowTableIndex = this.row.id &&
                    originalDataTable?.getLocalRowIndex(this.row.id);
                if (!originalDataTable || rowTableIndex === void 0) {
                    return false;
                }
                this.row.data[this.column.id] = this.value;
                originalDataTable.setCell(this.column.id, rowTableIndex, this.value);
                vp.grid.querying.shouldBeUpdated = true;
                if (vp.grid.querying.getModifiers().length < 1) {
                    return false;
                }
                await vp.updateRows();
                return true;
            }
            initEvents() {
                this.cellEvents.push(['dblclick', (e) => (this.onDblClick(e))]);
                this.cellEvents.push(['mouseout', () => this.onMouseOut()]);
                this.cellEvents.push(['mouseover', () => this.onMouseOver()]);
                this.cellEvents.push(['mousedown', (e) => {
                        this.onMouseDown(e);
                    }]);
                super.initEvents();
            }
            /**
             * Handles the focus event on the cell.
             */
            onFocus() {
                super.onFocus();
                const vp = this.row.viewport;
                vp.focusCursor = [
                    this.row.index,
                    this.column.index
                ];
            }
            /**
             * Handles the mouse down event on the cell.
             *
             * @param e
             * The mouse event object.
             *
             * @internal
             */
            onMouseDown(e) {
                if (e.target === this.htmlElement) {
                    this.htmlElement.focus();
                }
                fireEvent(this, 'mouseDown', {
                    target: this,
                    originalEvent: e
                });
            }
            /**
             * Handles the mouse over event on the cell.
             * @internal
             */
            onMouseOver() {
                const { grid } = this.row.viewport;
                grid.hoverRow(this.row.index);
                grid.hoverColumn(this.column.id);
                fireEvent(this, 'mouseOver', {
                    target: this
                });
            }
            /**
             * Handles the mouse out event on the cell.
             */
            onMouseOut() {
                const { grid } = this.row.viewport;
                grid.hoverRow();
                grid.hoverColumn();
                fireEvent(this, 'mouseOut', {
                    target: this
                });
            }
            /**
             * Handles the double click event on the cell.
             *
             * @param e
             * The mouse event object.
             */
            onDblClick(e) {
                fireEvent(this, 'dblClick', {
                    target: this,
                    originalEvent: e
                });
            }
            onClick() {
                fireEvent(this, 'click', {
                    target: this
                });
            }
            /**
             * Handles the key down event on the cell.
             *
             * @param e
             * Keyboard event object.
             *
             * @internal
             */
            onKeyDown(e) {
                if (e.target !== this.htmlElement) {
                    return;
                }
                fireEvent(this, 'keyDown', {
                    target: this,
                    originalEvent: e
                });
                super.onKeyDown(e);
            }
            /**
             * Destroys the cell.
             */
            destroy() {
                this.content?.destroy();
                delete this.content;
                super.destroy();
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return TableCell;
    });
    _registerModule(_modules, 'Grid/Core/Table/Body/TableRow.js', [_modules['Grid/Core/Table/Row.js'], _modules['Grid/Core/Table/Body/TableCell.js'], _modules['Grid/Core/Globals.js']], function (Row, TableCell, Globals) {
        /* *
         *
         *  Grid TableRow class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a row in the data grid.
         */
        class TableRow extends Row {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a row in the data grid.
             *
             * @param viewport
             * The Grid Table instance which the row belongs to.
             *
             * @param index
             * The index of the row in the data table.
             */
            constructor(viewport, index) {
                super(viewport);
                /* *
                *
                *  Properties
                *
                * */
                /**
                 * The row values from the data table in the original column order.
                 */
                this.data = {};
                /**
                 * The vertical translation of the row.
                 */
                this.translateY = 0;
                this.index = index;
                this.id = viewport.dataTable.getOriginalRowIndex(index);
                this.loadData();
                this.setRowAttributes();
            }
            /* *
            *
            *  Methods
            *
            * */
            createCell(column) {
                return new TableCell(this, column);
            }
            /**
             * Loads the row data from the data table.
             */
            loadData() {
                const data = this.viewport.dataTable.getRowObject(this.index);
                if (!data) {
                    return;
                }
                this.data = data;
            }
            /**
             * Updates the row data and its cells with the latest values from the data
             * table.
             */
            update() {
                this.id = this.viewport.dataTable.getOriginalRowIndex(this.index);
                this.updateRowAttributes();
                this.loadData();
                for (let i = 0, iEnd = this.cells.length; i < iEnd; ++i) {
                    const cell = this.cells[i];
                    void cell.setValue();
                }
                this.reflow();
            }
            /**
             * Adds or removes the hovered CSS class to the row element.
             *
             * @param hovered
             * Whether the row should be hovered.
             */
            setHoveredState(hovered) {
                this.htmlElement.classList[hovered ? 'add' : 'remove'](Globals.getClassName('hoveredRow'));
                if (hovered) {
                    this.viewport.grid.hoveredRowIndex = this.index;
                }
            }
            /**
             * Adds or removes the synced CSS class to the row element.
             *
             * @param synced
             * Whether the row should be synced.
             */
            setSyncedState(synced) {
                this.htmlElement.classList[synced ? 'add' : 'remove'](Globals.getClassName('syncedRow'));
                if (synced) {
                    this.viewport.grid.syncedRowIndex = this.index;
                }
            }
            /**
             * Sets the row HTML element attributes and additional classes.
             */
            setRowAttributes() {
                const idx = this.index;
                const el = this.htmlElement;
                el.classList.add(Globals.getClassName('rowElement'));
                // Index of the row in the presentation data table
                el.setAttribute('data-row-index', idx);
                this.updateRowAttributes();
                // Indexing from 0, so rows with even index are odd.
                el.classList.add(Globals.getClassName(idx % 2 ? 'rowEven' : 'rowOdd'));
                if (this.viewport.grid.hoveredRowIndex === idx) {
                    el.classList.add(Globals.getClassName('hoveredRow'));
                }
                if (this.viewport.grid.syncedRowIndex === idx) {
                    el.classList.add(Globals.getClassName('syncedRow'));
                }
            }
            /**
             * Sets the row HTML element attributes that are updateable in the row
             * lifecycle.
             */
            updateRowAttributes() {
                const a11y = this.viewport.grid.accessibility;
                const idx = this.index;
                const el = this.htmlElement;
                // Index of the row in the original data table (ID)
                if (this.id !== void 0) {
                    el.setAttribute('data-row-id', this.id);
                }
                // Calculate levels of header, 1 to avoid indexing from 0
                a11y?.setRowIndex(el, idx + (this.viewport.header?.levels ?? 1) + 1);
            }
            /**
             * Sets the vertical translation of the row. Used for virtual scrolling.
             *
             * @param value
             * The vertical translation of the row.
             */
            setTranslateY(value) {
                this.translateY = value;
                this.htmlElement.style.transform = `translateY(${value}px)`;
            }
            /**
             * Returns the default top offset of the row (before adjusting row heights).
             * @internal
             */
            getDefaultTopOffset() {
                return this.index * this.viewport.rowsVirtualizer.defaultRowHeight;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return TableRow;
    });
    _registerModule(_modules, 'Grid/Core/Table/Actions/RowsVirtualizer.js', [_modules['Grid/Core/Table/Body/TableRow.js'], _modules['Grid/Core/Globals.js']], function (TableRow, Globals) {
        /* *
         *
         *  Grid Rows Renderer class.
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a virtualized rows renderer for the data grid.
         */
        class RowsVirtualizer {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs an instance of the rows virtualizer.
             *
             * @param viewport
             * The viewport of the data grid to render rows in.
             */
            constructor(viewport) {
                /**
                 * The index of the first visible row.
                 */
                this.rowCursor = 0;
                /**
                 * Flag indicating if the scrolling handler should be prevented to avoid
                 * flickering loops when scrolling to the last row.
                 */
                this.preventScroll = false;
                this.rowSettings =
                    viewport.grid.options?.rendering?.rows;
                this.viewport = viewport;
                this.strictRowHeights = this.rowSettings.strictHeights;
                this.buffer = Math.max(this.rowSettings.bufferSize, 0);
                this.defaultRowHeight = this.getDefaultRowHeight();
                if (this.strictRowHeights) {
                    viewport.tbodyElement.classList.add(Globals.getClassName('rowsContentNowrap'));
                }
            }
            /* *
            *
            *  Functions
            *
            * */
            /**
             * Renders the rows in the viewport for the first time.
             */
            initialRender() {
                // Initial reflow to set the viewport height
                if (this.rowSettings?.virtualization) {
                    this.viewport.reflow();
                }
                // Load & render rows
                this.renderRows(this.rowCursor);
                this.adjustRowHeights();
            }
            /**
             * Renders the rows in the viewport. It is called when the rows need to be
             * re-rendered, e.g., after a sort or filter operation.
             */
            rerender() {
                const tbody = this.viewport.tbodyElement;
                let rows = this.viewport.rows;
                const oldScrollLeft = tbody.scrollLeft;
                let oldScrollTop;
                if (rows.length) {
                    oldScrollTop = tbody.scrollTop;
                    for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                        rows[i].destroy();
                    }
                    rows.length = 0;
                }
                this.renderRows(this.rowCursor);
                if (this.rowSettings?.virtualization) {
                    if (oldScrollTop !== void 0) {
                        tbody.scrollTop = oldScrollTop;
                    }
                    this.scroll();
                }
                rows = this.viewport.rows;
                // Reflow the rendered row cells widths (check redundancy)
                for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                    rows[i].reflow();
                }
                tbody.scrollLeft = oldScrollLeft;
            }
            /**
             * Method called on the viewport scroll event, only when the virtualization
             * is enabled.
             */
            scroll() {
                const target = this.viewport.tbodyElement;
                const { defaultRowHeight: rowHeight } = this;
                const lastScrollTop = target.scrollTop;
                if (this.preventScroll) {
                    if (lastScrollTop <= target.scrollTop) {
                        this.preventScroll = false;
                    }
                    this.adjustBottomRowHeights();
                    return;
                }
                // Do vertical virtual scrolling
                const rowCursor = Math.floor(target.scrollTop / rowHeight);
                if (this.rowCursor !== rowCursor) {
                    this.renderRows(rowCursor);
                }
                this.rowCursor = rowCursor;
                this.adjustRowHeights();
                if (!this.strictRowHeights &&
                    lastScrollTop > target.scrollTop &&
                    !this.preventScroll) {
                    target.scrollTop = lastScrollTop;
                    this.preventScroll = true;
                }
            }
            /**
             * Adjusts the visible row heights from the bottom of the viewport.
             */
            adjustBottomRowHeights() {
                const rows = this.viewport.rows;
                const rowsLn = rows.length;
                const lastRow = rows[rowsLn - 1];
                let rowTop = lastRow.translateY;
                const rowBottom = rowTop + lastRow.htmlElement.offsetHeight;
                let newHeight = lastRow.cells[0].htmlElement.offsetHeight;
                rowTop = rowBottom - newHeight;
                lastRow.htmlElement.style.height = newHeight + 'px';
                lastRow.setTranslateY(rowTop);
                for (let j = 0, jEnd = lastRow.cells.length; j < jEnd; ++j) {
                    lastRow.cells[j].htmlElement.style.transform = '';
                }
                for (let i = rowsLn - 2; i >= 0; i--) {
                    const row = rows[i];
                    newHeight = row.cells[0].htmlElement.offsetHeight;
                    rowTop -= newHeight;
                    row.htmlElement.style.height = newHeight + 'px';
                    row.setTranslateY(rowTop);
                    for (let j = 0, jEnd = row.cells.length; j < jEnd; ++j) {
                        row.cells[j].htmlElement.style.transform = '';
                    }
                }
            }
            /**
             * Renders rows in the specified range. Removes rows that are out of the
             * range except the last row.
             *
             * @param rowCursor
             * The index of the first visible row.
             */
            renderRows(rowCursor) {
                const { viewport: vp, buffer } = this;
                const rowCount = vp.dataTable.getRowCount();
                // Stop rendering if there are no rows to render.
                if (rowCount < 1) {
                    return;
                }
                const isVirtualization = this.rowSettings?.virtualization;
                const rowsPerPage = isVirtualization ? Math.ceil((vp.grid.tableElement?.clientHeight || 0) /
                    this.defaultRowHeight) : Infinity; // Need to be refactored when add pagination
                let rows = vp.rows;
                if (!isVirtualization && rows.length > 50) {
                    // eslint-disable-next-line no-console
                    console.warn('Grid: a large dataset can cause performance issues when ' +
                        'virtualization is disabled. Consider enabling ' +
                        'virtualization in the rows settings.');
                }
                if (!rows.length) {
                    const last = new TableRow(vp, rowCount - 1);
                    vp.tbodyElement.appendChild(last.htmlElement);
                    last.render();
                    rows.push(last);
                    if (isVirtualization) {
                        last.setTranslateY(last.getDefaultTopOffset());
                    }
                }
                const from = Math.max(0, Math.min(rowCursor - buffer, rowCount - rowsPerPage));
                const to = Math.min(rowCursor + rowsPerPage + buffer, rows[rows.length - 1].index - 1);
                const alwaysLastRow = rows.pop();
                const tempRows = [];
                // Remove rows that are out of the range except the last row.
                for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                    const row = rows[i];
                    const rowIndex = row.index;
                    if (rowIndex < from || rowIndex > to) {
                        row.destroy();
                    }
                    else {
                        tempRows.push(row);
                    }
                }
                rows = tempRows;
                vp.rows = rows;
                for (let i = from; i <= to; ++i) {
                    const row = rows[i - (rows[0]?.index || 0)];
                    // Recreate row when it is destroyed and it is in the range.
                    if (!row) {
                        const newRow = new TableRow(vp, i);
                        rows.push(newRow);
                        newRow.rendered = false;
                        if (isVirtualization) {
                            newRow.setTranslateY(newRow.getDefaultTopOffset());
                        }
                    }
                }
                rows.sort((a, b) => a.index - b.index);
                for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                    if (!rows[i].rendered) {
                        vp.tbodyElement.insertBefore(rows[i].htmlElement, vp.tbodyElement.lastChild);
                        rows[i].render();
                    }
                }
                if (alwaysLastRow) {
                    rows.push(alwaysLastRow);
                }
                // Focus the cell if the focus cursor is set
                if (vp.focusCursor) {
                    const [rowIndex, columnIndex] = vp.focusCursor;
                    const row = rows.find((row) => row.index === rowIndex);
                    if (row) {
                        row.cells[columnIndex]?.htmlElement.focus({
                            preventScroll: true
                        });
                    }
                }
                // Reset the focus anchor cell
                this.focusAnchorCell?.htmlElement.setAttribute('tabindex', '-1');
                const firstVisibleRow = rows[rowCursor - rows[0].index];
                this.focusAnchorCell = firstVisibleRow?.cells[0];
                this.focusAnchorCell?.htmlElement.setAttribute('tabindex', '0');
            }
            /**
             * Adjusts the heights of the rows based on the current scroll position.
             * It handles the possibility of the rows having different heights than
             * the default height.
             */
            adjustRowHeights() {
                if (this.strictRowHeights ||
                    !this.rowSettings?.virtualization) {
                    return;
                }
                const { rowCursor: cursor, defaultRowHeight: defaultH } = this;
                const { rows, tbodyElement } = this.viewport;
                const rowsLn = rows.length;
                let translateBuffer = rows[0].getDefaultTopOffset();
                for (let i = 0; i < rowsLn; ++i) {
                    const row = rows[i];
                    // Reset row height and cell transforms
                    row.htmlElement.style.height = '';
                    if (row.cells[0].htmlElement.style.transform) {
                        for (let j = 0, jEnd = row.cells.length; j < jEnd; ++j) {
                            const cell = row.cells[j];
                            cell.htmlElement.style.transform = '';
                        }
                    }
                    // Rows above the first visible row
                    if (row.index < cursor) {
                        row.htmlElement.style.height = defaultH + 'px';
                        continue;
                    }
                    const cellHeight = row.cells[0].htmlElement.offsetHeight;
                    row.htmlElement.style.height = cellHeight + 'px';
                    // Rows below the first visible row
                    if (row.index > cursor) {
                        continue;
                    }
                    // First visible row
                    if (row.htmlElement.offsetHeight > defaultH) {
                        const newHeight = Math.floor(cellHeight - (cellHeight - defaultH) * (tbodyElement.scrollTop / defaultH - cursor));
                        row.htmlElement.style.height = newHeight + 'px';
                        for (let j = 0, jEnd = row.cells.length; j < jEnd; ++j) {
                            const cell = row.cells[j];
                            cell.htmlElement.style.transform = `translateY(${newHeight - cellHeight}px)`;
                        }
                    }
                }
                rows[0].setTranslateY(translateBuffer);
                for (let i = 1, iEnd = rowsLn - 1; i < iEnd; ++i) {
                    translateBuffer += rows[i - 1].htmlElement.offsetHeight;
                    rows[i].setTranslateY(translateBuffer);
                }
                // Set the proper offset for the last row
                const lastRow = rows[rowsLn - 1];
                const preLastRow = rows[rowsLn - 2];
                if (preLastRow && preLastRow.index === lastRow.index - 1) {
                    lastRow.setTranslateY(preLastRow.htmlElement.offsetHeight + translateBuffer);
                }
            }
            /**
             * Reflow the rendered rows content dimensions.
             */
            reflowRows() {
                const rows = this.viewport.rows;
                if (rows.length < 1) {
                    return;
                }
                for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                    rows[i].reflow();
                }
                this.adjustRowHeights();
            }
            /**
             * Returns the default height of a row. This method should be called only
             * once on initialization.
             */
            getDefaultRowHeight() {
                const vp = this.viewport;
                const mockRow = new TableRow(vp, 0);
                mockRow.htmlElement.style.position = 'absolute';
                mockRow.htmlElement.classList.add(Globals.getClassName('mockedRow'));
                this.viewport.tbodyElement.appendChild(mockRow.htmlElement);
                mockRow.render();
                const defaultRowHeight = mockRow.htmlElement.offsetHeight;
                mockRow.destroy();
                return defaultRowHeight;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return RowsVirtualizer;
    });
    _registerModule(_modules, 'Grid/Core/Table/Actions/ColumnsResizer.js', [_modules['Grid/Core/GridUtils.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (GridUtils, Globals, Utils) {
        /* *
         *
         *  Grid Columns Resizer class.
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GridUtils;
        const { fireEvent } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * The class that handles the resizing of columns in the data grid.
         */
        class ColumnsResizer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(viewport) {
                /**
                 * Any column is being resized. Turned off after slight delay.
                 */
                this.isResizing = false;
                /**
                 * The handles and their mouse down event listeners.
                 */
                this.handles = [];
                /**
                 * Handles the mouse move event on the document.
                 *
                 * @param e
                 * The mouse event.
                 *
                 * @internal
                 */
                this.onDocumentMouseMove = (e) => {
                    if (!this.draggedResizeHandle || !this.draggedColumn) {
                        return;
                    }
                    const diff = e.pageX - (this.dragStartX || 0);
                    const vp = this.viewport;
                    vp.columnDistribution.resize(this, diff);
                    vp.reflow();
                    vp.rowsVirtualizer.adjustRowHeights();
                    fireEvent(this.draggedColumn, 'afterResize', {
                        target: this.draggedColumn,
                        originalEvent: e
                    });
                };
                /**
                 * Handles the mouse up event on the document.
                 */
                this.onDocumentMouseUp = () => {
                    this.draggedColumn?.header?.htmlElement?.classList.remove(Globals.getClassName('resizedColumn'));
                    this.dragStartX = void 0;
                    this.draggedColumn = void 0;
                    this.draggedResizeHandle = void 0;
                    this.columnStartWidth = void 0;
                    this.nextColumnStartWidth = void 0;
                    requestAnimationFrame(() => {
                        this.isResizing = false;
                    });
                };
                this.viewport = viewport;
                document.addEventListener('mousemove', this.onDocumentMouseMove);
                document.addEventListener('mouseup', this.onDocumentMouseUp);
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Render the drag handle for resizing columns.
             *
             * @param column
             * The reference to rendered column
             *
             * @param cell
             * The reference to rendered cell, where hadles should be added
             */
            renderColumnDragHandles(column, cell) {
                const vp = column.viewport;
                if (vp.columnsResizer && (vp.columnDistribution.type !== 'full' ||
                    (vp.grid.enabledColumns &&
                        column.index < vp.grid.enabledColumns.length - 1))) {
                    const handle = makeHTMLElement('div', {
                        className: Globals.getClassName('resizerHandles')
                    }, cell.htmlElement);
                    handle.setAttribute('aria-hidden', true);
                    vp.columnsResizer?.addHandleListeners(handle, column);
                }
            }
            /**
             * Adds event listeners to the handle.
             *
             * @param handle
             * The handle element.
             *
             * @param column
             * The column the handle belongs to.
             */
            addHandleListeners(handle, column) {
                const onHandleMouseDown = (e) => {
                    const vp = column.viewport;
                    this.isResizing = true;
                    vp.reflow();
                    this.dragStartX = e.pageX;
                    this.draggedColumn = column;
                    this.draggedResizeHandle = handle;
                    this.columnStartWidth = column.getWidth();
                    this.nextColumnStartWidth =
                        vp.columns[column.index + 1]?.getWidth();
                    column.header?.htmlElement.classList.add(Globals.getClassName('resizedColumn'));
                };
                this.handles.push([handle, onHandleMouseDown]);
                handle.addEventListener('mousedown', onHandleMouseDown);
            }
            /**
             * Removes all added event listeners from the document and handles. This
             * should be called on the destroy of the data grid.
             */
            removeEventListeners() {
                document.removeEventListener('mousemove', this.onDocumentMouseMove);
                document.removeEventListener('mouseup', this.onDocumentMouseUp);
                for (let i = 0, iEnd = this.handles.length; i < iEnd; i++) {
                    const [handle, listener] = this.handles[i];
                    handle.removeEventListener('mousedown', listener);
                }
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return ColumnsResizer;
    });
    _registerModule(_modules, 'Grid/Core/Table/Table.js', [_modules['Grid/Core/GridUtils.js'], _modules['Core/Utilities.js'], _modules['Grid/Core/Table/ColumnDistribution/ColumnDistribution.js'], _modules['Grid/Core/Table/Column.js'], _modules['Grid/Core/Table/Header/TableHeader.js'], _modules['Grid/Core/Table/Actions/RowsVirtualizer.js'], _modules['Grid/Core/Table/Actions/ColumnsResizer.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Core/Defaults.js']], function (GridUtils, Utils, ColumnDistribution, Column, TableHeader, RowsVirtualizer, ColumnsResizer, Globals, Defaults) {
        /* *
         *
         *  Grid Table Viewport class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GridUtils;
        const { fireEvent, getStyle, defined } = Utils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a table viewport of the data grid.
         */
        class Table {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a new data grid table.
             *
             * @param grid
             * The data grid instance which the table (viewport) belongs to.
             *
             * @param tableElement
             * The HTML table element of the data grid.
             */
            constructor(grid, tableElement) {
                /**
                 * The visible columns of the table.
                 */
                this.columns = [];
                /**
                 * The visible rows of the table.
                 */
                this.rows = [];
                /**
                 * Handles the focus event on the table body.
                 *
                 * @param e
                 * The focus event.
                 */
                this.onTBodyFocus = (e) => {
                    e.preventDefault();
                    this.rows[this.rowsVirtualizer.rowCursor - this.rows[0].index]
                        ?.cells[0]?.htmlElement.focus();
                };
                /**
                 * Handles the resize event.
                 */
                this.onResize = () => {
                    this.reflow();
                };
                /**
                 * Handles the scroll event.
                 */
                this.onScroll = () => {
                    if (this.virtualRows) {
                        this.rowsVirtualizer.scroll();
                    }
                    this.header?.scrollHorizontally(this.tbodyElement.scrollLeft);
                };
                this.grid = grid;
                this.dataTable = this.grid.presentationTable;
                const dgOptions = grid.options;
                const customClassName = dgOptions?.rendering?.table?.className;
                this.columnDistribution = ColumnDistribution.initStrategy(this);
                this.virtualRows = !!dgOptions?.rendering?.rows?.virtualization;
                if (dgOptions?.rendering?.header?.enabled) {
                    this.theadElement = makeHTMLElement('thead', {}, tableElement);
                }
                this.tbodyElement = makeHTMLElement('tbody', {}, tableElement);
                if (this.virtualRows) {
                    tableElement.classList.add(Globals.getClassName('virtualization'));
                }
                if (!(dgOptions?.rendering?.columns?.resizing?.enabled === false ||
                    dgOptions?.columnDefaults?.resizing === false)) {
                    this.columnsResizer = new ColumnsResizer(this);
                }
                if (customClassName) {
                    tableElement.classList.add(...customClassName.split(/\s+/g));
                }
                tableElement.classList.add(Globals.getClassName('scrollableContent'));
                // Load columns
                this.loadColumns();
                // Virtualization
                this.rowsVirtualizer = new RowsVirtualizer(this);
                // Init Table
                this.init();
                // Add event listeners
                this.resizeObserver = new ResizeObserver(this.onResize);
                this.resizeObserver.observe(tableElement);
                this.tbodyElement.addEventListener('scroll', this.onScroll);
                this.tbodyElement.addEventListener('focus', this.onTBodyFocus);
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Initializes the data grid table.
             */
            init() {
                fireEvent(this, 'beforeInit');
                this.setTbodyMinHeight();
                // Load & render head
                if (this.grid.options?.rendering?.header?.enabled) {
                    this.header = new TableHeader(this);
                    this.header.render();
                }
                // TODO: Load & render footer
                // this.footer = new TableFooter(this);
                // this.footer.render();
                this.rowsVirtualizer.initialRender();
                fireEvent(this, 'afterInit');
            }
            /**
             * Sets the minimum height of the table body.
             */
            setTbodyMinHeight() {
                const { options } = this.grid;
                const minVisibleRows = options?.rendering?.rows?.minVisibleRows;
                const tbody = this.tbodyElement;
                if (defined(minVisibleRows) &&
                    !getStyle(tbody, 'min-height', true)) {
                    tbody.style.minHeight = (minVisibleRows * this.rowsVirtualizer.defaultRowHeight) + 'px';
                }
            }
            /**
             * Loads the columns of the table.
             */
            loadColumns() {
                const { enabledColumns } = this.grid;
                if (!enabledColumns) {
                    return;
                }
                let columnId;
                for (let i = 0, iEnd = enabledColumns.length; i < iEnd; ++i) {
                    columnId = enabledColumns[i];
                    this.columns.push(new Column(this, columnId, i));
                }
                this.columnDistribution.loadColumns();
            }
            /**
             * Fires an empty update to properly load the virtualization, only if
             * there's a row count compared to the threshold change detected (due to
             * performance reasons).
             */
            updateVirtualization() {
                const rows = this.grid.options?.rendering?.rows;
                const threshold = Number(rows?.virtualizationThreshold ||
                    Defaults.defaultOptions.rendering?.rows?.virtualizationThreshold);
                const rowCount = Number(this.dataTable?.rowCount);
                if (rows?.virtualization !== (rowCount >= threshold)) {
                    void this.grid.update();
                }
            }
            /**
             * Updates the rows of the table.
             */
            async updateRows() {
                const vp = this;
                let focusedRowId;
                if (vp.focusCursor) {
                    focusedRowId = vp.dataTable.getOriginalRowIndex(vp.focusCursor[0]);
                }
                const oldRowsCount = (vp.rows[vp.rows.length - 1]?.index ?? -1) + 1;
                await vp.grid.querying.proceed();
                this.dataTable = this.grid.presentationTable;
                for (const column of this.columns) {
                    column.loadData();
                }
                if (oldRowsCount !== vp.dataTable.rowCount) {
                    this.updateVirtualization();
                    this.rowsVirtualizer.rerender();
                }
                else {
                    for (let i = 0, iEnd = this.rows.length; i < iEnd; ++i) {
                        this.rows[i].update();
                    }
                    this.rowsVirtualizer.adjustRowHeights();
                }
                if (focusedRowId !== void 0 && vp.focusCursor) {
                    const newRowIndex = vp.dataTable.getLocalRowIndex(focusedRowId);
                    if (newRowIndex !== void 0) {
                        // Scroll to the focused row.
                        vp.scrollToRow(newRowIndex);
                        // Focus the cell that was focused before the update.
                        setTimeout(() => {
                            if (!defined(vp.focusCursor?.[1])) {
                                return;
                            }
                            vp.rows[newRowIndex - vp.rows[0].index]?.cells[vp.focusCursor[1]].htmlElement.focus();
                        });
                    }
                }
            }
            /**
             * Loads the modified data from the data table and renders the rows. Always
             * removes all rows and re-renders them, so it's better to use `updateRows`
             * instead, because it is more performant in some cases.
             *
             * @deprecated
             * Use `updateRows` instead. This method is kept for backward compatibility
             * reasons, but it will be removed in the next major version.
             */
            loadPresentationData() {
                this.dataTable = this.grid.presentationTable;
                for (const column of this.columns) {
                    column.loadData();
                }
                this.updateVirtualization();
                this.rowsVirtualizer.rerender();
            }
            /**
             * Reflows the table's content dimensions.
             */
            reflow() {
                this.columnDistribution.reflow();
                // Reflow the head
                this.header?.reflow();
                // Reflow rows content dimensions
                this.rowsVirtualizer.reflowRows();
            }
            /**
             * Scrolls the table to the specified row.
             *
             * @param index
             * The index of the row to scroll to.
             *
             * Try it: {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/grid-lite/basic/scroll-to-row | Scroll to row}
             */
            scrollToRow(index) {
                if (this.grid.options?.rendering?.rows?.virtualization) {
                    this.tbodyElement.scrollTop =
                        index * this.rowsVirtualizer.defaultRowHeight;
                    return;
                }
                const rowClass = '.' + Globals.getClassName('rowElement');
                const firstRowTop = this.tbodyElement
                    .querySelectorAll(rowClass)[0]
                    .getBoundingClientRect().top;
                this.tbodyElement.scrollTop = (this.tbodyElement
                    .querySelectorAll(rowClass)[index]
                    .getBoundingClientRect().top) - firstRowTop;
            }
            /**
             * Get the widthRatio value from the width in pixels. The widthRatio is
             * calculated based on the width of the viewport.
             *
             * @param width
             * The width in pixels.
             *
             * @return The width ratio.
             *
             * @internal
             */
            getRatioFromWidth(width) {
                return width / this.tbodyElement.clientWidth;
            }
            /**
             * Get the width in pixels from the widthRatio value. The width is
             * calculated based on the width of the viewport.
             *
             * @param ratio
             * The width ratio.
             *
             * @returns The width in pixels.
             *
             * @internal
             */
            getWidthFromRatio(ratio) {
                return this.tbodyElement.clientWidth * ratio;
            }
            /**
             * Destroys the grid table.
             */
            destroy() {
                this.tbodyElement.removeEventListener('focus', this.onTBodyFocus);
                this.tbodyElement.removeEventListener('scroll', this.onScroll);
                this.resizeObserver.disconnect();
                this.columnsResizer?.removeEventListeners();
                for (let i = 0, iEnd = this.rows.length; i < iEnd; ++i) {
                    this.rows[i].destroy();
                }
                fireEvent(this, 'afterDestroy');
            }
            /**
             * Get the viewport state metadata. It is used to save the state of the
             * viewport and restore it when the data grid is re-rendered.
             *
             * @returns
             * The viewport state metadata.
             */
            getStateMeta() {
                return {
                    scrollTop: this.tbodyElement.scrollTop,
                    scrollLeft: this.tbodyElement.scrollLeft,
                    columnDistribution: this.columnDistribution,
                    focusCursor: this.focusCursor
                };
            }
            /**
             * Apply the metadata to the viewport state. It is used to restore the state
             * of the viewport when the data grid is re-rendered.
             *
             * @param meta
             * The viewport state metadata.
             */
            applyStateMeta(meta) {
                this.tbodyElement.scrollTop = meta.scrollTop;
                this.tbodyElement.scrollLeft = meta.scrollLeft;
                if (meta.focusCursor) {
                    const [rowIndex, columnIndex] = meta.focusCursor;
                    const row = this.rows[rowIndex - this.rows[0].index];
                    row?.cells[columnIndex]?.htmlElement.focus();
                }
            }
            /**
             * Returns the column with the provided ID.
             *
             * @param id
             * The ID of the column.
             */
            getColumn(id) {
                const columns = this.grid.enabledColumns;
                if (!columns) {
                    return;
                }
                const columnIndex = columns.indexOf(id);
                if (columnIndex < 0) {
                    return;
                }
                return this.columns[columnIndex];
            }
            /**
             * Returns the row with the provided ID.
             *
             * @param id
             * The ID of the row.
             */
            getRow(id) {
                // TODO: Change `find` to a method using `vp.dataTable.getLocalRowIndex`
                // and rows[presentationRowIndex - firstRowIndex]. Needs more testing,
                // but it should be faster.
                return this.rows.find((row) => row.id === id);
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Table;
    });
    _registerModule(_modules, 'Data/Modifiers/ChainModifier.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Core/Utilities.js']], function (DataModifier, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Modifies a table with the help of modifiers in an ordered chain.
         *
         */
        class ChainModifier extends DataModifier {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the modifier chain.
             *
             * @param {Partial<ChainModifier.Options>} [options]
             * Options to configure the modifier chain.
             *
             * @param {...DataModifier} [chain]
             * Ordered chain of modifiers.
             */
            constructor(options, ...chain) {
                super();
                this.chain = chain;
                this.options = merge(ChainModifier.defaultOptions, options);
                const optionsChain = this.options.chain || [];
                for (let i = 0, iEnd = optionsChain.length, modifierOptions, ModifierClass; i < iEnd; ++i) {
                    modifierOptions = optionsChain[i];
                    if (!modifierOptions.type) {
                        continue;
                    }
                    ModifierClass = DataModifier.types[modifierOptions.type];
                    if (ModifierClass) {
                        chain.push(new ModifierClass(modifierOptions));
                    }
                }
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Adds a configured modifier to the end of the modifier chain. Please note,
             * that the modifier can be added multiple times.
             *
             * @param {DataModifier} modifier
             * Configured modifier to add.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             */
            add(modifier, eventDetail) {
                this.emit({
                    type: 'addModifier',
                    detail: eventDetail,
                    modifier
                });
                this.chain.push(modifier);
                this.emit({
                    type: 'addModifier',
                    detail: eventDetail,
                    modifier
                });
            }
            /**
             * Clears all modifiers from the chain.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             */
            clear(eventDetail) {
                this.emit({
                    type: 'clearChain',
                    detail: eventDetail
                });
                this.chain.length = 0;
                this.emit({
                    type: 'afterClearChain',
                    detail: eventDetail
                });
            }
            /**
             * Applies several modifications to the table and returns a modified copy of
             * the given table.
             *
             * @param {Highcharts.DataTable} table
             * Table to modify.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Promise<Highcharts.DataTable>}
             * Table with `modified` property as a reference.
             */
            async modify(table, eventDetail) {
                const modifiers = (this.options.reverse ?
                    this.chain.slice().reverse() :
                    this.chain.slice());
                if (table.modified === table) {
                    table.modified = table.clone(false, eventDetail);
                }
                let modified = table;
                for (let i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
                    try {
                        await modifiers[i].modify(modified, eventDetail);
                    }
                    catch (error) {
                        this.emit({
                            type: 'error',
                            detail: eventDetail,
                            table
                        });
                        throw error;
                    }
                    modified = modified.modified;
                }
                table.modified = modified;
                return table;
            }
            /**
             * Applies partial modifications of a cell change to the property `modified`
             * of the given modified table.
             *
             * *Note:* The `modified` property of the table gets replaced.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {string} columnName
             * Column name of changed cell.
             *
             * @param {number|undefined} rowIndex
             * Row index of changed cell.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Changed cell value.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyCell(table, columnName, rowIndex, cellValue, eventDetail) {
                const modifiers = (this.options.reverse ?
                    this.chain.reverse() :
                    this.chain);
                if (modifiers.length) {
                    let clone = table.clone();
                    for (let i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
                        modifiers[i].modifyCell(clone, columnName, rowIndex, cellValue, eventDetail);
                        clone = clone.modified;
                    }
                    table.modified = clone;
                }
                return table;
            }
            /**
             * Applies partial modifications of column changes to the property
             * `modified` of the given table.
             *
             * *Note:* The `modified` property of the table gets replaced.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Highcharts.DataTableColumnCollection} columns
             * Changed columns as a collection, where the keys are the column names.
             *
             * @param {number} [rowIndex=0]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyColumns(table, columns, rowIndex, eventDetail) {
                const modifiers = (this.options.reverse ?
                    this.chain.reverse() :
                    this.chain.slice());
                if (modifiers.length) {
                    let clone = table.clone();
                    for (let i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
                        modifiers[i].modifyColumns(clone, columns, rowIndex, eventDetail);
                        clone = clone.modified;
                    }
                    table.modified = clone;
                }
                return table;
            }
            /**
             * Applies partial modifications of row changes to the property `modified`
             * of the given table.
             *
             * *Note:* The `modified` property of the table gets replaced.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
             * Changed rows.
             *
             * @param {number} [rowIndex]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyRows(table, rows, rowIndex, eventDetail) {
                const modifiers = (this.options.reverse ?
                    this.chain.reverse() :
                    this.chain.slice());
                if (modifiers.length) {
                    let clone = table.clone();
                    for (let i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
                        modifiers[i].modifyRows(clone, rows, rowIndex, eventDetail);
                        clone = clone.modified;
                    }
                    table.modified = clone;
                }
                return table;
            }
            /**
             * Applies several modifications to the table.
             *
             * *Note:* The `modified` property of the table gets replaced.
             *
             * @param {DataTable} table
             * Table to modify.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {DataTable}
             * Table as a reference.
             *
             * @emits ChainDataModifier#execute
             * @emits ChainDataModifier#afterExecute
             */
            modifyTable(table, eventDetail) {
                const chain = this;
                chain.emit({
                    type: 'modify',
                    detail: eventDetail,
                    table
                });
                const modifiers = (chain.options.reverse ?
                    chain.chain.reverse() :
                    chain.chain.slice());
                let modified = table.modified;
                for (let i = 0, iEnd = modifiers.length, modifier; i < iEnd; ++i) {
                    modifier = modifiers[i];
                    modified = modifier.modifyTable(modified, eventDetail).modified;
                }
                table.modified = modified;
                chain.emit({
                    type: 'afterModify',
                    detail: eventDetail,
                    table
                });
                return table;
            }
            /**
             * Removes a configured modifier from all positions in the modifier chain.
             *
             * @param {DataModifier} modifier
             * Configured modifier to remove.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             */
            remove(modifier, eventDetail) {
                const modifiers = this.chain;
                this.emit({
                    type: 'removeModifier',
                    detail: eventDetail,
                    modifier
                });
                modifiers.splice(modifiers.indexOf(modifier), 1);
                this.emit({
                    type: 'afterRemoveModifier',
                    detail: eventDetail,
                    modifier
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default option for the ordered modifier chain.
         */
        ChainModifier.defaultOptions = {
            type: 'Chain'
        };
        DataModifier.registerType('Chain', ChainModifier);
        /* *
         *
         *  Default Export
         *
         * */

        return ChainModifier;
    });
    _registerModule(_modules, 'Data/Modifiers/SortModifier.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Data/DataTable.js'], _modules['Core/Utilities.js']], function (DataModifier, DataTable, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Sort table rows according to values of a column.
         *
         */
        class SortModifier extends DataModifier {
            /* *
             *
             *  Static Functions
             *
             * */
            static ascending(a, b) {
                return ((a || 0) < (b || 0) ? -1 :
                    (a || 0) > (b || 0) ? 1 :
                        0);
            }
            static descending(a, b) {
                return ((b || 0) < (a || 0) ? -1 :
                    (b || 0) > (a || 0) ? 1 :
                        0);
            }
            static compareFactory(direction, customCompare) {
                if (customCompare) {
                    if (direction === 'desc') {
                        return (a, b) => -customCompare(a, b);
                    }
                    return customCompare;
                }
                return (direction === 'asc' ?
                    SortModifier.ascending :
                    SortModifier.descending);
            }
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the range modifier.
             *
             * @param {Partial<RangeDataModifier.Options>} [options]
             * Options to configure the range modifier.
             */
            constructor(options) {
                super();
                this.options = merge(SortModifier.defaultOptions, options);
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Returns index and row for sort reference.
             *
             * @private
             *
             * @param {Highcharts.DataTable} table
             * Table with rows to reference.
             *
             * @return {Array<SortModifier.RowReference>}
             * Array of row references.
             */
            getRowReferences(table) {
                const rows = table.getRows(), rowReferences = [];
                for (let i = 0, iEnd = rows.length; i < iEnd; ++i) {
                    rowReferences.push({
                        index: i,
                        row: rows[i]
                    });
                }
                return rowReferences;
            }
            /**
             * Applies partial modifications of a cell change to the property `modified`
             * of the given modified table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {string} columnName
             * Column name of changed cell.
             *
             * @param {number|undefined} rowIndex
             * Row index of changed cell.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Changed cell value.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyCell(table, columnName, rowIndex, cellValue, eventDetail) {
                const modifier = this, { orderByColumn, orderInColumn } = modifier.options;
                if (columnName === orderByColumn) {
                    if (orderInColumn) {
                        table.modified.setCell(columnName, rowIndex, cellValue);
                        table.modified.setColumn(orderInColumn, modifier
                            .modifyTable(new DataTable({
                            columns: table
                                .getColumns([orderByColumn, orderInColumn])
                        }))
                            .modified
                            .getColumn(orderInColumn));
                    }
                    else {
                        modifier.modifyTable(table, eventDetail);
                    }
                }
                return table;
            }
            /**
             * Applies partial modifications of column changes to the property
             * `modified` of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Highcharts.DataTableColumnCollection} columns
             * Changed columns as a collection, where the keys are the column names.
             *
             * @param {number} [rowIndex=0]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyColumns(table, columns, rowIndex, eventDetail) {
                const modifier = this, { orderByColumn, orderInColumn } = modifier.options, columnNames = Object.keys(columns);
                if (columnNames.indexOf(orderByColumn) > -1) {
                    if (orderInColumn &&
                        columns[columnNames[0]].length) {
                        table.modified.setColumns(columns, rowIndex);
                        table.modified.setColumn(orderInColumn, modifier
                            .modifyTable(new DataTable({
                            columns: table
                                .getColumns([orderByColumn, orderInColumn])
                        }))
                            .modified
                            .getColumn(orderInColumn));
                    }
                    else {
                        modifier.modifyTable(table, eventDetail);
                    }
                }
                return table;
            }
            /**
             * Applies partial modifications of row changes to the property `modified`
             * of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
             * Changed rows.
             *
             * @param {number} [rowIndex]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyRows(table, rows, rowIndex, eventDetail) {
                const modifier = this, { orderByColumn, orderInColumn } = modifier.options;
                if (orderInColumn &&
                    rows.length) {
                    table.modified.setRows(rows, rowIndex);
                    table.modified.setColumn(orderInColumn, modifier
                        .modifyTable(new DataTable({
                        columns: table
                            .getColumns([orderByColumn, orderInColumn])
                    }))
                        .modified
                        .getColumn(orderInColumn));
                }
                else {
                    modifier.modifyTable(table, eventDetail);
                }
                return table;
            }
            /**
             * Sorts rows in the table.
             *
             * @param {DataTable} table
             * Table to sort in.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {DataTable}
             * Table with `modified` property as a reference.
             */
            modifyTable(table, eventDetail) {
                const modifier = this;
                modifier.emit({ type: 'modify', detail: eventDetail, table });
                const columnNames = table.getColumnNames(), rowCount = table.getRowCount(), rowReferences = this.getRowReferences(table), { direction, orderByColumn, orderInColumn, compare: customCompare } = modifier.options, compare = SortModifier.compareFactory(direction, customCompare), orderByColumnIndex = columnNames.indexOf(orderByColumn), modified = table.modified;
                if (orderByColumnIndex !== -1) {
                    rowReferences.sort((a, b) => compare(a.row[orderByColumnIndex], b.row[orderByColumnIndex]));
                }
                if (orderInColumn) {
                    const column = [];
                    for (let i = 0; i < rowCount; ++i) {
                        column[rowReferences[i].index] = i;
                    }
                    modified.setColumns({ [orderInColumn]: column });
                }
                else {
                    const originalIndexes = [];
                    const rows = [];
                    let rowReference;
                    for (let i = 0; i < rowCount; ++i) {
                        rowReference = rowReferences[i];
                        originalIndexes.push(modified.getOriginalRowIndex(rowReference.index));
                        rows.push(rowReference.row);
                    }
                    modified.setRows(rows, 0);
                    modified.setOriginalRowIndexes(originalIndexes);
                }
                modifier.emit({ type: 'afterModify', detail: eventDetail, table });
                return table;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options to group table rows.
         */
        SortModifier.defaultOptions = {
            type: 'Sort',
            direction: 'desc',
            orderByColumn: 'y'
        };
        DataModifier.registerType('Sort', SortModifier);
        /* *
         *
         *  Default Export
         *
         * */

        return SortModifier;
    });
    _registerModule(_modules, 'Grid/Core/Querying/SortingController.js', [_modules['Data/Modifiers/SortModifier.js']], function (SortModifier) {
        /* *
         *
         *  Grid Sorting Controller class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that manages one of the data grid querying types - sorting.
         */
        class SortingController {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs the SortingController instance.
             *
             * @param querying
             * The querying controller instance.
             */
            constructor(querying) {
                this.querying = querying;
            }
            /* *
            *
            *  Functions
            *
            * */
            /**
             * Sets the sorting state. If the new sorting state is different than the
             * current one, the `shouldBeUpdated` flag is set to `true`. If the
             * same, the flag is set to `false`.
             *
             * @param order
             * The sorting order.
             *
             * @param columnId
             * The column ID to sort by.
             */
            setSorting(order, columnId) {
                if (this.currentSorting?.columnId !== columnId ||
                    this.currentSorting?.order !== order) {
                    this.querying.shouldBeUpdated = true;
                    this.currentSorting = {
                        columnId,
                        order
                    };
                }
                this.modifier = this.createModifier();
            }
            /**
             * Returns the sorting options from the data grid options.
             */
            getSortingOptions() {
                const grid = this.querying.grid, { columnOptionsMap } = grid;
                if (!columnOptionsMap) {
                    return { order: null };
                }
                const columnIDs = Object.keys(columnOptionsMap);
                let foundOrder = null;
                let foundColumnId;
                for (let i = columnIDs.length - 1; i > -1; --i) {
                    const columnId = columnIDs[i];
                    const columnOptions = columnOptionsMap[columnId]?.options || {};
                    const order = columnOptions.sorting?.order;
                    if (order) {
                        if (foundColumnId) {
                            // eslint-disable-next-line no-console
                            console.warn('Grid: Only one column can be sorted at a time. ' +
                                'Data will be sorted only by the last found column ' +
                                `with the sorting order defined in the options: "${foundColumnId}".`);
                            break;
                        }
                        foundOrder = order;
                        foundColumnId = columnId;
                    }
                }
                return {
                    columnId: foundColumnId,
                    order: foundOrder
                };
            }
            /**
             * Loads sorting options from the data grid options.
             */
            loadOptions() {
                const stateFromOptions = this.getSortingOptions();
                if (stateFromOptions.columnId !== this.initialSorting?.columnId ||
                    stateFromOptions.order !== this.initialSorting?.order) {
                    this.initialSorting = stateFromOptions;
                    this.setSorting(stateFromOptions.order, stateFromOptions.columnId);
                }
            }
            /**
             * Returns the sorting modifier based on the loaded sorting options.
             */
            createModifier() {
                if (!this.currentSorting) {
                    return;
                }
                const { columnId, order } = this.currentSorting;
                if (!order || !columnId) {
                    return;
                }
                return new SortModifier({
                    orderByColumn: columnId,
                    direction: order,
                    compare: this.querying.grid.columnOptionsMap?.[columnId]
                        ?.options?.sorting?.compare
                });
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return SortingController;
    });
    _registerModule(_modules, 'Grid/Core/Querying/QueryingController.js', [_modules['Data/Modifiers/ChainModifier.js'], _modules['Grid/Core/Querying/SortingController.js']], function (ChainModifier, SortingController) {
        /* *
         *
         *  Grid Querying Controller class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Imports
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that manage data modification of the visible data in the data grid.
         * It manages the modifiers that are applied to the data table.
         */
        class QueryingController {
            /* *
            *
            *  Constructor
            *
            * */
            constructor(grid) {
                /**
                 * This flag should be set to `true` if the modifiers should reapply to the
                 * data table due to some data change or other important reason.
                 */
                this.shouldBeUpdated = false;
                this.grid = grid;
                this.sorting = new SortingController(this);
            }
            /* *
            *
            *  Functions
            *
            * */
            /**
             * Proceeds with the data modification if needed.
             *
             * @param force
             * If the data should be modified even if the significant options are not
             * changed.
             */
            async proceed(force = false) {
                if (force || this.shouldBeUpdated) {
                    await this.modifyData();
                }
            }
            /**
             * Load all options needed to generate the modifiers.
             */
            loadOptions() {
                this.sorting.loadOptions();
            }
            /**
             * Creates a list of modifiers that should be applied to the data table.
             */
            getModifiers() {
                const modifiers = [];
                if (this.sorting.modifier) {
                    modifiers.push(this.sorting.modifier);
                }
                return modifiers;
            }
            /**
             * Apply all modifiers to the data table.
             */
            async modifyData() {
                const originalDataTable = this.grid.dataTable;
                if (!originalDataTable) {
                    return;
                }
                const modifiers = this.getModifiers();
                if (modifiers.length > 0) {
                    const chainModifier = new ChainModifier({}, ...modifiers);
                    const dataTableCopy = originalDataTable.clone();
                    await chainModifier.modify(dataTableCopy.modified);
                    this.grid.presentationTable = dataTableCopy.modified;
                }
                else {
                    this.grid.presentationTable = originalDataTable.modified;
                }
                this.shouldBeUpdated = false;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return QueryingController;
    });
    _registerModule(_modules, 'Grid/Core/Grid.js', [_modules['Grid/Core/Accessibility/Accessibility.js'], _modules['Core/Renderer/HTML/AST.js'], _modules['Grid/Core/Defaults.js'], _modules['Grid/Core/GridUtils.js'], _modules['Data/DataTable.js'], _modules['Grid/Core/Table/Table.js'], _modules['Core/Utilities.js'], _modules['Grid/Core/Querying/QueryingController.js'], _modules['Grid/Core/Globals.js'], _modules['Shared/TimeBase.js']], function (Accessibility, AST, Defaults, GridUtils, DataTable, Table, U, QueryingController, Globals, TimeBase) {
        /* *
         *
         *  Highcharts Grid class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement, setHTMLContent } = GridUtils;
        const { fireEvent, extend, getStyle, merge, pick, defined } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * A base class for the Grid.
         */
        class Grid {
            // Implementation
            static grid(renderTo, options, async) {
                if (async) {
                    return new Promise((resolve) => {
                        void new Grid(renderTo, options, (grid) => {
                            resolve(grid);
                        });
                    });
                }
                return new Grid(renderTo, options);
            }
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Constructs a new Grid.
             *
             * @param renderTo
             * The render target (container) of the Grid.
             *
             * @param options
             * The options of the Grid.
             *
             * @param afterLoadCallback
             * The callback that is called after the Grid is loaded.
             */
            constructor(renderTo, options, afterLoadCallback) {
                /**
                 * The user options declared for the columns as an object of column ID to
                 * column options.
                 * @internal
                 */
                this.columnOptionsMap = {};
                /**
                 * The options that were declared by the user when creating the Grid
                 * or when updating it.
                 */
                this.userOptions = {};
                /**
                 * The initial height of the container. Can be 0 also if not set.
                 * @internal
                 */
                this.initialContainerHeight = 0;
                this.loadUserOptions(options);
                this.querying = new QueryingController(this);
                this.id = this.options?.id || U.uniqueKey();
                this.initContainers(renderTo);
                this.initAccessibility();
                this.loadDataTable(this.options?.dataTable);
                this.initVirtualization();
                this.locale = this.options?.lang?.locale || (this.container?.closest('[lang]')?.lang);
                this.time = new TimeBase(extend(this.options?.time, { locale: this.locale }), this.options?.lang);
                this.querying.loadOptions();
                void this.querying.proceed().then(() => {
                    this.renderViewport();
                    afterLoadCallback?.(this);
                });
                Grid.grids.push(this);
            }
            /* *
             *
             *  Methods
             *
             * */
            /*
             * Initializes the accessibility controller.
             */
            initAccessibility() {
                this.accessibility?.destroy();
                delete this.accessibility;
                if (this.options?.accessibility?.enabled) {
                    this.accessibility = new Accessibility(this);
                }
            }
            /**
             * Initializes the container of the Grid.
             *
             * @param renderTo
             * The render target (html element or id) of the Grid.
             *
             */
            initContainers(renderTo) {
                const container = (typeof renderTo === 'string') ?
                    Globals.win.document.getElementById(renderTo) : renderTo;
                // Display an error if the renderTo is wrong
                if (!container) {
                    // eslint-disable-next-line no-console
                    console.error(`
                        Rendering div not found. It is unable to find the HTML element
                        to render the Grid in.
                    `);
                    return;
                }
                this.initialContainerHeight = getStyle(container, 'height', true) || 0;
                this.container = container;
                this.container.innerHTML = AST.emptyHTML;
                this.contentWrapper = makeHTMLElement('div', {
                    className: Globals.getClassName('container')
                }, this.container);
            }
            /**
             * Loads the new user options to all the important fields (`userOptions`,
             * `options` and `columnOptionsMap`).
             *
             * @param newOptions
             * The options that were declared by the user.
             *
             * @param oneToOne
             * When `false` (default), the existing column options will be merged with
             * the ones that are currently defined in the user options. When `true`,
             * the columns not defined in the new options will be removed.
             */
            loadUserOptions(newOptions, oneToOne = false) {
                // Operate on a copy of the options argument
                newOptions = merge(newOptions);
                if (newOptions.columns) {
                    if (oneToOne) {
                        this.setColumnOptionsOneToOne(newOptions.columns);
                    }
                    else {
                        this.setColumnOptions(newOptions.columns);
                    }
                    delete newOptions.columns;
                }
                this.userOptions = merge(this.userOptions, newOptions);
                this.options = merge(this.options ?? Defaults.defaultOptions, this.userOptions);
                // Generate column options map
                const columnOptionsArray = this.options?.columns;
                if (!columnOptionsArray) {
                    return;
                }
                const columnOptionsMap = {};
                for (let i = 0, iEnd = columnOptionsArray?.length ?? 0; i < iEnd; ++i) {
                    columnOptionsMap[columnOptionsArray[i].id] = {
                        index: i,
                        options: columnOptionsArray[i]
                    };
                }
                this.columnOptionsMap = columnOptionsMap;
            }
            /**
             * Sets the new column options to the userOptions field.
             *
             * @param newColumnOptions
             * The new column options that should be loaded.
             *
             * @param overwrite
             * Whether to overwrite the existing column options with the new ones.
             * Default is `false`.
             */
            setColumnOptions(newColumnOptions, overwrite = false) {
                if (!this.userOptions.columns) {
                    this.userOptions.columns = [];
                }
                const columnOptions = this.userOptions.columns;
                for (let i = 0, iEnd = newColumnOptions.length; i < iEnd; ++i) {
                    const newOptions = newColumnOptions[i];
                    const colOptionsIndex = this.columnOptionsMap?.[newOptions.id]?.index ?? -1;
                    // If the new column options contain only the id.
                    if (Object.keys(newOptions).length < 2) {
                        if (overwrite && colOptionsIndex !== -1) {
                            columnOptions.splice(colOptionsIndex, 1);
                        }
                        continue;
                    }
                    if (colOptionsIndex === -1) {
                        columnOptions.push(newOptions);
                    }
                    else if (overwrite) {
                        columnOptions[colOptionsIndex] = newOptions;
                    }
                    else {
                        merge(true, columnOptions[colOptionsIndex], newOptions);
                    }
                }
                if (columnOptions.length < 1) {
                    delete this.userOptions.columns;
                }
            }
            /**
             * Loads the new column options to the userOptions field in a one-to-one
             * manner. It means that all the columns that are not defined in the new
             * options will be removed.
             *
             * @param newColumnOptions
             * The new column options that should be loaded.
             */
            setColumnOptionsOneToOne(newColumnOptions) {
                const prevColumnOptions = this.userOptions.columns;
                const columnOptions = [];
                let prevOptions;
                for (let i = 0, iEnd = newColumnOptions.length; i < iEnd; ++i) {
                    const newOptions = newColumnOptions[i];
                    const indexInPrevOptions = prevColumnOptions?.findIndex((prev) => prev.id === newOptions.id);
                    if (indexInPrevOptions !== void 0 && indexInPrevOptions !== -1) {
                        prevOptions = prevColumnOptions?.[indexInPrevOptions];
                    }
                    const resultOptions = merge(prevOptions ?? {}, newOptions);
                    if (Object.keys(resultOptions).length > 1) {
                        columnOptions.push(resultOptions);
                    }
                }
                this.userOptions.columns = columnOptions;
            }
            /**
             * Updates the Grid with new options.
             *
             * @param options
             * The options of the Grid that should be updated. If not provided,
             * the update will be proceeded based on the `this.userOptions` property.
             * The `column` options are merged using the `id` property as a key.
             *
             * @param render
             * Whether to re-render the Grid after updating the options.
             *
             * @param oneToOne
             * When `false` (default), the existing column options will be merged with
             * the ones that are currently defined in the user options. When `true`,
             * the columns not defined in the new options will be removed.
             */
            async update(options = {}, render = true, oneToOne = false) {
                this.loadUserOptions(options, oneToOne);
                this.initAccessibility();
                let newDataTable = false;
                if (!this.dataTable || options.dataTable) {
                    this.userOptions.dataTable = options.dataTable;
                    (this.options ?? {}).dataTable = options.dataTable;
                    this.loadDataTable(this.options?.dataTable);
                    newDataTable = true;
                    this.initVirtualization();
                }
                this.querying.loadOptions();
                // Update locale.
                const locale = options.lang?.locale;
                if (locale) {
                    this.locale = locale;
                    this.time.update(extend(options.time || {}, { locale: this.locale }));
                }
                if (render) {
                    await this.querying.proceed(newDataTable);
                    this.renderViewport();
                }
            }
            /**
             * Updates the column of the Grid with new options.
             *
             * @param columnId
             * The ID of the column that should be updated.
             *
             * @param options
             * The options of the columns that should be updated. If null,
             * column options for this column ID will be removed.
             *
             * @param render
             * Whether to re-render the Grid after updating the columns.
             *
             * @param overwrite
             * If true, the column options will be updated by replacing the existing
             * options with the new ones instead of merging them.
             */
            async updateColumn(columnId, options, render = true, overwrite = false) {
                this.setColumnOptions([{
                        id: columnId,
                        ...options
                    }], overwrite);
                await this.update(void 0, render);
            }
            /**
             * Hovers the row with the provided index. It removes the hover effect from
             * the previously hovered row.
             *
             * @param rowIndex
             * The index of the row.
             */
            hoverRow(rowIndex) {
                const rows = this.viewport?.rows;
                if (!rows) {
                    return;
                }
                const firstRowIndex = this.viewport?.rows[0]?.index ?? 0;
                if (this.hoveredRowIndex !== void 0) {
                    rows[this.hoveredRowIndex - firstRowIndex]?.setHoveredState(false);
                }
                if (rowIndex !== void 0) {
                    rows[rowIndex - firstRowIndex]?.setHoveredState(true);
                }
                this.hoveredRowIndex = rowIndex;
            }
            /**
             * Hovers the column with the provided ID. It removes the hover effect from
             * the previously hovered column.
             *
             * @param columnId
             * The ID of the column.
             */
            hoverColumn(columnId) {
                const vp = this.viewport;
                if (!vp) {
                    return;
                }
                if (this.hoveredColumnId) {
                    vp.getColumn(this.hoveredColumnId)?.setHoveredState(false);
                }
                if (columnId) {
                    vp.getColumn(columnId)?.setHoveredState(true);
                }
                this.hoveredColumnId = columnId;
            }
            /**
             * Sets the sync state to the row with the provided index. It removes the
             * synced effect from the previously synced row.
             *
             * @param rowIndex
             * The index of the row.
             */
            syncRow(rowIndex) {
                const rows = this.viewport?.rows;
                if (!rows) {
                    return;
                }
                const firstRowIndex = this.viewport?.rows[0]?.index ?? 0;
                if (this.syncedRowIndex !== void 0) {
                    rows[this.syncedRowIndex - firstRowIndex]?.setSyncedState(false);
                }
                if (rowIndex !== void 0) {
                    rows[rowIndex - firstRowIndex]?.setSyncedState(true);
                }
                this.syncedRowIndex = rowIndex;
            }
            /**
             * Sets the sync state to the column with the provided ID. It removes the
             * synced effect from the previously synced column.
             *
             * @param columnId
             * The ID of the column.
             */
            syncColumn(columnId) {
                const vp = this.viewport;
                if (!vp) {
                    return;
                }
                if (this.syncedColumnId) {
                    vp.getColumn(this.syncedColumnId)?.setSyncedState(false);
                }
                if (columnId) {
                    vp.getColumn(columnId)?.setSyncedState(true);
                }
                this.syncedColumnId = columnId;
            }
            /**
             * Render caption above the grid.
             * @internal
             */
            renderCaption() {
                const captionOptions = this.options?.caption;
                const captionText = captionOptions?.text;
                if (!captionText) {
                    return;
                }
                // Create a caption element.
                this.captionElement = makeHTMLElement('div', {
                    className: Globals.getClassName('captionElement'),
                    id: this.id + '-caption'
                }, this.contentWrapper);
                // Render the caption element content.
                setHTMLContent(this.captionElement, captionText);
                if (captionOptions.className) {
                    this.captionElement.classList.add(...captionOptions.className.split(/\s+/g));
                }
            }
            /**
             * Render description under the grid.
             *
             * @internal
             */
            renderDescription() {
                const descriptionOptions = this.options?.description;
                const descriptionText = descriptionOptions?.text;
                if (!descriptionText) {
                    return;
                }
                // Create a description element.
                this.descriptionElement = makeHTMLElement('div', {
                    className: Globals.getClassName('descriptionElement'),
                    id: this.id + '-description'
                }, this.contentWrapper);
                // Render the description element content.
                setHTMLContent(this.descriptionElement, descriptionText);
                if (descriptionOptions.className) {
                    this.descriptionElement.classList.add(...descriptionOptions.className.split(/\s+/g));
                }
            }
            /**
             * Resets the content wrapper of the Grid. It clears the content and
             * resets the class names.
             * @internal
             */
            resetContentWrapper() {
                if (!this.contentWrapper) {
                    return;
                }
                this.contentWrapper.innerHTML = AST.emptyHTML;
                this.contentWrapper.className =
                    Globals.getClassName('container') + ' ' +
                        this.options?.rendering?.theme || '';
            }
            /**
             * Renders the viewport of the Grid. If the Grid is already
             * rendered, it will be destroyed and re-rendered with the new data.
             * @internal
             */
            renderViewport() {
                const viewportMeta = this.viewport?.getStateMeta();
                this.enabledColumns = this.getEnabledColumnIDs();
                this.credits?.destroy();
                this.viewport?.destroy();
                delete this.viewport;
                this.resetContentWrapper();
                this.renderCaption();
                if (this.enabledColumns.length > 0) {
                    this.viewport = this.renderTable();
                    if (viewportMeta && this.viewport) {
                        this.viewport.applyStateMeta(viewportMeta);
                    }
                }
                else {
                    this.renderNoData();
                }
                this.renderDescription();
                this.accessibility?.setA11yOptions();
                fireEvent(this, 'afterRenderViewport');
                this.viewport?.reflow();
            }
            /**
             * Renders the table (viewport) of the Grid.
             *
             * @returns
             * The newly rendered table (viewport) of the Grid.
             */
            renderTable() {
                this.tableElement = makeHTMLElement('table', {
                    className: Globals.getClassName('tableElement')
                }, this.contentWrapper);
                return new Table(this, this.tableElement);
            }
            /**
             * Renders a message that there is no data to display.
             */
            renderNoData() {
                makeHTMLElement('div', {
                    className: Globals.getClassName('noData'),
                    innerText: this.options?.lang?.noData
                }, this.contentWrapper);
            }
            /**
             * Returns the array of IDs of columns that should be displayed in the data
             * grid, in the correct order.
             */
            getEnabledColumnIDs() {
                const { columnOptionsMap } = this;
                const header = this.options?.header;
                const headerColumns = this.getColumnIds(header || [], false);
                const columnsIncluded = this.options?.rendering?.columns?.included || (headerColumns && headerColumns.length > 0 ?
                    headerColumns : this.dataTable?.getColumnNames());
                if (!columnsIncluded?.length) {
                    return [];
                }
                if (!columnOptionsMap) {
                    return columnsIncluded;
                }
                let columnName;
                const result = [];
                for (let i = 0, iEnd = columnsIncluded.length; i < iEnd; ++i) {
                    columnName = columnsIncluded[i];
                    if (columnOptionsMap?.[columnName]?.options?.enabled !== false) {
                        result.push(columnName);
                    }
                }
                return result;
            }
            loadDataTable(tableOptions) {
                // If the table is passed as a reference, it should be used instead of
                // creating a new one.
                if (tableOptions?.id) {
                    this.dataTable = tableOptions;
                    this.presentationTable = this.dataTable.modified;
                    return;
                }
                this.dataTable = this.presentationTable =
                    new DataTable(tableOptions);
            }
            /**
             * Extracts all references to columnIds on all levels below defined level
             * in the settings.header structure.
             *
             * @param columnsTree
             * Structure that we start calculation
             *
             * @param [onlyEnabledColumns=true]
             * Extract all columns from header or columns filtered by enabled param
             * @returns
             */
            getColumnIds(columnsTree, onlyEnabledColumns = true) {
                let columnIds = [];
                const { enabledColumns } = this;
                for (const column of columnsTree) {
                    const columnId = typeof column === 'string' ? column : column.columnId;
                    if (columnId &&
                        (!onlyEnabledColumns || (enabledColumns?.includes(columnId)))) {
                        columnIds.push(columnId);
                    }
                    if (typeof column !== 'string' && column.columns) {
                        columnIds = columnIds.concat(this.getColumnIds(column.columns, onlyEnabledColumns));
                    }
                }
                return columnIds;
            }
            /**
             * Destroys the Grid.
             */
            destroy() {
                const dgIndex = Grid.grids.findIndex((dg) => dg === this);
                this.viewport?.destroy();
                if (this.container) {
                    this.container.innerHTML = AST.emptyHTML;
                    this.container.classList.remove(Globals.getClassName('container'));
                }
                // Clear all properties
                Object.keys(this).forEach((key) => {
                    delete this[key];
                });
                Grid.grids.splice(dgIndex, 1);
            }
            /**
             * Grey out the Grid and show a loading indicator.
             *
             * @param message
             * The message to display in the loading indicator.
             */
            showLoading(message) {
                if (this.loadingWrapper) {
                    return;
                }
                // Create loading wrapper.
                this.loadingWrapper = makeHTMLElement('div', {
                    className: Globals.getClassName('loadingWrapper')
                }, this.contentWrapper);
                // Create spinner element.
                makeHTMLElement('div', {
                    className: Globals.getClassName('loadingSpinner')
                }, this.loadingWrapper);
                // Create loading message span element.
                const loadingSpan = makeHTMLElement('span', {
                    className: Globals.getClassName('loadingMessage')
                }, this.loadingWrapper);
                setHTMLContent(loadingSpan, pick(message, this.options?.lang?.loading, ''));
            }
            /**
             * Removes the loading indicator.
             */
            hideLoading() {
                this.loadingWrapper?.remove();
                delete this.loadingWrapper;
            }
            /**
             * Returns the current grid data as a JSON string.
             *
             * @return
             * JSON representation of the data
             */
            getData() {
                const json = this.viewport?.dataTable.modified.columns;
                if (!this.enabledColumns || !json) {
                    return '{}';
                }
                for (const key of Object.keys(json)) {
                    if (this.enabledColumns.indexOf(key) === -1) {
                        delete json[key];
                    }
                }
                return JSON.stringify(json);
            }
            /**
             * Returns the current grid data as a JSON string.
             *
             * @return
             * JSON representation of the data
             *
             * @deprecated
             */
            getJSON() {
                return this.getData();
            }
            /**
             * Returns the current Grid options.
             *
             * @param onlyUserOptions
             * Whether to return only the user options or all options (user options
             * merged with the default ones). Default is `true`.
             *
             * @returns
             * Grid options.
             */
            getOptions(onlyUserOptions = true) {
                const options = onlyUserOptions ? merge(this.userOptions) : merge(this.options);
                if (options.dataTable?.id) {
                    options.dataTable = {
                        columns: options.dataTable.columns
                    };
                }
                return options;
            }
            /**
             * Returns the current Grid options.
             *
             * @param onlyUserOptions
             * Whether to return only the user options or all options (user options
             * merged with the default ones). Default is `true`.
             *
             * @returns
             * Options as a JSON string
             *
             * @deprecated
             */
            getOptionsJSON(onlyUserOptions = true) {
                return JSON.stringify(this.getOptions(onlyUserOptions));
            }
            /**
             * Enables virtualization if the row count is greater than or equal to the
             * threshold or virtualization is enabled externally. Should be fired after
             * the data table is loaded.
             */
            initVirtualization() {
                var _a, _b;
                const rows = this.userOptions.rendering?.rows;
                const virtualization = rows?.virtualization;
                const threshold = Number(rows?.virtualizationThreshold ||
                    Defaults.defaultOptions.rendering?.rows?.virtualizationThreshold);
                const rowCount = Number(this.dataTable?.rowCount);
                // Makes sure all nested options are defined.
                (_b = ((_a = (this.options ?? (this.options = {}))).rendering ?? (_a.rendering = {}))).rows ?? (_b.rows = {});
                this.options.rendering.rows.virtualization =
                    defined(virtualization) ? virtualization : rowCount >= threshold;
            }
        }
        /* *
        *
        *  Properties
        *
        * */
        /**
         * An array containing the current Grid objects in the page.
         * @internal
         */
        Grid.grids = [];
        /* *
         *
         *  Default Export
         *
         * */

        return Grid;
    });
    _registerModule(_modules, 'Data/DataPoolDefaults.js', [], function () {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *
         * */
        /* *
         *
         *  API Options
         *
         * */
        const DataPoolDefaults = {
            connectors: []
        };
        /* *
         *
         *  Export Defaults
         *
         * */

        return DataPoolDefaults;
    });
    _registerModule(_modules, 'Data/DataPool.js', [_modules['Data/Connectors/DataConnector.js'], _modules['Data/DataPoolDefaults.js'], _modules['Core/Utilities.js']], function (DataConnector, DataPoolDefaults, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Data pool to load connectors on-demand.
         *
         * @class
         * @name Data.DataPool
         *
         * @param {Data.DataPoolOptions} options
         * Pool options with all connectors.
         */
        class DataPool {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(options = DataPoolDefaults) {
                options.connectors = (options.connectors || []);
                this.connectors = {};
                this.options = options;
                this.waiting = {};
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Emits an event on this data pool to all registered callbacks of the given
             * event.
             * @private
             *
             * @param {DataTable.Event} e
             * Event object with event information.
             */
            emit(e) {
                U.fireEvent(this, e.type, e);
            }
            /**
             * Loads the connector.
             *
             * @function Data.DataPool#getConnector
             *
             * @param {string} connectorId
             * ID of the connector.
             *
             * @return {Promise<Data.DataConnectorType>}
             * Returns the connector.
             */
            getConnector(connectorId) {
                const connector = this.connectors[connectorId];
                // Already loaded
                if (connector?.loaded) {
                    return Promise.resolve(connector);
                }
                let waitingList = this.waiting[connectorId];
                // Start loading
                if (!waitingList) {
                    waitingList = this.waiting[connectorId] = [];
                    const connectorOptions = this.getConnectorOptions(connectorId);
                    if (!connectorOptions) {
                        throw new Error(`Connector '${connectorId}' not found.`);
                    }
                    // eslint-disable-next-line @typescript-eslint/no-floating-promises
                    this
                        .loadConnector(connectorOptions)
                        .then((connector) => {
                        delete this.waiting[connectorId];
                        for (let i = 0, iEnd = waitingList.length; i < iEnd; ++i) {
                            waitingList[i][0](connector);
                        }
                    })['catch']((error) => {
                        delete this.waiting[connectorId];
                        for (let i = 0, iEnd = waitingList.length; i < iEnd; ++i) {
                            waitingList[i][1](error);
                        }
                    });
                }
                // Add request to waiting list
                return new Promise((resolve, reject) => {
                    waitingList.push([resolve, reject]);
                });
            }
            /**
             * Returns the IDs of all connectors.
             *
             * @private
             *
             * @return {Array<string>}
             * Names of all connectors.
             */
            getConnectorIds() {
                const connectors = this.options.connectors, connectorIds = [];
                for (let i = 0, iEnd = connectors.length; i < iEnd; ++i) {
                    connectorIds.push(connectors[i].id);
                }
                return connectorIds;
            }
            /**
             * Loads the options of the connector.
             *
             * @private
             *
             * @param {string} connectorId
             * ID of the connector.
             *
             * @return {DataPoolConnectorOptions|undefined}
             * Returns the options of the connector, or `undefined` if not found.
             */
            getConnectorOptions(connectorId) {
                const connectors = this.options.connectors;
                for (let i = 0, iEnd = connectors.length; i < iEnd; ++i) {
                    if (connectors[i].id === connectorId) {
                        return connectors[i];
                    }
                }
            }
            /**
             * Loads the connector table.
             *
             * @function Data.DataPool#getConnectorTable
             *
             * @param {string} connectorId
             * ID of the connector.
             *
             * @return {Promise<Data.DataTable>}
             * Returns the connector table.
             */
            getConnectorTable(connectorId) {
                return this
                    .getConnector(connectorId)
                    .then((connector) => connector.table);
            }
            /**
             * Tests whether the connector has never been requested.
             *
             * @param {string} connectorId
             * Name of the connector.
             *
             * @return {boolean}
             * Returns `true`, if the connector has never been requested, otherwise
             * `false`.
             */
            isNewConnector(connectorId) {
                return !this.connectors[connectorId];
            }
            /**
             * Creates and loads the connector.
             *
             * @private
             *
             * @param {Data.DataPoolConnectorOptions} options
             * Options of connector.
             *
             * @return {Promise<Data.DataConnectorType>}
             * Returns the connector.
             */
            loadConnector(options) {
                return new Promise((resolve, reject) => {
                    this.emit({
                        type: 'load',
                        options
                    });
                    const ConnectorClass = DataConnector.types[options.type];
                    if (!ConnectorClass) {
                        throw new Error(`Connector type not found. (${options.type})`);
                    }
                    const connector = this.connectors[options.id] = new ConnectorClass(options.options, options.dataTables);
                    // eslint-disable-next-line @typescript-eslint/no-floating-promises
                    connector
                        .load()
                        .then(({ converter, dataTables }) => {
                        connector.dataTables = dataTables;
                        connector.converter = converter;
                        connector.loaded = true;
                        this.emit({
                            type: 'afterLoad',
                            options
                        });
                        resolve(connector);
                    })['catch'](reject);
                });
            }
            /**
             * Cancels all data connectors pending requests.
             */
            cancelPendingRequests() {
                const { connectors } = this;
                for (const connectorKey of Object.keys(connectors)) {
                    connectors[connectorKey].stopPolling();
                }
            }
            /**
             * Registers a callback for a specific event.
             *
             * @function Highcharts.DataPool#on
             *
             * @param {string} type
             * Event type as a string.
             *
             * @param {Highcharts.EventCallbackFunction<Highcharts.DataPool>} callback
             * Function to register for an event callback.
             *
             * @return {Function}
             * Function to unregister callback from the event.
             */
            on(type, callback) {
                return U.addEvent(this, type, callback);
            }
            /**
             * Sets connector options under the specified `options.id`.
             *
             * @param {Data.DataPoolConnectorOptions} options
             * Connector options to set.
             */
            setConnectorOptions(options) {
                const connectors = this.options.connectors, instances = this.connectors;
                this.emit({
                    type: 'setConnectorOptions',
                    options
                });
                for (let i = 0, iEnd = connectors.length; i < iEnd; ++i) {
                    if (connectors[i].id === options.id) {
                        connectors.splice(i, 1);
                        break;
                    }
                }
                if (instances[options.id]) {
                    instances[options.id].stopPolling();
                    delete instances[options.id];
                }
                connectors.push(options);
                this.emit({
                    type: 'afterSetConnectorOptions',
                    options
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Semantic version string of the DataPool class.
         * @internal
         */
        DataPool.version = '1.0.0';
        /* *
         *
         *  Default Export
         *
         * */

        return DataPool;
    });
    _registerModule(_modules, 'Grid/Pro/GridEvents.js', [_modules['Core/Utilities.js'], _modules['Core/Globals.js']], function (U, Globals) {
        /* *
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { addEvent, fireEvent, pushUnique } = U;
        const propagate = {
            'cell_mouseOver': function () {
                fireEvent(this.row.viewport.grid, 'cellMouseOver', {
                    target: this
                });
            },
            'cell_mouseOut': function () {
                fireEvent(this.row.viewport.grid, 'cellMouseOut', {
                    target: this
                });
            }
        };
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Composition to add events to the TableCellClass methods.
         *
         * @param ColumnClass
         * The class to extend.
         *
         * @param HeaderCellClass
         * The class to extend.
         *
         * @param TableCellClass
         * The class to extend.
         *
         * @internal
         */
        function compose(ColumnClass, HeaderCellClass, TableCellClass) {
            if (!pushUnique(Globals.composed, 'GridEvents')) {
                return;
            }
            [
                'mouseOver',
                'mouseOut',
                'dblClick',
                'click',
                'afterRender'
            ].forEach((name) => {
                addEvent(TableCellClass, name, (e) => {
                    const cell = e.target;
                    const cellEvent = cell.column.options.cells?.events?.[name] ||
                        // Backward compatibility
                        cell.row.viewport.grid.options?.events?.cell?.[name];
                    cellEvent?.call(cell);
                    propagate['cell_' + name]?.call(cell);
                });
            });
            [
                'afterResize',
                'afterSorting'
            ].forEach((name) => {
                addEvent(ColumnClass, name, (e) => {
                    const column = e.target;
                    const columnEvent = column.options?.events?.[name] ||
                        // Backward compatibility
                        column.viewport.grid.options?.events?.column?.[name];
                    columnEvent?.call(column);
                });
            });
            // HeaderCell Events
            [
                'click',
                'afterRender'
            ].forEach((name) => {
                addEvent(HeaderCellClass, name, (e) => {
                    const column = e.target;
                    const headerEvent = column.options?.header?.events?.[name] ||
                        // Backward compatibility
                        column.viewport?.grid?.options?.events?.header?.[name];
                    headerEvent?.call(column);
                });
            });
        }
        /* *
         *
         *  Default Export
         *
         * */
        /**
         * @internal
         */

        return { compose };
    });
    _registerModule(_modules, 'Grid/Pro/CellEditing/CellEditing.js', [_modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (Globals, U) {
        /* *
         *
         *  Grid Cell Editing class.
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { fireEvent } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * The class that handles the manual editing of cells in the data grid.
         */
        class CellEditing {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(viewport) {
                /**
                 * Handles the blur event on the input field.
                 */
                this.onInputBlur = () => {
                    if (!this.stopEditing()) {
                        this.editModeContent?.getMainElement().focus();
                    }
                };
                /**
                 * Handles the change event on the input field.
                 */
                this.onInputChange = () => {
                    if (this.editModeContent?.finishAfterChange &&
                        !this.stopEditing()) {
                        this.editModeContent?.getMainElement().focus();
                    }
                };
                /**
                 * Handles the keydown event on the input field. Cancels editing on escape
                 * and saves the value on enter.
                 *
                 * @param e
                 * The keyboard event.
                 */
                this.onInputKeyDown = (e) => {
                    const { key } = e;
                    e.stopPropagation();
                    if (key === 'Escape') {
                        this.stopEditing(false);
                        return;
                    }
                    if (key === 'Enter') {
                        if (this.editModeContent?.finishAfterChange) {
                            this.onInputChange();
                            return;
                        }
                        this.stopEditing();
                    }
                };
                this.viewport = viewport;
            }
            /* *
             *
             *  Methods
             *
             * */
            /**
             * Turns the cell into an editable input field.
             *
             * @param cell
             * The cell that is to be edited.
             */
            startEditing(cell) {
                if (this.editedCell === cell || (
                // If value is invalid, do not start new editing
                this.editedCell && !this.stopEditing())) {
                    return;
                }
                this.editedCell = cell;
                cell.htmlElement.classList.add(Globals.getClassName('editedCell'));
                this.render();
                fireEvent(cell, 'startedEditing');
            }
            /**
             * Stops the editing of the cell.
             *
             * @param submit
             * Whether to save the value of the input to the cell. Defaults to true.
             *
             * @return
             * Returns `true` if the cell was successfully stopped editing.
             */
            stopEditing(submit = true) {
                const cell = this.editedCell;
                const emContent = this.editModeContent;
                if (!cell || !emContent) {
                    return false;
                }
                const { column } = cell;
                const vp = column.viewport;
                const newValue = emContent.value;
                if (submit) {
                    const validationErrors = [];
                    if (!vp.validator.validate(cell, validationErrors)) {
                        vp.validator.initErrorBox(cell, validationErrors);
                        return false;
                    }
                    vp.validator.hide();
                    vp.validator.errorCell = void 0;
                }
                // Hide notification
                this.viewport.validator.hide();
                // Hide input
                this.destroy();
                cell.htmlElement.classList.remove(Globals.getClassName('editedCell'));
                cell.htmlElement.focus();
                const isValueChanged = cell.value !== newValue;
                void cell.setValue(submit ? newValue : cell.value, submit && isValueChanged);
                if (isValueChanged) {
                    fireEvent(cell, 'stoppedEditing', { submit });
                }
                delete this.editedCell;
                return true;
            }
            /**
             * Renders the input field for the cell, focuses it and sets up event
             * listeners.
             */
            render() {
                const cell = this.editedCell;
                if (!cell || !cell.column.editModeRenderer) {
                    return;
                }
                this.containerElement = this.containerElement ||
                    document.createElement('div');
                this.containerElement.className =
                    CellEditing.classNames.cellEditingContainer;
                this.editedCell?.htmlElement.appendChild(this.containerElement);
                this.editModeContent = cell.column.editModeRenderer?.render(cell, this.containerElement);
                this.editModeContent.getMainElement().focus();
                this.editModeContent.blurHandler = this.onInputBlur;
                this.editModeContent.changeHandler = this.onInputChange;
                this.editModeContent.keyDownHandler = this.onInputKeyDown;
            }
            /**
             * Removes event listeners and the input element.
             */
            destroy() {
                if (!this.editModeContent) {
                    return;
                }
                this.editModeContent.destroy();
                this.containerElement?.remove();
                delete this.editModeContent;
                delete this.containerElement;
            }
        }
        /* *
         *
         *  Namespace
         *
         * */
        (function (CellEditing) {
            /**
             * The class names used by the CellEditing functionality.
             */
            CellEditing.classNames = {
                cellEditingContainer: Globals.classNamePrefix + 'cell-editing-container'
            };
        })(CellEditing || (CellEditing = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return CellEditing;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/CellRendererRegistry.js', [], function () {
        /* *
         *
         *  Cell Renderer Registry
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Namespace
         *
         * */
        var CellRendererRegistry;
        (function (CellRendererRegistry) {
            /* *
             *
             *  Constants
             *
             * */
            /**
             * Record of cell renderer classes
             */
            CellRendererRegistry.types = {};
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Method used to register new cell renderer classes.
             *
             * @param key
             * Registry key of the cell renderer class.
             *
             * @param CellRendererClass
             * Cell renderer class (aka class constructor) to register.
             */
            function registerRenderer(key, CellRendererClass) {
                return (!!key &&
                    !CellRendererRegistry.types[key] &&
                    !!(CellRendererRegistry.types[key] = CellRendererClass));
            }
            CellRendererRegistry.registerRenderer = registerRenderer;
        })(CellRendererRegistry || (CellRendererRegistry = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return CellRendererRegistry;
    });
    _registerModule(_modules, 'Grid/Pro/CellEditing/CellEditingComposition.js', [_modules['Grid/Core/Defaults.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Pro/CellEditing/CellEditing.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Core/GridUtils.js'], _modules['Core/Utilities.js']], function (Defaults, Globals, CellEditing, CellRendererRegistry, GU, U) {
        /* *
         *
         *  Grid Cell Editing class.
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement } = GU;
        const { addEvent, merge, pushUnique } = U;
        /* *
         *
         *  Composition
         *
         * */
        /**
         * @internal
         */
        var CellEditingComposition;
        (function (CellEditingComposition) {
            /**
             * Default options for the cell editing.
             */
            const defaultOptions = {
                accessibility: {
                    announcements: {
                        cellEditing: true
                    }
                },
                lang: {
                    accessibility: {
                        cellEditing: {
                            editable: 'Editable.',
                            announcements: {
                                started: 'Entered cell editing mode.',
                                edited: 'Edited cell value.',
                                cancelled: 'Editing canceled.',
                                notValid: 'Provided value is not valid.'
                            }
                        }
                    }
                }
            };
            /**
             * Extends the grid classes with cell editing functionality.
             *
             * @param TableClass
             * The class to extend.
             *
             * @param TableCellClass
             * The class to extend.
             *
             * @param ColumnClass
             * The class to extend.
             */
            function compose(TableClass, TableCellClass, ColumnClass) {
                if (!pushUnique(Globals.composed, 'CellEditing')) {
                    return;
                }
                merge(true, Defaults.defaultOptions, defaultOptions);
                addEvent(ColumnClass, 'afterInit', afterColumnInit);
                addEvent(TableClass, 'beforeInit', initTable);
                addEvent(TableCellClass, 'keyDown', onCellKeyDown);
                addEvent(TableCellClass, 'dblClick', onCellDblClick);
                addEvent(TableCellClass, 'afterRender', addEditableCellA11yHint);
                addEvent(TableCellClass, 'startedEditing', function () {
                    announceA11yUserEditedCell(this, 'started');
                });
                addEvent(TableCellClass, 'stoppedEditing', function (e) {
                    const cellEvents = merge(
                    // Backward compatibility
                    this.column.viewport.grid.options?.events?.cell, this.column.options.cells?.events);
                    if (e.submit) {
                        cellEvents?.afterEdit?.call(this);
                    }
                    announceA11yUserEditedCell(this, e.submit ? 'edited' : 'cancelled');
                });
            }
            CellEditingComposition.compose = compose;
            /**
             * Callback function called before table initialization.
             */
            function initTable() {
                this.cellEditing = new CellEditing(this);
            }
            /**
             * Creates the edit mode renderer for the column.
             *
             * @param column
             * The column to create the edit mode renderer for.
             */
            function createEditModeRenderer(column) {
                const editModeOptions = column.options.cells?.editMode;
                const selectedEditModeRendererTypeName = editModeOptions?.renderer?.type;
                const viewRendererTypeName = column.options?.cells?.renderer?.type || 'text';
                if (selectedEditModeRendererTypeName) {
                    return new CellRendererRegistry.types[selectedEditModeRendererTypeName](column, editModeOptions?.renderer || {});
                }
                const ViewRendererType = CellRendererRegistry.types[viewRendererTypeName] ||
                    CellRendererRegistry.types.text;
                let editModeRendererTypeName = ViewRendererType.defaultEditingRenderer;
                if (typeof editModeRendererTypeName !== 'string') {
                    editModeRendererTypeName =
                        editModeRendererTypeName[column.dataType] || 'textInput';
                }
                return new CellRendererRegistry.types[editModeRendererTypeName](column, editModeRendererTypeName === viewRendererTypeName ? merge(column.options.cells?.renderer, { disabled: false }) || {} : {});
            }
            /**
             * Callback function called after column initialization.
             */
            function afterColumnInit() {
                const { options } = this;
                if (options?.cells?.editMode?.enabled ||
                    options?.cells?.editable) {
                    this.editModeRenderer = createEditModeRenderer(this);
                }
            }
            /**
             * Callback function called when a key is pressed on a cell.
             *
             * @param e
             * The event object.
             */
            function onCellKeyDown(e) {
                if (e.originalEvent?.key !== 'Enter' ||
                    !this.column.editModeRenderer) {
                    return;
                }
                this.row.viewport.cellEditing?.startEditing(this);
            }
            /**
             * Callback function called when a cell is double clicked.
             */
            function onCellDblClick() {
                if (this.column.editModeRenderer) {
                    this.row.viewport.cellEditing?.startEditing(this);
                }
            }
            /**
             * Add the 'editable' hint span element for the editable cell.
             */
            function addEditableCellA11yHint() {
                const a11y = this.row.viewport.grid.accessibility;
                if (!a11y || this.a11yEditableHint?.isConnected) {
                    return;
                }
                const editableLang = this.row.viewport.grid.options
                    ?.lang?.accessibility?.cellEditing?.editable;
                if ((!this.column.options.cells?.editable &&
                    !this.column.options.cells?.editMode?.enabled) ||
                    !editableLang) {
                    return;
                }
                this.a11yEditableHint = makeHTMLElement('span', {
                    className: Globals.getClassName('visuallyHidden'),
                    innerText: ', ' + editableLang
                }, this.htmlElement);
            }
            /**
             * Announce that the cell editing started.
             *
             * @param cell
             * The cell that is being edited.
             *
             * @param msgType
             * The type of the message.
             */
            function announceA11yUserEditedCell(cell, msgType) {
                const a11y = cell.row.viewport.grid.accessibility;
                if (!a11y) {
                    return;
                }
                const { options } = a11y.grid;
                if (!options?.accessibility?.announcements?.cellEditing) {
                    return;
                }
                const lang = options?.lang?.accessibility?.cellEditing?.announcements;
                const msg = lang?.[msgType];
                if (!msg) {
                    return;
                }
                a11y.announce(msg);
            }
        })(CellEditingComposition || (CellEditingComposition = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return CellEditingComposition;
    });
    _registerModule(_modules, 'Grid/Pro/Dash3Compatibility.js', [_modules['Core/Utilities.js'], _modules['Core/Globals.js']], function (U, Globals) {
        /* *
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { pushUnique } = U;
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Composition to add compatibility with the old `dataGrid` property.
         *
         * @param TableClass
         * The class to extend.
         */
        function compose(TableClass) {
            if (!pushUnique(Globals.composed, 'Dash3Compatibility')) {
                return;
            }
            Object.defineProperty(TableClass.prototype, 'dataGrid', {
                get: function () {
                    return this.grid;
                },
                configurable: true,
                enumerable: false
            });
        }
        /* *
         *
         *  Default Export
         *
         * */

        return { compose };
    });
    _registerModule(_modules, 'Grid/Core/Credits.js', [_modules['Grid/Core/Globals.js'], _modules['Grid/Core/GridUtils.js']], function (Globals, GridUtils) {
        /* *
         *
         *  Grid Credits class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { makeHTMLElement, setHTMLContent } = GridUtils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a credits in the grid.
         */
        class Credits {
            /* *
            *
            *  Constructor
            *
            * */
            /**
             * Construct the credits.
             *
             * @param grid
             * The Grid instance which the credits belong to.
             *
             * @param options
             * Options for the credits label. Predefined if not provided.
             *
             */
            constructor(grid, options) {
                this.grid = grid;
                this.containerElement = makeHTMLElement('div', {
                    className: Globals.getClassName('creditsContainer')
                });
                this.textElement = this.renderAnchor();
                this.options = options ?? Credits.defaultOptions;
                this.render();
            }
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Render the credits. If the credits are disabled, they will be removed
             * from the container.
             */
            render() {
                const grid = this.grid;
                const contentWrapper = grid.contentWrapper;
                const { text, href } = this.options;
                this.containerElement.remove();
                if (!this.textElement) {
                    this.textElement = this.renderAnchor();
                }
                if (text && href) {
                    setHTMLContent(this.textElement, text);
                    this.textElement.setAttribute('href', href || '');
                }
                if (grid.descriptionElement) {
                    contentWrapper?.insertBefore(this.containerElement, grid.descriptionElement);
                }
                else {
                    contentWrapper?.appendChild(this.containerElement);
                }
            }
            renderAnchor() {
                const anchorElement = makeHTMLElement('a', {
                    className: Globals.getClassName('creditsText')
                }, this.containerElement);
                anchorElement.setAttribute('target', '_blank');
                return anchorElement;
            }
            /**
             * Get the height of the credits container.
             */
            getHeight() {
                return this.containerElement.offsetHeight;
            }
            /**
             * Destroy the credits. The credits will be removed from the container and
             * the reference to the credits will be deleted from the Grid instance
             * it belongs to.
             */
            destroy() {
                this.containerElement.remove();
            }
        }
        /* *
        *
        *  Static Properties
        *
        * */
        /**
         * Default options of the credits.
         */
        Credits.defaultOptions = {
            enabled: true,
            // eslint-disable-next-line no-console
            text: `<picture class="hcg-logo-wrapper">
                    <source srcset="https://assets.highcharts.com/grid/logo_darkx2.png 2x, https://assets.highcharts.com/grid/logo_dark.png 1x" media="(prefers-color-scheme: dark)">
                    <img src="https://assets.highcharts.com/grid/logo_light.png" srcset="https://assets.highcharts.com/grid/logo_lightx2.png 2x, https://assets.highcharts.com/grid/logo_light.png 1x" alt="Highcharts logo" style="height: 20px !important; width: auto !important; display: inline-block !important;">
                </picture>`,
            href: 'https://www.highcharts.com',
            position: 'bottom'
        };
        /* *
         *
         *  Default Export
         *
         * */

        return Credits;
    });
    _registerModule(_modules, 'Grid/Pro/Credits/CreditsPro.js', [_modules['Grid/Core/Globals.js'], _modules['Grid/Core/Credits.js'], _modules['Grid/Core/GridUtils.js']], function (Globals, Credits, GridUtils) {
        /* *
         *
         *  Grid Credits class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { setHTMLContent } = GridUtils;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a credits in the data grid.
         */
        class CreditsPro extends Credits {
            /* *
            *
            *  Methods
            *
            * */
            /**
             * Set the content of the credits.
             */
            setContent() {
                const { text, href } = this.options;
                setHTMLContent(this.textElement, text || '');
                this.textElement.setAttribute('href', href || '');
            }
            /**
             * Append the credits to the container. The position of the credits is
             * determined by the `position` option.
             */
            appendToContainer() {
                const grid = this.grid;
                const contentWrapper = grid.contentWrapper;
                const { position } = this.options;
                // Apply grid-pro class
                this.containerElement.classList.add(Globals.getClassName('creditsPro'));
                if (position === 'top') {
                    // Append the credits to the top of the table.
                    contentWrapper?.prepend(this.containerElement);
                    return;
                }
                // Append the credits to the bottom of the table.
                if (grid.descriptionElement) {
                    contentWrapper?.insertBefore(this.containerElement, grid.descriptionElement);
                }
                else {
                    contentWrapper?.appendChild(this.containerElement);
                }
            }
            /**
             * Update the credits with new options.
             *
             * @param options
             * The new options for the credits.
             *
             * @param render
             * Whether to render the credits after the update.
             */
            update(options, render = true) {
                if (options) {
                    this.grid.update({
                        credits: options
                    }, false);
                    this.options = this.grid.options?.credits ?? {};
                }
                if (render) {
                    this.render();
                }
            }
            /**
             * Render the credits. If the credits are disabled, they will be removed
             * from the container. If also reflows the viewport dimensions.
             */
            render() {
                const enabled = this.options.enabled ?? false;
                this.containerElement.remove();
                if (enabled) {
                    this.setContent();
                    this.appendToContainer();
                }
                else {
                    this.destroy();
                }
                this.grid.viewport?.reflow();
            }
            destroy() {
                super.destroy();
                delete this.grid.credits;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return CreditsPro;
    });
    _registerModule(_modules, 'Grid/Pro/Credits/CreditsProComposition.js', [_modules['Grid/Pro/Credits/CreditsPro.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js'], _modules['Grid/Core/Defaults.js']], function (CreditsPro, Globals, U, Defaults) {
        /* *
         *
         *  Grid Credits class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *  - Sebastian Bochan
         *
         * */
        const { addEvent, merge, pushUnique } = U;
        /* *
         *
         *  Class Namespace
         *
         * */
        var CreditsProComposition;
        (function (CreditsProComposition) {
            /**
             * Extends the grid classes with customizable credits.
             *
             * @param GridClass
             * The class to extend.
             *
             */
            function compose(GridClass) {
                if (!pushUnique(Globals.composed, 'CreditsPro')) {
                    return;
                }
                merge(true, Defaults.defaultOptions, {
                    credits: CreditsPro.defaultOptions
                });
                addEvent(GridClass, 'afterRenderViewport', initCredits);
            }
            CreditsProComposition.compose = compose;
            /**
             * Init configurable credits.
             * @param this
             * Reference to Grid.
             */
            function initCredits() {
                this.credits = new CreditsPro(this, this.options?.credits);
            }
        })(CreditsProComposition || (CreditsProComposition = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return CreditsProComposition;
    });
    _registerModule(_modules, 'Grid/Pro/ColumnTypes/Validator.js', [_modules['Core/Renderer/HTML/AST.js'], _modules['Grid/Core/Globals.js'], _modules['Grid/Core/GridUtils.js'], _modules['Core/Utilities.js']], function (AST, Globals, GridUtils, U) {
        /* *
         *
         *  Grid cell content validator
         *
         *  (c) 2009-2024 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { makeDiv, setHTMLContent } = GridUtils;
        const { defined } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class for validating cell content.
         */
        class Validator {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(viewport) {
                this.viewport = viewport;
                this.notifContainer = makeDiv(Validator.classNames.notifContainer);
                this.viewport.grid.contentWrapper?.appendChild(this.notifContainer);
            }
            /* *
             *
             *  Methods
             *
             * */
            /**
             * Validates the cell content.
             *
             * @param cell
             * Edited cell.
             *
             * @param errors
             * An output array for error messages.
             *
             * @returns
             * Returns true if the value is valid, false otherwise.
             */
            validate(cell, errors = []) {
                const { options, dataType } = cell.column;
                const validationErrors = cell.row.viewport.grid.options?.lang?.validationErrors;
                let rules = Array.from(options?.cells?.editMode?.validationRules || []);
                // Remove duplicates in validationRules
                const isArrayString = rules.every((rule) => typeof rule === 'string');
                if (rules.length > 0 && isArrayString) {
                    rules = [...new Set(rules)];
                }
                else {
                    const predefined = Validator.predefinedRules[dataType] || [];
                    const hasPredefined = rules.some((rule) => typeof rule !== 'string' &&
                        typeof rule.validate === 'string' &&
                        predefined.includes(rule.validate));
                    if (!hasPredefined) {
                        rules.push(...predefined);
                    }
                }
                for (const rule of rules) {
                    let ruleDef;
                    let err;
                    if (typeof rule === 'string') {
                        ruleDef = Validator.rulesRegistry[rule];
                        err = validationErrors?.[rule]?.notification;
                    }
                    else {
                        ruleDef = rule;
                    }
                    let validateFn;
                    if (typeof ruleDef.validate === 'string') {
                        const predefinedRules = (Validator.rulesRegistry[ruleDef.validate]);
                        validateFn =
                            predefinedRules?.validate;
                    }
                    else {
                        validateFn = ruleDef.validate;
                    }
                    const { editModeContent } = cell.column.viewport.cellEditing || {};
                    if (typeof validateFn === 'function' &&
                        editModeContent &&
                        !validateFn.call(cell, editModeContent)) {
                        if (typeof ruleDef.notification === 'function') {
                            err = ruleDef.notification.call(cell, editModeContent);
                        }
                        errors.push((err || ruleDef.notification));
                    }
                }
                return !errors.length;
            }
            /**
             * Set content of notification and adjust the position.
             *
             * @param cell
             * Cell that is currently edited and is not valid.
             *
             * @param errors
             * An array of error messages.
             *
             */
            initErrorBox(cell, errors) {
                const { grid } = this.viewport;
                this.errorCell = cell;
                // Set error container position
                this.reflow();
                // Set width and content
                setHTMLContent(this.notifContainer, errors.join('<br />'));
                // A11y announcement
                if (grid.options?.accessibility?.announcements?.cellEditing) {
                    this.viewport.grid.accessibility?.announce((grid.options?.lang?.accessibility?.cellEditing
                        ?.announcements?.notValid || '') + ' ' + errors.join('. '), true);
                }
                this.show();
            }
            /**
             * Highlight the non-valid cell and display error in the notification box.
             */
            show() {
                this.errorCell?.htmlElement.classList.add(Validator.classNames.editedCellError);
                this.notifContainer.classList.add(Validator.classNames.notifError, Validator.classNames.notifAnimation);
            }
            /**
             * Hide the notification, error and unset highlight on cell.
             *
             * @param hideErrorBox
             * The flag that hides the error on edited cell.
             *
             */
            hide(hideErrorBox = true) {
                this.errorCell?.htmlElement.classList.remove(Validator.classNames.editedCellError);
                this.notifContainer.classList.remove(Validator.classNames.notifError, Validator.classNames.notifAnimation);
                if (hideErrorBox) {
                    this.errorCell = void 0;
                }
                this.notifContainer.innerHTML = AST.emptyHTML;
            }
            /**
             * Set the position of the error box.
             */
            reflow() {
                const vp = this.viewport, errorCell = this.errorCell?.htmlElement, tableElement = vp.grid.tableElement, contentWrapper = vp.grid.contentWrapper;
                if (!errorCell || !tableElement || !contentWrapper) {
                    return;
                }
                const tableTop = tableElement.offsetTop, tableHeight = tableElement.offsetHeight, middlePoint = tableTop + (tableHeight / 2), errorCellTop = errorCell.offsetTop - tableTop;
                if (errorCellTop > middlePoint) {
                    this.notifContainer.style.top = // Avoid header overlap
                        tableTop + (vp.theadElement?.offsetHeight || 0) + 'px';
                    this.notifContainer.style.bottom = 'auto';
                }
                else {
                    this.notifContainer.style.top = 'auto';
                    this.notifContainer.style.bottom =
                        contentWrapper.offsetHeight - tableTop - tableHeight + 'px';
                }
            }
            /**
             * Destroy validator.
             */
            destroy() {
                this.errorCell = void 0;
                this.notifContainer.remove();
            }
        }
        /* *
         *
         *  Namespace
         *
         * */
        /**
         * Namespace for Validation functionality.
         */
        (function (Validator) {
            /**
             * The class names used by the validator functionality.
             */
            Validator.classNames = {
                notifContainer: Globals.classNamePrefix + 'notification',
                notifError: Globals.classNamePrefix + 'notification-error',
                notifAnimation: Globals.classNamePrefix + 'notification-animation',
                editedCellError: Globals.classNamePrefix + 'edited-cell-error'
            };
            /* *
             *
             *  Variables
             *
             * */
            /**
             * Definition of default validation rules.
             */
            Validator.rulesRegistry = {
                notEmpty: {
                    validate: ({ value, rawValue }) => (defined(value) && rawValue.length > 0),
                    notification: 'Value cannot be empty.'
                },
                number: {
                    validate: ({ rawValue }) => !isNaN(+rawValue),
                    notification: 'Value has to be a number.'
                },
                datetime: {
                    validate: ({ value }) => !defined(value) || !isNaN(+value),
                    notification: 'Value has to be parsed to a valid timestamp.'
                },
                'boolean': {
                    validate: ({ rawValue }) => (rawValue === 'true' || rawValue === 'false' ||
                        Number(rawValue) === 1 || Number(rawValue) === 0),
                    notification: 'Value has to be a boolean.'
                }
            };
            /**
             * Default validation rules for each dataType.
             */
            Validator.predefinedRules = {
                'boolean': ['boolean'],
                datetime: ['datetime'],
                number: ['number'],
                string: []
            };
        })(Validator || (Validator = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return Validator;
    });
    _registerModule(_modules, 'Grid/Pro/ColumnTypes/ValidatorComposition.js', [_modules['Grid/Pro/ColumnTypes/Validator.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (Validator, Globals, U) {
        /* *
         *
         *  Validator Composition.
         *
         *  (c) 2020-2024 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sebastian Bochan
         *
         * */
        const { addEvent, pushUnique } = U;
        /* *
         *
         *  Composition
         *
         * */
        /**
         * @internal
         */
        var ValidatorComposition;
        (function (ValidatorComposition) {
            /**
             * Extends the grid classes with cell editing functionality.
             *
             * @param TableClass
             * The class to extend.
             *
             */
            function compose(TableClass) {
                if (!pushUnique(Globals.composed, 'Validator')) {
                    return;
                }
                addEvent(TableClass, 'afterInit', initValidatorComposition);
                addEvent(TableClass, 'afterDestroy', destroy);
            }
            ValidatorComposition.compose = compose;
            /**
             * Callback function called after table initialization.
             */
            function initValidatorComposition() {
                this.validator = new Validator(this);
            }
            /**
             * Callback function called after table destroy.
             */
            function destroy() {
                this.validator.destroy();
            }
        })(ValidatorComposition || (ValidatorComposition = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return ValidatorComposition;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/CellRenderersComposition.js', [_modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (CellRendererRegistry, Globals, U) {
        /* *
         *
         *  Cell Content Pro composition
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { addEvent, pushUnique } = U;
        /* *
         *
         *  Composition
         *
         * */
        /**
         * @internal
         */
        var CellRenderersComposition;
        (function (CellRenderersComposition) {
            /**
             * Extends the grid classes with cell editing functionality.
             *
             * @param ColumnClass
             * The class to extend.
             */
            function compose(ColumnClass) {
                if (!pushUnique(Globals.composed, 'CellRenderers')) {
                    return;
                }
                addEvent(ColumnClass, 'afterInit', afterColumnInit);
                ColumnClass.prototype.createCellContent = createCellContent;
            }
            CellRenderersComposition.compose = compose;
            /**
             * Init a type of content for a column.
             * @param this
             * Current column.
             */
            function afterColumnInit() {
                const rendererType = this.options.cells?.renderer?.type || 'text';
                let Renderer = CellRendererRegistry.types[rendererType];
                if (!Renderer) {
                    // eslint-disable-next-line no-console
                    console.warn(`The cell renderer of type "${rendererType}" is not registered. Using default text renderer instead.`);
                    Renderer = CellRendererRegistry.types.text;
                }
                this.cellRenderer = new Renderer(this, this.options.cells?.renderer || {});
            }
            /**
             * Render content of cell.
             * @param this
             * Current column.
             *
             * @param cell
             * Current cell.
             *
             * @returns
             * Formatted cell content.
             */
            function createCellContent(cell) {
                return this.cellRenderer.render(cell);
            }
        })(CellRenderersComposition || (CellRenderersComposition = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return CellRenderersComposition;
    });
    _registerModule(_modules, 'Data/Converters/CSVConverter.js', [_modules['Data/Converters/DataConverter.js'], _modules['Core/Utilities.js']], function (DataConverter, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Christer Vasseng
         *  - Gøran Slettemark
         *  - Sophie Bremer
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Handles parsing and transforming CSV to a table.
         *
         * @private
         */
        class CSVConverter extends DataConverter {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the CSV parser.
             *
             * @param {CSVConverter.UserOptions} [options]
             * Options for the CSV parser.
             */
            constructor(options) {
                const mergedOptions = merge(CSVConverter.defaultOptions, options);
                super(mergedOptions);
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.columns = [];
                this.headers = [];
                this.dataTypes = [];
                this.options = mergedOptions;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Creates a CSV string from the datatable on the connector instance.
             *
             * @param {DataConnector} connector
             * Connector instance to export from.
             *
             * @param {CSVConverter.Options} [options]
             * Options used for the export.
             *
             * @return {string}
             * CSV string from the connector table.
             */
            export(connector, options = this.options) {
                const { useLocalDecimalPoint, lineDelimiter } = options, exportNames = (this.options.firstRowAsNames !== false);
                let { decimalPoint, itemDelimiter } = options;
                if (!decimalPoint) {
                    decimalPoint = (itemDelimiter !== ',' && useLocalDecimalPoint ?
                        (1.1).toLocaleString()[1] :
                        '.');
                }
                if (!itemDelimiter) {
                    itemDelimiter = (decimalPoint === ',' ? ';' : ',');
                }
                const columns = connector.getSortedColumns(options.usePresentationOrder), columnNames = Object.keys(columns), csvRows = [], columnsCount = columnNames.length;
                const rowArray = [];
                // Add the names as the first row if they should be exported
                if (exportNames) {
                    csvRows.push(columnNames.map((columnName) => `"${columnName}"`).join(itemDelimiter));
                }
                for (let columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
                    const columnName = columnNames[columnIndex], column = columns[columnName], columnLength = column.length;
                    const columnMeta = connector.whatIs(columnName);
                    let columnDataType;
                    if (columnMeta) {
                        columnDataType = columnMeta.dataType;
                    }
                    for (let rowIndex = 0; rowIndex < columnLength; rowIndex++) {
                        let cellValue = column[rowIndex];
                        if (!rowArray[rowIndex]) {
                            rowArray[rowIndex] = [];
                        }
                        // Prefer datatype from metadata
                        if (columnDataType === 'string') {
                            cellValue = '"' + cellValue + '"';
                        }
                        else if (typeof cellValue === 'number') {
                            cellValue = String(cellValue).replace('.', decimalPoint);
                        }
                        else if (typeof cellValue === 'string') {
                            cellValue = `"${cellValue}"`;
                        }
                        rowArray[rowIndex][columnIndex] = cellValue;
                        // On the final column, push the row to the CSV
                        if (columnIndex === columnsCount - 1) {
                            // Trim repeated undefined values starting at the end
                            // Currently, we export the first "comma" even if the
                            // second value is undefined
                            let i = columnIndex;
                            while (rowArray[rowIndex].length > 2) {
                                const cellVal = rowArray[rowIndex][i];
                                if (cellVal !== void 0) {
                                    break;
                                }
                                rowArray[rowIndex].pop();
                                i--;
                            }
                            csvRows.push(rowArray[rowIndex].join(itemDelimiter));
                        }
                    }
                }
                return csvRows.join(lineDelimiter);
            }
            /**
             * Initiates parsing of CSV
             *
             * @param {CSVConverter.UserOptions}[options]
             * Options for the parser
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits CSVDataParser#parse
             * @emits CSVDataParser#afterParse
             */
            parse(options, eventDetail) {
                const converter = this, dataTypes = converter.dataTypes, parserOptions = merge(this.options, options), { beforeParse, lineDelimiter, firstRowAsNames, itemDelimiter } = parserOptions;
                let lines, rowIt = 0, { csv, startRow, endRow } = parserOptions, column;
                converter.columns = [];
                converter.emit({
                    type: 'parse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.headers
                });
                if (csv && beforeParse) {
                    csv = beforeParse(csv);
                }
                if (csv) {
                    lines = csv
                        .replace(/\r\n|\r/g, '\n') // Windows | Mac
                        .split(lineDelimiter || '\n');
                    if (!startRow || startRow < 0) {
                        startRow = 0;
                    }
                    if (!endRow || endRow >= lines.length) {
                        endRow = lines.length - 1;
                    }
                    if (!itemDelimiter) {
                        converter.guessedItemDelimiter =
                            converter.guessDelimiter(lines);
                    }
                    // If the first row contain names, add them to the
                    // headers array and skip the row.
                    if (firstRowAsNames) {
                        const headers = lines[0].split(itemDelimiter || converter.guessedItemDelimiter || ',');
                        // Remove ""s from the headers
                        for (let i = 0; i < headers.length; i++) {
                            headers[i] = headers[i].trim().replace(/^["']|["']$/g, '');
                        }
                        converter.headers = headers;
                        startRow++;
                    }
                    let offset = 0;
                    for (rowIt = startRow; rowIt <= endRow; rowIt++) {
                        if (lines[rowIt][0] === '#') {
                            offset++;
                        }
                        else {
                            converter
                                .parseCSVRow(lines[rowIt], rowIt - startRow - offset);
                        }
                    }
                    if (dataTypes.length &&
                        dataTypes[0].length &&
                        dataTypes[0][1] === 'date' && // Format is a string date
                        !converter.options.dateFormat) {
                        converter.deduceDateFormat(converter.columns[0], null, true);
                    }
                    // Guess types.
                    for (let i = 0, iEnd = converter.columns.length; i < iEnd; ++i) {
                        column = converter.columns[i];
                        for (let j = 0, jEnd = column.length; j < jEnd; ++j) {
                            if (column[j] && typeof column[j] === 'string') {
                                let cellValue = converter.asGuessedType(column[j]);
                                if (cellValue instanceof Date) {
                                    cellValue = cellValue.getTime();
                                }
                                converter.columns[i][j] = cellValue;
                            }
                        }
                    }
                }
                converter.emit({
                    type: 'afterParse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.headers
                });
            }
            /**
             * Internal method that parses a single CSV row
             */
            parseCSVRow(columnStr, rowNumber) {
                const converter = this, columns = converter.columns || [], dataTypes = converter.dataTypes, { startColumn, endColumn } = converter.options, itemDelimiter = (converter.options.itemDelimiter ||
                    converter.guessedItemDelimiter);
                let { decimalPoint } = converter.options;
                if (!decimalPoint || decimalPoint === itemDelimiter) {
                    decimalPoint = converter.guessedDecimalPoint || '.';
                }
                let i = 0, c = '', token = '', actualColumn = 0, column = 0;
                const read = (j) => {
                    c = columnStr[j];
                };
                const pushType = (type) => {
                    if (dataTypes.length < column + 1) {
                        dataTypes.push([type]);
                    }
                    if (dataTypes[column][dataTypes[column].length - 1] !== type) {
                        dataTypes[column].push(type);
                    }
                };
                const push = () => {
                    if (startColumn > actualColumn || actualColumn > endColumn) {
                        // Skip this column, but increment the column count (#7272)
                        ++actualColumn;
                        token = '';
                        return;
                    }
                    // Save the type of the token.
                    if (typeof token === 'string') {
                        if (!isNaN(parseFloat(token)) && isFinite(token)) {
                            token = parseFloat(token);
                            pushType('number');
                        }
                        else if (!isNaN(Date.parse(token))) {
                            token = token.replace(/\//g, '-');
                            pushType('date');
                        }
                        else {
                            pushType('string');
                        }
                    }
                    else {
                        pushType('number');
                    }
                    if (columns.length < column + 1) {
                        columns.push([]);
                    }
                    // Try to apply the decimal point, and check if the token then is a
                    // number. If not, reapply the initial value
                    if (typeof token !== 'number' &&
                        converter.guessType(token) !== 'number' &&
                        decimalPoint) {
                        const initialValue = token;
                        token = token.replace(decimalPoint, '.');
                        if (converter.guessType(token) !== 'number') {
                            token = initialValue;
                        }
                    }
                    columns[column][rowNumber] = token;
                    token = '';
                    ++column;
                    ++actualColumn;
                };
                if (!columnStr.trim().length) {
                    return;
                }
                if (columnStr.trim()[0] === '#') {
                    return;
                }
                for (; i < columnStr.length; i++) {
                    read(i);
                    if (c === '#') {
                        // If there are hexvalues remaining (#13283)
                        if (!/^#[A-F\d]{3,3}|[A-F\d]{6,6}/i.test(columnStr.substring(i))) {
                            // The rest of the row is a comment
                            push();
                            return;
                        }
                    }
                    // Quoted string
                    if (c === '"') {
                        read(++i);
                        while (i < columnStr.length) {
                            if (c === '"') {
                                break;
                            }
                            token += c;
                            read(++i);
                        }
                    }
                    else if (c === itemDelimiter) {
                        push();
                        // Actual column data
                    }
                    else {
                        token += c;
                    }
                }
                push();
            }
            /**
             * Internal method that guesses the delimiter from the first
             * 13 lines of the CSV
             * @param {Array<string>} lines
             * The CSV, split into lines
             */
            guessDelimiter(lines) {
                let points = 0, commas = 0, guessed;
                const potDelimiters = {
                    ',': 0,
                    ';': 0,
                    '\t': 0
                }, linesCount = lines.length;
                for (let i = 0; i < linesCount; i++) {
                    let inStr = false, c, cn, cl, token = '';
                    // We should be able to detect dateformats within 13 rows
                    if (i > 13) {
                        break;
                    }
                    const columnStr = lines[i];
                    for (let j = 0; j < columnStr.length; j++) {
                        c = columnStr[j];
                        cn = columnStr[j + 1];
                        cl = columnStr[j - 1];
                        if (c === '#') {
                            // Skip the rest of the line - it's a comment
                            break;
                        }
                        if (c === '"') {
                            if (inStr) {
                                if (cl !== '"' && cn !== '"') {
                                    while (cn === ' ' && j < columnStr.length) {
                                        cn = columnStr[++j];
                                    }
                                    // After parsing a string, the next non-blank
                                    // should be a delimiter if the CSV is properly
                                    // formed.
                                    if (typeof potDelimiters[cn] !== 'undefined') {
                                        potDelimiters[cn]++;
                                    }
                                    inStr = false;
                                }
                            }
                            else {
                                inStr = true;
                            }
                        }
                        else if (typeof potDelimiters[c] !== 'undefined') {
                            token = token.trim();
                            if (!isNaN(Date.parse(token))) {
                                potDelimiters[c]++;
                            }
                            else if (isNaN(Number(token)) ||
                                !isFinite(Number(token))) {
                                potDelimiters[c]++;
                            }
                            token = '';
                        }
                        else {
                            token += c;
                        }
                        if (c === ',') {
                            commas++;
                        }
                        if (c === '.') {
                            points++;
                        }
                    }
                }
                // Count the potential delimiters.
                // This could be improved by checking if the number of delimiters
                // equals the number of columns - 1
                if (potDelimiters[';'] > potDelimiters[',']) {
                    guessed = ';';
                }
                else if (potDelimiters[','] > potDelimiters[';']) {
                    guessed = ',';
                }
                else {
                    // No good guess could be made..
                    guessed = ',';
                }
                // Try to deduce the decimal point if it's not explicitly set.
                // If both commas or points is > 0 there is likely an issue
                if (points > commas) {
                    this.guessedDecimalPoint = '.';
                }
                else {
                    this.guessedDecimalPoint = ',';
                }
                return guessed;
            }
            /**
             * Handles converting the parsed data to a table.
             *
             * @return {DataTable}
             * Table from the parsed CSV.
             */
            getTable() {
                return DataConverter.getTableFromColumns(this.columns, this.headers);
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options
         */
        CSVConverter.defaultOptions = {
            ...DataConverter.defaultOptions,
            lineDelimiter: '\n'
        };
        DataConverter.registerType('CSV', CSVConverter);
        /* *
         *
         *  Default Export
         *
         * */

        return CSVConverter;
    });
    _registerModule(_modules, 'Data/Connectors/CSVConnector.js', [_modules['Data/Converters/CSVConverter.js'], _modules['Data/Connectors/DataConnector.js'], _modules['Core/Utilities.js']], function (CSVConverter, DataConnector, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Christer Vasseng
         *  - Gøran Slettemark
         *  - Sophie Bremer
         *
         * */
        const { merge, defined } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that handles creating a DataConnector from CSV
         *
         * @private
         */
        class CSVConnector extends DataConnector {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of CSVConnector.
             *
             * @param {CSVConnector.UserOptions} [options]
             * Options for the connector and converter.
             *
             * @param {Array<DataTableOptions>} [dataTables]
             * Multiple connector data tables options.
             *
             */
            constructor(options, dataTables) {
                const mergedOptions = merge(CSVConnector.defaultOptions, options);
                super(mergedOptions, dataTables);
                this.options = defined(dataTables) ?
                    merge(mergedOptions, { dataTables }) : mergedOptions;
                if (mergedOptions.enablePolling) {
                    this.startPolling(Math.max(mergedOptions.dataRefreshRate || 0, 1) * 1000);
                }
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Initiates the loading of the CSV source to the connector
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits CSVConnector#load
             * @emits CSVConnector#afterLoad
             */
            load(eventDetail) {
                const connector = this, tables = connector.dataTables, { csv, csvURL, dataModifier, dataTables } = connector.options;
                connector.emit({
                    type: 'load',
                    csv,
                    detail: eventDetail,
                    tables
                });
                return Promise
                    .resolve(csvURL ?
                    fetch(csvURL, {
                        signal: connector?.pollingController?.signal
                    }).then((response) => response.text()) :
                    csv || '')
                    .then((csv) => {
                    if (csv) {
                        this.initConverters(csv, (key) => {
                            const options = this.options;
                            const tableOptions = dataTables?.find((dataTable) => dataTable.key === key);
                            // Takes over the connector default options.
                            const mergedTableOptions = {
                                dataTableKey: key,
                                firstRowAsNames: tableOptions?.firstRowAsNames ??
                                    options.firstRowAsNames,
                                beforeParse: tableOptions?.beforeParse ??
                                    options.beforeParse
                            };
                            return new CSVConverter(merge(this.options, mergedTableOptions));
                        }, (converter, data) => {
                            converter.parse({ csv: data });
                        });
                    }
                    return connector
                        .setModifierOptions(dataModifier, dataTables)
                        .then(() => csv);
                })
                    .then((csv) => {
                    connector.emit({
                        type: 'afterLoad',
                        csv,
                        detail: eventDetail,
                        tables
                    });
                    return connector;
                })['catch']((error) => {
                    connector.emit({
                        type: 'loadError',
                        detail: eventDetail,
                        error,
                        tables
                    });
                    throw error;
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        CSVConnector.defaultOptions = {
            csv: '',
            csvURL: '',
            enablePolling: false,
            dataRefreshRate: 1,
            firstRowAsNames: true
        };
        DataConnector.registerType('CSV', CSVConnector);
        /* *
         *
         *  Default Export
         *
         * */

        return CSVConnector;
    });
    _registerModule(_modules, 'Data/Converters/GoogleSheetsConverter.js', [_modules['Data/Converters/DataConverter.js'], _modules['Core/Utilities.js']], function (DataConverter, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Gøran Slettemark
         *  - Wojciech Chmiel
         *  - Sophie Bremer
         *
         * */
        const { merge, uniqueKey } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Handles parsing and transformation of an Google Sheets to a table.
         *
         * @private
         */
        class GoogleSheetsConverter extends DataConverter {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the GoogleSheetsConverter.
             *
             * @param {GoogleSheetsConverter.UserOptions} [options]
             * Options for the GoogleSheetsConverter.
             */
            constructor(options) {
                const mergedOptions = merge(GoogleSheetsConverter.defaultOptions, options);
                super(mergedOptions);
                this.columns = [];
                this.header = [];
                this.options = mergedOptions;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Initiates the parsing of the Google Sheet
             *
             * @param {GoogleSheetsConverter.UserOptions}[options]
             * Options for the parser
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits GoogleSheetsParser#parse
             * @emits GoogleSheetsParser#afterParse
             */
            parse(options, eventDetail) {
                const converter = this, parseOptions = merge(converter.options, options);
                let columns = ((parseOptions.json?.values) || []).map((column) => column.slice());
                if (columns.length === 0) {
                    return false;
                }
                converter.header = [];
                converter.columns = [];
                converter.emit({
                    type: 'parse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.header
                });
                // If beforeParse is defined, use it to modify the data
                const { beforeParse, json } = parseOptions;
                if (beforeParse && json) {
                    columns = beforeParse(json.values);
                }
                let column;
                converter.columns = columns;
                for (let i = 0, iEnd = columns.length; i < iEnd; i++) {
                    column = columns[i];
                    converter.header[i] = (parseOptions.firstRowAsNames ?
                        `${column.shift()}` :
                        uniqueKey());
                    for (let j = 0, jEnd = column.length; j < jEnd; ++j) {
                        if (column[j] && typeof column[j] === 'string') {
                            let cellValue = converter.asGuessedType(column[j]);
                            if (cellValue instanceof Date) {
                                cellValue = cellValue.getTime();
                            }
                            converter.columns[i][j] = cellValue;
                        }
                    }
                }
                converter.emit({
                    type: 'afterParse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.header
                });
            }
            /**
             * Handles converting the parsed data to a table.
             *
             * @return {DataTable}
             * Table from the parsed Google Sheet
             */
            getTable() {
                return DataConverter.getTableFromColumns(this.columns, this.header);
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options
         */
        GoogleSheetsConverter.defaultOptions = {
            ...DataConverter.defaultOptions
        };
        DataConverter.registerType('GoogleSheets', GoogleSheetsConverter);
        /* *
         *
         *  Default Export
         *
         * */

        return GoogleSheetsConverter;
    });
    _registerModule(_modules, 'Data/Connectors/GoogleSheetsConnector.js', [_modules['Data/Connectors/DataConnector.js'], _modules['Data/Converters/GoogleSheetsConverter.js'], _modules['Core/Utilities.js']], function (DataConnector, GoogleSheetsConverter, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Gøran Slettemark
         *  - Wojciech Chmiel
         *  - Sophie Bremer
         *  - Jomar Hønsi
         *
         * */
        const { merge, pick, defined } = U;
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Tests Google's response for error.
         * @private
         */
        function isGoogleError(json) {
            return (typeof json === 'object' && json &&
                typeof json.error === 'object' && json.error &&
                typeof json.error.code === 'number' &&
                typeof json.error.message === 'string' &&
                typeof json.error.status === 'string');
        }
        /* *
         *
         *  Class
         *
         * */
        /**
         * @private
         * @todo implement save, requires oauth2
         */
        class GoogleSheetsConnector extends DataConnector {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of GoogleSheetsConnector
             *
             * @param {GoogleSheetsConnector.UserOptions} [options]
             * Options for the connector and converter.
             *
             * @param {Array<DataTableOptions>} [dataTables]
             * Multiple connector data tables options.
             *
             */
            constructor(options, dataTables) {
                const mergedOptions = merge(GoogleSheetsConnector.defaultOptions, options);
                super(mergedOptions, dataTables);
                this.options = defined(dataTables) ?
                    merge(mergedOptions, { dataTables }) : mergedOptions;
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Loads data from a Google Spreadsheet.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Promise<this>}
             * Same connector instance with modified table.
             */
            load(eventDetail) {
                const connector = this, tables = connector.dataTables, { dataModifier, dataRefreshRate, enablePolling, googleAPIKey, googleSpreadsheetKey, dataTables } = connector.options, url = GoogleSheetsConnector.buildFetchURL(googleAPIKey, googleSpreadsheetKey, connector.options);
                connector.emit({
                    type: 'load',
                    detail: eventDetail,
                    tables,
                    url
                });
                if (!URL.canParse(url)) {
                    throw new Error('Invalid URL: ' + url);
                }
                return fetch(url, { signal: connector?.pollingController?.signal })
                    .then((response) => (response.json()))
                    .then((json) => {
                    if (isGoogleError(json)) {
                        throw new Error(json.error.message);
                    }
                    this.initConverters(json, (key) => {
                        const options = this.options;
                        const tableOptions = dataTables?.find((dataTable) => dataTable.key === key);
                        // Takes over the connector default options.
                        const mergedTableOptions = {
                            dataTableKey: key,
                            firstRowAsNames: tableOptions?.firstRowAsNames ??
                                options.firstRowAsNames,
                            beforeParse: tableOptions?.beforeParse ??
                                options.beforeParse
                        };
                        return new GoogleSheetsConverter(merge(this.options, mergedTableOptions));
                    }, (converter, data) => {
                        converter.parse({ json: data });
                    });
                    return connector.setModifierOptions(dataModifier, dataTables);
                })
                    .then(() => {
                    connector.emit({
                        type: 'afterLoad',
                        detail: eventDetail,
                        tables,
                        url
                    });
                    // Polling
                    if (enablePolling) {
                        setTimeout(() => connector.load(), Math.max(dataRefreshRate || 0, 1) * 1000);
                    }
                    return connector;
                })['catch']((error) => {
                    connector.emit({
                        type: 'loadError',
                        detail: eventDetail,
                        error,
                        tables
                    });
                    throw error;
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        GoogleSheetsConnector.defaultOptions = {
            googleAPIKey: '',
            googleSpreadsheetKey: '',
            enablePolling: false,
            dataRefreshRate: 2,
            firstRowAsNames: true
        };
        /* *
         *
         *  Class Namespace
         *
         * */
        (function (GoogleSheetsConnector) {
            /* *
             *
             *  Declarations
             *
             * */
            /* *
             *
             *  Constants
             *
             * */
            const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Creates GoogleSheets API v4 URL.
             * @private
             */
            function buildFetchURL(apiKey, sheetKey, options = {}) {
                const url = new URL(`https://sheets.googleapis.com/v4/spreadsheets/${sheetKey}/values/`);
                const range = options.onlyColumnNames ?
                    'A1:Z1' : buildQueryRange(options);
                url.pathname += range;
                const searchParams = url.searchParams;
                searchParams.set('alt', 'json');
                if (!options.onlyColumnNames) {
                    searchParams.set('dateTimeRenderOption', 'FORMATTED_STRING');
                    searchParams.set('majorDimension', 'COLUMNS');
                    searchParams.set('valueRenderOption', 'UNFORMATTED_VALUE');
                }
                searchParams.set('prettyPrint', 'false');
                searchParams.set('key', apiKey);
                return url.href;
            }
            GoogleSheetsConnector.buildFetchURL = buildFetchURL;
            /**
             * Creates sheets range.
             * @private
             */
            function buildQueryRange(options = {}) {
                const { endColumn, endRow, googleSpreadsheetRange, startColumn, startRow } = options;
                return googleSpreadsheetRange || ((alphabet[startColumn || 0] || 'A') +
                    (Math.max((startRow || 0), 0) + 1) +
                    ':' +
                    (alphabet[pick(endColumn, 25)] || 'Z') +
                    (endRow ?
                        Math.max(endRow, 0) :
                        'Z'));
            }
            GoogleSheetsConnector.buildQueryRange = buildQueryRange;
        })(GoogleSheetsConnector || (GoogleSheetsConnector = {}));
        DataConnector.registerType('GoogleSheets', GoogleSheetsConnector);
        /* *
         *
         *  Default Export
         *
         * */

        return GoogleSheetsConnector;
    });
    _registerModule(_modules, 'Data/Converters/HTMLTableConverter.js', [_modules['Data/Converters/DataConverter.js'], _modules['Core/Utilities.js']], function (DataConverter, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Gøran Slettemark
         *  - Wojciech Chmiel
         *  - Sophie Bremer
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Functions
         *
         * */
        /**
         * Row equal
         */
        function isRowEqual(row1, row2) {
            let i = row1.length;
            if (row2.length === i) {
                while (--i) {
                    if (row1[i] !== row2[i]) {
                        return false;
                    }
                }
            }
            else {
                return false;
            }
            return true;
        }
        /* *
         *
         *  Class
         *
         * */
        /**
         * Handles parsing and transformation of an HTML table to a table.
         *
         * @private
         */
        class HTMLTableConverter extends DataConverter {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the HTMLTableConverter.
             *
             * @param {HTMLTableConverter.UserOptions} [options]
             * Options for the HTMLTableConverter.
             */
            constructor(options) {
                const mergedOptions = merge(HTMLTableConverter.defaultOptions, options);
                super(mergedOptions);
                this.columns = [];
                this.headers = [];
                this.options = mergedOptions;
                if (mergedOptions.tableElement) {
                    this.tableElement = mergedOptions.tableElement;
                    this.tableElementID = mergedOptions.tableElement.id;
                }
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Exports the dataconnector as an HTML string, using the options
             * provided on      *
             * @param {DataConnector} connector
             * Connector instance to export from.
             *
             * @param {HTMLTableConnector.ExportOptions} [options]
             * Options that override default or existing export options.
             *
             * @return {string}
             * HTML from the current dataTable.
             */
            export(connector, options = this.options) {
                const exportNames = (options.firstRowAsNames !== false), useMultiLevelHeaders = options.useMultiLevelHeaders;
                const columns = connector.getSortedColumns(options.usePresentationOrder), columnNames = Object.keys(columns), htmlRows = [], columnsCount = columnNames.length;
                const rowArray = [];
                let tableHead = '';
                // Add the names as the first row if they should be exported
                if (exportNames) {
                    const subcategories = [];
                    // If using multilevel headers, the first value
                    // of each column is a subcategory
                    if (useMultiLevelHeaders) {
                        for (const name of columnNames) {
                            let column = columns[name];
                            if (!Array.isArray(column)) {
                                // Convert to conventional array from typed array
                                // if needed
                                column = Array.from(column);
                            }
                            const subhead = (column.shift() || '').toString();
                            columns[name] = column;
                            subcategories.push(subhead);
                        }
                        tableHead = this.getTableHeaderHTML(columnNames, subcategories, options);
                    }
                    else {
                        tableHead = this.getTableHeaderHTML(void 0, columnNames, options);
                    }
                }
                for (let columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
                    const columnName = columnNames[columnIndex], column = columns[columnName], columnLength = column.length;
                    for (let rowIndex = 0; rowIndex < columnLength; rowIndex++) {
                        let cellValue = column[rowIndex];
                        if (!rowArray[rowIndex]) {
                            rowArray[rowIndex] = [];
                        }
                        // Alternative: Datatype from HTML attribute with
                        // connector.whatIs(columnName)
                        if (!(typeof cellValue === 'string' ||
                            typeof cellValue === 'number' ||
                            typeof cellValue === 'undefined')) {
                            cellValue = (cellValue || '').toString();
                        }
                        rowArray[rowIndex][columnIndex] = this.getCellHTMLFromValue(columnIndex ? 'td' : 'th', null, columnIndex ? '' : 'scope="row"', cellValue);
                        // On the final column, push the row to the array
                        if (columnIndex === columnsCount - 1) {
                            htmlRows.push('<tr>' +
                                rowArray[rowIndex].join('') +
                                '</tr>');
                        }
                    }
                }
                let caption = '';
                // Add table caption
                // Current exportdata falls back to chart title
                // but that should probably be handled elsewhere?
                if (options.tableCaption) {
                    caption = '<caption class="highcharts-table-caption">' +
                        options.tableCaption +
                        '</caption>';
                }
                return ('<table>' +
                    caption +
                    tableHead +
                    '<tbody>' +
                    htmlRows.join('') +
                    '</tbody>' +
                    '</table>');
            }
            /**
             * Get table cell markup from row data.
             */
            getCellHTMLFromValue(tag, classes, attrs, value, decimalPoint) {
                let val = value, className = 'text' + (classes ? ' ' + classes : '');
                // Convert to string if number
                if (typeof val === 'number') {
                    val = val.toString();
                    if (decimalPoint === ',') {
                        val = val.replace('.', decimalPoint);
                    }
                    className = 'number';
                }
                else if (!value) {
                    val = '';
                    className = 'empty';
                }
                return '<' + tag + (attrs ? ' ' + attrs : '') +
                    ' class="' + className + '">' +
                    val + '</' + tag + '>';
            }
            /**
             * Get table header markup from row data.
             */
            getTableHeaderHTML(topheaders = [], subheaders = [], options = this.options) {
                const { useMultiLevelHeaders, useRowspanHeaders } = options;
                let html = '<thead>', i = 0, len = subheaders && subheaders.length, next, cur, curColspan = 0, rowspan;
                // Clean up multiple table headers. Exporting.getDataRows() returns two
                // levels of headers when using multilevel, not merged. We need to
                // merge identical headers, remove redundant headers, and keep it
                // all marked up nicely.
                if (useMultiLevelHeaders &&
                    topheaders &&
                    subheaders &&
                    !isRowEqual(topheaders, subheaders)) {
                    html += '<tr>';
                    for (; i < len; ++i) {
                        cur = topheaders[i];
                        next = topheaders[i + 1];
                        if (cur === next) {
                            ++curColspan;
                        }
                        else if (curColspan) {
                            // Ended colspan
                            // Add cur to HTML with colspan.
                            html += this.getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col" ' +
                                'colspan="' + (curColspan + 1) + '"', cur);
                            curColspan = 0;
                        }
                        else {
                            // Cur is standalone. If it is same as sublevel,
                            // remove sublevel and add just toplevel.
                            if (cur === subheaders[i]) {
                                if (useRowspanHeaders) {
                                    rowspan = 2;
                                    delete subheaders[i];
                                }
                                else {
                                    rowspan = 1;
                                    subheaders[i] = '';
                                }
                            }
                            else {
                                rowspan = 1;
                            }
                            html += this.getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col"' +
                                (rowspan > 1 ?
                                    ' valign="top" rowspan="' + rowspan + '"' :
                                    ''), cur);
                        }
                    }
                    html += '</tr>';
                }
                // Add the subheaders (the only headers if not using multilevels)
                if (subheaders) {
                    html += '<tr>';
                    for (i = 0, len = subheaders.length; i < len; ++i) {
                        if (typeof subheaders[i] !== 'undefined') {
                            html += this.getCellHTMLFromValue('th', null, 'scope="col"', subheaders[i]);
                        }
                    }
                    html += '</tr>';
                }
                html += '</thead>';
                return html;
            }
            /**
             * Initiates the parsing of the HTML table
             *
             * @param {HTMLTableConverter.UserOptions}[options]
             * Options for the parser
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits CSVDataParser#parse
             * @emits CSVDataParser#afterParse
             * @emits HTMLTableParser#parseError
             */
            parse(options, eventDetail) {
                const converter = this, columns = [], headers = [], parseOptions = merge(converter.options, options), { endRow, startColumn, endColumn, firstRowAsNames } = parseOptions, tableHTML = parseOptions.tableElement || this.tableElement;
                if (!(tableHTML instanceof HTMLElement)) {
                    converter.emit({
                        type: 'parseError',
                        columns,
                        detail: eventDetail,
                        headers,
                        error: 'Not a valid HTML Table'
                    });
                    return;
                }
                converter.tableElement = tableHTML;
                converter.tableElementID = tableHTML.id;
                this.emit({
                    type: 'parse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.headers
                });
                const rows = tableHTML.getElementsByTagName('tr'), rowsCount = rows.length;
                let rowIndex = 0, item, { startRow } = parseOptions;
                // Insert headers from the first row
                if (firstRowAsNames && rowsCount) {
                    const items = rows[0].children, itemsLength = items.length;
                    for (let i = startColumn; i < itemsLength; i++) {
                        if (i > endColumn) {
                            break;
                        }
                        item = items[i];
                        if (item.tagName === 'TD' ||
                            item.tagName === 'TH') {
                            headers.push(item.innerHTML);
                        }
                    }
                    startRow++;
                }
                while (rowIndex < rowsCount) {
                    if (rowIndex >= startRow && rowIndex <= endRow) {
                        const columnsInRow = rows[rowIndex].children, columnsInRowLength = columnsInRow.length;
                        let columnIndex = 0;
                        while (columnIndex < columnsInRowLength) {
                            const relativeColumnIndex = columnIndex - startColumn, row = columns[relativeColumnIndex];
                            item = columnsInRow[columnIndex];
                            if ((item.tagName === 'TD' ||
                                item.tagName === 'TH') &&
                                (columnIndex >= startColumn &&
                                    columnIndex <= endColumn)) {
                                if (!columns[relativeColumnIndex]) {
                                    columns[relativeColumnIndex] = [];
                                }
                                let cellValue = converter.asGuessedType(item.innerHTML);
                                if (cellValue instanceof Date) {
                                    cellValue = cellValue.getTime();
                                }
                                columns[relativeColumnIndex][rowIndex - startRow] = cellValue;
                                // Loop over all previous indices and make sure
                                // they are nulls, not undefined.
                                let i = 1;
                                while (rowIndex - startRow >= i &&
                                    row[rowIndex - startRow - i] === void 0) {
                                    row[rowIndex - startRow - i] = null;
                                    i++;
                                }
                            }
                            columnIndex++;
                        }
                    }
                    rowIndex++;
                }
                this.columns = columns;
                this.headers = headers;
                this.emit({
                    type: 'afterParse',
                    columns,
                    detail: eventDetail,
                    headers
                });
            }
            /**
             * Handles converting the parsed data to a table.
             *
             * @return {DataTable}
             * Table from the parsed HTML table
             */
            getTable() {
                return DataConverter.getTableFromColumns(this.columns, this.headers);
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options
         */
        HTMLTableConverter.defaultOptions = {
            ...DataConverter.defaultOptions,
            useRowspanHeaders: true,
            useMultiLevelHeaders: true
        };
        DataConverter.registerType('HTMLTable', HTMLTableConverter);
        /* *
         *
         *  Default Export
         *
         * */

        return HTMLTableConverter;
    });
    _registerModule(_modules, 'Data/Connectors/HTMLTableConnector.js', [_modules['Data/Connectors/DataConnector.js'], _modules['Core/Globals.js'], _modules['Data/Converters/HTMLTableConverter.js'], _modules['Core/Utilities.js']], function (DataConnector, H, HTMLTableConverter, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Torstein Hønsi
         *  - Gøran Slettemark
         *  - Wojciech Chmiel
         *  - Sophie Bremer
         *
         * */
        const { win } = H;
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that handles creating a data connector from an HTML table.
         *
         * @private
         */
        class HTMLTableConnector extends DataConnector {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of HTMLTableConnector.
             *
             * @param {HTMLTableConnector.UserOptions} [options]
             * Options for the connector and converter.
             */
            constructor(options) {
                const mergedOptions = merge(HTMLTableConnector.defaultOptions, options);
                super(mergedOptions);
                this.converter = new HTMLTableConverter(mergedOptions);
                this.options = mergedOptions;
            }
            /**
             * Initiates creating the dataconnector from the HTML table
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits HTMLTableConnector#load
             * @emits HTMLTableConnector#afterLoad
             * @emits HTMLTableConnector#loadError
             */
            load(eventDetail) {
                const connector = this, converter = connector.converter, table = connector.table, { dataModifier, table: tableHTML } = connector.options;
                connector.emit({
                    type: 'load',
                    detail: eventDetail,
                    tables: { table },
                    tableElement: connector.tableElement
                });
                let tableElement;
                if (typeof tableHTML === 'string') {
                    connector.tableID = tableHTML;
                    tableElement = win.document.getElementById(tableHTML);
                }
                else {
                    tableElement = tableHTML;
                    connector.tableID = tableElement.id;
                }
                connector.tableElement = tableElement || void 0;
                if (!connector.tableElement) {
                    const error = 'HTML table not provided, or element with ID not found';
                    connector.emit({
                        type: 'loadError',
                        detail: eventDetail,
                        error,
                        tables: { table }
                    });
                    return Promise.reject(new Error(error));
                }
                converter.parse(merge({ tableElement: connector.tableElement }, connector.options), eventDetail);
                // If already loaded, clear the current rows
                table.deleteColumns();
                table.setColumns(converter.getTable().getColumns());
                return connector
                    .setModifierOptions(dataModifier)
                    .then(() => {
                    connector.emit({
                        type: 'afterLoad',
                        detail: eventDetail,
                        tables: { table },
                        tableElement: connector.tableElement
                    });
                    return connector;
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        HTMLTableConnector.defaultOptions = {
            table: ''
        };
        DataConnector.registerType('HTMLTable', HTMLTableConnector);
        /* *
         *
         *  Default Export
         *
         * */

        return HTMLTableConnector;
    });
    _registerModule(_modules, 'Data/Converters/JSONConverter.js', [_modules['Data/Converters/DataConverter.js'], _modules['Data/DataTable.js'], _modules['Core/Utilities.js']], function (DataConverter, DataTable, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Pawel Lysy
         *
         * */
        const { error, isArray, merge, objectEach } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Handles parsing and transforming JSON to a table.
         *
         * @private
         */
        class JSONConverter extends DataConverter {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the JSON parser.
             *
             * @param {JSONConverter.UserOptions} [options]
             * Options for the JSON parser.
             */
            constructor(options) {
                const mergedOptions = merge(JSONConverter.defaultOptions, options);
                super(mergedOptions);
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.columns = [];
                this.headers = [];
                this.options = mergedOptions;
                this.table = new DataTable();
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Initiates parsing of JSON structure.
             *
             * @param {JSONConverter.UserOptions}[options]
             * Options for the parser
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits JSONConverter#parse
             * @emits JSONConverter#afterParse
             */
            parse(options, eventDetail) {
                const converter = this;
                options = merge(converter.options, options);
                const { beforeParse, orientation, firstRowAsNames, columnNames } = options;
                let data = options.data;
                if (!data) {
                    return;
                }
                converter.columns = [];
                converter.emit({
                    type: 'parse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.headers
                });
                if (beforeParse) {
                    data = beforeParse(data);
                }
                data = data.slice();
                if (orientation === 'columns') {
                    for (let i = 0, iEnd = data.length; i < iEnd; i++) {
                        const item = data[i];
                        if (!(item instanceof Array)) {
                            return;
                        }
                        if (converter.headers instanceof Array) {
                            if (firstRowAsNames) {
                                converter.headers.push(`${item.shift()}`);
                            }
                            else if (columnNames && columnNames instanceof Array) {
                                converter.headers.push(columnNames[i]);
                            }
                            converter.table.setColumn(converter.headers[i] || i.toString(), item);
                        }
                        else {
                            error('JSONConverter: Invalid `columnNames` option.', false);
                        }
                    }
                }
                else if (orientation === 'rows') {
                    if (firstRowAsNames) {
                        converter.headers = data.shift();
                    }
                    else if (columnNames) {
                        converter.headers = columnNames;
                    }
                    for (let rowIndex = 0, iEnd = data.length; rowIndex < iEnd; rowIndex++) {
                        let row = data[rowIndex];
                        if (isArray(row)) {
                            for (let columnIndex = 0, jEnd = row.length; columnIndex < jEnd; columnIndex++) {
                                if (converter.columns.length < columnIndex + 1) {
                                    converter.columns.push([]);
                                }
                                converter.columns[columnIndex].push(row[columnIndex]);
                                if (converter.headers instanceof Array) {
                                    this.table.setColumn(converter.headers[columnIndex] ||
                                        columnIndex.toString(), converter.columns[columnIndex]);
                                }
                                else {
                                    error('JSONConverter: Invalid `columnNames` option.', false);
                                }
                            }
                        }
                        else {
                            const columnNames = converter.headers;
                            if (columnNames && !(columnNames instanceof Array)) {
                                const newRow = {};
                                objectEach(columnNames, (arrayWithPath, name) => {
                                    newRow[name] = arrayWithPath.reduce((acc, key) => acc[key], row);
                                });
                                row = newRow;
                            }
                            this.table.setRows([row], rowIndex);
                        }
                    }
                }
                converter.emit({
                    type: 'afterParse',
                    columns: converter.columns,
                    detail: eventDetail,
                    headers: converter.headers
                });
            }
            /**
             * Handles converting the parsed data to a table.
             *
             * @return {DataTable}
             * Table from the parsed CSV.
             */
            getTable() {
                return this.table;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options
         */
        JSONConverter.defaultOptions = {
            ...DataConverter.defaultOptions,
            data: [],
            orientation: 'rows'
        };
        DataConverter.registerType('JSON', JSONConverter);
        /* *
         *
         *  Default Export
         *
         * */

        return JSONConverter;
    });
    _registerModule(_modules, 'Data/Connectors/JSONConnector.js', [_modules['Data/Connectors/DataConnector.js'], _modules['Core/Utilities.js'], _modules['Data/Converters/JSONConverter.js']], function (DataConnector, U, JSONConverter) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Pawel Lysy
         *
         * */
        const { merge, defined } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Class that handles creating a DataConnector from JSON structure
         *
         * @private
         */
        class JSONConnector extends DataConnector {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of JSONConnector.
             *
             * @param {JSONConnector.UserOptions} [options]
             * Options for the connector and converter.
             *
             * @param {Array<DataTableOptions>} [dataTables]
             * Multiple connector data tables options.
             */
            constructor(options, dataTables) {
                const mergedOptions = merge(JSONConnector.defaultOptions, options);
                super(mergedOptions, dataTables);
                this.options = defined(dataTables) ?
                    merge(mergedOptions, { dataTables }) : mergedOptions;
                if (mergedOptions.enablePolling) {
                    this.startPolling(Math.max(mergedOptions.dataRefreshRate || 0, 1) * 1000);
                }
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Initiates the loading of the JSON source to the connector
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @emits JSONConnector#load
             * @emits JSONConnector#afterLoad
             */
            load(eventDetail) {
                const connector = this, tables = connector.dataTables, { data, dataUrl, dataModifier, dataTables } = connector.options;
                connector.emit({
                    type: 'load',
                    data,
                    detail: eventDetail,
                    tables
                });
                return Promise
                    .resolve(dataUrl ?
                    fetch(dataUrl, {
                        signal: connector?.pollingController?.signal
                    }).then((response) => response.json())['catch']((error) => {
                        connector.emit({
                            type: 'loadError',
                            detail: eventDetail,
                            error,
                            tables
                        });
                        console.warn(`Unable to fetch data from ${dataUrl}.`); // eslint-disable-line no-console
                    }) :
                    data || [])
                    .then((data) => {
                    if (data) {
                        this.initConverters(data, (key) => {
                            const options = this.options;
                            const tableOptions = dataTables?.find((dataTable) => dataTable.key === key);
                            // Takes over the connector default options.
                            const mergedTableOptions = {
                                dataTableKey: key,
                                columnNames: tableOptions?.columnNames ??
                                    options.columnNames,
                                firstRowAsNames: tableOptions?.firstRowAsNames ??
                                    options.firstRowAsNames,
                                orientation: tableOptions?.orientation ??
                                    options.orientation,
                                beforeParse: tableOptions?.beforeParse ??
                                    options.beforeParse
                            };
                            return new JSONConverter(merge(this.options, mergedTableOptions));
                        }, (converter, data) => {
                            converter.parse({ data });
                        });
                    }
                    return connector.setModifierOptions(dataModifier, dataTables)
                        .then(() => data);
                })
                    .then((data) => {
                    connector.emit({
                        type: 'afterLoad',
                        data,
                        detail: eventDetail,
                        tables
                    });
                    return connector;
                })['catch']((error) => {
                    connector.emit({
                        type: 'loadError',
                        detail: eventDetail,
                        error,
                        tables
                    });
                    throw error;
                });
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        JSONConnector.defaultOptions = {
            data: [],
            enablePolling: false,
            dataRefreshRate: 0,
            firstRowAsNames: true,
            orientation: 'rows'
        };
        DataConnector.registerType('JSON', JSONConnector);
        /* *
         *
         *  Default Export
         *
         * */

        return JSONConnector;
    });
    _registerModule(_modules, 'Data/Modifiers/InvertModifier.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Core/Utilities.js']], function (DataModifier, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Wojciech Chmiel
         *  - Sophie Bremer
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Inverts columns and rows in a table.
         *
         * @private
         */
        class InvertModifier extends DataModifier {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the invert modifier.
             *
             * @param {Partial<InvertModifier.Options>} [options]
             * Options to configure the invert modifier.
             */
            constructor(options) {
                super();
                this.options = merge(InvertModifier.defaultOptions, options);
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Applies partial modifications of a cell change to the property `modified`
             * of the given modified table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {string} columnName
             * Column name of changed cell.
             *
             * @param {number|undefined} rowIndex
             * Row index of changed cell.
             *
             * @param {Highcharts.DataTableCellType} cellValue
             * Changed cell value.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyCell(table, columnName, rowIndex, cellValue, eventDetail) {
                const modified = table.modified, modifiedRowIndex = modified.getRowIndexBy('columnNames', columnName);
                if (typeof modifiedRowIndex === 'undefined') {
                    modified.setColumns(this.modifyTable(table.clone()).getColumns(), void 0, eventDetail);
                }
                else {
                    modified.setCell(`${rowIndex}`, modifiedRowIndex, cellValue, eventDetail);
                }
                return table;
            }
            /**
             * Applies partial modifications of column changes to the property
             * `modified` of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Highcharts.DataTableColumnCollection} columns
             * Changed columns as a collection, where the keys are the column names.
             *
             * @param {number} [rowIndex=0]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyColumns(table, columns, rowIndex, eventDetail) {
                const modified = table.modified, modifiedColumnNames = (modified.getColumn('columnNames') || []);
                let columnNames = table.getColumnNames(), reset = (table.getRowCount() !== modifiedColumnNames.length);
                if (!reset) {
                    for (let i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
                        if (columnNames[i] !== modifiedColumnNames[i]) {
                            reset = true;
                            break;
                        }
                    }
                }
                if (reset) {
                    return this.modifyTable(table, eventDetail);
                }
                columnNames = Object.keys(columns);
                for (let i = 0, iEnd = columnNames.length, column, columnName, modifiedRowIndex; i < iEnd; ++i) {
                    columnName = columnNames[i];
                    column = columns[columnName];
                    modifiedRowIndex = (modified.getRowIndexBy('columnNames', columnName) ||
                        modified.getRowCount());
                    for (let j = 0, j2 = rowIndex, jEnd = column.length; j < jEnd; ++j, ++j2) {
                        modified.setCell(`${j2}`, modifiedRowIndex, column[j], eventDetail);
                    }
                }
                return table;
            }
            /**
             * Applies partial modifications of row changes to the property `modified`
             * of the given table.
             *
             * @param {Highcharts.DataTable} table
             * Modified table.
             *
             * @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
             * Changed rows.
             *
             * @param {number} [rowIndex]
             * Index of the first changed row.
             *
             * @param {Highcharts.DataTableEventDetail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {Highcharts.DataTable}
             * Table with `modified` property as a reference.
             */
            modifyRows(table, rows, rowIndex, eventDetail) {
                const columnNames = table.getColumnNames(), modified = table.modified, modifiedColumnNames = (modified.getColumn('columnNames') || []);
                let reset = (table.getRowCount() !== modifiedColumnNames.length);
                if (!reset) {
                    for (let i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
                        if (columnNames[i] !== modifiedColumnNames[i]) {
                            reset = true;
                            break;
                        }
                    }
                }
                if (reset) {
                    return this.modifyTable(table, eventDetail);
                }
                for (let i = 0, i2 = rowIndex, iEnd = rows.length, row; i < iEnd; ++i, ++i2) {
                    row = rows[i];
                    if (row instanceof Array) {
                        modified.setColumn(`${i2}`, row);
                    }
                    else {
                        for (let j = 0, jEnd = columnNames.length; j < jEnd; ++j) {
                            modified.setCell(`${i2}`, j, row[columnNames[j]], eventDetail);
                        }
                    }
                }
                return table;
            }
            /**
             * Inverts rows and columns in the table.
             *
             * @param {DataTable} table
             * Table to invert.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {DataTable}
             * Table with inverted `modified` property as a reference.
             */
            modifyTable(table, eventDetail) {
                const modifier = this;
                modifier.emit({ type: 'modify', detail: eventDetail, table });
                const modified = table.modified;
                if (table.hasColumns(['columnNames'])) { // Inverted table
                    const columnNamesColumn = ((table.deleteColumns(['columnNames']) || {})
                        .columnNames || []), columns = {}, columnNames = [];
                    for (let i = 0, iEnd = columnNamesColumn.length; i < iEnd; ++i) {
                        columnNames.push('' + columnNamesColumn[i]);
                    }
                    for (let i = 0, iEnd = table.getRowCount(), row; i < iEnd; ++i) {
                        row = table.getRow(i);
                        if (row) {
                            columns[columnNames[i]] = row;
                        }
                    }
                    modified.deleteColumns();
                    modified.setColumns(columns);
                }
                else { // Regular table
                    const columns = {};
                    for (let i = 0, iEnd = table.getRowCount(), row; i < iEnd; ++i) {
                        row = table.getRow(i);
                        if (row) {
                            columns[`${i}`] = row;
                        }
                    }
                    columns.columnNames = table.getColumnNames();
                    modified.deleteColumns();
                    modified.setColumns(columns);
                }
                modifier.emit({ type: 'afterModify', detail: eventDetail, table });
                return table;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options for the invert modifier.
         */
        InvertModifier.defaultOptions = {
            type: 'Invert'
        };
        DataModifier.registerType('Invert', InvertModifier);
        /* *
         *
         *  Default Export
         *
         * */

        return InvertModifier;
    });
    _registerModule(_modules, 'Data/Modifiers/RangeModifier.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Core/Utilities.js']], function (DataModifier, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Sophie Bremer
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Filters out table rows with a specific value range.
         *
         */
        class RangeModifier extends DataModifier {
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the range modifier.
             *
             * @param {Partial<RangeModifier.Options>} [options]
             * Options to configure the range modifier.
             */
            constructor(options) {
                super();
                this.options = merge(RangeModifier.defaultOptions, options);
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Replaces table rows with filtered rows.
             *
             * @param {DataTable} table
             * Table to modify.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {DataTable}
             * Table with `modified` property as a reference.
             */
            modifyTable(table, eventDetail) {
                const modifier = this;
                modifier.emit({ type: 'modify', detail: eventDetail, table });
                let indexes = [];
                const { additive, ranges, strict } = modifier.options;
                if (ranges.length) {
                    const modified = table.modified;
                    let columns = table.getColumns(), rows = [];
                    for (let i = 0, iEnd = ranges.length, range, rangeColumn; i < iEnd; ++i) {
                        range = ranges[i];
                        if (strict &&
                            typeof range.minValue !== typeof range.maxValue) {
                            continue;
                        }
                        if (i > 0 && !additive) {
                            modified.deleteRows();
                            modified.setRows(rows);
                            modified.setOriginalRowIndexes(indexes, true);
                            columns = modified.getColumns();
                            rows = [];
                            indexes = [];
                        }
                        rangeColumn = (columns[range.column] || []);
                        for (let j = 0, jEnd = rangeColumn.length, cell, row, originalRowIndex; j < jEnd; ++j) {
                            cell = rangeColumn[j];
                            switch (typeof cell) {
                                default:
                                    continue;
                                case 'boolean':
                                case 'number':
                                case 'string':
                                    break;
                            }
                            if (strict &&
                                typeof cell !== typeof range.minValue) {
                                continue;
                            }
                            if (cell >= range.minValue &&
                                cell <= range.maxValue) {
                                if (additive) {
                                    row = table.getRow(j);
                                    originalRowIndex = table.getOriginalRowIndex(j);
                                }
                                else {
                                    row = modified.getRow(j);
                                    originalRowIndex = modified.getOriginalRowIndex(j);
                                }
                                if (row) {
                                    rows.push(row);
                                    indexes.push(originalRowIndex);
                                }
                            }
                        }
                    }
                    modified.deleteRows();
                    modified.setRows(rows);
                    modified.setOriginalRowIndexes(indexes);
                }
                modifier.emit({ type: 'afterModify', detail: eventDetail, table });
                return table;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options for the range modifier.
         */
        RangeModifier.defaultOptions = {
            type: 'Range',
            ranges: []
        };
        DataModifier.registerType('Range', RangeModifier);
        /* *
         *
         *  Default Export
         *
         * */

        return RangeModifier;
    });
    _registerModule(_modules, 'Data/Modifiers/FilterModifier.js', [_modules['Data/Modifiers/DataModifier.js'], _modules['Core/Utilities.js']], function (DataModifier, U) {
        /* *
         *
         *  (c) 2009-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { isFunction, merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Filters out table rows matching a given condition.
         */
        class FilterModifier extends DataModifier {
            /* *
             *
             *  Static Functions
             *
             * */
            /**
             * Compiles a filter condition into a callback function.
             *
             * @param {FilterCondition} condition
             * Condition to compile.
             */
            static compile(condition) {
                if (isFunction(condition)) {
                    return condition;
                }
                const op = condition.operator;
                switch (op) {
                    case 'and': {
                        const subs = condition.conditions.map((c) => this.compile(c));
                        return (row, table, i) => subs.every((cond) => cond(row, table, i));
                    }
                    case 'or': {
                        const subs = condition.conditions.map((c) => this.compile(c));
                        return (row, table, i) => subs.some((cond) => cond(row, table, i));
                    }
                    case 'not': {
                        const sub = this.compile(condition.condition);
                        return (row, table, i) => !sub(row, table, i);
                    }
                }
                const { columnName: col, value } = condition;
                switch (op) {
                    case '==':
                        // eslint-disable-next-line eqeqeq
                        return (row) => row[col] == value;
                    case '===':
                        return (row) => row[col] === value;
                    case '!=':
                        // eslint-disable-next-line eqeqeq
                        return (row) => row[col] != value;
                    case '!==':
                        return (row) => row[col] !== value;
                    case '>':
                        return (row) => (row[col] || 0) > (value || 0);
                    case '>=':
                        return (row) => (row[col] || 0) >= (value || 0);
                    case '<':
                        return (row) => (row[col] || 0) < (value || 0);
                    case '<=':
                        return (row) => (row[col] || 0) <= (value || 0);
                }
                const { ignoreCase } = condition;
                const str = (val) => {
                    const s = '' + val;
                    return (ignoreCase ?? true) ? s.toLowerCase() : s;
                };
                switch (op) {
                    case 'contains':
                        return (row) => str(row[col]).includes(str(value));
                    default:
                        return (row) => str(row[col])[op](str(value));
                }
            }
            /* *
             *
             *  Constructor
             *
             * */
            /**
             * Constructs an instance of the filter modifier.
             *
             * @param {Partial<FilterModifier.Options>} [options]
             * Options to configure the filter modifier.
             */
            constructor(options) {
                super();
                this.options = merge(FilterModifier.defaultOptions, options);
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Replaces table rows with filtered rows.
             *
             * @param {DataTable} table
             * Table to modify.
             *
             * @param {DataEvent.Detail} [eventDetail]
             * Custom information for pending events.
             *
             * @return {DataTable}
             * Table with `modified` property as a reference.
             */
            modifyTable(table, eventDetail) {
                const modifier = this;
                modifier.emit({ type: 'modify', detail: eventDetail, table });
                const { condition } = modifier.options;
                if (!condition) {
                    // If no condition is set, return the unmodified table.
                    return table;
                }
                const matchRow = FilterModifier.compile(condition);
                // This line should be investigated further when reworking Data Layer.
                const modified = table.modified;
                const rows = [];
                const indexes = [];
                for (let i = 0, iEnd = table.getRowCount(); i < iEnd; ++i) {
                    const row = table.getRowObject(i);
                    if (!row) {
                        continue;
                    }
                    if (matchRow(row, table, i)) {
                        rows.push(row);
                        indexes.push(modified.getOriginalRowIndex(i));
                    }
                }
                modified.deleteRows();
                modified.setRows(rows);
                modified.setOriginalRowIndexes(indexes);
                modifier.emit({ type: 'afterModify', detail: eventDetail, table });
                return table;
            }
        }
        /* *
         *
         *  Static Properties
         *
         * */
        /**
         * Default options for the filter modifier.
         */
        FilterModifier.defaultOptions = {
            type: 'Filter'
        };
        DataModifier.registerType('Filter', FilterModifier);
        /* *
         *
         *  Default Export
         *
         * */

        return FilterModifier;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/CellRenderer.js', [], function () {
        /* *
         *
         *  Cell Renderer abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer class that initialize all options per column.
         */
        class CellRenderer {
            /**
             * Constructs the CellRenderer instance.
             *
             * @param column
             * The column of the cell.
             *
             */
            constructor(column) {
                this.column = column;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return CellRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/TextRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Core/Table/CellContent/TextContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, TextContent, U) {
        /* *
         *
         *  Text Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Text in a column..
         */
        class TextRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column) {
                super(column);
                this.options = merge(TextRenderer.defaultOptions, this.column.options.cells?.renderer || {});
                const cellOptions = column.options.cells;
                this.format =
                    cellOptions?.format ??
                        TextContent.defaultFormatsForDataTypes[column.dataType];
                this.formatter = cellOptions?.formatter;
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell) {
                return new TextContent(cell);
            }
        }
        /**
         * The default edit mode renderer type names for this view renderer.
         */
        TextRenderer.defaultEditingRenderer = {
            string: 'textInput',
            number: 'textInput',
            'boolean': 'checkbox',
            datetime: 'dateInput'
        };
        /**
         * Default options for the text renderer.
         */
        TextRenderer.defaultOptions = {
            type: 'text'
        };
        CellRendererRegistry.registerRenderer('text', TextRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return TextRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/CellContentPro.js', [_modules['Grid/Core/Table/CellContent/CellContent.js']], function (CellContent) {
        /* *
         *
         *  Cell Content Pro abstract class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a cell content in the grid.
         */
        class CellContentPro extends CellContent {
            /**
             * Creates and renders the cell content.
             *
             * @param cell
             * The cell to which the content belongs.
             *
             * @param renderer
             * Renderer that allows print content (inputs, selects, etc.)
             */
            constructor(cell, renderer) {
                super(cell);
                this.renderer = renderer;
            }
        }
        /* *
         *
         * Default Export
         *
         * */

        return CellContentPro;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/ContentTypes/CheckboxContent.js', [_modules['Grid/Pro/CellRendering/CellContentPro.js'], _modules['Grid/Core/Globals.js']], function (CellContentPro, Globals) {
        /* *
         *
         *  Checkbox Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a checkbox type of cell content.
         */
        class CheckboxContent extends CellContentPro {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(cell, renderer, parentElement) {
                super(cell, renderer);
                this.finishAfterChange = false;
                this.onChange = (e) => {
                    if (this.changeHandler) {
                        this.changeHandler(e);
                    }
                    else {
                        void this.cell.setValue(this.value, true);
                    }
                };
                this.onKeyDown = (e) => {
                    this.keyDownHandler?.(e);
                };
                this.onBlur = (e) => {
                    this.blurHandler?.(e);
                };
                this.onCellKeyDown = (e) => {
                    if (e.key === ' ') {
                        this.input.click();
                    }
                };
                this.input = this.add(parentElement);
            }
            /* *
             *
             *  Methods
             *
             * */
            add(parentElement = this.cell.htmlElement) {
                const cell = this.cell;
                this.input = document.createElement('input');
                this.input.tabIndex = -1;
                this.input.type = 'checkbox';
                this.input.name = cell.column.id + '-' + cell.row.id;
                this.update();
                parentElement.appendChild(this.input);
                this.input.classList.add(Globals.classNamePrefix + 'field-auto-width');
                this.input.addEventListener('change', this.onChange);
                this.input.addEventListener('keydown', this.onKeyDown);
                this.input.addEventListener('blur', this.onBlur);
                this.cell.htmlElement.addEventListener('keydown', this.onCellKeyDown);
                return this.input;
            }
            update() {
                const cell = this.cell;
                const input = this.input;
                const { options } = this.renderer;
                input.checked = !!cell.value;
                input.disabled = !!options.disabled;
            }
            get rawValue() {
                return this.input.checked ? 'true' : 'false';
            }
            get value() {
                const val = this.input.checked;
                switch (this.cell.column.dataType) {
                    case 'datetime':
                    case 'number':
                        return +val;
                    case 'boolean':
                        return val;
                    case 'string':
                        return '' + val;
                }
            }
            getMainElement() {
                return this.input;
            }
            destroy() {
                const input = this.input;
                this.cell.htmlElement.removeEventListener('keydown', this.onCellKeyDown);
                input.removeEventListener('blur', this.onBlur);
                input.removeEventListener('keydown', this.onKeyDown);
                input.removeEventListener('change', this.onChange);
                input.remove();
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return CheckboxContent;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/CheckboxRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Pro/CellRendering/ContentTypes/CheckboxContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, CheckboxContent, U) {
        /* *
         *
         *  Checkbox Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Checkbox in a column.
         */
        class CheckboxRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column, options) {
                super(column);
                this.options = merge(CheckboxRenderer.defaultOptions, options);
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell, parentElement) {
                return new CheckboxContent(cell, this, parentElement);
            }
        }
        /**
         * The default edit mode renderer type name for this view renderer.
         */
        CheckboxRenderer.defaultEditingRenderer = 'checkbox';
        /**
         * Default options for the checkbox renderer.
         */
        CheckboxRenderer.defaultOptions = {
            type: 'checkbox'
        };
        CellRendererRegistry.registerRenderer('checkbox', CheckboxRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return CheckboxRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/ContentTypes/SelectContent.js', [_modules['Grid/Pro/CellRendering/CellContentPro.js'], _modules['Core/Renderer/HTML/AST.js']], function (CellContentPro, AST) {
        /* *
         *
         *  Select Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a select type of cell content.
         */
        class SelectContent extends CellContentPro {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(cell, renderer, parentElement) {
                super(cell, renderer);
                this.finishAfterChange = true;
                /**
                 * The HTML option elements representing the options in the select input.
                 */
                this.optionElements = [];
                this.onChange = (e) => {
                    if (this.changeHandler) {
                        this.changeHandler(e);
                    }
                    else {
                        this.cell.htmlElement.focus();
                        void this.cell.setValue(this.value, true);
                    }
                };
                this.onKeyDown = (e) => {
                    e.stopPropagation();
                    if (this.keyDownHandler) {
                        this.keyDownHandler?.(e);
                        return;
                    }
                    if (e.key === 'Escape' || e.key === 'Enter') {
                        this.cell.htmlElement.focus();
                    }
                };
                this.onBlur = (e) => {
                    this.blurHandler?.(e);
                };
                this.onCellKeyDown = (e) => {
                    if (e.key === ' ') {
                        this.select.focus();
                        e.preventDefault();
                    }
                };
                this.select = this.add(parentElement);
            }
            /* *
             *
             *  Methods
             *
             * */
            add(parentElement = this.cell.htmlElement) {
                const cell = this.cell;
                const select = this.select = document.createElement('select');
                select.tabIndex = -1;
                select.name = cell.column.id + '-' + cell.row.id;
                this.update();
                parentElement.appendChild(this.select);
                select.addEventListener('change', this.onChange);
                select.addEventListener('keydown', this.onKeyDown);
                select.addEventListener('blur', this.onBlur);
                this.cell.htmlElement.addEventListener('keydown', this.onCellKeyDown);
                return select;
            }
            update() {
                const cell = this.cell;
                const { options } = this.renderer;
                this.select.disabled = !!options.disabled;
                // If there will be a need, we can optimize this by not removing all
                // old options and only updating the ones that need to be updated.
                this.select.innerHTML = AST.emptyHTML;
                for (const option of options.options) {
                    const optionElement = document.createElement('option');
                    optionElement.value = option.value;
                    optionElement.textContent = option.label || option.value;
                    optionElement.disabled = !!option.disabled;
                    if (cell.value === option.value) {
                        optionElement.selected = true;
                    }
                    this.select.appendChild(optionElement);
                    this.optionElements.push(optionElement);
                }
            }
            destroy() {
                const select = this.select;
                this.cell.htmlElement.removeEventListener('keydown', this.onCellKeyDown);
                select.removeEventListener('blur', this.onBlur);
                select.removeEventListener('keydown', this.onKeyDown);
                select.removeEventListener('change', this.onChange);
                for (const optionElement of this.optionElements) {
                    optionElement.remove();
                }
                this.optionElements.length = 0;
                select.remove();
            }
            get rawValue() {
                return this.select.value;
            }
            get value() {
                const val = this.select.value;
                switch (this.cell.column.dataType) {
                    case 'datetime':
                    case 'number':
                        return +val;
                    case 'boolean':
                        return val;
                    case 'string':
                        return '' + val;
                }
            }
            getMainElement() {
                return this.select;
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return SelectContent;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/SelectRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Pro/CellRendering/ContentTypes/SelectContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, SelectContent, U) {
        /* *
         *
         *  Select Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Select in a column..
         */
        class SelectRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column, options) {
                super(column);
                this.options = merge(SelectRenderer.defaultOptions, options);
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell, parentElement) {
                return new SelectContent(cell, this, parentElement);
            }
        }
        /**
         * The default edit mode renderer type name for this view renderer.
         */
        SelectRenderer.defaultEditingRenderer = 'select';
        /**
         * Default options for the select renderer.
         */
        SelectRenderer.defaultOptions = {
            type: 'select',
            options: []
        };
        CellRendererRegistry.registerRenderer('select', SelectRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return SelectRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/ContentTypes/TextInputContent.js', [_modules['Grid/Pro/CellRendering/CellContentPro.js'], _modules['Core/Utilities.js']], function (CellContentPro, U) {
        /* *
         *
         *  Text Input Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { defined } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a text input type of cell content.
         */
        class TextInputContent extends CellContentPro {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(cell, renderer, parentElement) {
                super(cell, renderer);
                this.finishAfterChange = true;
                this.onChange = (e) => {
                    if (this.changeHandler) {
                        this.changeHandler(e);
                        return;
                    }
                    void this.cell.setValue(e.target.value, true);
                };
                this.onKeyDown = (e) => {
                    e.stopPropagation();
                    if (this.keyDownHandler) {
                        this.keyDownHandler(e);
                        return;
                    }
                    if (e.key === 'Escape') {
                        this.input.value = this.convertToInputValue();
                        this.cell.htmlElement.focus();
                        return;
                    }
                    if (e.key === 'Enter') {
                        this.cell.htmlElement.focus();
                    }
                };
                this.onBlur = (e) => {
                    this.blurHandler?.(e);
                };
                this.onCellKeyDown = (e) => {
                    if (e.key === ' ') {
                        this.input.focus();
                        e.preventDefault();
                    }
                };
                this.input = this.add(parentElement);
            }
            /* *
             *
             *  Methods
             *
             * */
            add(parentElement = this.cell.htmlElement) {
                const cell = this.cell;
                const input = this.input = document.createElement('input');
                input.tabIndex = -1;
                input.name = cell.column.id + '-' + cell.row.id;
                this.update();
                parentElement.appendChild(this.input);
                input.addEventListener('change', this.onChange);
                input.addEventListener('keydown', this.onKeyDown);
                input.addEventListener('blur', this.onBlur);
                this.cell.htmlElement.addEventListener('keydown', this.onCellKeyDown);
                return input;
            }
            update() {
                const { options } = this.renderer;
                this.input.value = this.convertToInputValue();
                this.input.disabled = !!options.disabled;
            }
            get rawValue() {
                return this.input.value;
            }
            get value() {
                const val = this.input.value;
                switch (this.cell.column.dataType) {
                    case 'datetime':
                    case 'number':
                        return val === '' ? null : +val;
                    case 'boolean':
                        if (val === '') {
                            return null;
                        }
                        if (val === 'false' || +val === 0) {
                            return false;
                        }
                        return true;
                    case 'string':
                        return val;
                }
            }
            /**
             * Converts the cell value to a string for the input.
             */
            convertToInputValue() {
                const val = this.cell.value;
                return defined(val) ? '' + val : '';
            }
            getMainElement() {
                return this.input;
            }
            destroy() {
                const input = this.input;
                this.cell.htmlElement.removeEventListener('keydown', this.onCellKeyDown);
                input.removeEventListener('blur', this.onBlur);
                input.removeEventListener('keydown', this.onKeyDown);
                input.removeEventListener('change', this.onChange);
                input.remove();
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return TextInputContent;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/TextInputRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Pro/CellRendering/ContentTypes/TextInputContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, TextInputContent, U) {
        /* *
         *
         *  Text Input Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Select in a column..
         */
        class TextInputRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column, options) {
                super(column);
                this.options = merge(TextInputRenderer.defaultOptions, options);
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell, parentElement) {
                return new TextInputContent(cell, this, parentElement);
            }
        }
        /**
         * The default edit mode renderer type names for this view renderer.
         */
        TextInputRenderer.defaultEditingRenderer = 'textInput';
        /**
         * Default options for the text input renderer.
         */
        TextInputRenderer.defaultOptions = {
            type: 'textInput'
        };
        CellRendererRegistry.registerRenderer('textInput', TextInputRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return TextInputRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/ContentTypes/DateInputContent.js', [_modules['Grid/Pro/CellRendering/CellContentPro.js']], function (CellContentPro) {
        /* *
         *
         *  Date Input Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a date input type of cell content.
         */
        class DateInputContent extends CellContentPro {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(cell, renderer, parentElement) {
                super(cell, renderer);
                this.finishAfterChange = false;
                this.onChange = (e) => {
                    this.changeHandler?.(e);
                };
                this.onKeyDown = (e) => {
                    e.stopPropagation();
                    if (this.keyDownHandler) {
                        this.keyDownHandler(e);
                        return;
                    }
                    if (e.key === 'Escape') {
                        this.cell.htmlElement.focus();
                        this.input.value = this.convertToInputValue();
                        return;
                    }
                    if (e.key === 'Enter') {
                        this.cell.htmlElement.focus();
                        void this.cell.setValue(this.value, true);
                    }
                };
                this.onBlur = (e) => {
                    if (this.blurHandler) {
                        this.blurHandler(e);
                        return;
                    }
                    void this.cell.setValue(this.value, true);
                };
                this.onCellKeyDown = (e) => {
                    if (e.key === ' ') {
                        this.input.focus();
                        e.preventDefault();
                    }
                };
                this.input = this.add(parentElement);
            }
            /* *
             *
             *  Methods
             *
             * */
            add(parentElement = this.cell.htmlElement) {
                const cell = this.cell;
                const input = this.input = document.createElement('input');
                input.tabIndex = -1;
                input.type = 'date';
                input.name = cell.column.id + '-' + cell.row.id;
                this.update();
                parentElement.appendChild(input);
                input.addEventListener('change', this.onChange);
                input.addEventListener('keydown', this.onKeyDown);
                input.addEventListener('blur', this.onBlur);
                this.cell.htmlElement.addEventListener('keydown', this.onCellKeyDown);
                return this.input;
            }
            update() {
                const input = this.input;
                const { options } = this.renderer;
                input.value = this.convertToInputValue();
                input.disabled = !!options.disabled;
            }
            get rawValue() {
                return this.input.value;
            }
            get value() {
                return new Date(this.input.value).getTime();
            }
            getMainElement() {
                return this.input;
            }
            destroy() {
                const input = this.input;
                this.cell.htmlElement.removeEventListener('keydown', this.onCellKeyDown);
                input.removeEventListener('blur', this.onBlur);
                input.removeEventListener('keydown', this.onKeyDown);
                input.removeEventListener('change', this.onChange);
                input.remove();
            }
            /**
             * Converts the cell value to a string for the input.
             */
            convertToInputValue() {
                const time = this.cell.column.viewport.grid.time;
                return time.dateFormat('%Y-%m-%d', Number(this.cell.value || 0));
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return DateInputContent;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/DateInputRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Pro/CellRendering/ContentTypes/DateInputContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, DateInputContent, U) {
        /* *
         *
         *  Date Input Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Select in a column..
         */
        class DateInputRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column, options) {
                super(column);
                this.options = merge(DateInputRenderer.defaultOptions, options);
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell, parentElement) {
                return new DateInputContent(cell, this, parentElement);
            }
        }
        /**
         * The default edit mode renderer type name for this view renderer.
         */
        DateInputRenderer.defaultEditingRenderer = 'dateInput';
        /**
         * Default options for the date input renderer.
         */
        DateInputRenderer.defaultOptions = {
            type: 'dateInput'
        };
        CellRendererRegistry.registerRenderer('dateInput', DateInputRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return DateInputRenderer;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/ContentTypes/SparklineContent.js', [_modules['Grid/Pro/CellRendering/CellContentPro.js'], _modules['Grid/Core/Globals.js'], _modules['Core/Utilities.js']], function (CellContentPro, Globals, U) {
        /* *
         *
         *  Sparkline Cell Content class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { defined, merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Represents a sparkline type of cell content.
         */
        class SparklineContent extends CellContentPro {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(cell, renderer, parentElement) {
                super(cell, renderer);
                this.onKeyDown = () => {
                    this.cell.htmlElement.focus();
                };
                this.add(parentElement);
            }
            /* *
             *
             *  Methods
             *
             * */
            add(parentElement = this.cell.htmlElement) {
                const H = SparklineContent.H;
                if (!H || !defined(this.cell.value)) {
                    return;
                }
                this.chartContainer = document.createElement('div');
                parentElement.classList.add(Globals.getClassName('noPadding'));
                parentElement.appendChild(this.chartContainer);
                this.chart = H.Chart.chart(this.chartContainer, merge(SparklineContent.defaultChartOptions, this.getProcessedOptions()));
                this.chartContainer.addEventListener('click', this.onKeyDown);
            }
            update() {
                const chartOptions = this.getProcessedOptions();
                this.chart?.update(chartOptions, true, false, chartOptions.chart?.animation);
            }
            destroy() {
                this.chartContainer?.removeEventListener('keydown', this.onKeyDown);
                this.chart?.destroy();
                this.chartContainer?.remove();
                delete this.chart;
                delete this.chartContainer;
                this.cell.htmlElement.classList.remove(Globals.getClassName('noPadding'));
            }
            getProcessedOptions() {
                const renderer = this.renderer;
                const { chartOptions } = renderer.options;
                let options;
                if (typeof chartOptions === 'function') {
                    options = chartOptions.call(this.cell, this.cell.value);
                }
                else {
                    options = merge(chartOptions) || {};
                }
                let trimmedValue = ('' + this.cell.value).trim();
                if (!trimmedValue.startsWith('[') && !trimmedValue.startsWith('{')) {
                    trimmedValue = `[${trimmedValue}]`;
                }
                if (!options.series) {
                    options.series = [{
                            data: JSON.parse(trimmedValue)
                        }];
                }
                return options;
            }
        }
        SparklineContent.defaultChartOptions = {
            chart: {
                height: 40,
                margin: [5, 8, 5, 8],
                backgroundColor: 'transparent',
                skipClone: true
            },
            accessibility: {
                enabled: false
            },
            tooltip: {
                enabled: false
            },
            title: {
                text: ''
            },
            credits: {
                enabled: false
            },
            xAxis: {
                visible: false
            },
            yAxis: {
                visible: false
            },
            legend: {
                enabled: false
            },
            plotOptions: {
                series: {
                    borderWidth: 0,
                    marker: {
                        enabled: false
                    },
                    states: {
                        hover: {
                            enabled: false
                        },
                        inactive: {
                            enabled: false
                        }
                    },
                    animation: false,
                    dataLabels: {
                        enabled: false
                    }
                },
                pie: {
                    slicedOffset: 0,
                    borderRadius: 0
                }
            }
        };
        /* *
         *
         *  Namespace
         *
         * */
        (function (SparklineContent) {
        })(SparklineContent || (SparklineContent = {}));
        /* *
         *
         *  Default Export
         *
         * */

        return SparklineContent;
    });
    _registerModule(_modules, 'Grid/Pro/CellRendering/Renderers/SparklineRenderer.js', [_modules['Grid/Pro/CellRendering/CellRenderer.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js'], _modules['Grid/Pro/CellRendering/ContentTypes/SparklineContent.js'], _modules['Core/Utilities.js']], function (CellRenderer, CellRendererRegistry, SparklineContent, U) {
        /* *
         *
         *  Sparkline Cell Renderer class
         *
         *  (c) 2020-2025 Highsoft AS
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         *  Authors:
         *  - Dawid Dragula
         *
         * */
        const { merge } = U;
        /* *
         *
         *  Class
         *
         * */
        /**
         * Renderer for the Text in a column..
         */
        class SparklineRenderer extends CellRenderer {
            /* *
             *
             *  Constructor
             *
             * */
            constructor(column) {
                super(column);
                if (!SparklineContent.H) {
                    throw new Error('Sparkline Renderer: Highcharts is not loaded. Please ensure ' +
                        'that Highcharts namespace is registered before the Sparkline' +
                        ' Renderer is used.');
                }
                this.options = merge(SparklineRenderer.defaultOptions, this.column.options.cells?.renderer || {});
            }
            /* *
             *
             *  Methods
             *
             * */
            render(cell) {
                return new SparklineContent(cell, this);
            }
        }
        /**
         * The default edit mode renderer type names for this view renderer.
         */
        SparklineRenderer.defaultEditingRenderer = 'textInput';
        /**
         * Default options for the sparkline renderer.
         */
        SparklineRenderer.defaultOptions = {
            type: 'sparkline'
        };
        /* *
         *
         *  Namespace
         *
         * */
        (function (SparklineRenderer) {
            /**
             * Imports the Highcharts namespace to be used by the Sparkline Renderer.
             *
             * @param H
             * Highcharts namespace.
             */
            function useHighcharts(H) {
                if (H && !SparklineContent.H) {
                    SparklineContent.H = H;
                }
            }
            SparklineRenderer.useHighcharts = useHighcharts;
        })(SparklineRenderer || (SparklineRenderer = {}));
        CellRendererRegistry.registerRenderer('sparkline', SparklineRenderer);
        /* *
         *
         *  Default Export
         *
         * */

        return SparklineRenderer;
    });
    _registerModule(_modules, 'masters/datagrid.src.js', [_modules['Core/Renderer/HTML/AST.js'], _modules['Core/Templating.js'], _modules['Grid/Core/Table/ColumnDistribution/ColumnDistribution.js'], _modules['Data/Connectors/DataConnector.js'], _modules['Data/Converters/DataConverter.js'], _modules['Data/DataCursor.js'], _modules['Grid/Core/Grid.js'], _modules['Data/Modifiers/DataModifier.js'], _modules['Data/DataPool.js'], _modules['Data/DataTable.js'], _modules['Grid/Core/Defaults.js'], _modules['Grid/Core/Globals.js'], _modules['Accessibility/HighContrastMode.js'], _modules['Core/Utilities.js'], _modules['Grid/Core/Table/Table.js'], _modules['Grid/Core/Table/Column.js'], _modules['Grid/Core/Table/Header/HeaderCell.js'], _modules['Grid/Core/Table/Body/TableCell.js'], _modules['Grid/Pro/GridEvents.js'], _modules['Grid/Pro/CellEditing/CellEditingComposition.js'], _modules['Grid/Pro/Dash3Compatibility.js'], _modules['Grid/Pro/Credits/CreditsProComposition.js'], _modules['Grid/Pro/ColumnTypes/ValidatorComposition.js'], _modules['Grid/Pro/CellRendering/CellRenderersComposition.js'], _modules['Grid/Pro/CellRendering/CellRendererRegistry.js']], function (AST, Templating, ColumnDistribution, DataConnector, DataConverter, DataCursor, _Grid, DataModifier, DataPool, DataTable, Defaults, Globals, whcm, Utilities, Table, Column, HeaderCell, TableCell, GridEvents, CellEditingComposition, Dash3Compatibility, CreditsProComposition, ValidatorComposition, CellRenderersComposition, CellRendererRegistry) {

        /* *
         *
         *  Registers Imports
         *
         * */
        // Connectors
        // Compositions
        // Cell Renderers
        /* *
         *
         *  Namespace
         *
         * */
        const G = Globals;
        G.AST = AST;
        G.classNamePrefix = 'highcharts-datagrid-';
        G.DataConnector = DataConnector;
        G.DataCursor = DataCursor;
        G.DataConverter = DataConverter;
        G.DataGrid = _Grid;
        G.dataGrid = _Grid.grid;
        G.dataGrids = _Grid.grids;
        G.Grid = _Grid;
        G.grid = _Grid.grid;
        G.grids = _Grid.grids;
        G.DataModifier = DataModifier;
        G.DataPool = DataPool;
        G.DataTable = DataTable;
        G.ColumnDistribution = ColumnDistribution;
        G.defaultOptions = Defaults.defaultOptions;
        G.isHighContrastModeActive = whcm.isHighContrastModeActive;
        G.setOptions = Defaults.setOptions;
        G.Templating = Templating;
        G.product = 'Grid Pro';
        G.merge = Utilities.merge;
        G.Table = G.Table || Table;
        G.Column = G.Column || Column;
        G.HeaderCell = G.HeaderCell || HeaderCell;
        G.TableCell = G.TableCell || TableCell;
        GridEvents.compose(G.Column, G.HeaderCell, G.TableCell);
        CellEditingComposition.compose(G.Table, G.TableCell, G.Column);
        CreditsProComposition.compose(G.Grid);
        Dash3Compatibility.compose(G.Table);
        ValidatorComposition.compose(G.Table);
        CellRenderersComposition.compose(G.Column);
        G.CellRendererRegistry = G.CellRendererRegistry || CellRendererRegistry;
        /* *
         *
         *  Classic Export
         *
         * */
        if (!G.win.DataGrid) {
            G.win.DataGrid = G;
        }
        if (!G.win.Grid) {
            G.win.Grid = G;
        }
        if (G.win.Highcharts) {
            G.CellRendererRegistry.types.sparkline.useHighcharts(G.win.Highcharts);
        }
        /* *
         *
         *  Default Export
         *
         * */

        return G;
    });
    _modules['masters/datagrid.src.js']._modules = _modules;
    return _modules['masters/datagrid.src.js'];
}));